From 89c35d2d41e202a532fc464f461584fa2c0b3b65 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 18 Jun 2025 17:24:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=B0=E5=A2=9E=E7=9A=84?= =?UTF-8?q?=E4=B8=A4=E4=B8=AA=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/api/CraftEngineBlocks.java | 4 +- .../behavior/StackableBlockBehavior.java | 50 +++++++++---------- .../behavior/SturdyBaseBlockBehavior.java | 26 +++++++--- .../src/main/resources/translations/en.yml | 1 + .../src/main/resources/translations/zh_cn.yml | 1 + 5 files changed, 48 insertions(+), 34 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java index f2ef0a2f5..f72440bf9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java @@ -13,6 +13,7 @@ import net.momirealms.craftengine.core.block.UpdateOption; 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.Key; import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldEvents; @@ -116,7 +117,8 @@ public final class CraftEngineBlocks { if (success) { FastNMS.INSTANCE.method$BlockStateBase$onPlace(blockState, worldServer, blockPos, oldBlockState, false); if (playSound) { - location.getWorld().playSound(location, block.sounds().placeSound().id().toString(), SoundCategory.BLOCKS, block.sounds().placeSound().volume(), block.sounds().placeSound().pitch()); + SoundData data = block.sounds().placeSound(); + location.getWorld().playSound(location, data.id().toString(), SoundCategory.BLOCKS, data.volume(), data.pitch()); } } return success; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StackableBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StackableBlockBehavior.java index 5ab282a28..f087036e9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StackableBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StackableBlockBehavior.java @@ -1,19 +1,20 @@ package net.momirealms.craftengine.bukkit.block.behavior; -import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.util.LocationUtils; 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.block.properties.IntegerProperty; 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.UseOnContext; import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.World; @@ -21,22 +22,19 @@ import org.bukkit.Location; import org.bukkit.SoundCategory; import org.bukkit.inventory.ItemStack; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class StackableBlockBehavior extends BukkitBlockBehavior { public static final Factory FACTORY = new Factory(); - private final Property amountProperty; - private final Set items; - private final SoundData soundData; + private final IntegerProperty amountProperty; + private final List items; + private final SoundData stackSound; - public StackableBlockBehavior(CustomBlock block,Property amountProperty, Set items, SoundData soundData) { + public StackableBlockBehavior(CustomBlock block, IntegerProperty amountProperty, List items, SoundData stackSound) { super(block); this.amountProperty = amountProperty; this.items = items; - this.soundData = soundData; + this.stackSound = stackSound; } @Override @@ -50,18 +48,17 @@ public class StackableBlockBehavior extends BukkitBlockBehavior { if (item == null) { return InteractionResult.PASS; } - if (this.items.contains(item.id()) && state.get(this.amountProperty) < this.amountProperty.possibleValues().getLast()) { + if (this.items.contains(item.id()) && state.get(this.amountProperty) < this.amountProperty.max) { ImmutableBlockState nextStage = state.cycle(this.amountProperty); World world = context.getLevel(); BlockPos pos = context.getClickedPos(); Location location = new Location((org.bukkit.World) world.platformWorld(), pos.x(), pos.y(), pos.z()); - if (CraftEngineBlocks.place(location, nextStage, UpdateOption.UPDATE_NONE, false)) { - if (soundData != null) { - location.getWorld().playSound(location, soundData.id().toString(), SoundCategory.BLOCKS, soundData.volume(), soundData.pitch()); - } - FastNMS.INSTANCE.method$ItemStack$consume(item.getLiteralObject(), 1, player.serverPlayer()); - player.swingHand(context.getHand()); + FastNMS.INSTANCE.method$LevelWriter$setBlock(world.serverWorld(), LocationUtils.toBlockPos(pos), nextStage.customBlockState().handle(), UpdateOption.UPDATE_NONE.flags()); + if (stackSound != null) { + location.getWorld().playSound(location, stackSound.id().toString(), SoundCategory.BLOCKS, stackSound.volume(), stackSound.pitch()); } + FastNMS.INSTANCE.method$ItemStack$consume(item.getLiteralObject(), 1, player.serverPlayer()); + player.swingHand(context.getHand()); return InteractionResult.SUCCESS_AND_CANCEL; } return InteractionResult.PASS; @@ -72,16 +69,15 @@ public class StackableBlockBehavior extends BukkitBlockBehavior { @Override @SuppressWarnings("unchecked") public BlockBehavior create(CustomBlock block, Map arguments) { - Property amount = (Property) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("amount"), "warning.config.block.behavior.stackable.missing_amount"); - SoundData soundData = arguments.containsKey("sound") ? SoundData.create(arguments.get("sound"), 1f, 0.8f) : null; - Set items = new HashSet<>(); - if (arguments.get("items") instanceof List list) { - for (Object obj : list) { - if (obj == null) continue; - items.add(Key.of(obj.toString())); - } + IntegerProperty amount = (IntegerProperty) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("amount"), "warning.config.block.behavior.stackable.missing_amount"); + Map sounds = (Map) arguments.get("sounds"); + SoundData stackSound = null; + if (sounds != null) { + stackSound = Optional.ofNullable(sounds.get("stack")).map(obj -> SoundData.create(obj, 1, 1)).orElse(null); } - return new StackableBlockBehavior(block, amount, items, soundData); + Object itemsObj = ResourceConfigUtils.requireNonNullOrThrow(arguments.get("items"), "warning.config.block.behavior.stackable.missing_items"); + List items = MiscUtils.getAsStringList(itemsObj).stream().map(Key::of).toList(); + return new StackableBlockBehavior(block, amount, items, stackSound); } } } 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 4916e7a2e..aca8e0baf 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,10 +1,13 @@ 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.DirectionUtils; 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.util.Direction; import net.momirealms.craftengine.core.util.ResourceConfigUtils; @@ -15,10 +18,12 @@ import java.util.Map; public class SturdyBaseBlockBehavior extends AbstractCanSurviveBlockBehavior { public static final Factory FACTORY = new Factory(); private final Direction direction; + private final boolean stackable; - public SturdyBaseBlockBehavior(CustomBlock block, int delay, Direction direction) { + public SturdyBaseBlockBehavior(CustomBlock block, int delay, Direction direction, boolean stackable) { super(block, delay); this.direction = direction; + this.stackable = stackable; } @Override @@ -28,10 +33,18 @@ public class SturdyBaseBlockBehavior extends AbstractCanSurviveBlockBehavior { int z = FastNMS.INSTANCE.field$Vec3i$z(blockPos) + this.direction.stepZ(); Object targetPos = FastNMS.INSTANCE.constructor$BlockPos(x, y, z); Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, targetPos); - return (boolean) CoreReflections.method$BlockStateBase$isFaceSturdy.invoke( - blockState, world, blockPos, DirectionUtils.toNMSDirection(this.direction.opposite()), + if ((boolean) CoreReflections.method$BlockStateBase$isFaceSturdy.invoke( + blockState, world, targetPos, DirectionUtils.toNMSDirection(this.direction.opposite()), CoreReflections.instance$SupportType$FULL - ); + )) { + return true; + } + 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; } public static class Factory implements BlockBehaviorFactory { @@ -39,8 +52,9 @@ public class SturdyBaseBlockBehavior extends AbstractCanSurviveBlockBehavior { @Override public BlockBehavior create(CustomBlock block, Map arguments) { int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay"); - Direction direction = Direction.valueOf(arguments.getOrDefault("direction", "down").toString().toUpperCase(Locale.ROOT)); - return new SturdyBaseBlockBehavior(block, delay, direction); + Direction direction = Direction.valueOf(arguments.getOrDefault("direction", "down").toString().toUpperCase(Locale.ENGLISH)); + boolean stackable = (boolean) arguments.getOrDefault("stackable", false); + return new SturdyBaseBlockBehavior(block, delay, direction, stackable); } } } diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index 39c9a8866..9b5a09aa2 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -257,6 +257,7 @@ warning.config.block.behavior.trapdoor.missing_facing: "Issue found in f warning.config.block.behavior.trapdoor.missing_open: "Issue found in file - The block '' is missing the required 'open' property for 'trapdoor_block' behavior." warning.config.block.behavior.trapdoor.missing_powered: "Issue found in file - The block '' is missing the required 'powered' property for 'trapdoor_block' behavior." warning.config.block.behavior.stackable.missing_amount: "Issue found in file - The block '' is missing the required 'amount' property for 'stackable_block' behavior." +warning.config.block.behavior.stackable.missing_items: "Issue found in file - The block '' is missing the required 'items' argument for 'stackable_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 06c93861b..3be3e86b2 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -257,6 +257,7 @@ warning.config.block.behavior.trapdoor.missing_facing: "在文件 在文件 发现问题 - 方块 '' 的 'trapdoor_block' 行为缺少必需的 'open' 属性" warning.config.block.behavior.trapdoor.missing_powered: "在文件 发现问题 - 方块 '' 的 'trapdoor_block' 行为缺少必需的 'powered' 属性" warning.config.block.behavior.stackable.missing_amount: "在文件 发现问题 - 方块 '' 的 'stackable_block' 行为缺少必需的 'amount' 属性" +warning.config.block.behavior.stackable.missing_items: "在文件 发现问题 - 方块 '' 的 'stackable_block' 行为缺少必需的 'items' 参数" warning.config.model.generation.missing_parent: "在文件 发现问题 - 配置项 '' 的 'generation' 段落缺少必需的 'parent' 参数" warning.config.model.generation.conflict: "在文件 发现问题 - 无法为 '' 生成模型 存在多个配置尝试使用相同路径 '' 生成不同的 JSON 模型" warning.config.model.generation.invalid_display_position: "在文件 发现问题 - 配置项 '' 在 'generation.display' 区域使用了无效的 display 位置类型 ''. 可用展示类型: []"