From 70cf61d9edff67a687cc528be2debfd1dfae0519 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 2 Apr 2025 20:22:11 +0800 Subject: [PATCH] faster nms --- .../bukkit/api/CraftEngineBlocks.java | 4 +- .../bukkit/block/BlockEventListener.java | 7 +- .../block/behavior/BukkitBlockBehavior.java | 121 ++++++++++++++++ .../block/behavior/BushBlockBehavior.java | 8 +- .../behavior/ConcretePowderBlockBehavior.java | 8 +- .../block/behavior/CropBlockBehavior.java | 10 +- .../block/behavior/FallingBlockBehavior.java | 8 +- .../block/behavior/HangingBlockBehavior.java | 6 +- .../block/behavior/LeavesBlockBehavior.java | 8 +- .../block/behavior/OnLiquidBlockBehavior.java | 6 +- .../block/behavior/SaplingBlockBehavior.java | 12 +- .../behavior/StrippableBlockBehavior.java | 8 +- .../behavior/SugarCaneBlockBehavior.java | 14 +- .../behavior/WaterLoggedBlockBehavior.java | 8 +- .../entity/furniture/LoadedFurniture.java | 4 +- .../item/behavior/BlockItemBehavior.java | 2 +- .../item/recipe/RecipeEventListener.java | 3 +- .../plugin/command/feature/TestCommand.java | 9 +- .../plugin/injector/BukkitInjector.java | 40 ++++- .../plugin/network/BukkitNetworkManager.java | 34 +---- .../plugin/network/PacketConsumers.java | 4 +- .../bukkit/util/DirectionUtils.java | 9 ++ .../craftengine/bukkit/util/LightUtils.java | 24 ++- .../craftengine/bukkit/util/MirrorUtils.java | 31 ++++ .../util/NoteBlockChainUpdateUtils.java | 2 +- .../craftengine/bukkit/util/Reflections.java | 137 ++++++++++++++---- .../bukkit/util/RotationUtils.java | 34 +++++ .../craftengine/bukkit/world/BukkitWorld.java | 4 +- .../bukkit/world/BukkitWorldBlock.java | 3 +- .../block/behavior/AbstractBlockBehavior.java | 6 + gradle.properties | 2 +- .../craftengine/mod/CraftEngineBlock.java | 27 +++- .../shared/block/BlockBehavior.java | 8 + 33 files changed, 458 insertions(+), 153 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehavior.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/MirrorUtils.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/RotationUtils.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java index ed4dc7d2e..79a27fcc7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java @@ -108,11 +108,11 @@ public final class CraftEngineBlocks { boolean playSound) { boolean success; try { - Object worldServer = Reflections.field$CraftWorld$ServerLevel.get(location.getWorld()); + Object worldServer = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()); Object blockPos = FastNMS.INSTANCE.constructor$BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); Object blockState = block.customBlockState().handle(); Object oldBlockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(worldServer, blockPos); - success = (boolean) Reflections.method$LevelWriter$setBlock.invoke(worldServer, blockPos, blockState, option.flags()); + success = FastNMS.INSTANCE.method$LevelWriter$setBlock(worldServer, blockPos, blockState, option.flags()); if (success) { Reflections.method$BlockStateBase$onPlace.invoke(blockState, worldServer, blockPos, oldBlockState, true); if (playSound) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java index befb9a1e2..32449e5d6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BlockEventListener.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.block; import io.papermc.paper.event.block.BlockBreakBlockEvent; import net.momirealms.craftengine.bukkit.api.event.CustomBlockBreakEvent; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.*; @@ -316,10 +317,10 @@ public class BlockEventListener implements Listener { Block sourceBlock = event.getSourceBlock(); BlockFace direction = sourceBlock.getFace(block); if (direction == BlockFace.UP || direction == BlockFace.DOWN) { - Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(world); - Object chunkSource = Reflections.field$ServerLevel$chunkSource.get(serverLevel); + Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world); + Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel); Object blockPos = LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - Reflections.method$ServerChunkCache$blockChanged.invoke(chunkSource, blockPos); + FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos); if (direction == BlockFace.UP) { NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, Reflections.instance$Direction$UP, blockPos, 0); } else { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehavior.java new file mode 100644 index 000000000..93ad23eb6 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehavior.java @@ -0,0 +1,121 @@ +package net.momirealms.craftengine.bukkit.block.behavior; + +import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.bukkit.util.MirrorUtils; +import net.momirealms.craftengine.bukkit.util.RotationUtils; +import net.momirealms.craftengine.core.block.CustomBlock; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.util.Direction; +import net.momirealms.craftengine.core.util.HorizontalDirection; +import net.momirealms.craftengine.core.util.Mirror; +import net.momirealms.craftengine.core.util.Rotation; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.Callable; +import java.util.function.BiConsumer; + +public class BukkitBlockBehavior extends AbstractBlockBehavior { + private static final Map>> HARD_CODED_PROPERTY_DATA = new HashMap<>(); + static { + HARD_CODED_PROPERTY_DATA.put("axis", (behavior, property) -> { + @SuppressWarnings("unchecked") + Property axisProperty = (Property) property; + behavior.rotateFunction = (thisBlock, blockState, rotation) -> { + Direction.Axis axis = blockState.get(axisProperty); + return switch (rotation) { + case COUNTERCLOCKWISE_90, CLOCKWISE_90 -> switch (axis) { + case X -> blockState.with(axisProperty, Direction.Axis.Z).customBlockState().handle(); + case Z -> blockState.with(axisProperty, Direction.Axis.X).customBlockState().handle(); + default -> blockState.customBlockState().handle(); + }; + default -> blockState.customBlockState().handle(); + }; + }; + }); + HARD_CODED_PROPERTY_DATA.put("facing", (behavior, property) -> { + if (property.valueClass() == HorizontalDirection.class) { + @SuppressWarnings("unchecked") + Property directionProperty = (Property) property; + behavior.rotateFunction = (thisBlock, blockState, rotation) -> + blockState.with(directionProperty, rotation.rotate(blockState.get(directionProperty).toDirection()).toHorizontalDirection()) + .customBlockState().handle(); + behavior.mirrorFunction = (thisBlock, blockState, mirror) -> { + Rotation rotation = mirror.getRotation(blockState.get(directionProperty).toDirection()); + return behavior.rotateFunction.rotate(thisBlock, blockState, rotation); + }; + } else if (property.valueClass() == Direction.class) { + @SuppressWarnings("unchecked") + Property directionProperty = (Property) property; + behavior.rotateFunction = (thisBlock, blockState, rotation) -> + blockState.with(directionProperty, rotation.rotate(blockState.get(directionProperty))) + .customBlockState().handle(); + behavior.mirrorFunction = (thisBlock, blockState, mirror) -> { + Rotation rotation = mirror.getRotation(blockState.get(directionProperty)); + return behavior.rotateFunction.rotate(thisBlock, blockState, rotation); + }; + } + }); + HARD_CODED_PROPERTY_DATA.put("facing_clockwise", (behavior, property) -> { + if (property.valueClass() == Direction.class) { + @SuppressWarnings("unchecked") + Property directionProperty = (Property) property; + behavior.rotateFunction = (thisBlock, blockState, rotation) -> + blockState.with(directionProperty, rotation.rotate(blockState.get(directionProperty))) + .customBlockState().handle(); + behavior.mirrorFunction = (thisBlock, blockState, mirror) -> { + Rotation rotation = mirror.getRotation(blockState.get(directionProperty)); + return behavior.rotateFunction.rotate(thisBlock, blockState, rotation); + }; + } + }); + } + + private MirrorFunction mirrorFunction; + private RotateFunction rotateFunction; + + public BukkitBlockBehavior(CustomBlock customBlock) { + super(customBlock); + for (Property property : customBlock.properties()) { + Optional.ofNullable(HARD_CODED_PROPERTY_DATA.get(property.name())).ifPresent( + c -> c.accept(this, property) + ); + } + } + + @Override + public Object mirror(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + if (this.mirrorFunction != null) { + int id = BlockStateUtils.blockStateToId(args[0]); + ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(id); + return this.mirrorFunction.mirror(thisBlock, state, MirrorUtils.fromNMSMirror(args[1])); + } + return super.mirror(thisBlock, args, superMethod); + } + + @Override + public Object rotate(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + if (this.rotateFunction != null) { + int id = BlockStateUtils.blockStateToId(args[0]); + ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(id); + return this.rotateFunction.rotate(thisBlock, state, RotationUtils.fromNMSRotation(args[1])); + } + return super.rotate(thisBlock, args, superMethod); + } + + @FunctionalInterface + interface MirrorFunction { + + Object mirror(Object thisBlock, ImmutableBlockState state, Mirror mirror) throws Exception; + } + + @FunctionalInterface + interface RotateFunction { + + Object rotate(Object thisBlock, ImmutableBlockState state, Rotation rotation) throws Exception; + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BushBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BushBlockBehavior.java index 13b6e32ae..7c42b3ad8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BushBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BushBlockBehavior.java @@ -9,7 +9,6 @@ import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.parameter.LootParameters; @@ -29,14 +28,15 @@ import org.bukkit.Registry; import java.util.*; import java.util.concurrent.Callable; -public class BushBlockBehavior extends AbstractBlockBehavior { +public class BushBlockBehavior extends BukkitBlockBehavior { public static final Factory FACTORY = new Factory(); protected final List tagsCanSurviveOn; protected final Set blocksCansSurviveOn; protected final Set customBlocksCansSurviveOn; protected final boolean any; - public BushBlockBehavior(List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn) { + public BushBlockBehavior(CustomBlock block, List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn) { + super(block); this.tagsCanSurviveOn = tagsCanSurviveOn; this.blocksCansSurviveOn = blocksCansSurviveOn; this.customBlocksCansSurviveOn = customBlocksCansSurviveOn; @@ -93,7 +93,7 @@ public class BushBlockBehavior extends AbstractBlockBehavior { @Override public BlockBehavior create(CustomBlock block, Map arguments) { Tuple, Set, Set> tuple = readTagsAndState(arguments); - return new BushBlockBehavior(tuple.left(), tuple.mid(), tuple.right()); + return new BushBlockBehavior(block, tuple.left(), tuple.mid(), tuple.right()); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ConcretePowderBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ConcretePowderBlockBehavior.java index 3df82844d..2f79abc20 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ConcretePowderBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/ConcretePowderBlockBehavior.java @@ -32,9 +32,9 @@ public class ConcretePowderBlockBehavior extends FallingBlockBehavior { private Object defaultBlockState; private ImmutableBlockState defaultImmutableBlockState; - public ConcretePowderBlockBehavior(float hurtAmount, int maxHurt, Key block) { - super(hurtAmount, maxHurt); - this.targetBlock = block; + public ConcretePowderBlockBehavior(CustomBlock block, float hurtAmount, int maxHurt, Key targetBlock) { + super(block, hurtAmount, maxHurt); + this.targetBlock = targetBlock; } public ImmutableBlockState defaultImmutableBlockState() { @@ -161,7 +161,7 @@ public class ConcretePowderBlockBehavior extends FallingBlockBehavior { if (solidBlock == null) { throw new IllegalArgumentException("No `solid-block` specified for concrete powder block behavior"); } - return new ConcretePowderBlockBehavior(hurtAmount, hurtMax, Key.of(solidBlock)); + return new ConcretePowderBlockBehavior(block, hurtAmount, hurtMax, Key.of(solidBlock)); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/CropBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/CropBlockBehavior.java index b4cde1bd8..a8b8881fd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/CropBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/CropBlockBehavior.java @@ -29,9 +29,9 @@ public class CropBlockBehavior extends BushBlockBehavior { private final float growSpeed; private final int minGrowLight; - public CropBlockBehavior(List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn, + public CropBlockBehavior(CustomBlock block, List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn, Property ageProperty, float growSpeed, int minGrowLight) { - super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn); + super(block, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn); this.ageProperty = (IntegerProperty) ageProperty; this.growSpeed = growSpeed; this.minGrowLight = minGrowLight; @@ -63,7 +63,7 @@ public class CropBlockBehavior extends BushBlockBehavior { if (currentState != null && !currentState.isEmpty()) { int age = this.getAge(currentState); if (age < this.ageProperty.max && RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) { - Reflections.method$Level$setBlock.invoke(level, pos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); } } } @@ -117,7 +117,7 @@ public class CropBlockBehavior extends BushBlockBehavior { if (i > maxAge) { i = maxAge; } - Reflections.method$Level$setBlock.invoke(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags()); if (sendParticles) { World world = FastNMS.INSTANCE.method$Level$getCraftWorld(level); int x = FastNMS.INSTANCE.field$Vec3i$x(pos); @@ -140,7 +140,7 @@ public class CropBlockBehavior extends BushBlockBehavior { // 存活条件是最小生长亮度-1 int minGrowLight = MiscUtils.getAsInt(arguments.getOrDefault("light-requirement", 9)); float growSpeed = MiscUtils.getAsFloat(arguments.getOrDefault("grow-speed", 0.25f)); - return new CropBlockBehavior(tuple.left(), tuple.mid(), tuple.right(), ageProperty, growSpeed, minGrowLight); + return new CropBlockBehavior(block, tuple.left(), tuple.mid(), tuple.right(), ageProperty, growSpeed, minGrowLight); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java index 08bbc708a..8b2813ea9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java @@ -8,7 +8,6 @@ import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.parameter.LootParameters; @@ -21,12 +20,13 @@ import net.momirealms.craftengine.shared.block.BlockBehavior; import java.util.Map; import java.util.concurrent.Callable; -public class FallingBlockBehavior extends AbstractBlockBehavior { +public class FallingBlockBehavior extends BukkitBlockBehavior { public static final Factory FACTORY = new Factory(); private final float hurtAmount; private final int maxHurt; - public FallingBlockBehavior(float hurtAmount, int maxHurt) { + public FallingBlockBehavior(CustomBlock block, float hurtAmount, int maxHurt) { + super(block); this.hurtAmount = hurtAmount; this.maxHurt = maxHurt; } @@ -131,7 +131,7 @@ public class FallingBlockBehavior extends AbstractBlockBehavior { public BlockBehavior create(CustomBlock block, Map arguments) { float hurtAmount = MiscUtils.getAsFloat(arguments.getOrDefault("hurt-amount", -1f)); int hurtMax = MiscUtils.getAsInt(arguments.getOrDefault("max-hurt", -1)); - return new FallingBlockBehavior(hurtAmount, hurtMax); + return new FallingBlockBehavior(block, hurtAmount, hurtMax); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/HangingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/HangingBlockBehavior.java index 2c43e4ea8..2d802ed2b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/HangingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/HangingBlockBehavior.java @@ -13,8 +13,8 @@ import java.util.Set; public class HangingBlockBehavior extends BushBlockBehavior { public static final Factory FACTORY = new Factory(); - public HangingBlockBehavior(List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn) { - super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn); + public HangingBlockBehavior(CustomBlock block, List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn) { + super(block, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn); } @Override @@ -32,7 +32,7 @@ public class HangingBlockBehavior extends BushBlockBehavior { @Override public BlockBehavior create(CustomBlock block, Map arguments) { Tuple, Set, Set> tuple = readTagsAndState(arguments); - return new HangingBlockBehavior(tuple.left(), tuple.mid(), tuple.right()); + return new HangingBlockBehavior(block, tuple.left(), tuple.mid(), tuple.right()); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LeavesBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LeavesBlockBehavior.java index d454b2c1b..99b543466 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LeavesBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LeavesBlockBehavior.java @@ -39,8 +39,8 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior { @Nullable private final Property waterloggedProperty; - public LeavesBlockBehavior(int maxDistance, Property distanceProperty, Property persistentProperty, @Nullable Property waterloggedProperty) { - super(waterloggedProperty); + public LeavesBlockBehavior(CustomBlock block, int maxDistance, Property distanceProperty, Property persistentProperty, @Nullable Property waterloggedProperty) { + super(block, waterloggedProperty); this.maxDistance = maxDistance; this.distanceProperty = distanceProperty; this.persistentProperty = persistentProperty; @@ -97,7 +97,7 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior { if (blockState == newState.customBlockState().handle()) { Reflections.method$BlockStateBase$updateNeighbourShapes.invoke(blockState, level, blockPos, UpdateOption.UPDATE_ALL.flags(), 512); } else { - Reflections.method$Level$setBlock.invoke(level, blockPos, newState.customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, newState.customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); } } } @@ -182,7 +182,7 @@ public class LeavesBlockBehavior extends WaterLoggedBlockBehavior { } Property waterlogged = (Property) block.getProperty("waterlogged"); int actual = distance.possibleValues().get(distance.possibleValues().size() - 1); - return new LeavesBlockBehavior(actual, distance, persistent, waterlogged); + return new LeavesBlockBehavior(block, actual, distance, persistent, waterlogged); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/OnLiquidBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/OnLiquidBlockBehavior.java index cb5934a2e..dda596013 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/OnLiquidBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/OnLiquidBlockBehavior.java @@ -16,8 +16,8 @@ public class OnLiquidBlockBehavior extends BushBlockBehavior { private final boolean onWater; private final boolean onLava; - public OnLiquidBlockBehavior(boolean onWater, boolean onLava) { - super(List.of(), Set.of(), Set.of()); + public OnLiquidBlockBehavior(CustomBlock block, boolean onWater, boolean onLava) { + super(block, List.of(), Set.of(), Set.of()); this.onWater = onWater; this.onLava = onLava; } @@ -34,7 +34,7 @@ public class OnLiquidBlockBehavior extends BushBlockBehavior { @Override public BlockBehavior create(CustomBlock block, Map arguments) { List liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-type", List.of("water"))); - return new OnLiquidBlockBehavior(liquidTypes.contains("water"), liquidTypes.contains("lava")); + return new OnLiquidBlockBehavior(block, liquidTypes.contains("water"), liquidTypes.contains("lava")); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java index 04df34dc8..e985c3d24 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java @@ -31,8 +31,8 @@ public class SaplingBlockBehavior extends BushBlockBehavior { private final double boneMealSuccessChance; private final float growSpeed; - public SaplingBlockBehavior(Key feature, Property stageProperty, List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn, double boneMealSuccessChance, float growSpeed) { - super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn); + public SaplingBlockBehavior(CustomBlock block, Key feature, Property stageProperty, List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn, double boneMealSuccessChance, float growSpeed) { + super(block, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn); this.feature = feature; this.stageProperty = stageProperty; this.boneMealSuccessChance = boneMealSuccessChance; @@ -79,18 +79,18 @@ public class SaplingBlockBehavior extends BushBlockBehavior { CraftEngine.instance().logger().warn("Configured feature not found: " + treeFeature()); return; } - Object chunkGenerator = Reflections.method$ServerChunkCache$getGenerator.invoke(Reflections.field$ServerLevel$chunkSource.get(world)); + Object chunkGenerator = Reflections.method$ServerChunkCache$getGenerator.invoke(FastNMS.INSTANCE.method$ServerLevel$getChunkSource(world)); Object configuredFeature = Reflections.method$Holder$value.invoke(holder.get()); Object fluidState = Reflections.method$Level$getFluidState.invoke(world, blockPos); Object legacyState = Reflections.method$FluidState$createLegacyBlock.invoke(fluidState); - Reflections.method$Level$setBlock.invoke(world, blockPos, legacyState, UpdateOption.UPDATE_NONE.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, legacyState, UpdateOption.UPDATE_NONE.flags()); if ((boolean) Reflections.method$ConfiguredFeature$place.invoke(configuredFeature, world, chunkGenerator, randomSource, blockPos)) { if (FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, blockPos) == legacyState) { Reflections.method$ServerLevel$sendBlockUpdated.invoke(world, blockPos, blockState, legacyState, 2); } } else { // failed to place, rollback changes - Reflections.method$Level$setBlock.invoke(world, blockPos, blockState, UpdateOption.UPDATE_NONE.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, blockState, UpdateOption.UPDATE_NONE.flags()); } } @@ -150,7 +150,7 @@ public class SaplingBlockBehavior extends BushBlockBehavior { } double boneMealSuccessChance = MiscUtils.getAsDouble(arguments.getOrDefault("bone-meal-success-chance", 0.45)); Tuple, Set, Set> tuple = readTagsAndState(arguments); - return new SaplingBlockBehavior(Key.of(feature), stageProperty, tuple.left(), tuple.mid(), tuple.right(), boneMealSuccessChance, + return new SaplingBlockBehavior(block, Key.of(feature), stageProperty, tuple.left(), tuple.mid(), tuple.right(), boneMealSuccessChance, MiscUtils.getAsFloat(arguments.getOrDefault("grow-speed", 1.0 / 7.0))); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StrippableBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StrippableBlockBehavior.java index 6d0429c37..6a5d4ee7f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StrippableBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StrippableBlockBehavior.java @@ -1,18 +1,18 @@ package net.momirealms.craftengine.bukkit.block.behavior; import net.momirealms.craftengine.core.block.CustomBlock; -import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.shared.block.BlockBehavior; import java.util.Map; -public class StrippableBlockBehavior extends AbstractBlockBehavior { +public class StrippableBlockBehavior extends BukkitBlockBehavior { public static final Factory FACTORY = new Factory(); private final Key stripped; - public StrippableBlockBehavior(Key stripped) { + public StrippableBlockBehavior(CustomBlock block, Key stripped) { + super(block); this.stripped = stripped; } @@ -28,7 +28,7 @@ public class StrippableBlockBehavior extends AbstractBlockBehavior { if (stripped == null) { throw new IllegalArgumentException("stripped is null"); } - return new StrippableBlockBehavior(Key.of(stripped)); + return new StrippableBlockBehavior(block, Key.of(stripped)); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SugarCaneBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SugarCaneBlockBehavior.java index c8f0dfc67..7fe72f9f6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SugarCaneBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SugarCaneBlockBehavior.java @@ -38,17 +38,15 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior { private final boolean nearLava; private final IntegerProperty ageProperty; private final float growSpeed; - private final CustomBlock customBlock; public SugarCaneBlockBehavior(CustomBlock customBlock, List tagsCanSurviveOn, Set blocksCansSurviveOn, Set customBlocksCansSurviveOn, Property ageProperty, int maxHeight, boolean nearWater, boolean nearLava, float growSpeed) { - super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn); + super(customBlock, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn); this.nearWater = nearWater; this.nearLava = nearLava; this.maxHeight = maxHeight; this.ageProperty = (IntegerProperty) ageProperty; this.growSpeed = growSpeed; - this.customBlock = customBlock; } @Override @@ -120,13 +118,13 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior { if (age >= this.ageProperty.max || RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) { Object abovePos = LocationUtils.above(blockPos); if (VersionHelper.isVersionNewerThan1_21_5()) { - Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, customBlock.defaultState().customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); + Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, super.customBlock.defaultState().customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); } else { - Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, customBlock.defaultState().customBlockState().handle()); + Reflections.method$CraftEventFactory$handleBlockGrowEvent.invoke(null, level, abovePos, super.customBlock.defaultState().customBlockState().handle()); } - Reflections.method$Level$setBlock.invoke(level, blockPos, currentState.with(this.ageProperty, this.ageProperty.min).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, currentState.with(this.ageProperty, this.ageProperty.min).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags()); } else if (RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) { - Reflections.method$Level$setBlock.invoke(level, blockPos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_NONE.flags()); } } } @@ -143,7 +141,7 @@ public class SugarCaneBlockBehavior extends BushBlockBehavior { // 如果下方是同种方块 if (!BlockStateUtils.isVanillaBlock(id)) { ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id); - if (immutableBlockState.owner().value() == this.customBlock) { + if (immutableBlockState.owner().value() == super.customBlock) { return true; } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java index 401c56bc0..ae874f173 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java @@ -1,7 +1,6 @@ package net.momirealms.craftengine.bukkit.block.behavior; import net.momirealms.craftengine.core.block.CustomBlock; -import net.momirealms.craftengine.core.block.behavior.AbstractBlockBehavior; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.shared.block.BlockBehavior; @@ -9,12 +8,13 @@ import org.jetbrains.annotations.Nullable; import java.util.Map; -public class WaterLoggedBlockBehavior extends AbstractBlockBehavior { +public class WaterLoggedBlockBehavior extends BukkitBlockBehavior { public static final Factory FACTORY = new Factory(); @Nullable private final Property waterloggedProperty; - public WaterLoggedBlockBehavior(@Nullable Property waterloggedProperty) { + public WaterLoggedBlockBehavior(CustomBlock block, @Nullable Property waterloggedProperty) { + super(block); this.waterloggedProperty = waterloggedProperty; } @@ -82,7 +82,7 @@ public class WaterLoggedBlockBehavior extends AbstractBlockBehavior { @Override public BlockBehavior create(CustomBlock block, Map arguments) { Property waterlogged = (Property) block.getProperty("waterlogged"); - return new WaterLoggedBlockBehavior(waterlogged); + return new WaterLoggedBlockBehavior(block, waterlogged); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java index 36d76dec5..668c35060 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java @@ -112,9 +112,9 @@ public class LoadedFurniture { }); } try { - this.cachedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(packets); + this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets); if (this.minimized) { - this.cachedMinimizedSpawnPacket = Reflections.constructor$ClientboundBundlePacket.newInstance(minimizedPackets); + this.cachedMinimizedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(minimizedPackets); } } catch (Exception e) { CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id, e); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java index e19d88049..511a3845b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java @@ -150,7 +150,7 @@ public class BlockItemBehavior extends ItemBehavior { Object blockState = state.customBlockState().handle(); Object blockPos = LocationUtils.toBlockPos(context.getClickedPos()); Object voxelShape = Reflections.method$CollisionContext$of.invoke(null, player); - Object world = Reflections.field$CraftWorld$ServerLevel.get(context.getLevel().platformWorld()); + Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel((World) context.getLevel().platformWorld()); boolean defaultReturn = ((!this.checkStatePlacement() || (boolean) Reflections.method$BlockStateBase$canSurvive.invoke(blockState, world, blockPos)) && (boolean) Reflections.method$ServerLevel$checkEntityCollision.invoke(world, blockState, player, voxelShape, blockPos, true)); Block block = FastNMS.INSTANCE.method$CraftBlock$at(world, blockPos); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index c513dc9b1..2a2f64bc8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.item.recipe; import com.destroystokyo.paper.event.inventory.PrepareResultEvent; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; @@ -347,7 +348,7 @@ public class RecipeEventListener implements Listener { BukkitRecipeManager.minecraftRecipeManager(), Reflections.instance$RecipeType$CAMPFIRE_COOKING, Reflections.constructor$SingleRecipeInput.newInstance(Reflections.method$CraftItemStack$asNMSCopy.invoke(null, itemStack)), - Reflections.field$CraftWorld$ServerLevel.get(event.getPlayer().getWorld()), + FastNMS.INSTANCE.field$CraftWorld$ServerLevel(event.getPlayer().getWorld()), null ); if (optionalMCRecipe.isEmpty()) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java index 608c891bc..688e8743b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/TestCommand.java @@ -1,9 +1,6 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; -import net.momirealms.craftengine.bukkit.nms.CollisionEntity; -import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; -import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; import org.bukkit.Location; @@ -25,11 +22,7 @@ public class TestCommand extends BukkitCommandFeature { Player player = context.sender(); Location location = player.getLocation(); try { - Object level = Reflections.field$CraftWorld$ServerLevel.get(player.getWorld()); - Object aabb = FastNMS.INSTANCE.constructor$AABB(location.getBlockX(), location.getBlockY(), location.getBlockZ(), - location.getBlockX() + 1, location.getBlockY() + 1, location.getBlockZ() + 1); - CollisionEntity nmsEntity = FastNMS.INSTANCE.createCollisionEntity(level, aabb, location.getBlockX() + 0.5, location.getBlockY(), location.getBlockZ() + 0.5, false); - FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(level, nmsEntity); + } catch (Exception e) { e.printStackTrace(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java index a2656ed50..5be2a0711 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java @@ -174,6 +174,12 @@ public class BukkitInjector { // getShape .method(ElementMatchers.is(Reflections.method$BlockBehaviour$getShape)) .intercept(MethodDelegation.to(GetShapeInterceptor.INSTANCE)) + // mirror + .method(ElementMatchers.is(Reflections.method$BlockBehaviour$mirror)) + .intercept(MethodDelegation.to(MirrorInterceptor.INSTANCE)) + // rotate + .method(ElementMatchers.is(Reflections.method$BlockBehaviour$rotate)) + .intercept(MethodDelegation.to(RotateInterceptor.INSTANCE)) // tick .method(ElementMatchers.is(Reflections.method$BlockBehaviour$tick)) .intercept(MethodDelegation.to(TickInterceptor.INSTANCE)) @@ -711,8 +717,8 @@ public class BukkitInjector { int id = (int) Reflections.field$Direction$data3d.get(direction); // Y axis if (id == 0 || id == 1) { - Object chunkSource = Reflections.field$ServerLevel$chunkSource.get(serverLevel); - Reflections.method$ServerChunkCache$blockChanged.invoke(chunkSource, blockPos); + Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel); + FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, blockPos); if (id == 1) { NoteBlockChainUpdateUtils.noteBlockChainUpdate(serverLevel, chunkSource, Reflections.instance$Direction$DOWN, blockPos, 0); } else { @@ -736,6 +742,36 @@ public class BukkitInjector { } } + public static class MirrorInterceptor { + public static final MirrorInterceptor INSTANCE = new MirrorInterceptor(); + + @RuntimeType + public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) throws Exception { + ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); + try { + return holder.value().mirror(thisObj, args, superMethod); + } catch (Exception e) { + CraftEngine.instance().logger().severe("Failed to run mirror", e); + return superMethod.call(); + } + } + } + + public static class RotateInterceptor { + public static final RotateInterceptor INSTANCE = new RotateInterceptor(); + + @RuntimeType + public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) throws Exception { + ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); + try { + return holder.value().rotate(thisObj, args, superMethod); + } catch (Exception e) { + CraftEngine.instance().logger().severe("Failed to run rotate", e); + return superMethod.call(); + } + } + } + public static class RandomTickInterceptor { public static final RandomTickInterceptor INSTANCE = new RandomTickInterceptor(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index c87622e84..d55ca3054 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -92,31 +92,19 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes } this.registerConsumers(); this.packetsConsumer = ((serverPlayer, packets) -> { - try { - Object bundle = Reflections.constructor$ClientboundBundlePacket.newInstance(packets); - Reflections.method$ServerGamePacketListenerImpl$sendPacket.invoke( - Reflections.field$ServerPlayer$connection.get(serverPlayer), bundle); - } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to create bundle packet", e); - } + Object bundle = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets); + FastNMS.INSTANCE.sendPacket(serverPlayer, bundle); }); - this.delayedPacketConsumer = (serverPlayer, packet) -> { - try { - Reflections.method$ServerGamePacketListenerImpl$sendPacket.invoke( - Reflections.field$ServerPlayer$connection.get(serverPlayer), packet); - } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to invoke send packet", e); - } - }; + this.delayedPacketConsumer = FastNMS.INSTANCE::sendPacket; this.immediatePacketConsumer = (serverPlayer, packet) -> { try { - Reflections.method$Connection$sendPacketImmediate.invoke(Reflections.field$ServerCommonPacketListenerImpl$connection.get(Reflections.field$ServerPlayer$connection.get(serverPlayer)), packet, null, true); + Reflections.method$Connection$sendPacketImmediate.invoke(FastNMS.INSTANCE.field$Player$connection$connection(serverPlayer), packet, null, true); } catch (ReflectiveOperationException e) { plugin.logger().warn("Failed to invoke send packet", e); } }; this.active = true; - this.hasModelEngine = Bukkit.getPluginManager().getPlugin("ModelEngine") != null; + hasModelEngine = Bukkit.getPluginManager().getPlugin("ModelEngine") != null; instance = this; } @@ -258,17 +246,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes } public Channel getChannel(Player player) { - try { - return (Channel) Reflections.field$Channel.get( - Reflections.field$NetworkManager.get( - Reflections.field$ServerPlayer$connection.get( - FastNMS.INSTANCE.method$CraftPlayer$getHandle(player) - ) - ) - ); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } + return (Channel) FastNMS.INSTANCE.field$Player$connection$connection$channel(FastNMS.INSTANCE.method$CraftPlayer$getHandle(player)); } public void sendPacket(@NotNull Player player, @NotNull Object packet) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 007854ac8..45121029f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -291,7 +291,7 @@ public class PacketConsumers { private static void handlePlayerActionPacketOnMainThread(BukkitServerPlayer player, World world, BlockPos pos, Object packet) throws Exception { Object action = Reflections.field$ServerboundPlayerActionPacket$action.get(packet); if (action == Reflections.instance$ServerboundPlayerActionPacket$Action$START_DESTROY_BLOCK) { - Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(world); + Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world); Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(serverLevel, LocationUtils.toBlockPos(pos)); int stateId = BlockStateUtils.blockStateToId(blockState); // not a custom block @@ -546,7 +546,7 @@ public class PacketConsumers { }; private static void handlePickItemFromBlockPacketOnMainThread(Player player, Object pos) throws Exception { - Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(player.getWorld()); + Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(player.getWorld()); Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(serverLevel, pos); ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); if (state == null) return; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DirectionUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DirectionUtils.java index 1f587764e..1a2e8be93 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DirectionUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/DirectionUtils.java @@ -40,4 +40,13 @@ public class DirectionUtils { case EAST -> Reflections.instance$Direction$EAST; }; } + + public static Direction fromNMSDirection(Object direction) { + try { + int index = (int) Reflections.method$Direction$ordinal.invoke(direction); + return Direction.values()[index]; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LightUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LightUtils.java index 27bb4e598..7d84c1a83 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LightUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LightUtils.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.util; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.core.plugin.CraftEngine; import org.bukkit.World; @@ -11,30 +12,25 @@ public class LightUtils { private LightUtils() {} - @SuppressWarnings("unchecked") public static void updateChunkLight(World world, Map sectionPosSet) { try { - Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(world); - Object chunkSource = Reflections.field$ServerLevel$chunkSource.get(serverLevel); + Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world); + Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel); for (Map.Entry entry : sectionPosSet.entrySet()) { long chunkKey = entry.getKey(); - Object chunkHolder = Reflections.method$ServerChunkCache$getVisibleChunkIfPresent.invoke(chunkSource, chunkKey); + Object chunkHolder = FastNMS.INSTANCE.method$ServerChunkCache$getVisibleChunkIfPresent(chunkSource, chunkKey); if (chunkHolder == null) continue; - List players; - if (Reflections.method$ChunkHolder$getPlayers != null) { - players = (List) Reflections.method$ChunkHolder$getPlayers.invoke(chunkHolder, false); - } else { - Object chunkHolder$PlayerProvider = Reflections.field$ChunkHolder$playerProvider.get(chunkHolder); - players = (List) Reflections.method$ChunkHolder$PlayerProvider$getPlayers.invoke(chunkHolder$PlayerProvider, false); - } + List players = FastNMS.INSTANCE.method$ChunkHolder$getPlayers(chunkHolder); if (players.isEmpty()) continue; Object lightEngine = Reflections.field$ChunkHolder$lightEngine.get(chunkHolder); BitSet blockChangedLightSectionFilter = (BitSet) Reflections.field$ChunkHolder$blockChangedLightSectionFilter.get(chunkHolder); blockChangedLightSectionFilter.or(entry.getValue()); BitSet skyChangedLightSectionFilter = (BitSet) Reflections.field$ChunkHolder$skyChangedLightSectionFilter.get(chunkHolder); - Object chunkPos = Reflections.constructor$ChunkPos.newInstance((int) chunkKey, (int) (chunkKey >> 32)); - Object lightPacket = Reflections.constructor$ClientboundLightUpdatePacket.newInstance(chunkPos, lightEngine, skyChangedLightSectionFilter, blockChangedLightSectionFilter); - Reflections.method$ChunkHolder$broadcast.invoke(chunkHolder, players, lightPacket); + Object chunkPos = FastNMS.INSTANCE.constructor$ChunkPos((int) chunkKey, (int) (chunkKey >> 32)); + Object lightPacket = FastNMS.INSTANCE.constructor$ClientboundLightUpdatePacket(chunkPos, lightEngine, skyChangedLightSectionFilter, blockChangedLightSectionFilter); + for (Object player : players) { + FastNMS.INSTANCE.sendPacket(player, lightPacket); + } blockChangedLightSectionFilter.clear(); skyChangedLightSectionFilter.clear(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/MirrorUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/MirrorUtils.java new file mode 100644 index 000000000..1aae07bd1 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/MirrorUtils.java @@ -0,0 +1,31 @@ +package net.momirealms.craftengine.bukkit.util; + +import net.momirealms.craftengine.core.util.Mirror; + +public class MirrorUtils { + + private MirrorUtils() {} + + public static Mirror fromNMSMirror(Object mirror) { + try { + int index = (int) Reflections.method$Mirror$ordinal.invoke(mirror); + return Mirror.values()[index]; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + public static Object toNMSMirror(Mirror mirror) { + switch (mirror) { + case FRONT_BACK -> { + return Reflections.instance$Mirror$FRONT_BACK; + } + case LEFT_RIGHT -> { + return Reflections.instance$Mirror$LEFT_RIGHT; + } + default -> { + return Reflections.instance$Mirror$NONE; + } + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/NoteBlockChainUpdateUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/NoteBlockChainUpdateUtils.java index 5b4f28f4a..5127e9916 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/NoteBlockChainUpdateUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/NoteBlockChainUpdateUtils.java @@ -12,7 +12,7 @@ public class NoteBlockChainUpdateUtils { Object relativePos = Reflections.method$BlockPos$relative.invoke(blockPos, direction); Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, relativePos); if (BlockStateUtils.isClientSideNoteBlock(state)) { - Reflections.method$ServerChunkCache$blockChanged.invoke(chunkSource, relativePos); + FastNMS.INSTANCE.method$ServerChunkCache$blockChanged(chunkSource, relativePos); noteBlockChainUpdate(level, chunkSource, direction, relativePos, times+1); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index 860171138..615964127 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -421,9 +421,9 @@ public class Reflections { ) ); - public static final Constructor constructor$ClientboundBundlePacket = requireNonNull( - ReflectionUtils.getConstructor(clazz$ClientboundBundlePacket, Iterable.class) - ); +// public static final Constructor constructor$ClientboundBundlePacket = requireNonNull( +// ReflectionUtils.getConstructor(clazz$ClientboundBundlePacket, Iterable.class) +// ); public static final Class clazz$Packet = requireNonNull( ReflectionUtils.getClazz( @@ -494,12 +494,6 @@ public class Reflections { ) ); - public static final Field field$NetworkManager = requireNonNull( - VersionHelper.isVersionNewerThan1_20_2() ? - ReflectionUtils.getDeclaredField(clazz$ServerGamePacketListenerImpl.getSuperclass(), clazz$Connection, 0) : - ReflectionUtils.getDeclaredField(clazz$ServerGamePacketListenerImpl, clazz$Connection, 0) - ); - public static final Field field$Channel = requireNonNull( ReflectionUtils.getDeclaredField( clazz$Connection, Channel.class, 0 @@ -1053,11 +1047,12 @@ public class Reflections { ) ); - public static final Field field$CraftWorld$ServerLevel = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$CraftWorld, clazz$ServerLevel, 0 - ) - ); +// @Deprecated +// public static final Field field$CraftWorld$ServerLevel = requireNonNull( +// ReflectionUtils.getDeclaredField( +// clazz$CraftWorld, clazz$ServerLevel, 0 +// ) +// ); public static final Method method$ServerLevel$getNoiseBiome = requireNonNull( ReflectionUtils.getMethod( @@ -1806,17 +1801,18 @@ public class Reflections { ) ); - public static final Field field$ServerLevel$chunkSource = requireNonNull( - ReflectionUtils.getDeclaredField( - clazz$ServerLevel, clazz$ServerChunkCache, 0 - ) - ); + @Deprecated +// public static final Field field$ServerLevel$chunkSource = requireNonNull( +// ReflectionUtils.getDeclaredField( +// clazz$ServerLevel, clazz$ServerChunkCache, 0 +// ) +// ); - public static final Method method$ServerChunkCache$blockChanged = requireNonNull( - ReflectionUtils.getMethod( - clazz$ServerChunkCache, void.class, clazz$BlockPos - ) - ); +// public static final Method method$ServerChunkCache$blockChanged = requireNonNull( +// ReflectionUtils.getMethod( +// clazz$ServerChunkCache, void.class, clazz$BlockPos +// ) +// ); // public static final Method method$ServerChunkCache$getChunkAtIfLoadedMainThread = requireNonNull( // ReflectionUtils.getMethod( @@ -2644,6 +2640,7 @@ public class Reflections { ) ); + @Deprecated public static final Constructor constructor$ChunkPos = requireNonNull( ReflectionUtils.getConstructor( clazz$ChunkPos, int.class, int.class @@ -2695,7 +2692,7 @@ public class Reflections { ) ); - // 1.20 ~ 1.21.4 + // 1.20 ~ 1.21.4 moonrise public static final Method method$ChunkHolder$getPlayers = ReflectionUtils.getMethod( clazz$ChunkHolder, List.class, boolean.class @@ -2725,6 +2722,7 @@ public class Reflections { ) ); + @Deprecated public static final Method method$ServerChunkCache$getVisibleChunkIfPresent = requireNonNull( ReflectionUtils.getDeclaredMethod( clazz$ServerChunkCache, clazz$ChunkHolder, long.class @@ -3577,12 +3575,6 @@ public class Reflections { ) ); - public static final Method method$Level$setBlock = requireNonNull( - ReflectionUtils.getMethod( - clazz$Level, boolean.class, clazz$BlockPos, clazz$BlockState, int.class - ) - ); - public static final Method method$Block$updateFromNeighbourShapes = requireNonNull( ReflectionUtils.getStaticMethod( clazz$Block, clazz$BlockState, clazz$BlockState, clazz$LevelAccessor, clazz$BlockPos @@ -3735,6 +3727,7 @@ public class Reflections { ) ); + @Deprecated public static final Method method$LevelWriter$setBlock = requireNonNull( ReflectionUtils.getMethod( clazz$LevelWriter, boolean.class, clazz$BlockPos, clazz$BlockState, int.class @@ -5963,4 +5956,86 @@ public class Reflections { clazz$ClientboundSetEntityMotionPacket, int.class, 0 ) ); + + public static final Class clazz$Rotation = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.level.block.Rotation"), + BukkitReflectionUtils.assembleMCClass("world.level.block.EnumBlockRotation") + ) + ); + + public static final Method method$Rotation$values = requireNonNull( + ReflectionUtils.getStaticMethod( + clazz$Rotation, clazz$Rotation.arrayType() + ) + ); + + public static final Object instance$Rotation$NONE; + public static final Object instance$Rotation$CLOCKWISE_90; + public static final Object instance$Rotation$CLOCKWISE_180; + public static final Object instance$Rotation$COUNTERCLOCKWISE_90; + + static { + try { + Object[] values = (Object[]) method$Rotation$values.invoke(null); + instance$Rotation$NONE = values[0]; + instance$Rotation$CLOCKWISE_90 = values[1]; + instance$Rotation$CLOCKWISE_180 = values[2]; + instance$Rotation$COUNTERCLOCKWISE_90 = values[3]; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + public static final Method method$Rotation$ordinal = requireNonNull( + ReflectionUtils.getMethod( + clazz$Rotation, int.class, new String[]{"ordinal"} + ) + ); + + public static final Class clazz$Mirror = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.level.block.Mirror"), + BukkitReflectionUtils.assembleMCClass("world.level.block.EnumBlockMirror") + ) + ); + + public static final Method method$Mirror$values = requireNonNull( + ReflectionUtils.getStaticMethod( + clazz$Mirror, clazz$Mirror.arrayType() + ) + ); + + public static final Object instance$Mirror$NONE; + public static final Object instance$Mirror$LEFT_RIGHT; + public static final Object instance$Mirror$FRONT_BACK; + + static { + try { + Object[] values = (Object[]) method$Mirror$values.invoke(null); + instance$Mirror$NONE = values[0]; + instance$Mirror$LEFT_RIGHT = values[1]; + instance$Mirror$FRONT_BACK = values[2]; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + public static final Method method$Mirror$ordinal = requireNonNull( + ReflectionUtils.getMethod( + clazz$Mirror, int.class, new String[]{"ordinal"} + ) + ); + + public static final Method method$BlockBehaviour$rotate = requireNonNull( + ReflectionUtils.getDeclaredMethod( + clazz$BlockBehaviour, clazz$BlockState, clazz$BlockState, clazz$Rotation + ) + ); + + public static final Method method$BlockBehaviour$mirror = requireNonNull( + ReflectionUtils.getDeclaredMethod( + clazz$BlockBehaviour, clazz$BlockState, clazz$BlockState, clazz$Mirror + ) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/RotationUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/RotationUtils.java new file mode 100644 index 000000000..95cd0b40c --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/RotationUtils.java @@ -0,0 +1,34 @@ +package net.momirealms.craftengine.bukkit.util; + +import net.momirealms.craftengine.core.util.Rotation; + +public class RotationUtils { + + private RotationUtils() {} + + public static Rotation fromNMSRotation(Object rotation) { + try { + int index = (int) Reflections.method$Rotation$ordinal.invoke(rotation); + return Rotation.values()[index]; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + public static Object toNMSRotation(Rotation rotation) { + switch (rotation) { + case CLOCKWISE_90 -> { + return Reflections.instance$Rotation$CLOCKWISE_90; + } + case CLOCKWISE_180 -> { + return Reflections.instance$Rotation$CLOCKWISE_180; + } + case COUNTERCLOCKWISE_90 -> { + return Reflections.instance$Rotation$COUNTERCLOCKWISE_90; + } + default -> { + return Reflections.instance$Rotation$NONE; + } + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java index 89192c5ac..5e6aa6235 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorld.java @@ -1,8 +1,8 @@ package net.momirealms.craftengine.bukkit.world; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.util.EntityUtils; import net.momirealms.craftengine.bukkit.util.ItemUtils; -import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; @@ -36,7 +36,7 @@ public class BukkitWorld implements World { @Override public Object serverWorld() { try { - return Reflections.field$CraftWorld$ServerLevel.get(platformWorld()); + return FastNMS.INSTANCE.field$CraftWorld$ServerLevel(platformWorld()); } catch (Exception e) { throw new RuntimeException("Failed to get server world", e); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldBlock.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldBlock.java index c7840ffb8..c1addb16d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldBlock.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitWorldBlock.java @@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.world; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.util.BlockStateUtils; import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.bukkit.util.Reflections; @@ -51,7 +52,7 @@ public class BukkitWorldBlock implements WorldBlock { public boolean isWaterSource(BlockPlaceContext blockPlaceContext) { try { Location location = block.getLocation(); - Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(block.getWorld()); + Object serverLevel = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld()); Object fluidData = Reflections.method$Level$getFluidState.invoke(serverLevel, LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ())); if (fluidData == null) return false; return (boolean) Reflections.method$FluidState$isSource.invoke(fluidData); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/AbstractBlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/AbstractBlockBehavior.java index 948700454..ae8d38e1e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/AbstractBlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/AbstractBlockBehavior.java @@ -1,10 +1,16 @@ package net.momirealms.craftengine.core.block.behavior; +import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.shared.block.BlockBehavior; public abstract class AbstractBlockBehavior extends BlockBehavior { + protected CustomBlock customBlock; + + public AbstractBlockBehavior(CustomBlock customBlock) { + this.customBlock = customBlock; + } public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) { return state; diff --git a/gradle.properties b/gradle.properties index cc5ca5e33..b7ec30623 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,7 +49,7 @@ mojang_brigadier_version=1.0.18 byte_buddy_version=1.15.11 snake_yaml_version=2.3 anti_grief_version=0.13 -nms_helper_version=0.29 +nms_helper_version=0.32 # Ignite Dependencies mixinextras_version=0.4.1 mixin_version=0.15.2+mixin.0.8.7 diff --git a/server-mod/src/main/java/net/momirealms/craftengine/mod/CraftEngineBlock.java b/server-mod/src/main/java/net/momirealms/craftengine/mod/CraftEngineBlock.java index 54effc4b0..f7d481ee7 100644 --- a/server-mod/src/main/java/net/momirealms/craftengine/mod/CraftEngineBlock.java +++ b/server-mod/src/main/java/net/momirealms/craftengine/mod/CraftEngineBlock.java @@ -10,10 +10,7 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.ScheduledTickAccess; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.BonemealableBlock; -import net.minecraft.world.level.block.Fallable; +import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; @@ -68,10 +65,30 @@ public class CraftEngineBlock } } + @Override + protected @NotNull BlockState rotate(@NotNull BlockState state, @NotNull Rotation rotation) { + try { + return (BlockState) this.behaviorHolder.value().rotate(this, new Object[]{state, rotation}, () -> super.rotate(state, rotation)); + } catch (Exception e) { + e.printStackTrace(); + return super.rotate(state, rotation); + } + } + + @Override + protected @NotNull BlockState mirror(@NotNull BlockState state, @NotNull Mirror mirror) { + try { + return (BlockState) this.behaviorHolder.value().mirror(this, new Object[]{state, mirror}, () -> super.mirror(state, mirror)); + } catch (Exception e) { + e.printStackTrace(); + return super.mirror(state, mirror); + } + } + @Override protected void tick(@NotNull BlockState state, @NotNull ServerLevel level, @NotNull BlockPos pos, @NotNull RandomSource random) { try { - behaviorHolder.value().tick(this, new Object[]{state, level, pos, random}, () -> { + this.behaviorHolder.value().tick(this, new Object[]{state, level, pos, random}, () -> { super.tick(state, level, pos, random); return null; }); diff --git a/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java b/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java index 957e207d2..67c22fbd8 100644 --- a/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java +++ b/shared/src/main/java/net/momirealms/craftengine/shared/block/BlockBehavior.java @@ -4,6 +4,14 @@ import java.util.concurrent.Callable; public abstract class BlockBehavior { + public Object rotate(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + return superMethod.call(); + } + + public Object mirror(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + return superMethod.call(); + } + public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { return superMethod.call(); }