Detecting blocks pushed by piston

I’m trying to make some vanilla-ish autocrafting. The basic idea is that when a piston pushes a given block (say an iron block) against the top of, say, a smithing table, it does something. Kind of like an automated anvil with pistons.

I looked a bit into quilted-fapi’s javadoc, qsl’s javadoc and fabric tutorials, but I couldn’t find anything like a pistonExtendedEvent or whatever that would allow me simply register a callback when a block is pushed by a piston, so I’m guessing I should go the mixin route and inject some code ran when a piston finishes extending. I’ve tried to fiddle around a bit, but:

  • I never really used mixins, I’m not afraid to use them but I do want to do it right, and I don’t really have an idea how.
  • I have no idea which method I should target. I’m not really knowledgable of the minecraft codebase, even less so of how pistons work.

So far I succeeded detecting moving piston by hooking into net/minecraft/block/entity/PistonBlockEntity;tick:

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import net.minecraft.block.entity.PistonBlockEntity;

@Mixin(PistonBlockEntity.class)
public class PistonBlockEntityMixin {
    @Inject(
            at = @At("RETURN"),
            method = "Lnet/minecraft/block/entity/PistonBlockEntity;tick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/block/entity/PistonBlockEntity;)V"
    )
    static private void onFinish(CallbackInfo info) {
        Mod.LOGGER.info("boom");
    }
}

But my understanding of this is that it runs every tick while the piston is moving. Where tick may not be game tick ? I don’t know, just toggling a piston printed more “boom” than it should then ? Anyway, I think I need something that fires once, when the piston is done extending. I tried targeting net/minecraft/block/entity/PistonBlockEntity;finish(), but it didn’t seem to get called ? I can keep doing trial and error a long time before I find the right target methinks :stuck_out_tongue:

Note: I know just detecting the smashing isn’t enough to enable actual autocrafting, but this I was thinking this is one step toward it. I don’t have the “adding an inventory to the smithing table” part figured out yet, so if someone thinks there’s another (better/simpler/…) way, please tell me :slight_smile: Il’ll be thankfull if I can save some time not figuring out the Y part of an XY problem :grin:

So the actual questions are:

  • How can I reliably detect two blocks being smashed by a piston ?
  • If I need a mixin, which target should I use ?
  • If you think doing it by detecting pushed blocks is a dead end, do you have any other idea ? Vague pointers still appreciated, I can dig down the rabbit whole myself :slight_smile:

Thanks in advance !
:whale: :sparkles:

PS: I also posted a topic in quilt’s discord. I don’t know if this is alright to “double-post” like that, I’ll promptly archive/remove one of the topics if told to. In any case here’s the link, for potential future reference.