From 8d4b9e3705aabaf68143ac1fd348265eeba29b66 Mon Sep 17 00:00:00 2001 From: Catnies Date: Sun, 6 Jul 2025 12:05:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EDoubleBlockBehavior.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/BukkitBlockBehaviors.java | 2 + .../block/behavior/DoubleBlockBehavior.java | 90 +++++++++++++++++++ .../src/main/resources/translations/en.yml | 1 + .../src/main/resources/translations/zh_cn.yml | 1 + 4 files changed, 94 insertions(+) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoubleBlockBehavior.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java index 30b980508..3f1d586b7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java @@ -26,6 +26,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors { public static final Key SLAB_BLOCK = Key.from("craftengine:slab_block"); public static final Key STAIRS_BLOCK = Key.from("craftengine:stairs_block"); public static final Key PRESSURE_PLATE_BLOCK = Key.from("craftengine:pressure_plate_block"); + public static final Key DOUBLE_BLOCK = Key.from("craftengine:double_block"); public static void init() { register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE); @@ -50,5 +51,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors { register(SLAB_BLOCK, SlabBlockBehavior.FACTORY); register(STAIRS_BLOCK, StairsBlockBehavior.FACTORY); register(PRESSURE_PLATE_BLOCK, PressurePlateBlockBehavior.FACTORY); + register(DOUBLE_BLOCK, DoubleBlockBehavior.FACTORY); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoubleBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoubleBlockBehavior.java new file mode 100644 index 000000000..bf8a57526 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoubleBlockBehavior.java @@ -0,0 +1,90 @@ +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.MBlocks; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.bukkit.util.LocationUtils; +import net.momirealms.craftengine.bukkit.world.BukkitWorld; +import net.momirealms.craftengine.core.block.*; +import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.block.state.properties.DoubleBlockHalf; +import net.momirealms.craftengine.core.item.context.BlockPlaceContext; +import net.momirealms.craftengine.core.util.Direction; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.*; + +import java.util.Map; +import java.util.concurrent.Callable; + + +public class DoubleBlockBehavior extends BukkitBlockBehavior { + public static final Factory FACTORY = new Factory(); + private final Property halfProperty; + + public DoubleBlockBehavior(CustomBlock customBlock, Property halfProperty) { + super(customBlock); + this.halfProperty = halfProperty; + } + + @Override + public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + Object level = args[updateShape$level]; + Object blockPos = args[updateShape$blockPos]; + Object blockState = args[0]; + + ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); + if (customState == null || customState.isEmpty()) return blockState; + DoubleBlockHalf half = customState.get(this.halfProperty); + if (half == null) return blockState; + + // 获取另一半 + Object anotherHalfPos = FastNMS.INSTANCE.method$BlockPos$relative(blockPos, + half == DoubleBlockHalf.UPPER + ? CoreReflections.instance$Direction$DOWN + : CoreReflections.instance$Direction$UP + ); + Object anotherHalfState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, anotherHalfPos); + ImmutableBlockState anotherHalfCustomState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(anotherHalfState)); + if (anotherHalfCustomState != null && !anotherHalfCustomState.isEmpty()) return blockState; + + // 破坏 + 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)); + world.playBlockSound(position, customState.settings().sounds().breakSound()); + FastNMS.INSTANCE.method$Level$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId()); + return MBlocks.AIR$defaultState; + } + + @Override + public void setPlacedBy(BlockPlaceContext context, ImmutableBlockState state) { + World level = context.getLevel(); + BlockPos anotherHalfPos = context.getClickedPos().relative(Direction.UP); + BlockStateWrapper blockStateWrapper = state.with(this.halfProperty, DoubleBlockHalf.UPPER).customBlockState(); + FastNMS.INSTANCE.method$LevelWriter$setBlock(level.serverWorld(), LocationUtils.toBlockPos(anotherHalfPos), blockStateWrapper.handle(), UpdateOption.Flags.UPDATE_CLIENTS); + } + + @Override + public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) { + World world = context.getLevel(); + BlockPos pos = context.getClickedPos(); + if (pos.y() < context.getLevel().worldHeight().getMaxBuildHeight() && world.getBlockAt(pos.above()).canBeReplaced(context)) { + return state.with(this.halfProperty, DoubleBlockHalf.LOWER); + } + return null; + } + + @SuppressWarnings("unchecked") + public static class Factory implements BlockBehaviorFactory { + + @Override + public BlockBehavior create(CustomBlock block, Map arguments) { + Property half = (Property) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("half"), "warning.config.block.behavior.double.missing_half"); + return new DoubleBlockBehavior(block, half); + } + } +} diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index 4806888c3..b6bb8ac81 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -282,6 +282,7 @@ warning.config.block.behavior.stairs.missing_half: "Issue found in file warning.config.block.behavior.stairs.missing_shape: "Issue found in file - The block '' is missing the required 'shape' property for 'stairs_block' behavior." warning.config.block.behavior.pressure_plate.missing_powered: "Issue found in file - The block '' is missing the required 'powered' property for 'pressure_plate_block' behavior." warning.config.block.behavior.grass.missing_feature: "Issue found in file - The block '' is missing the required 'feature' argument for 'grass_block' behavior." +warning.config.block.behavior.double.missing_half: "Issue found in file - The block '' is missing the required 'half' property for 'double_block' behavior." warning.config.model.generation.missing_parent: "Issue found in file - The config '' is missing the required 'parent' argument in 'generation' section." warning.config.model.generation.invalid_display_position: "Issue found in file - The config '' is using an invalid display position '' in 'generation.display' section. Allowed display positions: []" warning.config.model.generation.invalid_gui_light: "Issue found in file - The config '' is using an invalid gui-light option '' in 'generation' section. Allowed gui light options: []" diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index b0c543e5b..56a24600f 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -282,6 +282,7 @@ warning.config.block.behavior.stairs.missing_half: "在文件 warning.config.block.behavior.stairs.missing_shape: "在文件 发现问题 - 方块 '' 的 'stairs_block' 行为缺少必需的 'shape' 属性" warning.config.block.behavior.pressure_plate.missing_powered: "在文件 发现问题 - 方块 '' 的 'pressure_plate_block' 行为缺少必需的 'powered' 属性" warning.config.block.behavior.grass.missing_feature: "在文件 发现问题 - 方块 '' 的 'grass_block' 行为缺少必需的 'feature' 参数" +warning.config.block.behavior.double.missing_half: "在文件 发现问题 - 方块 '' 的 'double_block' 行为缺少必需的 'half' 属性" warning.config.model.generation.missing_parent: "在文件 发现问题 - 配置项 '' 的 'generation' 段落缺少必需的 'parent' 参数" warning.config.model.generation.conflict: "在文件 发现问题 - 无法为 '' 生成模型 存在多个配置尝试使用相同路径 '' 生成不同的 JSON 模型" warning.config.model.generation.invalid_display_position: "在文件 发现问题 - 配置项 '' 在 'generation.display' 区域使用了无效的 display 位置类型 ''. 可用展示类型: []"