From b893e3bc6cd0b1c1a048de6d3459d1e8f20f141c Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 13 Jul 2025 12:56:43 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(core):=20=E6=B7=BB=E5=8A=A0=E7=9B=91?= =?UTF-8?q?=E5=90=ACspawnAfterBreak=E5=86=85=E9=83=A8=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UnsafeCompositeBlockBehavior.java | 7 +++++++ .../plugin/injector/BlockGenerator.java | 19 ++++++++++++++++++- .../reflection/minecraft/CoreReflections.java | 6 ++++++ .../craftengine/core/block/BlockBehavior.java | 5 +++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java index e70881894..70078d29b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java @@ -268,4 +268,11 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior { } return previous; } + + @Override + public void spawnAfterBreak(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + for (AbstractBlockBehavior behavior : this.behaviors) { + behavior.spawnAfterBreak(thisBlock, args, superMethod); + } + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java index e92214714..e5a5acb85 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java @@ -180,7 +180,10 @@ public final class BlockGenerator { .intercept(MethodDelegation.to(IsSignalSourceInterceptor.INSTANCE)) // playerWillDestroy .method(ElementMatchers.is(CoreReflections.method$Block$playerWillDestroy)) - .intercept(MethodDelegation.to(PlayerWillDestroyInterceptor.INSTANCE)); + .intercept(MethodDelegation.to(PlayerWillDestroyInterceptor.INSTANCE)) + // spawnAfterBreak + .method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$spawnAfterBreak)) + .intercept(MethodDelegation.to(SpawnAfterBreakInterceptor.INSTANCE)); if (CoreReflections.method$BlockBehaviour$affectNeighborsAfterRemoval != null) { builder.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$affectNeighborsAfterRemoval)) .intercept(MethodDelegation.to(AffectNeighborsAfterRemovalInterceptor.INSTANCE)); @@ -643,4 +646,18 @@ public final class BlockGenerator { } } } + + public static class SpawnAfterBreakInterceptor { + public static final SpawnAfterBreakInterceptor INSTANCE = new SpawnAfterBreakInterceptor(); + + @RuntimeType + public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { + ObjectHolder holder = ((DelegatingBlock) thisObj).behaviorDelegate(); + try { + holder.value().spawnAfterBreak(thisObj, args, superMethod); + } catch (Exception e) { + CraftEngine.instance().logger().severe("Failed to run spawnAfterBreak", e); + } + } + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index 927ff1e16..d0c25b978 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -3816,4 +3816,10 @@ public final class CoreReflections { VersionHelper.isOrAbove1_20_2() ? ReflectionUtils.getStaticMethod(clazz$ArmorTrim, Optional.class, clazz$RegistryAccess, clazz$ItemStack, boolean.class) : ReflectionUtils.getStaticMethod(clazz$ArmorTrim, Optional.class, clazz$RegistryAccess, clazz$ItemStack); + + public static final Method method$BlockBehaviour$spawnAfterBreak = requireNonNull( + ReflectionUtils.getDeclaredMethod( + clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$ServerLevel, clazz$BlockPos, clazz$ItemStack, boolean.class + ) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java index 0cca29faf..6b805327c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java @@ -143,6 +143,11 @@ public abstract class BlockBehavior { return superMethod.call(); } + // BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience + public void spawnAfterBreak(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + superMethod.call(); + } + public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) { return state; } From 3ce1917df54755137eccee2d98b064f868e6edb6 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 13 Jul 2025 15:11:19 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(core):=20=E6=B7=BB=E5=8A=A0=E7=9B=91?= =?UTF-8?q?=E5=90=AConRemove=E5=86=85=E9=83=A8=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../behavior/UnsafeCompositeBlockBehavior.java | 7 +++++++ .../bukkit/plugin/injector/BlockGenerator.java | 18 ++++++++++++++++++ .../reflection/minecraft/CoreReflections.java | 8 ++++++++ .../craftengine/core/block/BlockBehavior.java | 4 +++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java index 70078d29b..4542f71d2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java @@ -225,6 +225,13 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior { } } + @Override + public void onRemove(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + for (AbstractBlockBehavior behavior : this.behaviors) { + behavior.onRemove(thisBlock, args, superMethod); + } + } + @Override public int getSignal(Object thisBlock, Object[] args, Callable superMethod) { for (AbstractBlockBehavior behavior : this.behaviors) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java index e5a5acb85..1db5d52dc 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java @@ -188,6 +188,10 @@ public final class BlockGenerator { builder.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$affectNeighborsAfterRemoval)) .intercept(MethodDelegation.to(AffectNeighborsAfterRemovalInterceptor.INSTANCE)); } + if (CoreReflections.method$BlockBehaviour$onRemove != null) { + builder.method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$onRemove)) + .intercept(MethodDelegation.to(OnRemoveInterceptor.INSTANCE)); + } Class clazz$CraftEngineBlock = builder.make().load(BlockGenerator.class.getClassLoader()).getLoaded(); constructor$CraftEngineBlock = MethodHandles.publicLookup().in(clazz$CraftEngineBlock) @@ -618,6 +622,20 @@ public final class BlockGenerator { } } + public static class OnRemoveInterceptor { + public static final OnRemoveInterceptor INSTANCE = new OnRemoveInterceptor(); + + @RuntimeType + public void intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { + ObjectHolder holder = ((DelegatingBlock) thisObj).behaviorDelegate(); + try { + holder.value().onRemove(thisObj, args, superMethod); + } catch (Exception e) { + CraftEngine.instance().logger().severe("Failed to run onRemove", e); + } + } + } + public static class EntityInsideInterceptor { public static final EntityInsideInterceptor INSTANCE = new EntityInsideInterceptor(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index d0c25b978..0bd7981a8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -3822,4 +3822,12 @@ public final class CoreReflections { clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$ServerLevel, clazz$BlockPos, clazz$ItemStack, boolean.class ) ); + + // 1.20~1.21.4 + public static final Method method$BlockBehaviour$onRemove = MiscUtils.requireNonNullIf( + ReflectionUtils.getDeclaredMethod( + clazz$BlockBehaviour, void.class, clazz$BlockState, clazz$Level, clazz$BlockPos, clazz$BlockState, boolean.class + ), + !VersionHelper.isOrAbove1_21_5() + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java index 6b805327c..9b61dd9e2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java @@ -123,6 +123,9 @@ public abstract class BlockBehavior { public void affectNeighborsAfterRemoval(Object thisBlock, Object[] args, Callable superMethod) throws Exception { } + public void onRemove(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + } + // BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side public int getSignal(Object thisBlock, Object[] args, Callable superMethod) { return 0; @@ -145,7 +148,6 @@ public abstract class BlockBehavior { // BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience public void spawnAfterBreak(Object thisBlock, Object[] args, Callable superMethod) throws Exception { - superMethod.call(); } public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) { From cf2fa2b333da5267f82dce9fcbdcbf327a77e65e Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 13 Jul 2025 15:12:08 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat(core):=20=E6=B7=BB=E5=8A=A0=E7=9B=91?= =?UTF-8?q?=E5=90=AConRemove=E5=86=85=E9=83=A8=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../net/momirealms/craftengine/core/block/BlockBehavior.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java index 9b61dd9e2..01c6cc04b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java @@ -123,6 +123,7 @@ public abstract class BlockBehavior { public void affectNeighborsAfterRemoval(Object thisBlock, Object[] args, Callable superMethod) throws Exception { } + // 1.20~1.21.4 BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston public void onRemove(Object thisBlock, Object[] args, Callable superMethod) throws Exception { } From 8854d8afc30f9ca92f4aef5cdd2c980253836c89 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Sun, 13 Jul 2025 15:19:27 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(block):=20=E5=8E=8B=E5=8A=9B=E6=9D=BF?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=97=B6=E6=AD=A3=E7=A1=AE=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=BA=A2=E7=9F=B3=E4=BF=A1=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../behavior/PressurePlateBlockBehavior.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PressurePlateBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PressurePlateBlockBehavior.java index 51ad4edb3..999fe0da3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PressurePlateBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PressurePlateBlockBehavior.java @@ -182,6 +182,21 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior { } } + @Override + public void onRemove(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + Object state = args[0]; + Object level = args[1]; + Object pos = args[2]; + Object newState = args[3]; + boolean movedByPiston = (boolean) args[4]; + if (!movedByPiston && !FastNMS.INSTANCE.method$BlockStateBase$is(state, FastNMS.INSTANCE.method$BlockState$getBlock(newState))) { + if (this.getSignalForState(state) > 0) { + this.updateNeighbours(level, pos, thisBlock); + } + superMethod.call(); + } + } + private void updateNeighbours(Object level, Object pos, Object thisBlock) { FastNMS.INSTANCE.method$Level$updateNeighborsAt(level, pos, thisBlock); FastNMS.INSTANCE.method$Level$updateNeighborsAt(level, LocationUtils.below(pos), thisBlock);