From 4e1de1c9af374cd030af1f1dd0c605e421bed9d8 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Thu, 19 Jun 2025 03:50:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E5=AE=9D=E8=B4=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../behavior/WaterLoggedBlockBehavior.java | 113 +++++++++--------- .../bukkit/item/BukkitItemManager.java | 6 +- .../item/behavior/BucketItemBehavior.java | 91 -------------- .../item/behavior/BukkitItemBehaviors.java | 4 - .../behavior/WaterBucketItemBehavior.java | 70 ----------- .../plugin/injector/BlockGenerator.java | 58 ++++++++- .../craftengine/core/block/BlockBehavior.java | 12 ++ 7 files changed, 125 insertions(+), 229 deletions(-) delete mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BucketItemBehavior.java delete mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/WaterBucketItemBehavior.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java index 80990325d..b6f34846f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/WaterLoggedBlockBehavior.java @@ -1,12 +1,21 @@ 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.plugin.reflection.minecraft.MItems; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; 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.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.util.VersionHelper; import org.jetbrains.annotations.Nullable; import java.util.Map; +import java.util.concurrent.Callable; public class WaterLoggedBlockBehavior extends BukkitBlockBehavior { public static final Factory FACTORY = new Factory(); @@ -18,64 +27,52 @@ public class WaterLoggedBlockBehavior extends BukkitBlockBehavior { this.waterloggedProperty = waterloggedProperty; } - // TODO create real waterlogged blocks, needs to have real waterlogged property -// @Override -// public Object pickupBlock(Object thisBlock, Object[] args, Callable superMethod) throws Exception { -// if (this.waterloggedProperty == null) return Reflections.instance$ItemStack$EMPTY; -// Object blockState; -// Object world; -// Object pos; -// if (VersionHelper.isVersionNewerThan1_20_2()) { -// world = args[1]; -// pos = args[2]; -// blockState = args[3]; -// } else { -// world = args[0]; -// pos = args[1]; -// blockState = args[2]; -// } -// ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); -// if (immutableBlockState != null) { -// if (immutableBlockState.get(this.waterloggedProperty)) { -// Reflections.method$LevelWriter$setBlock.invoke(world, pos, immutableBlockState.with(this.waterloggedProperty, false).customBlockState().handle(), 3); -// // TODO check can survive -// Object itemStack = Reflections.constructor$ItemStack.newInstance(Reflections.instance$Items$WATER_BUCKET); -// return itemStack; -// } -// } -// return Reflections.instance$ItemStack$EMPTY; -// } -// -// @Override -// public boolean placeLiquid(Object thisBlock, Object[] args, Callable superMethod) throws Exception { -// if (this.waterloggedProperty == null) return false; -// Object blockState = args[2]; -// ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); -// if (immutableBlockState != null) { -// Object fluidType = Reflections.method$FluidState$getType.invoke(args[3]); -// if (!immutableBlockState.get(this.waterloggedProperty) && fluidType == Reflections.instance$Fluids$WATER) { -// Reflections.method$LevelWriter$setBlock.invoke(args[0], args[1], immutableBlockState.with(this.waterloggedProperty, true).customBlockState().handle(), 3); -// Reflections.method$LevelAccessor$scheduleTick.invoke(args[0], fluidType, Reflections.method$Fluid$getTickDelay.invoke(fluidType, args[0])); -// return true; -// } -// } -// return false; -// } -// -// // use water -// @Override -// public boolean canPlaceLiquid(Object thisBlock, Object[] args, Callable superMethod) throws Exception { -// return super.canPlaceLiquid(thisBlock, args, superMethod); -// } -// -// @Override -// public Object getFluidState(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() || this.waterloggedProperty == null) return super.getFluidState(thisBlock, args, superMethod); -// boolean waterlogged = state.get(this.waterloggedProperty); -// return waterlogged ? Reflections.method$FlowingFluid$getSource.invoke(Reflections.instance$Fluids$WATER, false) : super.getFluidState(thisBlock, args, superMethod); -// } + @Override + public Object pickupBlock(Object thisBlock, Object[] args, Callable superMethod) { + if (this.waterloggedProperty == null) return CoreReflections.instance$ItemStack$EMPTY; + Object blockState; + Object world; + Object pos; + if (VersionHelper.isOrAbove1_20_2()) { + world = args[1]; + pos = args[2]; + blockState = args[3]; + } else { + world = args[0]; + pos = args[1]; + blockState = args[2]; + } + 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); + } + } + return CoreReflections.instance$ItemStack$EMPTY; + } + + @Override + 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; + } + } + return false; + } + + @Override + public boolean canPlaceLiquid(Object thisBlock, Object[] args, Callable superMethod) { + if (this.waterloggedProperty == null) return false; + return (VersionHelper.isOrAbove1_20_2() ? args[4] : args[3]) == MFluids.WATER; + } @SuppressWarnings("unchecked") public static class Factory implements BlockBehaviorFactory { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index c313049ee..11d072bf4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -1,8 +1,6 @@ package net.momirealms.craftengine.bukkit.item; -import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior; import net.momirealms.craftengine.bukkit.item.behavior.FlintAndSteelItemBehavior; -import net.momirealms.craftengine.bukkit.item.behavior.WaterBucketItemBehavior; import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory; import net.momirealms.craftengine.bukkit.item.listener.ArmorEventListener; import net.momirealms.craftengine.bukkit.item.listener.DebugStickListener; @@ -40,8 +38,8 @@ import java.util.Set; public class BukkitItemManager extends AbstractItemManager { static { - registerVanillaItemExtraBehavior(WaterBucketItemBehavior.INSTANCE, ItemKeys.WATER_BUCKETS); - registerVanillaItemExtraBehavior(BucketItemBehavior.INSTANCE, ItemKeys.BUCKET); +// registerVanillaItemExtraBehavior(WaterBucketItemBehavior.INSTANCE, ItemKeys.WATER_BUCKETS); +// registerVanillaItemExtraBehavior(BucketItemBehavior.INSTANCE, ItemKeys.BUCKET); registerVanillaItemExtraBehavior(FlintAndSteelItemBehavior.INSTANCE, ItemKeys.FLINT_AND_STEEL); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BucketItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BucketItemBehavior.java deleted file mode 100644 index cefc0255b..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BucketItemBehavior.java +++ /dev/null @@ -1,91 +0,0 @@ -package net.momirealms.craftengine.bukkit.item.behavior; - -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; -import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.util.BlockStateUtils; -import net.momirealms.craftengine.bukkit.util.LocationUtils; -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.properties.Property; -import net.momirealms.craftengine.core.entity.player.InteractionHand; -import net.momirealms.craftengine.core.entity.player.InteractionResult; -import net.momirealms.craftengine.core.item.behavior.ItemBehavior; -import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; -import net.momirealms.craftengine.core.item.context.UseOnContext; -import net.momirealms.craftengine.core.pack.Pack; -import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.util.VersionHelper; -import net.momirealms.craftengine.core.world.BlockPos; -import org.bukkit.FluidCollisionMode; -import org.bukkit.Material; -import org.bukkit.Statistic; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.RayTraceResult; - -import java.nio.file.Path; -import java.util.Map; - -public class BucketItemBehavior extends ItemBehavior { - public static final BucketItemBehavior INSTANCE = new BucketItemBehavior(); - public static final Factory FACTORY = new Factory(); - - @Override - public InteractionResult useOnBlock(UseOnContext context) { - return use(context.getLevel(), context.getPlayer(), context.getHand()); - } - - @Override - public InteractionResult use(net.momirealms.craftengine.core.world.World world, net.momirealms.craftengine.core.entity.player.Player player, InteractionHand hand) { - if (player.isAdventureMode()) return InteractionResult.PASS; - Player bukkitPlayer = (Player) player.platformPlayer(); - RayTraceResult result = bukkitPlayer.rayTraceBlocks(player.getCachedInteractionRange(), FluidCollisionMode.SOURCE_ONLY); - if (result == null) return InteractionResult.PASS; - Block block = result.getHitBlock(); - if (block == null) return InteractionResult.PASS; - return tryFillBucket(world, player, hand, new BlockPos(block.getX(), block.getY(), block.getZ())); - } - - @SuppressWarnings("unchecked") - private InteractionResult tryFillBucket(net.momirealms.craftengine.core.world.World world, - net.momirealms.craftengine.core.entity.player.Player player, - InteractionHand hand, - BlockPos pos) { - Object nmsPos = LocationUtils.toBlockPos(pos.x(), pos.y(), pos.z()); - Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world.serverWorld(), nmsPos); - ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); - if (customState == null || customState.isEmpty()) return InteractionResult.PASS; - CustomBlock customBlock = customState.owner().value(); - Property waterlogged = (Property) customBlock.getProperty("waterlogged"); - if (waterlogged == null) return InteractionResult.PASS; - boolean waterloggedState = customState.get(waterlogged); - if (!waterloggedState) return InteractionResult.PASS; - EquipmentSlot slot = hand == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND; - FastNMS.INSTANCE.method$LevelWriter$setBlock(world.serverWorld(), nmsPos, customState.with(waterlogged, false).customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); - Player bukkitPlayer = (Player) player.platformPlayer(); - if (player.isSurvivalMode()) { - // to prevent dupe in moment - bukkitPlayer.getInventory().setItem(slot, new ItemStack(Material.AIR)); - if (VersionHelper.isFolia()) { - bukkitPlayer.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), (t) -> bukkitPlayer.getInventory().setItem(slot, new ItemStack(Material.WATER_BUCKET)), () -> {}); - } else { - BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> bukkitPlayer.getInventory().setItem(slot, new ItemStack(Material.WATER_BUCKET))); - } - } - bukkitPlayer.setStatistic(Statistic.USE_ITEM, Material.BUCKET, bukkitPlayer.getStatistic(Statistic.USE_ITEM, Material.BUCKET) + 1); - // client will assume it has sounds - // context.getPlayer().level().playBlockSound(Vec3d.atCenterOf(context.getClickedPos()), ITEM_BUCKET_FILL, 1, 1); - return InteractionResult.SUCCESS_AND_CANCEL; - } - - public static class Factory implements ItemBehaviorFactory { - @Override - public ItemBehavior create(Pack pack, Path path, Key id, Map arguments) { - return INSTANCE; - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BukkitItemBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BukkitItemBehaviors.java index b38f4c65b..902b06a80 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BukkitItemBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BukkitItemBehaviors.java @@ -8,8 +8,6 @@ public class BukkitItemBehaviors extends ItemBehaviors { public static final Key BLOCK_ITEM = Key.from("craftengine:block_item"); public static final Key ON_LIQUID_BLOCK_ITEM = Key.from("craftengine:liquid_collision_block_item"); public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item"); - public static final Key WATER_BUCKET_ITEM = Key.from("craftengine:water_bucket_item"); - public static final Key BUCKET_ITEM = Key.from("craftengine:bucket_item"); public static final Key FLINT_AND_STEEL_ITEM = Key.from("craftengine:flint_and_steel_item"); public static final Key COMPOSTABLE_ITEM = Key.from("craftengine:compostable_item"); @@ -18,8 +16,6 @@ public class BukkitItemBehaviors extends ItemBehaviors { register(BLOCK_ITEM, BlockItemBehavior.FACTORY); register(ON_LIQUID_BLOCK_ITEM, LiquidCollisionBlockItemBehavior.FACTORY); register(FURNITURE_ITEM, FurnitureItemBehavior.FACTORY); - register(WATER_BUCKET_ITEM, WaterBucketItemBehavior.FACTORY); - register(BUCKET_ITEM, BucketItemBehavior.FACTORY); register(FLINT_AND_STEEL_ITEM, FlintAndSteelItemBehavior.FACTORY); register(COMPOSTABLE_ITEM, CompostableItemBehavior.FACTORY); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/WaterBucketItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/WaterBucketItemBehavior.java deleted file mode 100644 index cb1d3d60a..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/WaterBucketItemBehavior.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.momirealms.craftengine.bukkit.item.behavior; - -import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; -import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MFluids; -import net.momirealms.craftengine.bukkit.util.BlockStateUtils; -import net.momirealms.craftengine.bukkit.util.LocationUtils; -import net.momirealms.craftengine.bukkit.world.BukkitBlockInWorld; -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.properties.Property; -import net.momirealms.craftengine.core.entity.player.InteractionResult; -import net.momirealms.craftengine.core.item.behavior.ItemBehavior; -import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; -import net.momirealms.craftengine.core.item.context.UseOnContext; -import net.momirealms.craftengine.core.pack.Pack; -import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.world.BlockPos; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; - -import java.nio.file.Path; -import java.util.Map; - -public class WaterBucketItemBehavior extends ItemBehavior { - public static final WaterBucketItemBehavior INSTANCE = new WaterBucketItemBehavior(); - public static final Factory FACTORY = new Factory(); - - // todo 需要修复不完整方块取水 - @SuppressWarnings("unchecked") - @Override - public InteractionResult useOnBlock(UseOnContext context) { - if (context.getPlayer().isAdventureMode()) return InteractionResult.PASS; - BlockPos pos = context.getClickedPos(); - BukkitBlockInWorld clicked = (BukkitBlockInWorld) context.getLevel().getBlockAt(pos); - Block block = clicked.block(); - ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData())); - if (state == null || state.isEmpty()) return InteractionResult.PASS; - CustomBlock customBlock = state.owner().value(); - Property waterlogged = (Property) customBlock.getProperty("waterlogged"); - if (waterlogged == null) return InteractionResult.PASS; - - Player player = (Player) context.getPlayer().platformPlayer(); - World world = player.getWorld(); - Location location = new Location(world, pos.x(), pos.y(), pos.z()); - - // TODO Refactor all of this because it's playing a trick with the server - ImmutableBlockState nextState = state.with(waterlogged, true); - block.setBlockData(BlockStateUtils.fromBlockData(nextState.vanillaBlockState().handle()), false); - // actually we should broadcast this change - context.getPlayer().sendPacket(BlockStateUtils.createBlockUpdatePacket(pos, state), true); - BukkitCraftEngine.instance().scheduler().sync().runDelayed(() -> { - Object blockPos = LocationUtils.toBlockPos(pos); - FastNMS.INSTANCE.method$LevelWriter$setBlock(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world), blockPos, nextState.customBlockState().handle(), UpdateOption.UPDATE_ALL.flags()); - FastNMS.INSTANCE.method$LevelAccessor$scheduleFluidTick(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world), blockPos, MFluids.WATER, 5); - }, world, location.getBlockX() >> 4, location.getBlockZ() >> 4); - return InteractionResult.SUCCESS; - } - - public static class Factory implements ItemBehaviorFactory { - @Override - public ItemBehavior create(Pack pack, Path path, Key id, Map arguments) { - return INSTANCE; - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java index cff9733d3..75c694fc3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BlockGenerator.java @@ -55,7 +55,7 @@ public final class BlockGenerator { // should always implement this interface .implement(CoreReflections.clazz$Fallable) .implement(CoreReflections.clazz$BonemealableBlock) - // TODO .implement(CoreReflections.clazz$SimpleWaterloggedBlock) + .implement(CoreReflections.clazz$SimpleWaterloggedBlock) // internal interfaces .implement(BehaviorHolder.class) .implement(ShapeHolder.class) @@ -152,7 +152,16 @@ public final class BlockGenerator { .intercept(MethodDelegation.to(OnExplosionHitInterceptor.INSTANCE)) // neighborChanged .method(ElementMatchers.is(CoreReflections.method$BlockBehaviour$neighborChanged)) - .intercept(MethodDelegation.to(NeighborChangedInterceptor.INSTANCE)); + .intercept(MethodDelegation.to(NeighborChangedInterceptor.INSTANCE)) + // pickupBlock + .method(ElementMatchers.is(CoreReflections.method$SimpleWaterloggedBlock$pickupBlock)) + .intercept(MethodDelegation.to(PickUpBlockInterceptor.INSTANCE)) + // placeLiquid + .method(ElementMatchers.is(CoreReflections.method$SimpleWaterloggedBlock$placeLiquid)) + .intercept(MethodDelegation.to(PlaceLiquidInterceptor.INSTANCE)) + // canPlaceLiquid + .method(ElementMatchers.is(CoreReflections.method$SimpleWaterloggedBlock$canPlaceLiquid)) + .intercept(MethodDelegation.to(CanPlaceLiquidInterceptor.INSTANCE)); Class clazz$CraftEngineBlock = builder.make().load(BlockGenerator.class.getClassLoader()).getLoaded(); constructor$CraftEngineBlock = MethodHandles.publicLookup().in(clazz$CraftEngineBlock) .findConstructor(clazz$CraftEngineBlock, MethodType.methodType(void.class, CoreReflections.clazz$BlockBehaviour$Properties)) @@ -468,4 +477,49 @@ public final class BlockGenerator { } } } + + public static class PickUpBlockInterceptor { + public static final PickUpBlockInterceptor INSTANCE = new PickUpBlockInterceptor(); + + @RuntimeType + public Object intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { + ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); + try { + return holder.value().pickupBlock(thisObj, args, () -> CoreReflections.instance$ItemStack$EMPTY); + } catch (Exception e) { + CraftEngine.instance().logger().severe("Failed to run pickupBlock", e); + return CoreReflections.instance$ItemStack$EMPTY; + } + } + } + + public static class PlaceLiquidInterceptor { + public static final PlaceLiquidInterceptor INSTANCE = new PlaceLiquidInterceptor(); + + @RuntimeType + public boolean intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) throws Exception { + ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); + try { + return holder.value().placeLiquid(thisObj, args, superMethod); + } catch (Exception e) { + CraftEngine.instance().logger().severe("Failed to run placeLiquid", e); + return false; + } + } + } + + public static class CanPlaceLiquidInterceptor { + public static final CanPlaceLiquidInterceptor INSTANCE = new CanPlaceLiquidInterceptor(); + + @RuntimeType + public boolean intercept(@This Object thisObj, @AllArguments Object[] args, @SuperCall Callable superMethod) { + ObjectHolder holder = ((BehaviorHolder) thisObj).getBehaviorHolder(); + try { + return holder.value().canPlaceLiquid(thisObj, args, superMethod); + } catch (Exception e) { + CraftEngine.instance().logger().severe("Failed to run canPlaceLiquid", e); + return false; + } + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java index a1dd27069..c01b5e4a8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java @@ -98,4 +98,16 @@ public abstract class BlockBehavior { public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) { return InteractionResult.PASS; } + + public Object pickupBlock(Object thisObj, Object[] args, Callable superMethod) throws Exception { + return superMethod.call(); + } + + public boolean placeLiquid(Object thisObj, Object[] args, Callable superMethod) { + return false; + } + + public boolean canPlaceLiquid(Object thisObj, Object[] args, Callable superMethod) { + return false; + } }