From 7da8d75dad85006fadc81dc14ba46daf20f90865 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sat, 28 Jun 2025 03:23:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advancement/BukkitAdvancementManager.java | 2 - .../bukkit/block/BlockEventListener.java | 84 ---------- .../bukkit/block/BukkitCustomBlock.java | 1 - .../AbstractCanSurviveBlockBehavior.java | 54 ++----- .../block/behavior/BukkitBlockBehavior.java | 46 +++--- .../block/behavior/BushBlockBehavior.java | 30 ++-- .../behavior/ConcretePowderBlockBehavior.java | 13 +- .../block/behavior/CropBlockBehavior.java | 63 +++----- .../block/behavior/DoorBlockBehavior.java | 59 +++---- .../block/behavior/FallingBlockBehavior.java | 22 +-- .../behavior/FenceGateBlockBehavior.java | 57 ++++--- .../block/behavior/GrassBlockBehavior.java | 33 ++-- .../block/behavior/LampBlockBehavior.java | 23 ++- .../block/behavior/LeavesBlockBehavior.java | 32 ++-- .../behavior/NearLiquidBlockBehavior.java | 11 +- .../block/behavior/OnLiquidBlockBehavior.java | 11 +- .../behavior/PressurePlateBlockBehavior.java | 36 ++--- .../block/behavior/SaplingBlockBehavior.java | 51 +++--- .../block/behavior/SlabBlockBehavior.java | 23 ++- .../block/behavior/StairsBlockBehavior.java | 147 ++++++------------ .../behavior/SturdyBaseBlockBehavior.java | 7 +- .../block/behavior/TrapDoorBlockBehavior.java | 41 ++--- .../behavior/VerticalCropBlockBehavior.java | 29 ++-- .../furniture/BukkitFurnitureManager.java | 1 - .../projectile/BukkitProjectileManager.java | 11 +- .../command/feature/DebugItemDataCommand.java | 3 - .../plugin/injector/BlockStateGenerator.java | 45 +++++- .../reflection/minecraft/CoreReflections.java | 15 +- .../minecraft/MLootContextParams.java | 47 ++++++ .../plugin/user/BukkitServerPlayer.java | 1 - .../bukkit/util/BlockStateUtils.java | 22 +-- .../craftengine/bukkit/util/ItemUtils.java | 1 - .../bukkit/util/ParticleUtils.java | 2 - .../config/template/TemplateManager.java | 1 - .../craftengine/core/util/SNBTReader.java | 5 +- gradle.properties | 2 +- 36 files changed, 428 insertions(+), 603 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/MLootContextParams.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/advancement/BukkitAdvancementManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/advancement/BukkitAdvancementManager.java index b1b2dc1ed..38ead6b3f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/advancement/BukkitAdvancementManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/advancement/BukkitAdvancementManager.java @@ -1,14 +1,12 @@ package net.momirealms.craftengine.bukkit.advancement; import com.google.gson.JsonElement; -import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.core.advancement.AbstractAdvancementManager; import net.momirealms.craftengine.core.pack.LoadingSequence; import net.momirealms.craftengine.core.pack.Pack; import net.momirealms.craftengine.core.plugin.config.ConfigParser; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; -import net.momirealms.craftengine.core.util.GsonHelper; import net.momirealms.craftengine.core.util.Key; import java.nio.file.Path; 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 af98df75a..88e5a350d 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 @@ -11,7 +11,6 @@ import net.momirealms.craftengine.bukkit.util.*; import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; @@ -24,7 +23,6 @@ import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextPar import net.momirealms.craftengine.core.util.Cancellable; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; -import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldPosition; import org.bukkit.*; import org.bukkit.block.Block; @@ -34,16 +32,13 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.world.GenericGameEvent; import org.bukkit.inventory.ItemStack; -import java.util.List; import java.util.Optional; public class BlockEventListener implements Listener { @@ -179,36 +174,8 @@ public class BlockEventListener implements Listener { return; } - // handle waterlogged blocks - @SuppressWarnings("unchecked") - Property waterloggedProperty = (Property) state.owner().value().getProperty("waterlogged"); - if (waterloggedProperty != null) { - boolean waterlogged = state.get(waterloggedProperty); - if (waterlogged) { - location.getWorld().setBlockData(location, Material.WATER.createBlockData()); - } - } - // play sound world.playBlockSound(position, state.sounds().breakSound()); - if (player.getGameMode() == GameMode.CREATIVE || !customBreakEvent.dropItems()) { - return; - } - - // do not drop if it's not the correct tool - if (!BlockStateUtils.isCorrectTool(state, itemInHand)) { - return; - } - - // drop items - ContextHolder.Builder lootContext = ContextHolder.builder() - .withParameter(DirectContextParameters.POSITION, position) - .withParameter(DirectContextParameters.PLAYER, serverPlayer) - .withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)) - .withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand); - for (Item item : state.getDrops(lootContext, world, serverPlayer)) { - world.dropItemNaturally(position, item); - } } } else { // override vanilla block loots @@ -254,19 +221,6 @@ public class BlockEventListener implements Listener { Object blockState = BlockStateUtils.blockDataToBlockState(block.getBlockData()); int stateId = BlockStateUtils.blockStateToId(blockState); if (!BlockStateUtils.isVanillaBlock(stateId)) { - // custom blocks - ImmutableBlockState immutableBlockState = this.manager.getImmutableBlockStateUnsafe(stateId); - if (!immutableBlockState.isEmpty()) { - Location location = block.getLocation(); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(block.getWorld()); - WorldPosition position = new WorldPosition(world, location.getBlockX() + 0.5, location.getBlockY() + 0.5, location.getBlockZ() + 0.5); - for (Item item : immutableBlockState.getDrops(ContextHolder.builder() - .withParameter(DirectContextParameters.POSITION, position) - .withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)), world, null)) { - world.dropItemNaturally(position, item); - } - } - } else { // override vanilla block loots this.plugin.vanillaLootManager().getBlockLoot(stateId).ifPresent(it -> { if (it.override()) { @@ -326,44 +280,6 @@ public class BlockEventListener implements Listener { } } - @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) - public void onEntityExplode(EntityExplodeEvent event) { - if (VersionHelper.isOrAbove1_21()) { - if (!ExplosionUtils.isDroppingItems(event)) return; - } - handleExplodeEvent(event.blockList(), new BukkitWorld(event.getEntity().getWorld()), event.getYield()); - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) - public void onBlockExplode(BlockExplodeEvent event) { - if (VersionHelper.isOrAbove1_21()) { - if (!ExplosionUtils.isDroppingItems(event)) return; - } - handleExplodeEvent(event.blockList(), new BukkitWorld(event.getBlock().getWorld()), event.getYield()); - } - - private void handleExplodeEvent(List blocks, net.momirealms.craftengine.core.world.World world, float yield) { - for (int i = blocks.size() - 1; i >= 0; i--) { - Block block = blocks.get(i); - Location location = block.getLocation(); - BlockPos blockPos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - ImmutableBlockState state = this.manager.getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData())); - if (state != null && !state.isEmpty()) { - WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(blockPos)); - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.POSITION, position) - .withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block)); - if (yield < 1f) { - builder.withParameter(DirectContextParameters.EXPLOSION_RADIUS, 1.0f / yield); - } - for (Item item : state.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); - } - world.playBlockSound(position, state.sounds().breakSound()); - } - } - } - @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) public void onBlockPhysics(BlockPhysicsEvent event) { if (!this.enableNoteBlockCheck) return; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java index 0a3deba81..bb53200b7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java @@ -28,7 +28,6 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.Field; import java.util.*; public class BukkitCustomBlock extends AbstractCustomBlock { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/AbstractCanSurviveBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/AbstractCanSurviveBlockBehavior.java index 14b7e086e..c8eab6874 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/AbstractCanSurviveBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/AbstractCanSurviveBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks; import net.momirealms.craftengine.bukkit.util.BlockStateUtils; @@ -8,15 +7,12 @@ import net.momirealms.craftengine.bukkit.util.LocationUtils; 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.item.Item; -import net.momirealms.craftengine.core.plugin.context.ContextHolder; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; -import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldEvents; import net.momirealms.craftengine.core.world.WorldPosition; +import java.util.Optional; import java.util.concurrent.Callable; public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavior { @@ -34,21 +30,15 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio Object level = args[1]; Object blockPos = args[2]; if (!canSurvive(thisBlock, args, () -> true)) { - int stateId = BlockStateUtils.blockStateToId(blockState); - ImmutableBlockState currentState = BukkitBlockManager.instance().getImmutableBlockState(stateId); - if (currentState != null && !currentState.isEmpty() && currentState.owner().value() == this.customBlock) { - // break the crop - FastNMS.INSTANCE.method$Level$removeBlock(level, blockPos, false); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); - WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(LocationUtils.fromBlockPos(blockPos))); - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.POSITION, position); - for (Item item : currentState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); + BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(customState -> { + if (!customState.isEmpty() && customState.owner().value() == this.customBlock) { + FastNMS.INSTANCE.method$Level$removeBlock(level, blockPos, false); + net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); + WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(LocationUtils.fromBlockPos(blockPos))); + world.playBlockSound(position, customState.sounds().breakSound()); + FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId()); } - world.playBlockSound(position, currentState.sounds().breakSound()); - FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId); - } + }); } } @@ -69,19 +59,11 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio @Override public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { - Object level; - Object blockPos; + Object level = args[updateShape$level]; + Object blockPos = args[updateShape$blockPos]; Object state = args[0]; - if (VersionHelper.isOrAbove1_21_2()) { - level = args[1]; - blockPos = args[3]; - } else { - level = args[3]; - blockPos = args[4]; - } - int stateId = BlockStateUtils.blockStateToId(state); - ImmutableBlockState previousState = BukkitBlockManager.instance().getImmutableBlockState(stateId); - if (previousState == null || previousState.isEmpty()) { + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state); + if (optionalCustomState.isEmpty()) { return state; } if (this.delay != 0) { @@ -90,15 +72,11 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio } if (!canSurvive(thisBlock, new Object[] {state, level, blockPos}, () -> true)) { BlockPos pos = LocationUtils.fromBlockPos(blockPos); + ImmutableBlockState customState = optionalCustomState.get(); net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos)); - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.POSITION, position); - for (Item item : previousState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); - } - world.playBlockSound(position, previousState.sounds().breakSound()); - FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId); + world.playBlockSound(position, customState.sounds().breakSound()); + FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId()); return MBlocks.AIR$defaultState; } return state; 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 index dd92dc19c..a094bfd90 100644 --- 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 @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids; @@ -96,9 +95,9 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior { @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])); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]); + if (optionalCustomState.isEmpty()) return args[0]; + return this.mirrorFunction.mirror(thisBlock, optionalCustomState.get(), MirrorUtils.fromNMSMirror(args[1])); } return super.mirror(thisBlock, args, superMethod); } @@ -106,9 +105,9 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior { @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])); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]); + if (optionalCustomState.isEmpty()) return args[0]; + return this.rotateFunction.rotate(thisBlock, optionalCustomState.get(), RotationUtils.fromNMSRotation(args[1])); } return super.rotate(thisBlock, args, superMethod); } @@ -135,12 +134,12 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior { Object blockState = args[pickupBlock$blockState]; Object world = args[pickupBlock$world]; Object pos = args[pickupBlock$pos]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState != null) { - if (immutableBlockState.get(this.waterloggedProperty)) { - FastNMS.INSTANCE.method$LevelWriter$setBlock(world, pos, immutableBlockState.with(this.waterloggedProperty, false).customBlockState().handle(), 3); - return FastNMS.INSTANCE.constructor$ItemStack(MItems.WATER_BUCKET, 1); - } + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return CoreReflections.instance$ItemStack$EMPTY; + ImmutableBlockState immutableBlockState = optionalCustomState.get(); + if (immutableBlockState.get(this.waterloggedProperty)) { + FastNMS.INSTANCE.method$LevelWriter$setBlock(world, pos, immutableBlockState.with(this.waterloggedProperty, false).customBlockState().handle(), 3); + return FastNMS.INSTANCE.constructor$ItemStack(MItems.WATER_BUCKET, 1); } return CoreReflections.instance$ItemStack$EMPTY; } @@ -149,14 +148,14 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior { public boolean placeLiquid(Object thisBlock, Object[] args, Callable superMethod) { if (this.waterloggedProperty == null) return false; Object blockState = args[2]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState != null) { - Object fluidType = FastNMS.INSTANCE.method$FluidState$getType(args[3]); - if (!immutableBlockState.get(this.waterloggedProperty) && fluidType == MFluids.WATER) { - FastNMS.INSTANCE.method$LevelWriter$setBlock(args[0], args[1], immutableBlockState.with(this.waterloggedProperty, true).customBlockState().handle(), 3); - FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[0], args[1], fluidType, 5); - return true; - } + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return false; + ImmutableBlockState immutableBlockState = optionalCustomState.get(); + Object fluidType = FastNMS.INSTANCE.method$FluidState$getType(args[3]); + if (!immutableBlockState.get(this.waterloggedProperty) && fluidType == MFluids.WATER) { + FastNMS.INSTANCE.method$LevelWriter$setBlock(args[0], args[1], immutableBlockState.with(this.waterloggedProperty, true).customBlockState().handle(), 3); + FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[0], args[1], fluidType, 5); + return true; } return false; } @@ -168,4 +167,9 @@ public class BukkitBlockBehavior extends AbstractBlockBehavior { if (this.waterloggedProperty == null) return false; return args[canPlaceLiquid$liquid] == MFluids.WATER; } + + protected static final int updateShape$level = VersionHelper.isOrAbove1_21_2() ? 1 : 3; + protected static final int updateShape$blockPos = VersionHelper.isOrAbove1_21_2() ? 3 : 4; + protected static final int updateShape$neighborState = VersionHelper.isOrAbove1_21_2() ? 6 : 2; + protected static final int updateShape$direction = VersionHelper.isOrAbove1_21_2() ? 4 : 1; } 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 a29878a0f..d244b23e0 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 @@ -1,8 +1,6 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.util.BlockStateUtils; import net.momirealms.craftengine.bukkit.util.BlockTags; import net.momirealms.craftengine.core.block.BlockBehavior; @@ -85,29 +83,27 @@ public class BushBlockBehavior extends AbstractCanSurviveBlockBehavior { return mayPlaceOn(belowState, world, belowPos); } - protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) throws ReflectiveOperationException { + protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) { for (Object tag : this.tagsCanSurviveOn) { - if ((boolean) CoreReflections.method$BlockStateBase$hasTag.invoke(belowState, tag)) { + if (FastNMS.INSTANCE.method$BlockStateBase$is(belowState, tag)) { return !this.blacklistMode; } } - int id = BlockStateUtils.blockStateToId(belowState); - if (BlockStateUtils.isVanillaBlock(id)) { + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState); + if (optionalCustomState.isEmpty()) { if (!this.blockStatesCanSurviveOn.isEmpty() && this.blockStatesCanSurviveOn.contains(belowState)) { return !this.blacklistMode; } } else { - ImmutableBlockState belowCustomState = BukkitBlockManager.instance().getImmutableBlockState(id); - if (belowCustomState != null && !belowCustomState.isEmpty()) { - if (belowCustomState.owner().value() == super.customBlock) { - return this.stackable; - } - if (this.customBlocksCansSurviveOn.contains(belowCustomState.owner().value().id().toString())) { - return !this.blacklistMode; - } - if (this.customBlocksCansSurviveOn.contains(belowCustomState.toString())) { - return !this.blacklistMode; - } + ImmutableBlockState belowCustomState = optionalCustomState.get(); + if (belowCustomState.owner().value() == super.customBlock) { + return this.stackable; + } + if (this.customBlocksCansSurviveOn.contains(belowCustomState.owner().value().id().toString())) { + return !this.blacklistMode; + } + if (this.customBlocksCansSurviveOn.contains(belowCustomState.toString())) { + return !this.blacklistMode; } } return this.blacklistMode; 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 cb7151555..f1dc2529e 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 @@ -16,7 +16,6 @@ import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; -import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.block.BlockState; import org.bukkit.event.block.BlockFormEvent; @@ -94,17 +93,11 @@ public class ConcretePowderBlockBehavior extends BukkitBlockBehavior { } } + @SuppressWarnings("UnstableApiUsage") @Override public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { - Object level; - Object pos; - if (VersionHelper.isOrAbove1_21_2()) { - level = args[1]; - pos = args[3]; - } else { - level = args[3]; - pos = args[4]; - } + Object level = args[updateShape$level]; + Object pos = args[updateShape$blockPos]; if (touchesLiquid(level, pos)) { if (!CoreReflections.clazz$Level.isInstance(level)) { return getDefaultBlockState(); 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 16765f6e4..433423e5c 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 @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.util.BlockStateUtils; @@ -18,7 +17,6 @@ import net.momirealms.craftengine.core.entity.player.InteractionResult; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.item.context.UseOnContext; -import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.SimpleContext; import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; @@ -33,6 +31,7 @@ import org.bukkit.World; import java.lang.reflect.InvocationTargetException; import java.util.Map; +import java.util.Optional; import java.util.concurrent.Callable; public class CropBlockBehavior extends BukkitBlockBehavior { @@ -90,13 +89,12 @@ public class CropBlockBehavior extends BukkitBlockBehavior { Object level = args[1]; Object pos = args[2]; if (getRawBrightness(level, pos) >= this.minGrowLight) { - ImmutableBlockState currentState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state)); - if (currentState != null && !currentState.isEmpty()) { - int age = this.getAge(currentState); + BlockStateUtils.getOptionalCustomBlockState(state).ifPresent(customState -> { + int age = this.getAge(customState); if (age < this.ageProperty.max && RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) { - FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, currentState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, customState.with(this.ageProperty, age + 1).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); } - } + }); } } @@ -116,12 +114,8 @@ public class CropBlockBehavior extends BukkitBlockBehavior { public boolean isValidBoneMealTarget(Object thisBlock, Object[] args) { if (!this.isBoneMealTarget) return false; Object state = args[2]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state)); - if (immutableBlockState != null && !immutableBlockState.isEmpty()) { - return getAge(immutableBlockState) != this.ageProperty.max; - } else { - return false; - } + Optional optionalState = BlockStateUtils.getOptionalCustomBlockState(state); + return optionalState.filter(immutableBlockState -> getAge(immutableBlockState) != this.ageProperty.max).isPresent(); } @Override @@ -137,20 +131,15 @@ public class CropBlockBehavior extends BukkitBlockBehavior { if (isMaxAge(state)) return InteractionResult.PASS; boolean sendSwing = false; - try { - Object visualState = state.vanillaBlockState().handle(); - Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState); - if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { - boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState); - if (!is) { - sendSwing = true; - } - } else { + Object visualState = state.vanillaBlockState().handle(); + Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState); + if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { + boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState); + if (!is) { sendSwing = true; } - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to check visual state bone meal state", e); - return InteractionResult.FAIL; + } else { + sendSwing = true; } if (sendSwing) { context.getPlayer().swingHand(context.getHand()); @@ -158,14 +147,15 @@ public class CropBlockBehavior extends BukkitBlockBehavior { return InteractionResult.SUCCESS; } - private void performBoneMeal(Object level, Object pos, Object state) throws InvocationTargetException, IllegalAccessException { - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) { + private void performBoneMeal(Object level, Object pos, Object state) { + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state); + if (optionalCustomState.isEmpty()) { return; } + ImmutableBlockState customState = optionalCustomState.get(); boolean sendParticles = false; - Object visualState = immutableBlockState.vanillaBlockState().handle(); - Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState); + Object visualState = customState.vanillaBlockState().handle(); + Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState); if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, level, pos, visualState); if (!is) { @@ -174,24 +164,21 @@ public class CropBlockBehavior extends BukkitBlockBehavior { } else { sendParticles = true; } - World world = FastNMS.INSTANCE.method$Level$getCraftWorld(level); int x = FastNMS.INSTANCE.field$Vec3i$x(pos); int y = FastNMS.INSTANCE.field$Vec3i$y(pos); int z = FastNMS.INSTANCE.field$Vec3i$z(pos); - int i = this.getAge(immutableBlockState) + this.boneMealBonus.getInt( - SimpleContext.of( - ContextHolder.builder() - .withParameter(DirectContextParameters.CUSTOM_BLOCK_STATE, immutableBlockState) + int i = this.getAge(customState) + this.boneMealBonus.getInt( + SimpleContext.of(ContextHolder.builder() + .withParameter(DirectContextParameters.CUSTOM_BLOCK_STATE, customState) .withParameter(DirectContextParameters.POSITION, new WorldPosition(new BukkitWorld(world), Vec3d.atCenterOf(new Vec3i(x, y, z)))) - .build() - ) + .build()) ); int maxAge = this.ageProperty.max; if (i > maxAge) { i = maxAge; } - FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, immutableBlockState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, pos, customState.with(this.ageProperty, i).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); if (sendParticles) { world.spawnParticle(ParticleUtils.HAPPY_VILLAGER, x + 0.5, y + 0.5, z + 0.5, 15, 0.25, 0.25, 0.25); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoorBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoorBlockBehavior.java index 2fd035163..b4370634c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoorBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoorBlockBehavior.java @@ -18,11 +18,8 @@ import net.momirealms.craftengine.core.block.state.properties.DoorHinge; import net.momirealms.craftengine.core.block.state.properties.DoubleBlockHalf; import net.momirealms.craftengine.core.entity.player.InteractionResult; import net.momirealms.craftengine.core.entity.player.Player; -import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.item.context.UseOnContext; -import net.momirealms.craftengine.core.plugin.context.ContextHolder; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.HorizontalDirection; @@ -83,20 +80,15 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { @Override public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { - Object level; - Object blockPos; + Object level = args[updateShape$level]; + Object blockPos = args[updateShape$blockPos]; Object blockState = args[0]; - if (VersionHelper.isOrAbove1_21_2()) { - level = args[1]; - blockPos = args[3]; - } else { - level = args[3]; - blockPos = args[4]; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) { + return blockState; } - int stateId = BlockStateUtils.blockStateToId(blockState); - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return blockState; - DoubleBlockHalf half = immutableBlockState.get(this.halfProperty); + ImmutableBlockState customState = optionalCustomState.get(); + DoubleBlockHalf half = customState.get(this.halfProperty); Object direction = VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]; if (DirectionUtils.isYAxis(direction) && half == DoubleBlockHalf.LOWER == (direction == CoreReflections.instance$Direction$UP)) { ImmutableBlockState neighborState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(VersionHelper.isOrAbove1_21_2() ? args[6] : args[2])); @@ -117,13 +109,8 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { BlockPos pos = LocationUtils.fromBlockPos(blockPos); net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos)); - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.POSITION, position); - for (Item item : immutableBlockState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); - } - world.playBlockSound(position, immutableBlockState.sounds().breakSound()); - FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId); + world.playBlockSound(position, customState.sounds().breakSound()); + FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId()); return MBlocks.AIR$defaultState; } return blockState; @@ -234,7 +221,7 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { } @Override - public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) { + public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) { if (!this.canOpenWithHand) { return InteractionResult.PASS; } @@ -260,18 +247,19 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { Object blockPos = args[2]; Object level = args[1]; Object blockState = args[0]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return; - Object anotherHalfPos = immutableBlockState.get(this.halfProperty) == DoubleBlockHalf.LOWER ? LocationUtils.above(blockPos) : LocationUtils.below(blockPos); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return; + ImmutableBlockState customState = optionalCustomState.get(); + Object anotherHalfPos = customState.get(this.halfProperty) == DoubleBlockHalf.LOWER ? LocationUtils.above(blockPos) : LocationUtils.below(blockPos); Block bukkitBlock = FastNMS.INSTANCE.method$CraftBlock$at(level, blockPos); Block anotherBukkitBlock = FastNMS.INSTANCE.method$CraftBlock$at(level, anotherHalfPos); int power = Math.max(bukkitBlock.getBlockPower(), anotherBukkitBlock.getBlockPower()); - int oldPower = immutableBlockState.get(this.poweredProperty) ? 15 : 0; + int oldPower = customState.get(this.poweredProperty) ? 15 : 0; if (oldPower == 0 ^ power == 0) { BlockRedstoneEvent event = new BlockRedstoneEvent(bukkitBlock, oldPower, power); Bukkit.getPluginManager().callEvent(event); boolean flag = event.getNewCurrent() > 0; - if (flag != immutableBlockState.get(this.openProperty)) { + if (flag != customState.get(this.openProperty)) { org.bukkit.World world = FastNMS.INSTANCE.method$Level$getCraftWorld(level); world.sendGameEvent(null, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, new Vector(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ())); SoundData soundData = flag ? this.openSound : this.closeSound; @@ -282,25 +270,24 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { ); } } - FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, immutableBlockState.with(this.poweredProperty, flag).with(this.openProperty, flag).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, customState.with(this.poweredProperty, flag).with(this.openProperty, flag).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS); } } @Override public boolean canSurvive(Object thisBlock, Object state, Object world, Object blockPos) throws Exception { - ImmutableBlockState customBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state)); - if (customBlockState == null || customBlockState.isEmpty()) return false; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state); + if (optionalCustomState.isEmpty()) return false; int x = FastNMS.INSTANCE.field$Vec3i$x(blockPos); int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos) - 1; int z = FastNMS.INSTANCE.field$Vec3i$z(blockPos); Object belowPos = FastNMS.INSTANCE.constructor$BlockPos(x, y, z); Object belowState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, belowPos); - if (customBlockState.get(this.halfProperty) == DoubleBlockHalf.UPPER) { - ImmutableBlockState belowCustomState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(belowState)); - if (belowCustomState == null || belowCustomState.isEmpty()) return false; - return belowCustomState.owner().value() == super.customBlock; + if (optionalCustomState.get().get(this.halfProperty) == DoubleBlockHalf.UPPER) { + Optional belowCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState); + return belowCustomState.filter(immutableBlockState -> immutableBlockState.owner().value() == super.customBlock).isPresent(); } else { - return (boolean) CoreReflections.method$BlockStateBase$isFaceSturdy.invoke( + return FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy( belowState, world, belowPos, CoreReflections.instance$Direction$UP, CoreReflections.instance$SupportType$FULL ); 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 8f1c7e5e6..487976c4a 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 @@ -19,6 +19,7 @@ import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldPosition; import java.util.Map; +import java.util.Optional; import java.util.concurrent.Callable; public class FallingBlockBehavior extends BukkitBlockBehavior { @@ -41,15 +42,8 @@ public class FallingBlockBehavior extends BukkitBlockBehavior { @Override public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) { - Object world; - Object blockPos; - if (VersionHelper.isOrAbove1_21_2()) { - world = args[1]; - blockPos = args[3]; - } else { - world = args[3]; - blockPos = args[4]; - } + Object world = args[updateShape$level]; + Object blockPos = args[updateShape$blockPos]; FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 2); return args[0]; } @@ -88,21 +82,21 @@ public class FallingBlockBehavior extends BukkitBlockBehavior { boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity); if (cancelDrop) return; Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity); - int stateId = BlockStateUtils.blockStateToId(blockState); - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return; + ImmutableBlockState customState = optionalCustomState.get(); net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity)); ContextHolder.Builder builder = ContextHolder.builder() .withParameter(DirectContextParameters.FALLING_BLOCK, true) .withParameter(DirectContextParameters.POSITION, position); - for (Item item : immutableBlockState.getDrops(builder, world, null)) { + for (Item item : customState.getDrops(builder, world, null)) { world.dropItemNaturally(position, item); } Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity); boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT); if (!isSilent) { - world.playBlockSound(position, immutableBlockState.sounds().destroySound()); + world.playBlockSound(position, customState.sounds().destroySound()); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FenceGateBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FenceGateBlockBehavior.java index 24c2eff5b..c200a4d17 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FenceGateBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FenceGateBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; @@ -93,14 +92,15 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { @Override public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { Object blockState = args[0]; - Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]); - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (state == null || state.isEmpty()) return blockState; - if (state.get(this.facingProperty).toDirection().clockWise().axis() != direction.axis()) { + Direction direction = DirectionUtils.fromNMSDirection(args[updateShape$direction]); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return blockState; + ImmutableBlockState customState = optionalCustomState.get(); + if (customState.get(this.facingProperty).toDirection().clockWise().axis() != direction.axis()) { return superMethod.call(); } - Object neighborState = VersionHelper.isOrAbove1_21_2() ? args[6] : args[2]; - Object level = VersionHelper.isOrAbove1_21_2() ? args[1] : args[3]; + Object neighborState = args[updateShape$neighborState]; + Object level = args[updateShape$level]; BlockPos blockPos = LocationUtils.fromBlockPos(VersionHelper.isOrAbove1_21_2() ? args[3] : args[4]); Object relativeState = getBlockState(level, blockPos.relative(direction.opposite())); boolean neighborStateIsWall = this.isWall(neighborState); @@ -112,7 +112,7 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { if (relativeStateIsWall) { // TODO: 连接原版方块 } - return state.with(this.inWallProperty, flag).customBlockState().handle(); + return customState.with(this.inWallProperty, flag).customBlockState().handle(); } @Override @@ -135,19 +135,12 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { } @Override - public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) { + public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) { if (!this.canOpenWithHand) { return InteractionResult.PASS; } - if (context.getItem() == null) { - playerToggle(context, state); - return InteractionResult.SUCCESS; - } else if (!context.getPlayer().isSecondaryUseActive()) { - playerToggle(context, state); - return InteractionResult.SUCCESS_AND_CANCEL; - } else { - return InteractionResult.PASS; - } + playerToggle(context, state); + return InteractionResult.SUCCESS_AND_CANCEL; } @SuppressWarnings("unchecked") @@ -163,10 +156,10 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { public boolean isPathFindable(Object thisBlock, Object[] args, Callable superMethod) { Object type = VersionHelper.isOrAbove1_20_5() ? args[1] : args[3]; Object blockState = args[0]; - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (state == null || state.isEmpty()) return false; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return false; if (type == CoreReflections.instance$PathComputationType$LAND || type == CoreReflections.instance$PathComputationType$AIR) { - return isOpen(state); + return isOpen(optionalCustomState.get()); } return false; } @@ -174,9 +167,9 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { @Override public void onExplosionHit(Object thisBlock, Object[] args, Callable superMethod) { if (this.canOpenByWindCharge && FastNMS.INSTANCE.method$Explosion$canTriggerBlocks(args[3])) { - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(args[0])); - if (state == null || state.isEmpty()) return; - this.toggle(state, new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])), LocationUtils.fromBlockPos(args[2]), null); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]); + if (optionalCustomState.isEmpty()) return; + this.toggle(optionalCustomState.get(), new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])), LocationUtils.fromBlockPos(args[2]), null); } } @@ -184,16 +177,17 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { @Override public void neighborChanged(Object thisBlock, Object[] args, Callable superMethod) { Object blockState = args[0]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return; Object level = args[1]; Object blockPos = args[2]; boolean hasSignal = FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, blockPos); - if (hasSignal == immutableBlockState.get(this.poweredProperty)) return; + ImmutableBlockState customState = optionalCustomState.get(); + if (hasSignal == customState.get(this.poweredProperty)) return; Block bblock = FastNMS.INSTANCE.method$CraftBlock$at(level, blockPos); int power = bblock.getBlockPower(); - int oldPower = isOpen(immutableBlockState) ? 15 : 0; + int oldPower = isOpen(customState) ? 15 : 0; Object neighborBlock = args[3]; if (oldPower == 0 ^ power == 0 || FastNMS.INSTANCE.method$BlockStateBase$isSignalSource(FastNMS.INSTANCE.method$Block$defaultState(neighborBlock))) { @@ -203,7 +197,7 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { } World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); - boolean changed = isOpen(immutableBlockState) != hasSignal; + boolean changed = isOpen(customState) != hasSignal; if (hasSignal && changed) { Object abovePos = LocationUtils.above(blockPos); Object aboveBlockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, abovePos); @@ -220,7 +214,7 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { } if (changed) { - immutableBlockState = immutableBlockState.with(this.openProperty, hasSignal); + customState = customState.with(this.openProperty, hasSignal); FastNMS.INSTANCE.method$Level$getCraftWorld(level).sendGameEvent(null, hasSignal ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, new Vector(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos), FastNMS.INSTANCE.field$Vec3i$z(blockPos)) @@ -228,8 +222,9 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior { this.playSound(LocationUtils.fromBlockPos(blockPos), world, hasSignal); } - FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, immutableBlockState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, customState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS); } + private void toggle(ImmutableBlockState state, World world, BlockPos pos, @Nullable Player player) { ImmutableBlockState newState; if (state.get(this.openProperty)) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/GrassBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/GrassBlockBehavior.java index f304d4c2c..235484c8f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/GrassBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/GrassBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.util.BlockStateUtils; @@ -15,13 +14,13 @@ import net.momirealms.craftengine.core.entity.player.InteractionResult; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.item.context.UseOnContext; -import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; import org.bukkit.World; import org.bukkit.block.Block; import java.util.Map; +import java.util.Optional; public class GrassBlockBehavior extends BukkitBlockBehavior { public static final Factory FACTORY = new Factory(); @@ -38,18 +37,19 @@ public class GrassBlockBehavior extends BukkitBlockBehavior { } @Override - public boolean isBoneMealSuccess(Object thisBlock, Object[] args) throws Exception { + public boolean isBoneMealSuccess(Object thisBlock, Object[] args) { if (!VersionHelper.isOrAbove1_20_2()) return true; Object level = args[0]; Object blockPos = args[2]; Object blockState = args[3]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) { + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) { return false; } boolean sendParticles = false; - Object visualState = immutableBlockState.vanillaBlockState().handle(); - Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState); + ImmutableBlockState customState = optionalCustomState.get(); + Object visualState = customState.vanillaBlockState().handle(); + Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState); if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, level, blockPos, visualState); if (!is) { @@ -80,20 +80,15 @@ public class GrassBlockBehavior extends BukkitBlockBehavior { if (!block.isEmpty()) return InteractionResult.PASS; boolean sendSwing = false; - try { - Object visualState = state.vanillaBlockState().handle(); - Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState); - if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { - boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState); - if (!is) { - sendSwing = true; - } - } else { + Object visualState = state.vanillaBlockState().handle(); + Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState); + if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { + boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState); + if (!is) { sendSwing = true; } - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to check visual state bone meal state", e); - return InteractionResult.FAIL; + } else { + sendSwing = true; } if (sendSwing) { context.getPlayer().swingHand(context.getHand()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LampBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LampBlockBehavior.java index e10a63782..45cdf6a2e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LampBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/LampBlockBehavior.java @@ -13,6 +13,7 @@ import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import java.util.Map; +import java.util.Optional; import java.util.concurrent.Callable; public class LampBlockBehavior extends BukkitBlockBehavior { @@ -34,20 +35,16 @@ public class LampBlockBehavior extends BukkitBlockBehavior { @Override public void tick(Object thisBlock, Object[] args, Callable superMethod) throws Exception { Object blockState = args[0]; - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (state == null || state.isEmpty()) return; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return; Object world = args[1]; Object blockPos = args[2]; - if (state.get(this.litProperty)) { - if (!FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) { - // TODO Call Event - FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2); - } - } else { - if (FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) { - // TODO Call Event - FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2); + ImmutableBlockState customState = optionalCustomState.get(); + if (customState.get(this.litProperty) && !FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(world, blockPos)) { + if (FastNMS.INSTANCE.method$CraftEventFactory$callRedstoneChange(world, blockPos, 0, 15).getNewCurrent() != 15) { + return; } + FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, customState.cycle(this.litProperty).customBlockState().handle(), 2); } } @@ -63,7 +60,9 @@ public class LampBlockBehavior extends BukkitBlockBehavior { if (lit) { FastNMS.INSTANCE.method$LevelAccessor$scheduleBlockTick(world, blockPos, thisBlock, 4); } else { - // TODO Call Event + if (FastNMS.INSTANCE.method$CraftEventFactory$callRedstoneChange(world, blockPos, 0, 15).getNewCurrent() != 15) { + return; + } FastNMS.INSTANCE.method$LevelWriter$setBlock(world, blockPos, state.cycle(this.litProperty).customBlockState().handle(), 2); } } 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 fc041c924..493da39b8 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 @@ -6,25 +6,18 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect import net.momirealms.craftengine.bukkit.util.BlockStateUtils; import net.momirealms.craftengine.bukkit.util.BlockTags; import net.momirealms.craftengine.bukkit.util.LocationUtils; -import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.BlockBehavior; import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.UpdateOption; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.Property; -import net.momirealms.craftengine.core.item.Item; -import net.momirealms.craftengine.core.plugin.context.ContextHolder; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; -import net.momirealms.craftengine.core.world.Vec3d; -import net.momirealms.craftengine.core.world.WorldPosition; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.World; import org.bukkit.event.block.LeavesDecayEvent; @@ -113,16 +106,18 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior { } } + @SuppressWarnings("UnstableApiUsage") @Override public void randomTick(Object thisBlock, Object[] args, Callable superMethod) { + Object blockState = args[0]; Object level = args[1]; Object blockPos = args[2]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(args[0])); - if (immutableBlockState != null) { - Optional optionalBehavior = immutableBlockState.behavior().getAs(LeavesBlockBehavior.class); + BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(customState -> { + // 可能是另一种树叶 + Optional optionalBehavior = customState.behavior().getAs(LeavesBlockBehavior.class); if (optionalBehavior.isPresent()) { LeavesBlockBehavior behavior = optionalBehavior.get(); - if (behavior.isDecaying(immutableBlockState)) { + if (behavior.isDecaying(customState)) { World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(level); BlockPos pos = LocationUtils.fromBlockPos(blockPos); // call bukkit event @@ -132,19 +127,10 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior { return; } FastNMS.INSTANCE.method$Level$removeBlock(level, blockPos, false); - if (isWaterLogged(immutableBlockState)) { - bukkitWorld.setBlockData(pos.x(), pos.y(), pos.z(), Material.WATER.createBlockData()); - } - net.momirealms.craftengine.core.world.World world = new BukkitWorld(bukkitWorld); - WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos)); - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.POSITION, position); - for (Item item : immutableBlockState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); - } + FastNMS.INSTANCE.method$Block$dropResources(blockState, level, blockPos); } } - } + }); } private boolean isDecaying(ImmutableBlockState blockState) { @@ -168,7 +154,7 @@ public class LeavesBlockBehavior extends BukkitBlockBehavior { } private int getDistanceAt(Object blockState) throws ReflectiveOperationException { - boolean isLog = (boolean) CoreReflections.method$BlockStateBase$hasTag.invoke(blockState, LOG_TAG); + boolean isLog = FastNMS.INSTANCE.method$BlockStateBase$is(blockState, LOG_TAG); if (isLog) return 0; int id = BlockStateUtils.blockStateToId(blockState); if (BlockStateUtils.isVanillaBlock(id)) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/NearLiquidBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/NearLiquidBlockBehavior.java index 9fb1686b2..2affa742b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/NearLiquidBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/NearLiquidBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids; @@ -16,6 +15,7 @@ import net.momirealms.craftengine.core.world.BlockPos; import java.util.List; import java.util.Map; +import java.util.Optional; public class NearLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior { private static final List WATER = List.of(MFluids.WATER, MFluids.FLOWING_WATER); @@ -70,12 +70,9 @@ public class NearLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior { if (this.stackable) { Object belowPos = FastNMS.INSTANCE.constructor$BlockPos(x, y - 1, z); Object belowState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, belowPos); - int id = BlockStateUtils.blockStateToId(belowState); - if (!BlockStateUtils.isVanillaBlock(id)) { - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id); - if (immutableBlockState.owner().value() == super.customBlock) { - return true; - } + Optional optionalBelowCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState); + if (optionalBelowCustomState.isPresent() && optionalBelowCustomState.get().owner().value() == super.customBlock) { + return true; } } for (BlockPos pos : positions) { 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 8b892760f..77817bcee 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 @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids; @@ -15,6 +14,7 @@ import net.momirealms.craftengine.core.util.ResourceConfigUtils; import java.util.List; import java.util.Map; +import java.util.Optional; public class OnLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior { public static final Factory FACTORY = new Factory(); @@ -59,12 +59,9 @@ public class OnLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior { protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) { if (this.stackable) { - int id = BlockStateUtils.blockStateToId(belowState); - if (!BlockStateUtils.isVanillaBlock(id)) { - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(id); - if (immutableBlockState.owner().value() == super.customBlock) { - return true; - } + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState); + if (optionalCustomState.isPresent() && optionalCustomState.get().owner().value() == super.customBlock) { + return true; } } Object fluidState = FastNMS.INSTANCE.method$Level$getFluidState(world, belowPos); 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 0c7a33e71..66b2b4e28 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 @@ -16,9 +16,6 @@ import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.Property; -import net.momirealms.craftengine.core.item.Item; -import net.momirealms.craftengine.core.plugin.context.ContextHolder; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.PressurePlateSensitivity; @@ -60,30 +57,20 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior { @Override public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { Object state = args[0]; - Object level; - Object blockPos; - if (VersionHelper.isOrAbove1_21_2()) { - level = args[1]; - blockPos = args[3]; - } else { - level = args[3]; - blockPos = args[4]; - } + Object level = args[updateShape$level]; + Object blockPos = args[updateShape$blockPos]; Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]); if (direction == Direction.DOWN && !FastNMS.INSTANCE.method$BlockStateBase$canSurvive(state, level, blockPos)) { + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state); + if (optionalCustomState.isEmpty()) { + return MBlocks.AIR$defaultState; + } + ImmutableBlockState customState = optionalCustomState.get(); BlockPos pos = LocationUtils.fromBlockPos(blockPos); net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos)); - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.POSITION, position); - int stateId = BlockStateUtils.blockStateToId(state); - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return MBlocks.AIR$defaultState; - for (Item item : immutableBlockState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); - } - world.playBlockSound(position, immutableBlockState.sounds().breakSound()); - FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, stateId); + world.playBlockSound(position, customState.sounds().breakSound()); + FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId()); return MBlocks.AIR$defaultState; } return state; @@ -205,9 +192,8 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior { } private int getSignalForState(Object state) { - ImmutableBlockState blockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state)); - if (blockState == null || blockState.isEmpty()) return 0; - return blockState.get(this.poweredProperty) ? 15 : 0; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state); + return optionalCustomState.filter(immutableBlockState -> immutableBlockState.get(this.poweredProperty)).map(immutableBlockState -> 15).orElse(0); } @Override 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 bc30eb7b7..db1749cae 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 @@ -1,7 +1,6 @@ package net.momirealms.craftengine.bukkit.block.behavior; import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries; @@ -14,6 +13,7 @@ import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.UpdateOption; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; +import net.momirealms.craftengine.core.block.properties.IntegerProperty; import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.entity.player.InteractionResult; import net.momirealms.craftengine.core.item.Item; @@ -33,11 +33,11 @@ import java.util.concurrent.Callable; public class SaplingBlockBehavior extends BukkitBlockBehavior { public static final Factory FACTORY = new Factory(); private final Key feature; - private final Property stageProperty; + private final IntegerProperty stageProperty; private final double boneMealSuccessChance; private final float growSpeed; - public SaplingBlockBehavior(CustomBlock block, Key feature, Property stageProperty, double boneMealSuccessChance, float growSpeed) { + public SaplingBlockBehavior(CustomBlock block, Key feature, IntegerProperty stageProperty, double boneMealSuccessChance, float growSpeed) { super(block); this.feature = feature; this.stageProperty = stageProperty; @@ -55,17 +55,18 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior { Object blockPos = args[2]; Object blockState = args[0]; Object aboveBlockPos = LocationUtils.above(blockPos); - if ((int) CoreReflections.method$LevelReader$getMaxLocalRawBrightness.invoke(world, aboveBlockPos) >= 9 && RandomUtils.generateRandomFloat(0, 1) < growSpeed) { + if ((int) CoreReflections.method$LevelReader$getMaxLocalRawBrightness.invoke(world, aboveBlockPos) >= 9 && RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) { increaseStage(world, blockPos, blockState, args[3]); } } private void increaseStage(Object world, Object blockPos, Object blockState, Object randomSource) throws Exception { - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return; - int currentStage = immutableBlockState.get(this.stageProperty); - if (currentStage != this.stageProperty.possibleValues().get(this.stageProperty.possibleValues().size() - 1)) { - ImmutableBlockState nextStage = immutableBlockState.cycle(this.stageProperty); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return; + ImmutableBlockState customState = optionalCustomState.get(); + int currentStage = customState.get(this.stageProperty); + if (currentStage != this.stageProperty.max) { + ImmutableBlockState nextStage = customState.cycle(this.stageProperty); World bukkitWorld = FastNMS.INSTANCE.method$Level$getCraftWorld(world); int x = FastNMS.INSTANCE.field$Vec3i$x(blockPos); int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos); @@ -101,18 +102,19 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior { } @Override - public boolean isBoneMealSuccess(Object thisBlock, Object[] args) throws Exception { + public boolean isBoneMealSuccess(Object thisBlock, Object[] args) { boolean success = RandomUtils.generateRandomDouble(0d, 1d) < this.boneMealSuccessChance; Object level = args[0]; Object blockPos = args[2]; Object blockState = args[3]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) { + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) { return false; } + ImmutableBlockState customState = optionalCustomState.get(); boolean sendParticles = false; - Object visualState = immutableBlockState.vanillaBlockState().handle(); - Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState); + Object visualState = customState.vanillaBlockState().handle(); + Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState); if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, level, blockPos, visualState); if (!is) { @@ -148,20 +150,15 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior { if (item == null || !item.vanillaId().equals(ItemKeys.BONE_MEAL) || context.getPlayer().isAdventureMode()) return InteractionResult.PASS; boolean sendSwing = false; - try { - Object visualState = state.vanillaBlockState().handle(); - Object visualStateBlock = CoreReflections.method$BlockStateBase$getBlock.invoke(visualState); - if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { - boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState); - if (!is) { - sendSwing = true; - } - } else { + Object visualState = state.vanillaBlockState().handle(); + Object visualStateBlock = BlockStateUtils.getBlockOwner(visualState); + if (CoreReflections.clazz$BonemealableBlock.isInstance(visualStateBlock)) { + boolean is = FastNMS.INSTANCE.method$BonemealableBlock$isValidBonemealTarget(visualStateBlock, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()), visualState); + if (!is) { sendSwing = true; } - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to check visual state bone meal state", e); - return InteractionResult.FAIL; + } else { + sendSwing = true; } if (sendSwing) { context.getPlayer().swingHand(context.getHand()); @@ -177,7 +174,7 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior { String feature = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("feature"), "warning.config.block.behavior.sapling.missing_feature"); Property stageProperty = (Property) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("stage"), "warning.config.block.behavior.sapling.missing_stage"); double boneMealSuccessChance = ResourceConfigUtils.getAsDouble(arguments.getOrDefault("bone-meal-success-chance", 0.45), "bone-meal-success-chance"); - return new SaplingBlockBehavior(block, Key.of(feature), stageProperty, boneMealSuccessChance, + return new SaplingBlockBehavior(block, Key.of(feature), (IntegerProperty) stageProperty, boneMealSuccessChance, ResourceConfigUtils.getAsFloat(arguments.getOrDefault("grow-speed", 1.0 / 7.0), "grow-speed")); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SlabBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SlabBlockBehavior.java index abfea5b85..534c51339 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SlabBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SlabBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids; @@ -81,26 +80,24 @@ public class SlabBlockBehavior extends BukkitBlockBehavior { @Override public boolean placeLiquid(Object thisBlock, Object[] args, Callable superMethod) { Object blockState = args[2]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return false; - return immutableBlockState.get(this.typeProperty) != SlabType.DOUBLE && super.placeLiquid(thisBlock, args, superMethod); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + return optionalCustomState.filter(state -> state.get(this.typeProperty) != SlabType.DOUBLE && super.placeLiquid(thisBlock, args, superMethod)).isPresent(); } @Override public boolean canPlaceLiquid(Object thisBlock, Object[] args, Callable superMethod) { Object blockState = VersionHelper.isOrAbove1_20_2() ? args[3] : args[2]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return false; - return immutableBlockState.get(this.typeProperty) != SlabType.DOUBLE && super.canPlaceLiquid(thisBlock, args, superMethod); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + return optionalCustomState.filter(state -> state.get(this.typeProperty) != SlabType.DOUBLE && super.canPlaceLiquid(thisBlock, args, superMethod)).isPresent(); } @Override public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { Object blockState = args[0]; if (super.waterloggedProperty == null) return blockState; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return blockState; - if (immutableBlockState.get(super.waterloggedProperty)) { + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return blockState; + if (optionalCustomState.get().get(super.waterloggedProperty)) { FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5); } return blockState; @@ -110,10 +107,10 @@ public class SlabBlockBehavior extends BukkitBlockBehavior { public boolean isPathFindable(Object thisBlock, Object[] args, Callable superMethod) { Object type = VersionHelper.isOrAbove1_20_5() ? args[1] : args[3]; Object blockState = args[0]; - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (state == null || state.isEmpty()) return false; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return false; if (type == CoreReflections.instance$PathComputationType$WATER) { - return super.waterloggedProperty != null && state.get(this.typeProperty) != SlabType.DOUBLE && state.get(super.waterloggedProperty); + return super.waterloggedProperty != null && optionalCustomState.get().get(this.typeProperty) != SlabType.DOUBLE && optionalCustomState.get().get(super.waterloggedProperty); } return false; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StairsBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StairsBlockBehavior.java index cd25d0466..ff015f251 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StairsBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StairsBlockBehavior.java @@ -1,8 +1,6 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids; import net.momirealms.craftengine.bukkit.util.BlockStateUtils; import net.momirealms.craftengine.bukkit.util.DirectionUtils; @@ -54,127 +52,76 @@ public class StairsBlockBehavior extends BukkitBlockBehavior { @Override public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { - Object level; - Object blockPos; + Object level = args[updateShape$level]; + Object blockPos = args[updateShape$blockPos]; Object blockState = args[0]; - if (VersionHelper.isOrAbove1_21_2()) { - level = args[1]; - blockPos = args[3]; - } else { - level = args[3]; - blockPos = args[4]; - } - int stateId = BlockStateUtils.blockStateToId(blockState); - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return blockState; - if (super.waterloggedProperty != null && immutableBlockState.get(this.waterloggedProperty)) { - FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return blockState; + ImmutableBlockState customState = optionalCustomState.get(); + if (super.waterloggedProperty != null && customState.get(this.waterloggedProperty)) { + FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5); } Direction direction = DirectionUtils.fromNMSDirection(VersionHelper.isOrAbove1_21_2() ? args[4] : args[1]); - StairsShape stairsShape = getStairsShape(immutableBlockState, level, LocationUtils.fromBlockPos(blockPos)); + StairsShape stairsShape = getStairsShape(customState, level, LocationUtils.fromBlockPos(blockPos)); return direction.axis().isHorizontal() - ? immutableBlockState.with(this.shapeProperty, stairsShape).customBlockState().handle() + ? customState.with(this.shapeProperty, stairsShape).customBlockState().handle() : superMethod.call(); } private StairsShape getStairsShape(ImmutableBlockState state, Object level, BlockPos pos) { Direction direction = state.get(this.facingProperty).toDirection(); - Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(direction))); - int stateId = BlockStateUtils.blockStateToId(blockState); - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(stateId); - if (immutableBlockState != null && !immutableBlockState.isEmpty()) { - if (isStairs(blockState) && state.get(this.halfProperty) == immutableBlockState.get(this.halfProperty)) { - Direction direction1 = immutableBlockState.get(this.facingProperty).toDirection(); - if (direction1.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction1.opposite())) { - if (direction1 == direction.counterClockWise()) { - return StairsShape.OUTER_LEFT; + Object relativeBlockState1 = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(direction))); + Optional optionalCustomState1 = BlockStateUtils.getOptionalCustomBlockState(relativeBlockState1); + if (optionalCustomState1.isPresent()) { + ImmutableBlockState customState1 = optionalCustomState1.get(); + Optional optionalStairsBlockBehavior = customState1.behavior().getAs(StairsBlockBehavior.class); + if (optionalStairsBlockBehavior.isPresent()) { + StairsBlockBehavior stairsBlockBehavior = optionalStairsBlockBehavior.get(); + if (state.get(this.halfProperty) == customState1.get(stairsBlockBehavior.halfProperty)) { + Direction direction1 = customState1.get(stairsBlockBehavior.facingProperty).toDirection(); + if (direction1.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction1.opposite())) { + if (direction1 == direction.counterClockWise()) { + return StairsShape.OUTER_LEFT; + } + return StairsShape.OUTER_RIGHT; } - return StairsShape.OUTER_RIGHT; } } - } else if (isStairs(blockState)) { - // 处理可能是原版楼梯 - // try { - // Object nmsHalf = CoreReflections.method$StateHolder$getValue.invoke(blockState, CoreReflections.instance$StairBlock$HALF); - // SingleBlockHalf half = SingleBlockHalf.valueOf(nmsHalf.toString().toUpperCase(Locale.ROOT)); - // if (state.get(this.halfProperty).equals(half)) { - // Object nmsFacing = CoreReflections.method$StateHolder$getValue.invoke(blockState, CoreReflections.instance$StairBlock$FACING); - // Direction direction1 = DirectionUtils.fromNMSDirection(nmsFacing); - // if (direction1.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction1.opposite())) { - // if (direction1 == direction.counterClockWise()) { - // return StairsShape.OUTER_LEFT; - // } - // return StairsShape.OUTER_RIGHT; - // } - // } - // } catch (Exception e) { - // CraftEngine.instance().logger().warn("Failed to get facing from blockState", e); - // } } - - Object blockState1 = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(direction.opposite()))); - int stateId1 = BlockStateUtils.blockStateToId(blockState1); - ImmutableBlockState immutableBlockState1 = BukkitBlockManager.instance().getImmutableBlockState(stateId1); - if (immutableBlockState1 != null && !immutableBlockState1.isEmpty()) { - if (isStairs(blockState1) && state.get(this.halfProperty) == immutableBlockState1.get(this.halfProperty)) { - Direction direction2 = immutableBlockState1.get(this.facingProperty).toDirection(); - if (direction2.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction2)) { - if (direction2 == direction.counterClockWise()) { - return StairsShape.INNER_LEFT; + Object relativeBlockState2 = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(direction.opposite()))); + Optional optionalCustomState2 = BlockStateUtils.getOptionalCustomBlockState(relativeBlockState2); + if (optionalCustomState2.isPresent()) { + ImmutableBlockState customState2 = optionalCustomState2.get(); + Optional optionalStairsBlockBehavior = customState2.behavior().getAs(StairsBlockBehavior.class); + if (optionalStairsBlockBehavior.isPresent()) { + StairsBlockBehavior stairsBlockBehavior = optionalStairsBlockBehavior.get(); + if (state.get(this.halfProperty) == customState2.get(stairsBlockBehavior.halfProperty)) { + Direction direction2 = customState2.get(stairsBlockBehavior.facingProperty).toDirection(); + if (direction2.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction2)) { + if (direction2 == direction.counterClockWise()) { + return StairsShape.INNER_LEFT; + } + return StairsShape.INNER_RIGHT; } - return StairsShape.INNER_RIGHT; } } - } else if (isStairs(blockState1)) { - // 处理可能是原版楼梯 - // try { - // Object nmsHalf = CoreReflections.method$StateHolder$getValue.invoke(blockState1, CoreReflections.instance$StairBlock$HALF); - // SingleBlockHalf half = SingleBlockHalf.valueOf(nmsHalf.toString().toUpperCase(Locale.ROOT)); - // if (state.get(this.halfProperty).equals(half)) { - // Object nmsFacing = CoreReflections.method$StateHolder$getValue.invoke(blockState1, CoreReflections.instance$StairBlock$FACING); - // Direction direction1 = DirectionUtils.fromNMSDirection(nmsFacing); - // if (direction1.axis() != state.get(this.facingProperty).toDirection().axis() && canTakeShape(state, level, pos, direction1)) { - // if (direction1 == direction.counterClockWise()) { - // return StairsShape.INNER_LEFT; - // } - // return StairsShape.INNER_RIGHT; - // } - // } - // } catch (Exception e) { - // CraftEngine.instance().logger().warn("Failed to get facing from blockState", e); - // } } - return StairsShape.STRAIGHT; } - private boolean isStairs(Object state) { - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(state)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) { - return FastNMS.INSTANCE.method$BlockState$getBlock(state).equals(CoreReflections.clazz$StairBlock); - } - Optional optionalBehavior = immutableBlockState.behavior().getAs(StairsBlockBehavior.class); - return optionalBehavior.isPresent(); - } - private boolean canTakeShape(ImmutableBlockState state, Object level, BlockPos pos, Direction face) { Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, LocationUtils.toBlockPos(pos.relative(face))); - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) { - // 处理可能是原版楼梯 - // try { - // Object nmsFacing = CoreReflections.method$StateHolder$getValue.invoke(blockState, CoreReflections.instance$StairBlock$FACING); - // Direction direction = DirectionUtils.fromNMSDirection(nmsFacing); - // if (direction != state.get(this.facingProperty).toDirection()) return true; - // Object nmsHalf = CoreReflections.method$StateHolder$getValue.invoke(blockState, CoreReflections.instance$StairBlock$HALF); - // SingleBlockHalf half = SingleBlockHalf.valueOf(nmsHalf.toString().toUpperCase(Locale.ROOT)); - // if (half != state.get(this.halfProperty)) return true; - // } catch (Exception e) { - // CraftEngine.instance().logger().warn("Failed to handle canTakeShape", e); - // } - return !isStairs(blockState); + Optional optionalAnotherState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalAnotherState.isEmpty()) { + return true; } - return !isStairs(blockState) || immutableBlockState.get(this.facingProperty) != state.get(this.facingProperty) || immutableBlockState.get(this.halfProperty) != state.get(this.halfProperty); + ImmutableBlockState anotherState = optionalAnotherState.get(); + Optional optionalBehavior = anotherState.behavior().getAs(StairsBlockBehavior.class); + if (optionalBehavior.isEmpty()) { + return true; + } + StairsBlockBehavior anotherBehavior = optionalBehavior.get(); + return anotherState.get(anotherBehavior.facingProperty) != state.get(this.facingProperty) || anotherState.get(anotherBehavior.halfProperty) != state.get(this.halfProperty); } public static class Factory implements BlockBehaviorFactory { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SturdyBaseBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SturdyBaseBlockBehavior.java index e835b702a..b4ce8fe4c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SturdyBaseBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SturdyBaseBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.util.BlockStateUtils; @@ -16,6 +15,7 @@ import net.momirealms.craftengine.core.util.ResourceConfigUtils; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; public class SturdyBaseBlockBehavior extends AbstractCanSurviveBlockBehavior { public static final Factory FACTORY = new Factory(); @@ -56,9 +56,8 @@ public class SturdyBaseBlockBehavior extends AbstractCanSurviveBlockBehavior { if (!this.stackable) { return false; } - ImmutableBlockState targetCustomState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (targetCustomState == null || targetCustomState.isEmpty()) return false; - return targetCustomState.owner().value() == super.customBlock; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + return optionalCustomState.filter(immutableBlockState -> immutableBlockState.owner().value() == super.customBlock).isPresent(); } public static class Factory implements BlockBehaviorFactory { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/TrapDoorBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/TrapDoorBlockBehavior.java index da4024c35..093d8f0ac 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/TrapDoorBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/TrapDoorBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; @@ -75,10 +74,11 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior { public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) { Object blockState = args[0]; if (super.waterloggedProperty != null) { - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (state != null && !state.isEmpty() && state.get(super.waterloggedProperty)) { - FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(VersionHelper.isOrAbove1_21_2() ? args[2] : args[3], VersionHelper.isOrAbove1_21_2() ? args[3] : args[4], MFluids.WATER, 5); - } + BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(customState -> { + if (customState.get(super.waterloggedProperty)) { + FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5); + } + }); } return blockState; } @@ -126,12 +126,12 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior { public boolean isPathFindable(Object thisBlock, Object[] args, Callable superMethod) { Object type = VersionHelper.isOrAbove1_20_5() ? args[1] : args[3]; Object blockState = args[0]; - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (state == null || state.isEmpty()) return false; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return false; if (type == CoreReflections.instance$PathComputationType$LAND || type == CoreReflections.instance$PathComputationType$AIR) { - return state.get(this.openProperty); + return optionalCustomState.get().get(this.openProperty); } else if (type == CoreReflections.instance$PathComputationType$WATER) { - return state.get(super.waterloggedProperty); + return optionalCustomState.get().get(super.waterloggedProperty); } return false; } @@ -139,9 +139,9 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior { @Override public void onExplosionHit(Object thisBlock, Object[] args, Callable superMethod) { if (this.canOpenByWindCharge && FastNMS.INSTANCE.method$Explosion$canTriggerBlocks(args[3])) { - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(args[0])); - if (state == null || state.isEmpty()) return; - this.toggle(state, new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])), LocationUtils.fromBlockPos(args[2]), null); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(args[0]); + if (optionalCustomState.isEmpty()) return; + this.toggle(optionalCustomState.get(), new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(args[1])), LocationUtils.fromBlockPos(args[2]), null); } } @@ -149,16 +149,17 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior { @Override public void neighborChanged(Object thisBlock, Object[] args, Callable superMethod) { Object blockState = args[0]; - ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (immutableBlockState == null || immutableBlockState.isEmpty()) return; + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return; + ImmutableBlockState customState = optionalCustomState.get(); Object level = args[1]; Object blockPos = args[2]; boolean hasSignal = FastNMS.INSTANCE.method$SignalGetter$hasNeighborSignal(level, blockPos); - if (hasSignal == immutableBlockState.get(this.poweredProperty)) return; + if (hasSignal == customState.get(this.poweredProperty)) return; Block bblock = FastNMS.INSTANCE.method$CraftBlock$at(level, blockPos); int power = bblock.getBlockPower(); - int oldPower = immutableBlockState.get(this.openProperty) ? 15 : 0; + int oldPower = customState.get(this.openProperty) ? 15 : 0; Object neighborBlock = args[3]; if (oldPower == 0 ^ power == 0 || FastNMS.INSTANCE.method$BlockStateBase$isSignalSource(FastNMS.INSTANCE.method$Block$defaultState(neighborBlock))) { @@ -168,7 +169,7 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior { } World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); - boolean changed = immutableBlockState.get(this.openProperty) != hasSignal; + boolean changed = customState.get(this.openProperty) != hasSignal; if (hasSignal && changed) { Object abovePos = LocationUtils.above(blockPos); Object aboveBlockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, abovePos); @@ -185,7 +186,7 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior { } if (changed) { - immutableBlockState = immutableBlockState.with(this.openProperty, hasSignal); + customState = customState.with(this.openProperty, hasSignal); FastNMS.INSTANCE.method$Level$getCraftWorld(level).sendGameEvent(null, hasSignal ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, new Vector(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos), FastNMS.INSTANCE.field$Vec3i$z(blockPos)) @@ -193,8 +194,8 @@ public class TrapDoorBlockBehavior extends BukkitBlockBehavior { this.playSound(LocationUtils.fromBlockPos(blockPos), world, hasSignal); } - FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, immutableBlockState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS); - if (this.waterloggedProperty != null && immutableBlockState.get(this.waterloggedProperty)) { + FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, customState.with(this.poweredProperty, hasSignal).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS); + if (this.waterloggedProperty != null && customState.get(this.waterloggedProperty)) { FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(level, blockPos, MFluids.WATER, 5); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/VerticalCropBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/VerticalCropBlockBehavior.java index 2adb39f60..b5d2d9c9a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/VerticalCropBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/VerticalCropBlockBehavior.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks; @@ -19,6 +18,7 @@ import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; import java.util.Map; +import java.util.Optional; import java.util.concurrent.Callable; public class VerticalCropBlockBehavior extends BukkitBlockBehavior { @@ -42,26 +42,25 @@ public class VerticalCropBlockBehavior extends BukkitBlockBehavior { Object blockState = args[0]; Object level = args[1]; Object blockPos = args[2]; + Optional optionalCurrentState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCurrentState.isEmpty()) { + return; + } + ImmutableBlockState currentState = optionalCurrentState.get(); // above block is empty if (FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, (this.direction ? LocationUtils.above(blockPos) : LocationUtils.below(blockPos))) == MBlocks.AIR$defaultState) { int currentHeight = 1; BlockPos currentPos = LocationUtils.fromBlockPos(blockPos); - ImmutableBlockState currentState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (currentState != null && !currentState.isEmpty()) { - while (true) { - Object nextPos = LocationUtils.toBlockPos(currentPos.x(), this.direction ? currentPos.y() - currentHeight : currentPos.y() + currentHeight, currentPos.z()); - Object nextState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, nextPos); - ImmutableBlockState belowImmutableState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(nextState)); - if (belowImmutableState != null && !belowImmutableState.isEmpty() && belowImmutableState.owner() == currentState.owner()) { - currentHeight++; - } else { - break; - } + while (true) { + Object nextPos = LocationUtils.toBlockPos(currentPos.x(), this.direction ? currentPos.y() - currentHeight : currentPos.y() + currentHeight, currentPos.z()); + Object nextState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, nextPos); + Optional optionalBelowCustomState = BlockStateUtils.getOptionalCustomBlockState(nextState); + if (optionalBelowCustomState.isPresent() && optionalBelowCustomState.get().owner().value() == super.customBlock) { + currentHeight++; + } else { + break; } - } else { - return; } - if (currentHeight < this.maxHeight) { int age = currentState.get(ageProperty); if (age >= this.ageProperty.max || RandomUtils.generateRandomFloat(0, 1) < this.growSpeed) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index ba4ca6bf9..798f5c105 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -26,7 +26,6 @@ import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; import java.io.IOException; -import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java index 4464bd6f6..1bdb20096 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/projectile/BukkitProjectileManager.java @@ -2,8 +2,6 @@ package net.momirealms.craftengine.bukkit.entity.projectile; import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent; -import io.papermc.paper.event.player.PlayerStopUsingItemEvent; -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.reflection.minecraft.CoreReflections; @@ -11,25 +9,24 @@ import net.momirealms.craftengine.bukkit.plugin.scheduler.impl.FoliaTask; import net.momirealms.craftengine.bukkit.util.ParticleUtils; import net.momirealms.craftengine.core.entity.projectile.ProjectileManager; import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta; -import net.momirealms.craftengine.core.entity.projectile.ProjectileType; -import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask; import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.*; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.ThrowableProjectile; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityPortalEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; import org.bukkit.event.world.EntitiesLoadEvent; import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugItemDataCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugItemDataCommand.java index 131e1166a..d9bf2f7d1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugItemDataCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugItemDataCommand.java @@ -1,11 +1,8 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; -import com.saicone.rtag.RtagMirror; import com.saicone.rtag.item.ItemTagStream; -import com.saicone.rtag.tag.TagCompound; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; import net.momirealms.craftengine.bukkit.util.ItemUtils; import net.momirealms.craftengine.core.plugin.CraftEngine; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockStateGenerator.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockStateGenerator.java index 16346f990..8aebf215d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockStateGenerator.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockStateGenerator.java @@ -13,12 +13,23 @@ import net.bytebuddy.implementation.bind.annotation.AllArguments; import net.bytebuddy.implementation.bind.annotation.RuntimeType; import net.bytebuddy.implementation.bind.annotation.This; import net.bytebuddy.matcher.ElementMatchers; +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.reflection.minecraft.CoreReflections; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MItems; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MLootContextParams; +import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; +import net.momirealms.craftengine.bukkit.world.BukkitWorld; +import net.momirealms.craftengine.core.block.BlockSettings; import net.momirealms.craftengine.core.block.CustomBlockStateHolder; import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.context.ContextHolder; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.util.ReflectionUtils; +import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; +import org.bukkit.inventory.ItemStack; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -69,7 +80,37 @@ public final class BlockStateGenerator { ImmutableBlockState state = ((CustomBlockStateHolder) thisObj).customBlockState(); if (state == null) return List.of(); Object builder = args[0]; - return List.of(FastNMS.INSTANCE.constructor$ItemStack(MItems.WATER_BUCKET, 1)); + Object vec3 = FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.ORIGIN); + if (vec3 == null) return List.of(); + + Object tool = FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.TOOL); + + Item item = BukkitItemManager.instance().wrap(tool == null || FastNMS.INSTANCE.method$ItemStack$isEmpty(tool) ? null : FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(tool)); + + // do not drop if it's not the correct tool + BlockSettings settings = state.settings(); + if (settings.requireCorrectTool()) { + if (tool == null) return List.of(); + if (!settings.isCorrectTool(item.id()) && + (!settings.respectToolComponent() || !FastNMS.INSTANCE.method$ItemStack$isCorrectToolForDrops(tool, state.customBlockState().handle()))) { + return List.of(); + } + } + + Object serverLevel = FastNMS.INSTANCE.method$LootParams$Builder$getLevel(builder); + World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(serverLevel)); + ContextHolder.Builder lootBuilder = new ContextHolder.Builder() + .withParameter(DirectContextParameters.POSITION, new WorldPosition(world, FastNMS.INSTANCE.field$Vec3$x(vec3), FastNMS.INSTANCE.field$Vec3$y(vec3), FastNMS.INSTANCE.field$Vec3$z(vec3))); + if (item != null) { + lootBuilder.withParameter(DirectContextParameters.ITEM_IN_HAND, item); + } + Object optionalPlayer = FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.THIS_ENTITY); + BukkitServerPlayer player = optionalPlayer != null ? BukkitCraftEngine.instance().adapt(FastNMS.INSTANCE.method$ServerPlayer$getBukkitEntity(optionalPlayer)) : null; + Float radius = (Float) FastNMS.INSTANCE.method$LootParams$Builder$getOptionalParameter(builder, MLootContextParams.EXPLOSION_RADIUS); + if (radius != null) { + lootBuilder.withParameter(DirectContextParameters.EXPLOSION_RADIUS, radius); + } + return state.getDrops(lootBuilder, world, player).stream().map(Item::getLiteralObject).toList(); } } 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 bbaf739da..6730c7c63 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 @@ -1691,10 +1691,6 @@ public final class CoreReflections { ReflectionUtils.getInstanceDeclaredField(clazz$Entity, double.class, 2) ); - public static final Method method$BlockStateBase$hasTag = requireNonNull( - ReflectionUtils.getMethod(clazz$BlockStateBase, boolean.class, clazz$TagKey) - ); - public static final Method method$Level$removeBlock = requireNonNull( ReflectionUtils.getMethod(clazz$Level, boolean.class, clazz$BlockPos, boolean.class) ); @@ -2492,10 +2488,6 @@ public final class CoreReflections { ReflectionUtils.getDeclaredField(clazz$BlockInWorld, clazz$BlockState, 0) ); - public static final Method method$BlockStateBase$getBlock = requireNonNull( - ReflectionUtils.getMethod(clazz$BlockStateBase, clazz$Block) - ); - public static final Method method$BlockBehaviour$getDescriptionId = requireNonNull( VersionHelper.isOrAbove1_21_2() ? ReflectionUtils.getMethod(clazz$BlockBehaviour, String.class) @@ -3545,5 +3537,10 @@ public final class CoreReflections { ReflectionUtils.getMethod(clazz$BlockStateBase, List.class, clazz$LootParams$Builder) ); - + public static final Class clazz$LootContextParams = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "world.level.storage.loot.parameters.LootContextParameters", + "world.level.storage.loot.parameters.LootContextParams" + ) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/MLootContextParams.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/MLootContextParams.java new file mode 100644 index 000000000..9d515b567 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/MLootContextParams.java @@ -0,0 +1,47 @@ +package net.momirealms.craftengine.bukkit.plugin.reflection.minecraft; + +import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import static java.util.Objects.requireNonNull; + +public final class MLootContextParams { + public static final Object THIS_ENTITY; + public static final Object ORIGIN; + public static final Object TOOL; + public static final Object EXPLOSION_RADIUS; + + static { + try { + Object params$THIS_ENTITY = null; + Object params$ORIGIN = null; + Object params$TOOL = null; + Object params$EXPLOSION_RADIUS = null; + Field[] fields = CoreReflections.clazz$LootContextParams.getDeclaredFields(); + for (Field field : fields) { + Type fieldType = field.getGenericType(); + if (fieldType instanceof ParameterizedType paramType) { + Type type = paramType.getActualTypeArguments()[0]; + if (type == CoreReflections.clazz$Entity && params$THIS_ENTITY == null) { + params$THIS_ENTITY = field.get(null); + } else if (type == CoreReflections.clazz$ItemStack) { + params$TOOL = field.get(null); + } else if (type == CoreReflections.clazz$Vec3) { + params$ORIGIN = field.get(null); + } else if (type == Float.class) { + params$EXPLOSION_RADIUS = field.get(null); + } + } + } + THIS_ENTITY = requireNonNull(params$THIS_ENTITY); + TOOL = requireNonNull(params$TOOL); + ORIGIN = requireNonNull(params$ORIGIN); + EXPLOSION_RADIUS = requireNonNull(params$EXPLOSION_RADIUS); + } catch (ReflectiveOperationException e) { + throw new ReflectionInitException("Failed to init LootContextParams", e); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 239cd232b..1f488f653 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -10,7 +10,6 @@ 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.gui.CraftEngineInventoryHolder; -import net.momirealms.craftengine.bukkit.plugin.network.BukkitNetworkManager; import net.momirealms.craftengine.bukkit.plugin.network.payload.DiscardedPayload; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java index 434a1dd74..f5b236a6a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java @@ -1,23 +1,17 @@ package net.momirealms.craftengine.bukkit.util; -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException; -import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections; -import net.momirealms.craftengine.core.block.*; +import net.momirealms.craftengine.core.block.BlockSettings; +import net.momirealms.craftengine.core.block.BlockStateWrapper; +import net.momirealms.craftengine.core.block.CustomBlockStateHolder; +import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.item.Item; -import net.momirealms.craftengine.core.util.Instrument; import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.util.MapColor; -import net.momirealms.craftengine.core.world.BlockPos; -import org.bukkit.Bukkit; -import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; -import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -138,6 +132,14 @@ public class BlockStateUtils { return vanillaStateSize; } + public static Optional getOptionalCustomBlockState(Object state) { + if (state instanceof CustomBlockStateHolder holder) { + return Optional.ofNullable(holder.customBlockState()); + } else { + return Optional.empty(); + } + } + public static boolean isBurnable(Object state) { Object blockOwner = getBlockOwner(state); return IGNITE_ODDS.getOrDefault(blockOwner, 0) > 0; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemUtils.java index bae4930c1..2c6704e9a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemUtils.java @@ -3,7 +3,6 @@ package net.momirealms.craftengine.bukkit.util; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Contract; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java index 052517752..0703d45ea 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ParticleUtils.java @@ -1,9 +1,7 @@ package net.momirealms.craftengine.bukkit.util; import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries; -import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.Context; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/TemplateManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/TemplateManager.java index a69d39c67..55fba96cb 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/TemplateManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/TemplateManager.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.core.plugin.config.template; -import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.Manageable; import net.momirealms.craftengine.core.plugin.config.ConfigParser; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/SNBTReader.java b/core/src/main/java/net/momirealms/craftengine/core/util/SNBTReader.java index e9b0f0ffc..0be81388d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/SNBTReader.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/SNBTReader.java @@ -1,6 +1,9 @@ package net.momirealms.craftengine.core.util; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.function.Function; public final class SNBTReader extends DefaultStringReader { diff --git a/gradle.properties b/gradle.properties index 1de6d4c73..447507462 100644 --- a/gradle.properties +++ b/gradle.properties @@ -51,7 +51,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.17 -nms_helper_version=1.0.8 +nms_helper_version=1.0.13 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23