diff --git a/src/main/java/xyz/nucleoid/stimuli/event/block/BlockFallEvent.java b/src/main/java/xyz/nucleoid/stimuli/event/block/BlockFallEvent.java new file mode 100644 index 0000000..35622ba --- /dev/null +++ b/src/main/java/xyz/nucleoid/stimuli/event/block/BlockFallEvent.java @@ -0,0 +1,36 @@ +package xyz.nucleoid.stimuli.event.block; + +import net.minecraft.block.BlockState; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.ActionResult; +import net.minecraft.util.math.BlockPos; +import xyz.nucleoid.stimuli.event.StimulusEvent; + +/** + * Called when a gravity-affected block attempts to fall. + * + *

Upon return: + *

+ *

+ * If all listeners return {@link ActionResult#PASS}, the block successfully falls. + */ +public interface BlockFallEvent { + StimulusEvent EVENT = StimulusEvent.create(BlockFallEvent.class, ctx -> (world, pos, state) -> { + try { + for (BlockFallEvent listener : ctx.getListeners()) { + ActionResult result = listener.onBlockFall(world, pos, state); + if (result != ActionResult.PASS) { + return result; + } + } + } catch (Throwable t) { + ctx.handleException(t); + } + return ActionResult.PASS; + }); + + ActionResult onBlockFall(ServerWorld world, BlockPos pos, BlockState state); +} diff --git a/src/main/java/xyz/nucleoid/stimuli/mixin/block/FallingBlockMixin.java b/src/main/java/xyz/nucleoid/stimuli/mixin/block/FallingBlockMixin.java new file mode 100644 index 0000000..677b138 --- /dev/null +++ b/src/main/java/xyz/nucleoid/stimuli/mixin/block/FallingBlockMixin.java @@ -0,0 +1,30 @@ +package xyz.nucleoid.stimuli.mixin.block; + +import java.util.Random; + +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.BlockState; +import net.minecraft.block.FallingBlock; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.ActionResult; +import net.minecraft.util.math.BlockPos; +import xyz.nucleoid.stimuli.EventInvokers; +import xyz.nucleoid.stimuli.Stimuli; +import xyz.nucleoid.stimuli.event.block.BlockFallEvent; + +@Mixin(FallingBlock.class) +public class FallingBlockMixin { + @Inject(method = "scheduledTick", at = @At("HEAD"), cancellable = true) + private void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random, CallbackInfo ci) { + try (EventInvokers invokers = Stimuli.select().at(world, pos)) { + ActionResult result = invokers.get(BlockFallEvent.EVENT).onBlockFall(world, pos, state); + if (result == ActionResult.FAIL) { + ci.cancel(); + } + } + } +} diff --git a/src/main/resources/stimuli.mixins.json b/src/main/resources/stimuli.mixins.json index cc8f45f..b1e02e2 100644 --- a/src/main/resources/stimuli.mixins.json +++ b/src/main/resources/stimuli.mixins.json @@ -6,6 +6,7 @@ "mixins": [ "block.BlockItemMixin", "block.BlockMixin", + "block.FallingBlockMixin", "block.FarmlandBlockMixin", "entity.LivingEntityMixin", "player.CraftingResultInventoryMixin",