From 8f3583ae85f27dd2190a4a47d7fb6da7aa8157ff Mon Sep 17 00:00:00 2001 From: modmuss Date: Mon, 17 Jun 2024 22:32:06 +0100 Subject: [PATCH] Fix BlockEntity Load/Unload events (#3865) --- .../lifecycle/client/WorldChunkMixin.java | 25 +++++++++++-------- .../lifecycle/server/WorldChunkMixin.java | 8 +++--- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/mixin/event/lifecycle/client/WorldChunkMixin.java b/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/mixin/event/lifecycle/client/WorldChunkMixin.java index 14d9bb09d..998319f2c 100644 --- a/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/mixin/event/lifecycle/client/WorldChunkMixin.java +++ b/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/mixin/event/lifecycle/client/WorldChunkMixin.java @@ -44,21 +44,26 @@ abstract class WorldChunkMixin { @Shadow public abstract World getWorld(); - @Inject(method = "setBlockEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;markRemoved()V")) - private void onLoadBlockEntity(BlockEntity blockEntity, CallbackInfo ci) { - if (this.getWorld() instanceof ServerWorld) { - ServerBlockEntityEvents.BLOCK_ENTITY_LOAD.invoker().onLoad(blockEntity, (ServerWorld) this.getWorld()); - } else if (this.getWorld() instanceof ClientWorld) { - ClientBlockEntityEvents.BLOCK_ENTITY_LOAD.invoker().onLoad(blockEntity, (ClientWorld) this.getWorld()); + @Inject(method = "setBlockEntity", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", shift = At.Shift.BY, by = 3)) + private void onLoadBlockEntity(BlockEntity blockEntity, CallbackInfo ci, @Local(ordinal = 1) BlockEntity removedBlockEntity) { + // Only fire the load event if the block entity has actually changed + if (blockEntity != null && blockEntity != removedBlockEntity) { + if (this.getWorld() instanceof ServerWorld) { + ServerBlockEntityEvents.BLOCK_ENTITY_LOAD.invoker().onLoad(blockEntity, (ServerWorld) this.getWorld()); + } else if (this.getWorld() instanceof ClientWorld) { + ClientBlockEntityEvents.BLOCK_ENTITY_LOAD.invoker().onLoad(blockEntity, (ClientWorld) this.getWorld()); + } } } @Inject(method = "setBlockEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;markRemoved()V", shift = At.Shift.AFTER)) private void onRemoveBlockEntity(BlockEntity blockEntity, CallbackInfo info, @Local(ordinal = 1) BlockEntity removedBlockEntity) { - if (this.getWorld() instanceof ServerWorld) { - ServerBlockEntityEvents.BLOCK_ENTITY_UNLOAD.invoker().onUnload(removedBlockEntity, (ServerWorld) this.getWorld()); - } else if (this.getWorld() instanceof ClientWorld) { - ClientBlockEntityEvents.BLOCK_ENTITY_UNLOAD.invoker().onUnload(removedBlockEntity, (ClientWorld) this.getWorld()); + if (removedBlockEntity != null) { + if (this.getWorld() instanceof ServerWorld) { + ServerBlockEntityEvents.BLOCK_ENTITY_UNLOAD.invoker().onUnload(removedBlockEntity, (ServerWorld) this.getWorld()); + } else if (this.getWorld() instanceof ClientWorld) { + ClientBlockEntityEvents.BLOCK_ENTITY_UNLOAD.invoker().onUnload(removedBlockEntity, (ClientWorld) this.getWorld()); + } } } diff --git a/fabric-lifecycle-events-v1/src/main/java/net/fabricmc/fabric/mixin/event/lifecycle/server/WorldChunkMixin.java b/fabric-lifecycle-events-v1/src/main/java/net/fabricmc/fabric/mixin/event/lifecycle/server/WorldChunkMixin.java index e9c35ae53..9e73b5db1 100644 --- a/fabric-lifecycle-events-v1/src/main/java/net/fabricmc/fabric/mixin/event/lifecycle/server/WorldChunkMixin.java +++ b/fabric-lifecycle-events-v1/src/main/java/net/fabricmc/fabric/mixin/event/lifecycle/server/WorldChunkMixin.java @@ -47,11 +47,13 @@ abstract class WorldChunkMixin { @Shadow public abstract World getWorld(); - @Inject(method = "setBlockEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;markRemoved()V")) + @Inject(method = "setBlockEntity", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", shift = At.Shift.BY, by = 3)) private void onLoadBlockEntity(BlockEntity blockEntity, CallbackInfo ci, @Local(ordinal = 1) BlockEntity removedBlockEntity) { // Only fire the load event if the block entity has actually changed - if (this.getWorld() instanceof ServerWorld) { - ServerBlockEntityEvents.BLOCK_ENTITY_LOAD.invoker().onLoad(blockEntity, (ServerWorld) this.getWorld()); + if (blockEntity != null && blockEntity != removedBlockEntity) { + if (this.getWorld() instanceof ServerWorld) { + ServerBlockEntityEvents.BLOCK_ENTITY_LOAD.invoker().onLoad(blockEntity, (ServerWorld) this.getWorld()); + } } }