From e9106d8de882047a00247bab8dc1112542e38d97 Mon Sep 17 00:00:00 2001 From: LeSynz Date: Mon, 14 Sep 2026 22:56:05 +0100 Subject: [PATCH] feat: log block state changes made with debug sticks Ledger doesn't log debug stick usage, so this adds a mixin on DebugStickItem to catch the block state changes it makes. They show up as normal block-change actions with rollback support. Gave it its own debug_stick source rather than player so it can be pulled up with source:@debug_stick and blacklisted on its own. Also stores the block entity, otherwise rolling back a change on a chest or furnace throws. --- .../ledger/mixin/DebugStickItemMixin.java | 37 +++++++++++++++++++ .../ledger/utility/Sources.kt | 1 + src/main/resources/ledger.mixins.json | 1 + 3 files changed, 39 insertions(+) create mode 100644 src/main/java/com/github/quiltservertools/ledger/mixin/DebugStickItemMixin.java diff --git a/src/main/java/com/github/quiltservertools/ledger/mixin/DebugStickItemMixin.java b/src/main/java/com/github/quiltservertools/ledger/mixin/DebugStickItemMixin.java new file mode 100644 index 00000000..8ebab609 --- /dev/null +++ b/src/main/java/com/github/quiltservertools/ledger/mixin/DebugStickItemMixin.java @@ -0,0 +1,37 @@ +package com.github.quiltservertools.ledger.mixin; + +import com.github.quiltservertools.ledger.callbacks.BlockChangeCallback; +import com.github.quiltservertools.ledger.utility.Sources; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.DebugStickItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArgs; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +@Mixin(DebugStickItem.class) +public abstract class DebugStickItemMixin { + @ModifyArgs( + method = "handleInteraction", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/LevelAccessor;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) + private void logDebugStickUsage(Args args, ServerPlayer player, BlockState oldState, LevelAccessor worldAccess, BlockPos pos, boolean update, ItemStack stack) { + if (worldAccess instanceof Level world) { + BlockEntity blockEntity = oldState.hasBlockEntity() ? world.getBlockEntity(pos) : null; + BlockChangeCallback.EVENT.invoker().changeBlock( + world, + pos.immutable(), + oldState, + args.get(1), + blockEntity, + blockEntity, + Sources.DEBUG_STICK, + player); + } + } +} diff --git a/src/main/kotlin/com/github/quiltservertools/ledger/utility/Sources.kt b/src/main/kotlin/com/github/quiltservertools/ledger/utility/Sources.kt index b7565156..fba08ef9 100644 --- a/src/main/kotlin/com/github/quiltservertools/ledger/utility/Sources.kt +++ b/src/main/kotlin/com/github/quiltservertools/ledger/utility/Sources.kt @@ -39,5 +39,6 @@ object Sources { const val COPPER_GOLEM = "copper_golem" const val WAX = "wax" const val REANIMATE = "reanimate" + const val DEBUG_STICK = "debug_stick" const val UNKNOWN = "unknown" } diff --git a/src/main/resources/ledger.mixins.json b/src/main/resources/ledger.mixins.json index 90fea326..e8cd315c 100644 --- a/src/main/resources/ledger.mixins.json +++ b/src/main/resources/ledger.mixins.json @@ -16,6 +16,7 @@ "CompoundContainerMixin", "ContainersMixin", "CopperGolemGiveMixin", + "DebugStickItemMixin", "DyeItemMixin", "FillCommandMixin", "FlintAndSteelItemMixin",