diff options
Diffstat (limited to 'src/main/kotlin')
28 files changed, 1111 insertions, 26 deletions
diff --git a/src/main/kotlin/AllModules.kt b/src/main/kotlin/AllModules.kt new file mode 100644 index 0000000..01cfb36 --- /dev/null +++ b/src/main/kotlin/AllModules.kt @@ -0,0 +1,17 @@ +package moe.nea.ultranotifier + +import moe.nea.ultranotifier.commands.Commands +import moe.nea.ultranotifier.datamodel.ChatCategoryArbiter +import moe.nea.ultranotifier.event.SubscriptionTarget +import moe.nea.ultranotifier.event.TickEvent +import moe.nea.ultranotifier.gui.ScreenUtil + +object AllModules { + val allModules: List<SubscriptionTarget> = listOf( + ChatStore, + Commands, + ScreenUtil, + TickEvent, + ChatCategoryArbiter, + ) +} diff --git a/src/main/kotlin/ChatStore.kt b/src/main/kotlin/ChatStore.kt new file mode 100644 index 0000000..4cc6ee1 --- /dev/null +++ b/src/main/kotlin/ChatStore.kt @@ -0,0 +1,53 @@ +package moe.nea.ultranotifier + +import com.mojang.brigadier.builder.LiteralArgumentBuilder +import moe.nea.ultranotifier.commands.UltraCommandSource +import moe.nea.ultranotifier.commands.literalText +import moe.nea.ultranotifier.event.ChatGuiLineEvent +import moe.nea.ultranotifier.event.CommandRegistrationEvent +import moe.nea.ultranotifier.event.PacketChatLineEvent +import moe.nea.ultranotifier.event.SubscriptionTarget +import moe.nea.ultranotifier.event.UltraSubscribe +import moe.nea.ultranotifier.gui.MessageUi +import moe.nea.ultranotifier.gui.ScreenUtil +import moe.nea.ultranotifier.util.IdentityCharacteristics +import net.minecraft.text.Text + +object ChatStore : SubscriptionTarget { + + data class ChatLine( + val text: Text, + var fromPacket: Boolean = false, + var isDisplayed: Boolean = false, + ) + + val allLines = object : LinkedHashMap<IdentityCharacteristics<Text>, ChatLine>() { + override fun removeEldestEntry(eldest: MutableMap.MutableEntry<IdentityCharacteristics<Text>, ChatLine>?): Boolean { + return size > 500 // TODO: config + } + } + + fun insertChatLine(text: Text): ChatLine { + return allLines.getOrPut(IdentityCharacteristics(text)) { ChatLine(text) } + } + + @UltraSubscribe + fun onMessageDisplayed(event: ChatGuiLineEvent) { + insertChatLine(event.component).isDisplayed = true + } + + @UltraSubscribe + fun registerCommands(event: CommandRegistrationEvent) { + event.dispatcher.register(LiteralArgumentBuilder.literal<UltraCommandSource?>("ultranotifier") + .executes { + it.source.sendFeedback(literalText("Opening screen")) + ScreenUtil.openScreen = (MessageUi()) + 0 + }) + } + + @UltraSubscribe + fun onMessageReceived(event: PacketChatLineEvent) { + insertChatLine(event.component).fromPacket = true + } +} diff --git a/src/main/kotlin/Constants.kt b/src/main/kotlin/Constants.kt index a1903ce..46d4236 100644 --- a/src/main/kotlin/Constants.kt +++ b/src/main/kotlin/Constants.kt @@ -1,6 +1,6 @@ package moe.nea.ultranotifier - +// TODO: blossom this shit object Constants { const val MOD_ID = "ultranotifier" const val VERSION = "1.0.0" @@ -23,5 +23,15 @@ object Constants { "1.20.6" //#elseif MC == 11404 //$$ "1.14.4" +//#elseif MC == 11202 +//$$ "1.12.2" +//#elseif MC == 11605 +//$$ "1.16.5" +//#elseif MC == 11602 +//$$ "1.16.2" +//#elseif MC == 12100 +//$$ "1.21" +//#elseif MC == 12101 +//$$ "1.21.1" //#endif } diff --git a/src/main/kotlin/UltraNotifier.kt b/src/main/kotlin/UltraNotifier.kt index dce1fda..ddf8e87 100644 --- a/src/main/kotlin/UltraNotifier.kt +++ b/src/main/kotlin/UltraNotifier.kt @@ -1,12 +1,14 @@ package moe.nea.ultranotifier -import moe.nea.ultranotifier.commands.Commands +import moe.nea.ultranotifier.event.RegistrationFinishedEvent +import moe.nea.ultranotifier.event.UltraEvent +import moe.nea.ultranotifier.event.UltraNotifierEvents import moe.nea.ultranotifier.init.NeaMixinConfig import java.io.File object UltraNotifier { val logger = -//#if MC <= 11404 +//#if MC <= 1.17 //$$ org.apache.logging.log4j.LogManager.getLogger("UltraNotifier")!! //#else org.slf4j.LoggerFactory.getLogger("UltraNotifier")!! @@ -17,7 +19,15 @@ object UltraNotifier { for (mixinPlugin in NeaMixinConfig.getMixinPlugins()) { logger.info("Loaded ${mixinPlugin.mixins.size} mixins for ${mixinPlugin.mixinPackage}.") } - Commands.init() + logger.info("All modules: ${AllModules.allModules}") + AllModules.allModules.forEach { + logger.info("Registering $it") + UltraNotifierEvents.register(it) + it.init() + } + + RegistrationFinishedEvent().post() + } val configFolder = File("config/ultra-notifier").also { diff --git a/src/main/kotlin/UltraNotifierEntryPoint.kt b/src/main/kotlin/UltraNotifierEntryPoint.kt index 42ae064..aa84dc5 100644 --- a/src/main/kotlin/UltraNotifierEntryPoint.kt +++ b/src/main/kotlin/UltraNotifierEntryPoint.kt @@ -3,14 +3,14 @@ package moe.nea.ultranotifier //#if FORGE //$$import net.minecraftforge.fml.common.Mod //$$ -//#if MC == 10809 +//#if MC < 1.13 //$$import net.minecraftforge.fml.common.event.FMLInitializationEvent //$$@Mod(modid = Constants.MOD_ID, version = Constants.VERSION, useMetadata = true) //#else //$$@Mod(Constants.MOD_ID) //#endif //$$class UltraNotifierEntryPoint { -//#if MC == 10809 +//#if MC < 1.13 //$$ @Mod.EventHandler //$$ fun onInit(@Suppress("UNUSED_PARAMETER") event: FMLInitializationEvent) { //#else diff --git a/src/main/kotlin/commands/BrigadierPatchbay.kt b/src/main/kotlin/commands/BrigadierPatchbay.kt new file mode 100644 index 0000000..b88d0e7 --- /dev/null +++ b/src/main/kotlin/commands/BrigadierPatchbay.kt @@ -0,0 +1,119 @@ +package moe.nea.ultranotifier.commands + +//#if MC < 1.16 +//$$import com.mojang.brigadier.CommandDispatcher +//$$import com.mojang.brigadier.builder.LiteralArgumentBuilder +//$$import com.mojang.brigadier.tree.CommandNode +//$$import moe.nea.ultranotifier.event.CommandRegistrationEvent +//$$import moe.nea.ultranotifier.event.RegistrationFinishedEvent +//$$import moe.nea.ultranotifier.event.UltraNotifierEvents +//$$import moe.nea.ultranotifier.event.UltraSubscribe +//$$import moe.nea.ultranotifier.event.SubscriptionTarget +//$$import moe.nea.ultranotifier.mixin.AccessorCommandHandler +//$$import net.minecraft.command.CommandBase +//$$import net.minecraft.command.CommandHandler +//$$import net.minecraft.command.ICommandSender +//$$import net.minecraft.server.MinecraftServer +//$$import net.minecraft.util.text.ITextComponent +//$$import net.minecraftforge.client.ClientCommandHandler +//$$ +//$$fun CommandHandler.getCommandSet() = (this as AccessorCommandHandler).commandSet_ultraNotifier +//$$ +//$$class BridgedCommandSource( +//$$ val sender: ICommandSender +//$$) : UltraCommandSource { +//$$ override fun sendFeedback(text: ITextComponent) { +//$$ sender.sendMessage(text) +//$$ } +//$$} +//$$ +//$$class BrigadierCommand( +//$$ val dispatcher: CommandDispatcher<UltraCommandSource>, +//$$ val node: CommandNode<UltraCommandSource> +//$$) : CommandBase() { +//#if MC >= 1.12 +//$$ override fun checkPermission(server: MinecraftServer, sender: ICommandSender): Boolean { +//$$ return true +//$$ } +//#else +//$$ override fun canCommandSenderUseCommand(sender: ICommandSender): Boolean { +//$$ return true +//$$ } +//#endif +//$$ +//$$ override fun getName(): String { +//$$ return node.name +//$$ } +//$$ +//$$ override fun getUsage(sender: ICommandSender): String { +//$$ return "" +//$$ } +//$$ +//$$ private fun getCommandLineText(args: Array<out String>) = "${node.name} ${args.joinToString(" ")}".trim() +//$$ +//$$ +//#if MC < 1.12 +//$$ override fun processCommand(sender: ICommandSender, args: Array<out String>) { +//#else +//$$ override fun execute(server: MinecraftServer, sender: ICommandSender, args: Array<out String>) { +//#endif +//$$ val source = BridgedCommandSource(sender) +//$$ val results = dispatcher.parse(getCommandLineText(args), source) +//$$ kotlin.runCatching { +//$$ dispatcher.execute(results) +//$$ Unit +//$$ }.recoverCatching { +//$$ source.sendFeedback(literalText("Could not execute ultra command: ${it.message}")) +//$$ } +//$$ } +//$$} +//$$ +//$$object BrigadierPatchbay : SubscriptionTarget { +//$$ +//$$ @UltraSubscribe +//$$ fun onAfterRegistration(event: RegistrationFinishedEvent) { +//$$ fullReload() +//$$ } +//$$ +//$$ @UltraSubscribe +//$$ fun onCommands(event: CommandRegistrationEvent) { +//$$ event.dispatcher +//$$ .register(LiteralArgumentBuilder.literal<UltraCommandSource>("reloadcommands") +//$$ .executes { +//$$ it.source.sendFeedback(literalText("Reloading commands")) +//$$ fullReload() +//$$ it.source.sendFeedback(literalText("Reload completed")) +//$$ 0 +//$$ }) +//$$ } +//$$ +//$$ fun fullReload() { +//$$ val handler = ClientCommandHandler.instance +//$$ unpatch(handler) +//$$ val dispatcher = createDispatcher() +//$$ UltraNotifierEvents.post(CommandRegistrationEvent(dispatcher)) +//$$ patch(handler, dispatcher) +//$$ } +//$$ +//$$ fun createDispatcher() = CommandDispatcher<UltraCommandSource>() +//$$ +//$$ fun unpatch(handler: CommandHandler) { +//$$ handler.getCommandSet() +//$$ .removeIf { +//$$ it is BrigadierCommand +//$$ } +//$$ handler.commands.entries +//$$ .removeIf { +//$$ it.value is BrigadierCommand +//$$ } +//$$ } +//$$ +//$$ fun patch(handler: CommandHandler, dispatcher: CommandDispatcher<UltraCommandSource>) { +//$$ dispatcher.root.children +//$$ .map { BrigadierCommand(dispatcher, it) } +//$$ .forEach(handler::registerCommand) +//$$ } +//$$} +//#endif + + diff --git a/src/main/kotlin/commands/Commands.kt b/src/main/kotlin/commands/Commands.kt index 75047cd..5975bb2 100644 --- a/src/main/kotlin/commands/Commands.kt +++ b/src/main/kotlin/commands/Commands.kt @@ -1,9 +1,11 @@ package moe.nea.ultranotifier.commands -import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.builder.LiteralArgumentBuilder import moe.nea.ultranotifier.UltraNotifier +import moe.nea.ultranotifier.event.CommandRegistrationEvent +import moe.nea.ultranotifier.event.SubscriptionTarget import moe.nea.ultranotifier.event.UltraNotifierEvents +import moe.nea.ultranotifier.event.UltraSubscribe import net.minecraft.text.Text interface CustomSource { @@ -14,35 +16,50 @@ interface CustomSource { typealias UltraCommandSource = //#if FORGE //$$ CustomSource -//#else +//#elseif MC > 1.18 net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource - +//#else +//$$ net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource //#endif +fun translatableText(key: String, vararg args: String) = +//#if MC > 1.17 + Text.translatable(key, *args) +//#else +//$$ net.minecraft.text.TranslatableText(key, *args) +//#endif + fun literalText(string: String): Text = -//#if MC >= 11400 +//#if MC > 1.17 Text.literal(string) //#else -//$$ net.minecraft.util.ChatComponentText(string) +//$$ net.minecraft.text.LiteralText(string) //#endif -object Commands { - fun registerAll(dispatcher: CommandDispatcher<UltraCommandSource>) { - dispatcher.register(LiteralArgumentBuilder.literal<UltraCommandSource>("hello") - .executes { - it.source.sendFeedback(literalText("Hello World")) - 0 - }) +object Commands : SubscriptionTarget { + @UltraSubscribe + fun registerTestCommand(event: CommandRegistrationEvent) { + event.dispatcher.register(LiteralArgumentBuilder.literal<UltraCommandSource>("hello") + .executes { + it.source.sendFeedback(literalText("Hello World")) + 0 + }) } - fun init() { - UltraNotifierEvents.register(this) +//#if MC <= 1.18 && FABRIC +//$$ @UltraSubscribe +//$$ fun registerEverythingOnce(event: moe.nea.ultranotifier.event.RegistrationFinishedEvent) { +//$$ CommandRegistrationEvent(net.fabricmc.fabric.api.client.command.v1.ClientCommandManager.DISPATCHER).post() +//$$ } +//#endif + + override fun init() { //#if FORGE -//$$ -//#else +//$$ UltraNotifierEvents.register(BrigadierPatchbay) +//#elseif MC > 1.18 net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback.EVENT.register { dispatcher, registryAccess -> - registerAll(dispatcher) + UltraNotifierEvents.post(CommandRegistrationEvent(dispatcher)) } //#endif UltraNotifier.logger.info("Initialized command subsystem") diff --git a/src/main/kotlin/datamodel/ChatType.kt b/src/main/kotlin/datamodel/ChatType.kt new file mode 100644 index 0000000..47abe2a --- /dev/null +++ b/src/main/kotlin/datamodel/ChatType.kt @@ -0,0 +1,175 @@ +package moe.nea.ultranotifier.datamodel + +import moe.nea.ultranotifier.UltraNotifier +import moe.nea.ultranotifier.event.SubscriptionTarget +import moe.nea.ultranotifier.event.TickEvent +import moe.nea.ultranotifier.event.UltraSubscribe +import moe.nea.ultranotifier.event.VisibleChatMessageAddedEvent +import moe.nea.ultranotifier.util.GsonUtil +import moe.nea.ultranotifier.util.duplicatesBy +import moe.nea.ultranotifier.util.minecrat.MC +import moe.nea.ultranotifier.util.minecrat.category +import moe.nea.ultranotifier.util.minecrat.getFormattedTextCompat +import moe.nea.ultranotifier.util.minecrat.removeFormattingCodes +import net.minecraft.text.Text +import util.KSerializable +import java.util.function.Predicate +import java.util.regex.Pattern + +data class ChatTypeId( + val id: String +) + +@KSerializable +data class ChatType( + val name: String, + val patterns: List<ChatPattern>, +) + +data class ChatPattern( + val text: String +) { + val pattern = Pattern.compile(text) + val predicate: Predicate<String> = +//#if JAVA > 11 + pattern.asMatchPredicate() +//#else +//$$ Predicate { it: String -> pattern.matcher(it).matches() } +//#endif +} + +data class CategoryId(val id: String) + +@KSerializable +data class ChatCategory( + val id: CategoryId, + val label: String, + val chatTypes: Set<ChatTypeId>, +) + +data class ChatUniverse( + val name: String, + val types: Map<ChatTypeId, ChatType>, + val categories: List<ChatCategory>, +) { + fun categorize( + text: String + ): CategorizedChatLine { + val types = this.types + .asSequence() + .filter { + it.value.patterns.any { + it.predicate.test(text) + } + } + .map { + it.key + } + .toSet() + return CategorizedChatLine( + text, types + ) + } +} + +data class CategorizedChatLine( + val text: String, + val types: Set<ChatTypeId>, +// val categories: Set<ChatCategory>, +) + +@KSerializable +data class UniverseMeta( + // TODO: implement the ip filter + val ipFilter: List<ChatPattern> = listOf(), + val name: String, +) + +interface HasCategorizedChatLine { + val categorizedChatLine_ultraNotifier: CategorizedChatLine +} + +data class UniverseId( + val id: String +) + +private fun loadAllUniverses(): Map<UniverseId, ChatUniverse> = buildMap { + for (file in UltraNotifier.configFolder + .resolve("universes/") + .listFiles() ?: emptyArray()) { + runCatching { + val meta = GsonUtil.read<UniverseMeta>(file.resolve("meta.json")) + val types = GsonUtil.read<Map<ChatTypeId, ChatType>>(file.resolve("chattypes.json")) + val categories = GsonUtil.read<List<ChatCategory>>(file.resolve("categories.json")) + // Validate categories linking properly + for (category in categories) { + for (chatType in category.chatTypes) { + if (chatType in types.keys) { + UltraNotifier.logger.warn("Missing definition for $chatType required by ${category.id} in $file") + } + } + } + for (category in categories.asSequence().duplicatesBy { it.id }) { + UltraNotifier.logger.warn("Found duplicate category ${category.id} in $file") + } + + put( + UniverseId(file.name), + ChatUniverse( + meta.name, + types, + categories, + )) + }.getOrElse { + UltraNotifier.logger.warn("Could not load universe at $file", it) + } + } +} + +object ChatCategoryArbiter : SubscriptionTarget { + val specialAll = CategoryId("special-all") + + var allUniverses = loadAllUniverses() + + var activeUniverse: ChatUniverse? = allUniverses.values.single() + private val allCategoryList = listOf( + ChatCategory(specialAll, "All", setOf()) + ) + + val categories // TODO: memoize + get() = (activeUniverse?.categories ?: listOf()) + allCategoryList + + var selectedCategoryId = specialAll + set(value) { + field = value + selectedCategory = findCategory(value) + } + private var lastSelectedId = selectedCategoryId + var selectedCategory: ChatCategory = findCategory(selectedCategoryId) + private set + + @UltraSubscribe + fun onTick(event: TickEvent) { + if (lastSelectedId != selectedCategoryId) { + MC.chatHud.reset() + lastSelectedId = selectedCategoryId + } + } + + @UltraSubscribe + fun onVisibleChatMessage(event: VisibleChatMessageAddedEvent) { + val cl = event.chatLine.category + if (selectedCategory.id == specialAll) + return + if (cl.types.none { it in selectedCategory.chatTypes }) + event.cancel() + } + + fun findCategory(id: CategoryId) = categories.find { it.id == id }!! + + fun categorize(content: Text): CategorizedChatLine { + val stringContent = content.getFormattedTextCompat().removeFormattingCodes() + return activeUniverse?.categorize(stringContent) ?: CategorizedChatLine(stringContent, setOf()) + } +} + diff --git a/src/main/kotlin/event/ChatGuiLineEvent.kt b/src/main/kotlin/event/ChatGuiLineEvent.kt index e37d31f..eb585dd 100644 --- a/src/main/kotlin/event/ChatGuiLineEvent.kt +++ b/src/main/kotlin/event/ChatGuiLineEvent.kt @@ -3,7 +3,13 @@ package moe.nea.ultranotifier.event import net.minecraft.text.Text class ChatGuiLineEvent(val component: Text) : UltraEvent() { - val string = component.string + val string = +//#if MC < 1.16 +//$$ component.unformattedText // Why does remap not do this automatically? hello? +//#else + component.string +//#endif + override fun toString(): String { return "ChatLineAddedEvent($string)" } diff --git a/src/main/kotlin/event/CommandRegistrationEvent.kt b/src/main/kotlin/event/CommandRegistrationEvent.kt new file mode 100644 index 0000000..49bc637 --- /dev/null +++ b/src/main/kotlin/event/CommandRegistrationEvent.kt @@ -0,0 +1,10 @@ +package moe.nea.ultranotifier.event + +import com.mojang.brigadier.CommandDispatcher +import moe.nea.ultranotifier.commands.UltraCommandSource + +/** + * Fired whenever commands need to be registered. This may be multiple times during each launch. Old commands will be + * automatically unregistered first. + */ +class CommandRegistrationEvent(val dispatcher: CommandDispatcher<UltraCommandSource>) : UltraEvent() diff --git a/src/main/kotlin/event/RegistrationFinishedEvent.kt b/src/main/kotlin/event/RegistrationFinishedEvent.kt new file mode 100644 index 0000000..325e1d8 --- /dev/null +++ b/src/main/kotlin/event/RegistrationFinishedEvent.kt @@ -0,0 +1,6 @@ +package moe.nea.ultranotifier.event + +/** + * Indicates that the registration of all ultra event handlers is done + */ +class RegistrationFinishedEvent : UltraEvent() diff --git a/src/main/kotlin/event/SubscriptionTarget.kt b/src/main/kotlin/event/SubscriptionTarget.kt new file mode 100644 index 0000000..e66eb94 --- /dev/null +++ b/src/main/kotlin/event/SubscriptionTarget.kt @@ -0,0 +1,5 @@ +package moe.nea.ultranotifier.event + +interface SubscriptionTarget { + fun init() = Unit +} diff --git a/src/main/kotlin/event/TickEvent.kt b/src/main/kotlin/event/TickEvent.kt new file mode 100644 index 0000000..4bd2c6c --- /dev/null +++ b/src/main/kotlin/event/TickEvent.kt @@ -0,0 +1,26 @@ +package moe.nea.ultranotifier.event + +//#if FABRIC +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents +//#endif + +class TickEvent : UltraEvent(), UltraEvent.Silent<TickEvent> { + + companion object : SubscriptionTarget { + override fun init() { +//#if FABRIC + ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { + TickEvent().post() + }) +//#else +//$$ net.minecraftforge.common.MinecraftForge.EVENT_BUS.register(object { +//$$ @UltraSubscribe +//$$ fun onForgeEvent(event: net.minecraftforge.event.TickEvent.ClientTickEvent) { +//$$ if (event.phase == net.minecraftforge.event.TickEvent.Phase.END) +//$$ TickEvent().post() +//$$ } +//$$ }) +//#endif + } + } +} diff --git a/src/main/kotlin/event/UltraEvent.kt b/src/main/kotlin/event/UltraEvent.kt index 42fa4f2..80f63fc 100644 --- a/src/main/kotlin/event/UltraEvent.kt +++ b/src/main/kotlin/event/UltraEvent.kt @@ -7,6 +7,8 @@ abstract class UltraEvent : me.bush.eventbus.event.Event() //#endif { + interface Silent<T> where T : Silent<T>, T : UltraEvent + //#if FORGE //$$ override fun isCancelable(): Boolean { //$$ return this.isCancellable() @@ -32,6 +34,10 @@ abstract class UltraEvent : setCancelled(true) } + fun post() { + UltraNotifierEvents.post(this) + } + } diff --git a/src/main/kotlin/event/UltraNotifierEvents.kt b/src/main/kotlin/event/UltraNotifierEvents.kt index 34d1769..9c1e1ee 100644 --- a/src/main/kotlin/event/UltraNotifierEvents.kt +++ b/src/main/kotlin/event/UltraNotifierEvents.kt @@ -9,14 +9,17 @@ object UltraNotifierEvents { //#else me.bush.eventbus.bus.EventBus { UltraNotifier.logger.warn("EventBus: $it") } //#endif + @JvmStatic fun <T : UltraEvent> post(event: T): T { - UltraNotifier.logger.info("Posting $event") + if (event !is UltraEvent.Silent<*>) { + UltraNotifier.logger.info("Posting $event") + } eventBus.post(event) return event } - fun register(obj: Any) { + fun register(obj: SubscriptionTarget) { //#if FORGE //$$ eventBus.register(obj) //#else diff --git a/src/main/kotlin/event/VisibleChatMessageAddedEvent.kt b/src/main/kotlin/event/VisibleChatMessageAddedEvent.kt new file mode 100644 index 0000000..97d919b --- /dev/null +++ b/src/main/kotlin/event/VisibleChatMessageAddedEvent.kt @@ -0,0 +1,17 @@ +package moe.nea.ultranotifier.event + +import net.minecraft.client.gui.hud.ChatHudLine +import net.minecraft.text.Text + +typealias ChattyHudLine = + ChatHudLine +//#if MC < 1.20 +//#if MC > 1.16 +//$$ <Text> +//#endif +//#endif + + +data class VisibleChatMessageAddedEvent( + val chatLine: ChattyHudLine, +) : UltraEvent() diff --git a/src/main/kotlin/gui/ChatUi.kt b/src/main/kotlin/gui/ChatUi.kt new file mode 100644 index 0000000..b812b73 --- /dev/null +++ b/src/main/kotlin/gui/ChatUi.kt @@ -0,0 +1,91 @@ +package moe.nea.ultranotifier.gui + +import gg.essential.universal.UGraphics +import gg.essential.universal.UMatrixStack +import moe.nea.ultranotifier.datamodel.ChatCategory +import moe.nea.ultranotifier.datamodel.ChatCategoryArbiter +import moe.nea.ultranotifier.util.minecrat.MC +import moe.nea.ultranotifier.util.minecrat.accessor +import moe.nea.ultranotifier.util.render.ScreenRenderUtils +import net.minecraft.client.gui.screen.ChatScreen +import java.awt.Color + +class ChatUi(val chatScreen: ChatScreen) { + + val Double.value get() = this + val Float.value get() = this + fun getChatBgOpacity(opacityMultiplier: Double = 1.0): Color { + return Color((MC.instance.options.textBackgroundOpacity.value * opacityMultiplier * 255).toInt() shl 24, true) + } + + fun calculateChatTop(): Double { + val ch = MC.chatHud + ch.accessor() + val chatOffset = + 40 + val chatTop = + (chatScreen.height - chatOffset) / ch.chatScale - ch.visibleLineCount * ch.lineHeight_ultranotifier + return chatTop.toDouble() + } + + fun iterateButtons( + onEach: ( + label: ChatCategory, + isSelected: Boolean, + pos: Rect, + ) -> Unit + ) { + val chatTop = calculateChatTop() + var xOffset = 5 + val top = chatTop - 16.0 + for (button in ChatCategoryArbiter.categories) { + val w = ScreenRenderUtils.getTextWidth(button.label) + 3 + val isSelected = button == ChatCategoryArbiter.selectedCategory + onEach(button, isSelected, Rect(xOffset.toDouble(), top, w.toDouble(), 16.0)) + xOffset += w + 5 + } + } + + data class Rect( + val x: Double, val y: Double, + val w: Double, val h: Double, + ) { + fun contains(mouseX: Double, mouseY: Double): Boolean { + return mouseX in (l..<r) && mouseY in (t..<b) + } + + val l get() = x + val t get() = y + val r get() = x + w + val b get() = y + h + val cy get() = y + h / 2 + val cx get() = x + w / 2 + } + + fun renderButtons( + matrixStack: UMatrixStack, + mouseX: Double, mouseY: Double, + ) { + iterateButtons { button, isSelected, pos -> + UGraphics.enableBlend() + ScreenRenderUtils.fillRect(matrixStack, + pos.l, pos.t, pos.r, pos.b, + if (isSelected) getChatBgOpacity() else getChatBgOpacity(0.75)) + UGraphics.disableBlend() + ScreenRenderUtils.renderText(matrixStack, + pos.l + 2, pos.cy - 9 / 2, + if (isSelected) "§a${button.label}" else "§f${button.label}") + } + } + + fun clickMouse(mouseX: Double, mouseY: Double, button: Int) { + iterateButtons { label, isSelected, pos -> + if (pos.contains(mouseX, mouseY)) { + if (button == 0) { + ChatCategoryArbiter.selectedCategoryId = label.id + } + // TODO: right click options or something + } + } + } +} diff --git a/src/main/kotlin/gui/MessageUi.kt b/src/main/kotlin/gui/MessageUi.kt new file mode 100644 index 0000000..5f337f3 --- /dev/null +++ b/src/main/kotlin/gui/MessageUi.kt @@ -0,0 +1,28 @@ +package moe.nea.ultranotifier.gui + +import gg.essential.universal.UMatrixStack +import gg.essential.universal.UScreen +import juuxel.libninepatch.NinePatch +import moe.nea.ultranotifier.util.render.ScreenRenderUtils +import moe.nea.ultranotifier.util.ultraIdentifier +import java.awt.Color + +class MessageUi : UScreen() { + override fun onDrawScreen(matrixStack: UMatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float) { + super.onDrawScreen(matrixStack, mouseX, mouseY, partialTicks) + ScreenRenderUtils.fillRect(matrixStack, 0.0, 0.0, width.toDouble(), height.toDouble(), Color.RED) + ScreenRenderUtils.renderTexture( + ultraIdentifier("textures/gui/square_panel.png"), + matrixStack, + 200.0, 0.0, 300.0, 100.0 + ) + ScreenRenderUtils.renderNineSlice( + NinePatch.builder(ultraIdentifier("textures/gui/square_panel.png")) + .cornerSize(10) + .mode(NinePatch.Mode.STRETCHING) + .cornerUv(0.1F, 0.1F).build(), + matrixStack, + 225.0, 25.0, 275.0, 75.0 + ) + } +} diff --git a/src/main/kotlin/gui/ScreenUtil.kt b/src/main/kotlin/gui/ScreenUtil.kt new file mode 100644 index 0000000..bb3dfc3 --- /dev/null +++ b/src/main/kotlin/gui/ScreenUtil.kt @@ -0,0 +1,19 @@ +package moe.nea.ultranotifier.gui + +import gg.essential.universal.UScreen +import moe.nea.ultra |
