1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.config.commands.CommandCategory
import at.hannibal2.skyhanni.config.commands.CommandRegistrationEvent
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.LorenzKeyPressEvent
import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
import at.hannibal2.skyhanni.utils.GuiRenderUtils
import at.hannibal2.skyhanni.utils.InventoryUtils
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.TimeUtils.format
import at.hannibal2.skyhanni.utils.compat.GuiScreenUtils
import io.github.notenoughupdates.moulconfig.internal.RenderUtils
import net.minecraft.client.Minecraft
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.lwjgl.input.Keyboard
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
@SkyHanniModule
object NotificationManager {
private val notificationQueue = mutableListOf<SkyHanniNotification>()
private var currentNotification: SkyHanniNotification? = null
private var lastNotificationClosed = SimpleTimeMark.farPast()
private const val CLOSE_TEXT = "§c[X] Close"
@SubscribeEvent
fun onKeyClick(event: LorenzKeyPressEvent) {
currentNotification ?: return
if (lastNotificationClosed.passedSince() < 200.milliseconds) return
if (event.keyCode != Keyboard.KEY_X) return
currentNotification = null
lastNotificationClosed = SimpleTimeMark.now()
}
@SubscribeEvent
fun onRenderOverlay(event: GuiRenderEvent) {
val notification = getCurrentNotification() ?: return
if (InventoryUtils.inInventory() && !notification.showOverInventory) return
val midX = GuiScreenUtils.scaledWindowWidth / 2
val topY = (GuiScreenUtils.scaledWindowHeight * 0.75 - notification.height / 2).toInt()
RenderUtils.drawFloatingRectDark(midX - notification.width / 2, topY, notification.width, notification.height)
val closeTextWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(CLOSE_TEXT)
GuiRenderUtils.drawString(CLOSE_TEXT, midX + notification.width / 2 - 3 - closeTextWidth, topY + 4)
if (notification.length.isFinite()) {
val remainingTime = "§8" + notification.endTime.timeUntil().format()
GuiRenderUtils.drawString(remainingTime, midX - notification.width / 2 + 4, topY + 4)
}
notification.message.forEachIndexed { index, line ->
GuiRenderUtils.drawStringCentered("§7$line", midX, topY + 19 + index * 10)
}
}
private fun getCurrentNotification(): SkyHanniNotification? {
currentNotification?.let {
if (it.endTime.isInPast()) currentNotification = null
}
if (currentNotification == null) {
currentNotification = notificationQueue.removeFirstOrNull()
currentNotification?.setEndTime()
}
return currentNotification
}
fun queueNotification(notification: SkyHanniNotification) {
notificationQueue.add(notification)
}
@HandleEvent
fun onCommandRegistration(event: CommandRegistrationEvent) {
event.register("shtestnotification") {
description = "Shows a test notification"
category = CommandCategory.DEVELOPER_TEST
callback {
val testingText = it.joinToString(" ").replace("\\n", "\n")
queueNotification(SkyHanniNotification(testingText, Duration.INFINITE))
}
}
}
}
data class SkyHanniNotification(
val message: List<String>,
val length: Duration,
val showOverInventory: Boolean = false,
) {
constructor(message: String, length: Duration, showOverInventory: Boolean = false) : this(
message.lines(),
length,
showOverInventory,
)
var endTime = SimpleTimeMark.farFuture()
val width by lazy { (message.maxOfOrNull { Minecraft.getMinecraft().fontRendererObj.getStringWidth(it) } ?: 0) + 8 }
val height by lazy { message.size * 10 + 18 }
fun setEndTime() {
if (length.isInfinite()) return
endTime = SimpleTimeMark.now() + length
}
}
|