From 8e386bcf8d10784fc7784333be9e4470598c71d4 Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Thu, 30 Jan 2025 20:11:37 +0100 Subject: feat: Add ledger event as a baseclass for events with error reporting --- .../ledger/mixin/AccessorContainerDispenser.java | 12 ++++ .../nea/ledger/mixin/AccessorContainerHopper.java | 13 +++++ .../main/kotlin/moe/nea/ledger/ItemIdProvider.kt | 4 +- mod/src/main/kotlin/moe/nea/ledger/Ledger.kt | 5 +- mod/src/main/kotlin/moe/nea/ledger/QueryCommand.kt | 2 +- .../kotlin/moe/nea/ledger/TelemetryProvider.kt | 66 --------------------- .../moe/nea/ledger/events/BeforeGuiAction.kt | 12 +++- .../kotlin/moe/nea/ledger/events/LedgerEvent.kt | 22 +++++++ .../moe/nea/ledger/telemetry/GuiContextValue.kt | 16 +++++ .../moe/nea/ledger/telemetry/TelemetryProvider.kt | 68 ++++++++++++++++++++++ .../main/kotlin/moe/nea/ledger/utils/ScreenUtil.kt | 29 +++++++++ .../kotlin/moe/nea/ledger/utils/telemetry/Span.kt | 3 +- 12 files changed, 180 insertions(+), 72 deletions(-) create mode 100644 mod/src/main/java/moe/nea/ledger/mixin/AccessorContainerDispenser.java create mode 100644 mod/src/main/java/moe/nea/ledger/mixin/AccessorContainerHopper.java delete mode 100644 mod/src/main/kotlin/moe/nea/ledger/TelemetryProvider.kt create mode 100644 mod/src/main/kotlin/moe/nea/ledger/events/LedgerEvent.kt create mode 100644 mod/src/main/kotlin/moe/nea/ledger/telemetry/GuiContextValue.kt create mode 100644 mod/src/main/kotlin/moe/nea/ledger/telemetry/TelemetryProvider.kt create mode 100644 mod/src/main/kotlin/moe/nea/ledger/utils/ScreenUtil.kt (limited to 'mod/src/main') diff --git a/mod/src/main/java/moe/nea/ledger/mixin/AccessorContainerDispenser.java b/mod/src/main/java/moe/nea/ledger/mixin/AccessorContainerDispenser.java new file mode 100644 index 0000000..a3d32c4 --- /dev/null +++ b/mod/src/main/java/moe/nea/ledger/mixin/AccessorContainerDispenser.java @@ -0,0 +1,12 @@ +package moe.nea.ledger.mixin; + +import net.minecraft.inventory.ContainerDispenser; +import net.minecraft.inventory.IInventory; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ContainerDispenser.class) +public interface AccessorContainerDispenser { + @Accessor("dispenserInventory") + IInventory getDispenserInventory_ledger(); +} diff --git a/mod/src/main/java/moe/nea/ledger/mixin/AccessorContainerHopper.java b/mod/src/main/java/moe/nea/ledger/mixin/AccessorContainerHopper.java new file mode 100644 index 0000000..ee29d4f --- /dev/null +++ b/mod/src/main/java/moe/nea/ledger/mixin/AccessorContainerHopper.java @@ -0,0 +1,13 @@ +package moe.nea.ledger.mixin; + +import net.minecraft.inventory.ContainerDispenser; +import net.minecraft.inventory.ContainerHopper; +import net.minecraft.inventory.IInventory; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ContainerHopper.class) +public interface AccessorContainerHopper { + @Accessor("hopperInventory") + IInventory getHopperInventory_ledger(); +} diff --git a/mod/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt b/mod/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt index 0bacf32..ff2c691 100644 --- a/mod/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt +++ b/mod/src/main/kotlin/moe/nea/ledger/ItemIdProvider.kt @@ -20,12 +20,12 @@ class ItemIdProvider { @SubscribeEvent fun onMouseInput(event: GuiScreenEvent.MouseInputEvent.Pre) { if (Mouse.getEventButton() == -1) return - MinecraftForge.EVENT_BUS.post(BeforeGuiAction(event.gui)) + BeforeGuiAction(event.gui).post() } @SubscribeEvent fun onKeyInput(event: GuiScreenEvent.KeyboardInputEvent.Pre) { - MinecraftForge.EVENT_BUS.post(BeforeGuiAction(event.gui)) + BeforeGuiAction(event.gui).post() } private val knownNames = mutableMapOf() diff --git a/mod/src/main/kotlin/moe/nea/ledger/Ledger.kt b/mod/src/main/kotlin/moe/nea/ledger/Ledger.kt index 9bbc8e1..6d3c592 100644 --- a/mod/src/main/kotlin/moe/nea/ledger/Ledger.kt +++ b/mod/src/main/kotlin/moe/nea/ledger/Ledger.kt @@ -42,6 +42,7 @@ import moe.nea.ledger.modules.NpcDetection import moe.nea.ledger.modules.PestRepellentDetection import moe.nea.ledger.modules.UpdateChecker import moe.nea.ledger.modules.VisitorDetection +import moe.nea.ledger.telemetry.TelemetryProvider import moe.nea.ledger.utils.ErrorUtil import moe.nea.ledger.utils.MinecraftExecutor import moe.nea.ledger.utils.di.DI @@ -112,7 +113,9 @@ class Ledger { tickQueue.add(runnable) } - val di = DI() + private val di = DI() + + fun leakDI() = di } @Mod.EventHandler diff --git a/mod/src/main/kotlin/moe/nea/ledger/QueryCommand.kt b/mod/src/main/kotlin/moe/nea/ledger/QueryCommand.kt index abdc13a..80dd54c 100644 --- a/mod/src/main/kotlin/moe/nea/ledger/QueryCommand.kt +++ b/mod/src/main/kotlin/moe/nea/ledger/QueryCommand.kt @@ -172,7 +172,7 @@ class QueryCommand : CommandBase() { override val name: String get() = "withitem" - private val itemIdProvider = Ledger.di.provide() // TODO: close this escape hatch + private val itemIdProvider = Ledger.leakDI().provide() // TODO: close this escape hatch override fun getFilter(text: String): BooleanExpression { return Clause { column(DBItemEntry.itemId) like text } } diff --git a/mod/src/main/kotlin/moe/nea/ledger/TelemetryProvider.kt b/mod/src/main/kotlin/moe/nea/ledger/TelemetryProvider.kt deleted file mode 100644 index d9c7108..0000000 --- a/mod/src/main/kotlin/moe/nea/ledger/TelemetryProvider.kt +++ /dev/null @@ -1,66 +0,0 @@ -package moe.nea.ledger - -import com.google.gson.JsonArray -import com.google.gson.JsonElement -import com.google.gson.JsonObject -import moe.nea.ledger.gen.BuildConfig -import moe.nea.ledger.utils.di.DI -import moe.nea.ledger.utils.di.DIProvider -import moe.nea.ledger.utils.telemetry.CommonKeys -import moe.nea.ledger.utils.telemetry.ContextValue -import moe.nea.ledger.utils.telemetry.EventRecorder -import moe.nea.ledger.utils.telemetry.JsonElementContext -import moe.nea.ledger.utils.telemetry.LoggingEventRecorder -import moe.nea.ledger.utils.telemetry.Span -import net.minecraft.client.Minecraft -import net.minecraft.util.Session -import net.minecraftforge.fml.common.Loader - -object TelemetryProvider { - fun injectTo(di: DI) { - di.register( - EventRecorder::class.java, - if (DevUtil.isDevEnv) DIProvider.singeleton(LoggingEventRecorder(Ledger.logger, true)) - else DIProvider.singeleton( - LoggingEventRecorder(Ledger.logger, false)) // TODO: replace with upload to server - ) - } - - val USER = "minecraft_user" - val MINECRAFT_VERSION = "minecraft_version" - val MODS = "mods" - - class MinecraftUser(val session: Session) : ContextValue { - override fun serialize(): JsonElement { - val obj = JsonObject() - obj.addProperty("uuid", session.playerID) - obj.addProperty("name", session.username) - return obj - } - } - - fun setupDefaultSpan() { - val sp = Span.current() - sp.add(USER, MinecraftUser(Minecraft.getMinecraft().session)) - sp.add(MINECRAFT_VERSION, ContextValue.compound( - "static" to "1.8.9", - "rt" to Minecraft.getMinecraft().version, - )) - val mods = JsonArray() - Loader.instance().activeModList.map { - val obj = JsonObject() - obj.addProperty("id", it.modId) - obj.addProperty("version", it.version) - obj.addProperty("displayVersion", it.displayVersion) - obj - }.forEach(mods::add) - sp.add(MODS, JsonElementContext(mods)) - sp.add(CommonKeys.VERSION, ContextValue.string(BuildConfig.FULL_VERSION)) - sp.add(CommonKeys.COMMIT_VERSION, ContextValue.string(BuildConfig.GIT_COMMIT)) - } - - fun setupFor(di: DI) { - injectTo(di) - setupDefaultSpan() - } -} \ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt b/mod/src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt index 098912a..7f6eae9 100644 --- a/mod/src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt +++ b/mod/src/main/kotlin/moe/nea/ledger/events/BeforeGuiAction.kt @@ -1,11 +1,21 @@ package moe.nea.ledger.events +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import moe.nea.ledger.telemetry.GuiContextValue +import moe.nea.ledger.utils.telemetry.ContextValue import net.minecraft.client.gui.GuiScreen import net.minecraft.client.gui.inventory.GuiChest +import net.minecraft.client.gui.inventory.GuiContainer import net.minecraft.inventory.ContainerChest import net.minecraftforge.fml.common.eventhandler.Event -data class BeforeGuiAction(val gui: GuiScreen) : Event() { +data class BeforeGuiAction(val gui: GuiScreen) : LedgerEvent() { val chest = gui as? GuiChest val chestSlots = chest?.inventorySlots as ContainerChest? + override fun serialize(): JsonElement { + return JsonObject().apply { + add("gui", GuiContextValue(gui).serialize()) + } + } } diff --git a/mod/src/main/kotlin/moe/nea/ledger/events/LedgerEvent.kt b/mod/src/main/kotlin/moe/nea/ledger/events/LedgerEvent.kt new file mode 100644 index 0000000..cbb3f81 --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/events/LedgerEvent.kt @@ -0,0 +1,22 @@ +package moe.nea.ledger.events + +import moe.nea.ledger.Ledger +import moe.nea.ledger.utils.ErrorUtil +import moe.nea.ledger.utils.telemetry.CommonKeys +import moe.nea.ledger.utils.telemetry.ContextValue +import net.minecraftforge.common.MinecraftForge +import net.minecraftforge.fml.common.eventhandler.Event + +abstract class LedgerEvent : Event(), ContextValue { + fun post() { + Ledger.leakDI() + .provide() + .catch( + CommonKeys.EVENT_MESSAGE to ContextValue.string("Error during event execution"), + "event_instance" to this, + "event_type" to ContextValue.string(javaClass.name) + ) { + MinecraftForge.EVENT_BUS.post(this) + } + } +} \ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/telemetry/GuiContextValue.kt b/mod/src/main/kotlin/moe/nea/ledger/telemetry/GuiContextValue.kt new file mode 100644 index 0000000..2d7db39 --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/telemetry/GuiContextValue.kt @@ -0,0 +1,16 @@ +package moe.nea.ledger.telemetry + +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import moe.nea.ledger.utils.ScreenUtil +import moe.nea.ledger.utils.telemetry.ContextValue +import net.minecraft.client.gui.GuiScreen + +class GuiContextValue(val gui: GuiScreen) : ContextValue { + override fun serialize(): JsonElement { + return JsonObject().apply { + addProperty("class", gui.javaClass.name) + addProperty("name", ScreenUtil.estimateName(gui)) + } + } +} diff --git a/mod/src/main/kotlin/moe/nea/ledger/telemetry/TelemetryProvider.kt b/mod/src/main/kotlin/moe/nea/ledger/telemetry/TelemetryProvider.kt new file mode 100644 index 0000000..c2fff23 --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/telemetry/TelemetryProvider.kt @@ -0,0 +1,68 @@ +package moe.nea.ledger.telemetry + +import com.google.gson.JsonArray +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import moe.nea.ledger.DevUtil +import moe.nea.ledger.Ledger +import moe.nea.ledger.gen.BuildConfig +import moe.nea.ledger.utils.di.DI +import moe.nea.ledger.utils.di.DIProvider +import moe.nea.ledger.utils.telemetry.CommonKeys +import moe.nea.ledger.utils.telemetry.ContextValue +import moe.nea.ledger.utils.telemetry.EventRecorder +import moe.nea.ledger.utils.telemetry.JsonElementContext +import moe.nea.ledger.utils.telemetry.LoggingEventRecorder +import moe.nea.ledger.utils.telemetry.Span +import net.minecraft.client.Minecraft +import net.minecraft.util.Session +import net.minecraftforge.fml.common.Loader + +object TelemetryProvider { + fun injectTo(di: DI) { + di.register( + EventRecorder::class.java, + if (DevUtil.isDevEnv) DIProvider.singeleton(LoggingEventRecorder(Ledger.logger, true)) + else DIProvider.singeleton( + LoggingEventRecorder(Ledger.logger, false)) // TODO: replace with upload to server + ) + } + + val USER = "minecraft_user" + val MINECRAFT_VERSION = "minecraft_version" + val MODS = "mods" + + class MinecraftUser(val session: Session) : ContextValue { + override fun serialize(): JsonElement { + val obj = JsonObject() + obj.addProperty("uuid", session.playerID) + obj.addProperty("name", session.username) + return obj + } + } + + fun setupDefaultSpan() { + val sp = Span.rootSpan + sp.add(USER, MinecraftUser(Minecraft.getMinecraft().session)) + sp.add(MINECRAFT_VERSION, ContextValue.compound( + "static" to "1.8.9", + "rt" to Minecraft.getMinecraft().version, + )) + val mods = JsonArray() + Loader.instance().activeModList.map { + val obj = JsonObject() + obj.addProperty("id", it.modId) + obj.addProperty("version", it.version) + obj.addProperty("displayVersion", it.displayVersion) + obj + }.forEach(mods::add) + sp.add(MODS, JsonElementContext(mods)) + sp.add(CommonKeys.VERSION, ContextValue.string(BuildConfig.FULL_VERSION)) + sp.add(CommonKeys.COMMIT_VERSION, ContextValue.string(BuildConfig.GIT_COMMIT)) + } + + fun setupFor(di: DI) { + injectTo(di) + setupDefaultSpan() + } +} \ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/utils/ScreenUtil.kt b/mod/src/main/kotlin/moe/nea/ledger/utils/ScreenUtil.kt new file mode 100644 index 0000000..0305126 --- /dev/null +++ b/mod/src/main/kotlin/moe/nea/ledger/utils/ScreenUtil.kt @@ -0,0 +1,29 @@ +package moe.nea.ledger.utils + +import moe.nea.ledger.mixin.AccessorContainerDispenser +import moe.nea.ledger.mixin.AccessorContainerHopper +import net.minecraft.client.gui.GuiScreen +import net.minecraft.client.gui.inventory.GuiContainer +import net.minecraft.inventory.ContainerChest +import net.minecraft.inventory.IInventory + +object ScreenUtil { + fun estimateInventory(screen: GuiScreen?): IInventory? { + if (screen !is GuiContainer) { + return null + } + val container = screen.inventorySlots ?: return null + if (container is ContainerChest) + return container.lowerChestInventory + if (container is AccessorContainerDispenser) + return container.dispenserInventory_ledger + if (container is AccessorContainerHopper) + return container.hopperInventory_ledger + return null + + } + + fun estimateName(screen: GuiScreen?): String? { + return estimateInventory(screen)?.name + } +} \ No newline at end of file diff --git a/mod/src/main/kotlin/moe/nea/ledger/utils/telemetry/Span.kt b/mod/src/main/kotlin/moe/nea/ledger/utils/telemetry/Span.kt index 0d680a9..8b8e284 100644 --- a/mod/src/main/kotlin/moe/nea/ledger/utils/telemetry/Span.kt +++ b/mod/src/main/kotlin/moe/nea/ledger/utils/telemetry/Span.kt @@ -2,9 +2,10 @@ package moe.nea.ledger.utils.telemetry class Span(val parent: Span?) : AutoCloseable { companion object { + val rootSpan = Span(null) private val _current = object : InheritableThreadLocal() { override fun initialValue(): Span { - return Span(null) + return Span(rootSpan) } override fun childValue(parentValue: Span?): Span { -- cgit