From 16fea80479b65edb70af1639357d6227824aa625 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sat, 21 Jun 2025 04:41:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=E5=8F=B0?= =?UTF-8?q?=E9=98=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/BukkitBlockBehaviors.java | 4 + .../block/behavior/SlabBlockBehavior.java | 127 ++++++++++++++++++ .../block/behavior/StairsBlockBehavior.java | 23 ++++ .../UnsafeCompositeBlockBehavior.java | 21 +++ .../item/behavior/BlockItemBehavior.java | 6 +- .../bukkit/world/BukkitBlockInWorld.java | 16 +-- common-files/src/main/resources/mappings.yml | 10 ++ .../default/configuration/block_name.yml | 6 +- .../default/configuration/categories.yml | 2 + .../resources/default/configuration/i18n.yml | 4 + .../default/configuration/palm_tree.yml | 113 ++++++++++++++-- .../default/configuration/templates.yml | 68 ++++++++++ .../craftengine/core/block/BlockBehavior.java | 52 +++++-- .../core/block/EmptyBlockBehavior.java | 6 +- .../block/behavior/AbstractBlockBehavior.java | 1 + .../core/block/properties/Properties.java | 7 +- .../core/block/state/properties/SlabType.java | 7 + .../item/behavior/BlockBoundItemBehavior.java | 8 ++ .../core/item/behavior/ItemBehavior.java | 5 - 19 files changed, 435 insertions(+), 51 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SlabBlockBehavior.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StairsBlockBehavior.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/block/state/properties/SlabType.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/item/behavior/BlockBoundItemBehavior.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 70cc2a541..01c6e2200 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 @@ -23,6 +23,8 @@ public class BukkitBlockBehaviors extends BlockBehaviors { public static final Key STACKABLE_BLOCK = Key.from("craftengine:stackable_block"); public static final Key STURDY_BASE_BLOCK = Key.from("craftengine:sturdy_base_block"); public static final Key FENCE_GATE_BLOCK = Key.from("craftengine:fence_gate_block"); + public static final Key SLAB_BLOCK = Key.from("craftengine:slab_block"); + public static final Key STAIRS_BLOCK = Key.from("craftengine:stairs_block"); public static void init() { register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE); @@ -44,5 +46,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors { register(STACKABLE_BLOCK, StackableBlockBehavior.FACTORY); register(STURDY_BASE_BLOCK, SturdyBaseBlockBehavior.FACTORY); register(FENCE_GATE_BLOCK, FenceGateBlockBehavior.FACTORY); + register(SLAB_BLOCK, SlabBlockBehavior.FACTORY); + register(STAIRS_BLOCK, StairsBlockBehavior.FACTORY); } } 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 new file mode 100644 index 000000000..d8c5190a5 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SlabBlockBehavior.java @@ -0,0 +1,127 @@ +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.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.behavior.BlockBehaviorFactory; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.block.state.properties.SlabType; +import net.momirealms.craftengine.core.item.CustomItem; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.behavior.BlockBoundItemBehavior; +import net.momirealms.craftengine.core.item.behavior.ItemBehavior; +import net.momirealms.craftengine.core.item.context.BlockPlaceContext; +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 org.bukkit.inventory.ItemStack; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.Callable; + +public class SlabBlockBehavior extends BukkitBlockBehavior { + public static final Factory FACTORY = new Factory(); + private final Property typeProperty; + + public SlabBlockBehavior(CustomBlock block, Property typeProperty) { + super(block); + this.typeProperty = typeProperty; + } + + @SuppressWarnings("unchecked") + @Override + public boolean canBeReplaced(BlockPlaceContext context, ImmutableBlockState state) { + SlabType type = state.get(this.typeProperty); + Item item = (Item) context.getItem(); + if (type == SlabType.DOUBLE) return false; + Optional> itemInHand = item.getCustomItem(); + if (itemInHand.isEmpty()) return false; + CustomItem customItem = itemInHand.get(); + Key blockId = null; + for (ItemBehavior itemBehavior : customItem.behaviors()) { + if (itemBehavior instanceof BlockBoundItemBehavior behavior) { + blockId = behavior.block(); + } + } + if (blockId == null || !blockId.equals(super.customBlock.id())) return false; + if (!context.replacingClickedOnBlock()) return true; + boolean upper = context.getClickLocation().y - (double) context.getClickedPos().y() > (double) 0.5F; + Direction clickedFace = context.getClickedFace(); + return type == SlabType.BOTTOM ? + clickedFace == Direction.UP || upper && clickedFace.axis().isHorizontal() : + clickedFace == Direction.DOWN || !upper && clickedFace.axis().isHorizontal(); + } + + @Override + public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) { + BlockPos clickedPos = context.getClickedPos(); + ImmutableBlockState blockState = context.getLevel().getBlockAt(clickedPos).customBlockState(); + if (blockState != null && blockState.owner().value() == super.customBlock) { + return blockState.with(this.typeProperty, SlabType.DOUBLE).with(super.waterloggedProperty, false); + } else { + Object fluidState = FastNMS.INSTANCE.method$Level$getFluidState(context.getLevel().serverWorld(), LocationUtils.toBlockPos(clickedPos)); + state = state.with(super.waterloggedProperty, FastNMS.INSTANCE.method$FluidState$getType(fluidState) == MFluids.WATER); + Direction clickedFace = context.getClickedFace(); + return clickedFace == Direction.DOWN || clickedFace != Direction.UP && context.getClickLocation().y - (double) clickedPos.y() > (double) 0.5F ? state.with(this.typeProperty, SlabType.TOP) : state.with(this.typeProperty, SlabType.BOTTOM); + } + } + + @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); + } + + @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); + } + + @Override + public Object updateShape(Object thisBlock, Object[] args, Callable superMethod) throws Exception { + Object blockState = args[0]; + ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState)); + if (immutableBlockState == null || immutableBlockState.isEmpty()) return blockState; + if (immutableBlockState.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; + } + + @Override + 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; + if (type == CoreReflections.instance$PathComputationType$WATER) { + return state.get(this.typeProperty) != SlabType.DOUBLE && state.get(super.waterloggedProperty); + } + return false; + } + + public static class Factory implements BlockBehaviorFactory { + + @SuppressWarnings("unchecked") + @Override + public BlockBehavior create(CustomBlock block, Map arguments) { + Property type = (Property) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("type"), "warning.config.block.behavior.trapdoor.missing_type"); + + return new SlabBlockBehavior(block, type); + } + } +} 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 new file mode 100644 index 000000000..4ae6829e4 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/StairsBlockBehavior.java @@ -0,0 +1,23 @@ +package net.momirealms.craftengine.bukkit.block.behavior; + +import net.momirealms.craftengine.core.block.BlockBehavior; +import net.momirealms.craftengine.core.block.CustomBlock; +import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; + +import java.util.Map; + +public class StairsBlockBehavior extends BukkitBlockBehavior { + public static final Factory FACTORY = new Factory(); + + public StairsBlockBehavior(CustomBlock block) { + super(block); + } + + public static class Factory implements BlockBehaviorFactory { + + @Override + public BlockBehavior create(CustomBlock block, Map arguments) { + return new StairsBlockBehavior(block); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java index a92693583..946994b88 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/UnsafeCompositeBlockBehavior.java @@ -42,6 +42,17 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior { return super.useOnBlock(context, state); } + @Override + public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) { + for (AbstractBlockBehavior behavior : this.behaviors) { + InteractionResult result = behavior.useWithoutItem(context, state); + if (result != InteractionResult.PASS) { + return result; + } + } + return super.useWithoutItem(context, state); + } + @Override public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) { for (AbstractBlockBehavior behavior : this.behaviors) { @@ -189,4 +200,14 @@ public class UnsafeCompositeBlockBehavior extends BukkitBlockBehavior { behavior.setPlacedBy(context, state); } } + + @Override + public boolean canBeReplaced(BlockPlaceContext context, ImmutableBlockState state) { + for (AbstractBlockBehavior behavior : this.behaviors) { + if (!behavior.canBeReplaced(context, state)) { + return false; + } + } + return super.canBeReplaced(context, state); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java index 213c4ca49..2e071a68c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BlockItemBehavior.java @@ -17,6 +17,7 @@ import net.momirealms.craftengine.core.entity.player.InteractionHand; 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.behavior.BlockBoundItemBehavior; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; import net.momirealms.craftengine.core.item.context.BlockPlaceContext; @@ -52,7 +53,7 @@ import java.nio.file.Path; import java.util.Map; import java.util.Optional; -public class BlockItemBehavior extends ItemBehavior { +public class BlockItemBehavior extends BlockBoundItemBehavior { public static final Factory FACTORY = new Factory(); private final Key blockId; @@ -196,7 +197,8 @@ public class BlockItemBehavior extends ItemBehavior { } } - public Key blockId() { + @Override + public Key block() { return this.blockId; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitBlockInWorld.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitBlockInWorld.java index 902d082a7..80c3a3c30 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitBlockInWorld.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/BukkitBlockInWorld.java @@ -30,25 +30,11 @@ public class BukkitBlockInWorld implements BlockInWorld { this.block = block; } - @SuppressWarnings("unchecked") @Override public boolean canBeReplaced(BlockPlaceContext context) { ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(this.block.getBlockData())); if (customState != null && !customState.isEmpty()) { - Key clickedBlockId = customState.owner().value().id(); - Item item = (Item) context.getPlayer().getItemInHand(context.getHand()); - Optional> customItem = BukkitItemManager.instance().getCustomItem(item.id()); - if (customItem.isPresent()) { - CustomItem custom = customItem.get(); - for (ItemBehavior behavior : custom.behaviors()) { - if (behavior instanceof BlockItemBehavior blockItemBehavior) { - Key blockId = blockItemBehavior.blockId(); - if (blockId.equals(clickedBlockId)) { - return false; - } - } - } - } + return customState.behavior().canBeReplaced(context, customState); } return this.block.isReplaceable(); } diff --git a/common-files/src/main/resources/mappings.yml b/common-files/src/main/resources/mappings.yml index 2393811ea..02a6b556b 100644 --- a/common-files/src/main/resources/mappings.yml +++ b/common-files/src/main/resources/mappings.yml @@ -3928,26 +3928,36 @@ $$>=1.21.4#fence_gate: #### Slab #### minecraft:petrified_oak_slab[type=bottom,waterlogged=false]: minecraft:oak_slab[type=bottom,waterlogged=false] minecraft:petrified_oak_slab[type=top,waterlogged=false]: minecraft:oak_slab[type=top,waterlogged=false] +minecraft:petrified_oak_slab[type=double,waterlogged=false]: minecraft:oak_slab[type=double,waterlogged=false] minecraft:petrified_oak_slab[type=bottom,waterlogged=true]: minecraft:oak_slab[type=bottom,waterlogged=true] minecraft:petrified_oak_slab[type=top,waterlogged=true]: minecraft:oak_slab[type=top,waterlogged=true] +minecraft:petrified_oak_slab[type=double,waterlogged=true]: minecraft:oak_slab[type=double,waterlogged=true] $$>=1.20.3#slab: minecraft:cut_copper_slab[type=bottom,waterlogged=false]: minecraft:waxed_cut_copper_slab[type=bottom,waterlogged=false] minecraft:cut_copper_slab[type=top,waterlogged=false]: minecraft:waxed_cut_copper_slab[type=top,waterlogged=false] + minecraft:cut_copper_slab[type=double,waterlogged=false]: minecraft:waxed_cut_copper_slab[type=double,waterlogged=false] minecraft:cut_copper_slab[type=bottom,waterlogged=true]: minecraft:waxed_cut_copper_slab[type=bottom,waterlogged=true] minecraft:cut_copper_slab[type=top,waterlogged=true]: minecraft:waxed_cut_copper_slab[type=top,waterlogged=true] + minecraft:cut_copper_slab[type=double,waterlogged=true]: minecraft:waxed_cut_copper_slab[type=double,waterlogged=true] minecraft:exposed_cut_copper_slab[type=bottom,waterlogged=false]: minecraft:waxed_exposed_cut_copper_slab[type=bottom,waterlogged=false] minecraft:exposed_cut_copper_slab[type=top,waterlogged=false]: minecraft:waxed_exposed_cut_copper_slab[type=top,waterlogged=false] + minecraft:exposed_cut_copper_slab[type=double,waterlogged=false]: minecraft:waxed_exposed_cut_copper_slab[type=double,waterlogged=false] minecraft:exposed_cut_copper_slab[type=bottom,waterlogged=true]: minecraft:waxed_exposed_cut_copper_slab[type=bottom,waterlogged=true] minecraft:exposed_cut_copper_slab[type=top,waterlogged=true]: minecraft:waxed_exposed_cut_copper_slab[type=top,waterlogged=true] + minecraft:exposed_cut_copper_slab[type=double,waterlogged=true]: minecraft:waxed_exposed_cut_copper_slab[type=double,waterlogged=true] minecraft:weathered_cut_copper_slab[type=bottom,waterlogged=false]: minecraft:waxed_weathered_cut_copper_slab[type=bottom,waterlogged=false] minecraft:weathered_cut_copper_slab[type=top,waterlogged=false]: minecraft:waxed_weathered_cut_copper_slab[type=top,waterlogged=false] + minecraft:weathered_cut_copper_slab[type=double,waterlogged=false]: minecraft:waxed_weathered_cut_copper_slab[type=double,waterlogged=false] minecraft:weathered_cut_copper_slab[type=bottom,waterlogged=true]: minecraft:waxed_weathered_cut_copper_slab[type=bottom,waterlogged=true] minecraft:weathered_cut_copper_slab[type=top,waterlogged=true]: minecraft:waxed_weathered_cut_copper_slab[type=top,waterlogged=true] + minecraft:weathered_cut_copper_slab[type=double,waterlogged=true]: minecraft:waxed_weathered_cut_copper_slab[type=double,waterlogged=true] minecraft:oxidized_cut_copper_slab[type=bottom,waterlogged=false]: minecraft:waxed_oxidized_cut_copper_slab[type=bottom,waterlogged=false] minecraft:oxidized_cut_copper_slab[type=top,waterlogged=false]: minecraft:waxed_oxidized_cut_copper_slab[type=top,waterlogged=false] + minecraft:oxidized_cut_copper_slab[type=double,waterlogged=false]: minecraft:waxed_oxidized_cut_copper_slab[type=double,waterlogged=false] minecraft:oxidized_cut_copper_slab[type=bottom,waterlogged=true]: minecraft:waxed_oxidized_cut_copper_slab[type=bottom,waterlogged=true] minecraft:oxidized_cut_copper_slab[type=top,waterlogged=true]: minecraft:waxed_oxidized_cut_copper_slab[type=top,waterlogged=true] + minecraft:oxidized_cut_copper_slab[type=double,waterlogged=true]: minecraft:waxed_oxidized_cut_copper_slab[type=double,waterlogged=true] #### Chorus Plant #### # Chorus Plant does support transparent textures, but man... its hitbox is super weird. You're probably better off using leaves. diff --git a/common-files/src/main/resources/resources/default/configuration/block_name.yml b/common-files/src/main/resources/resources/default/configuration/block_name.yml index 7840b5e0e..5619af49a 100644 --- a/common-files/src/main/resources/resources/default/configuration/block_name.yml +++ b/common-files/src/main/resources/resources/default/configuration/block_name.yml @@ -17,6 +17,8 @@ lang: block_name:default:palm_trapdoor: Palm Trapdoor block_name:default:palm_door: Palm Door block_name:default:palm_fence_gate: Palm Fence Gate + block_name:default:palm_slab: Palm Slab + block_name:default:palm_stairs: Palm Stairs block_name:default:fairy_flower: Fairy Flower block_name:default:reed: Reed block_name:default:flame_cane: Flame Cane @@ -38,7 +40,9 @@ lang: block_name:default:palm_leaves: 棕榈树叶 block_name:default:palm_trapdoor: 棕榈木活板门 block_name:default:palm_door: 棕榈木门 - block_name:default:palm_fence_gate: 棕榈木栅门 + block_name:default:palm_fence_gate: 棕榈木栅栏门 + block_name:default:palm_slab: 棕榈木台阶 + block_name:default:palm_stairs: 棕榈木楼梯 block_name:default:fairy_flower: 仙灵花 block_name:default:reed: 芦苇 block_name:default:flame_cane: 烈焰甘蔗 diff --git a/common-files/src/main/resources/resources/default/configuration/categories.yml b/common-files/src/main/resources/resources/default/configuration/categories.yml index 2ed1200cf..87ff57ca2 100644 --- a/common-files/src/main/resources/resources/default/configuration/categories.yml +++ b/common-files/src/main/resources/resources/default/configuration/categories.yml @@ -25,6 +25,8 @@ categories: - default:palm_trapdoor - default:palm_door - default:palm_fence_gate + - default:palm_slab + - default:palm_stairs default:topaz: name: <#FF8C00> hidden: true diff --git a/common-files/src/main/resources/resources/default/configuration/i18n.yml b/common-files/src/main/resources/resources/default/configuration/i18n.yml index cdc467fac..8e39f0d8e 100644 --- a/common-files/src/main/resources/resources/default/configuration/i18n.yml +++ b/common-files/src/main/resources/resources/default/configuration/i18n.yml @@ -34,6 +34,8 @@ i18n: item.palm_trapdoor: Palm Trapdoor item.palm_door: Palm Door item.palm_fence_gate: Palm Fence Gate + item.palm_slab: Palm Slab + item.palm_stairs: Palm Stairs item.netherite_anvil: Netherite Anvil item.gunpowder_block: GunPowder Block item.solid_gunpowder_block: Solid GunPowder Block @@ -84,6 +86,8 @@ i18n: item.palm_trapdoor: 棕榈木活板门 item.palm_door: 棕榈木门 item.palm_fence_gate: 棕榈木栅栏门 + item.palm_slab: 棕榈木台阶 + item.palm_stairs: 棕榈木楼梯 item.netherite_anvil: 下界合金砧 item.gunpowder_block: 火药粉末 item.solid_gunpowder_block: 凝固火药块 diff --git a/common-files/src/main/resources/resources/default/configuration/palm_tree.yml b/common-files/src/main/resources/resources/default/configuration/palm_tree.yml index d54331d26..0230604f3 100644 --- a/common-files/src/main/resources/resources/default/configuration/palm_tree.yml +++ b/common-files/src/main/resources/resources/default/configuration/palm_tree.yml @@ -286,6 +286,8 @@ items: custom-model-data: 1006 data: item-name: + settings: + fuel-time: 300 model: type: minecraft:model path: minecraft:item/custom/palm_trapdoor @@ -339,6 +341,8 @@ items: custom-model-data: 1007 data: item-name: + settings: + fuel-time: 200 model: template: default:model/simplified_generated arguments: @@ -426,6 +430,8 @@ items: custom-model-data: 1008 data: item-name: + settings: + fuel-time: 300 model: type: minecraft:model path: minecraft:item/custom/palm_fence_gate @@ -444,17 +450,18 @@ items: loot: template: default:loot_table/self settings: - item: default:palm_fence_gate - sounds: - break: minecraft:block.wood.break - step: minecraft:block.wood.step - place: minecraft:block.wood.place - hit: minecraft:block.wood.hit - fall: minecraft:block.wood.fall - tags: - - minecraft:fence_gates - - minecraft:mineable/axe - - minecraft:unstable_bottom_center + template: + - default:sound/wood + overrides: + map-color: 2 + instrument: bass + hardness: 2.0 + resistance: 3.0 + burnable: true + tags: + - minecraft:fence_gates + - minecraft:mineable/axe + - minecraft:unstable_bottom_center states: template: default:block_state/fence_gate arguments: @@ -476,6 +483,57 @@ items: model_fence_gate_wall_open_generation: parent: minecraft:block/template_fence_gate_wall_open textures: *textures + default:palm_slab: + material: nether_brick + custom-model-data: 1009 + data: + item-name: + settings: + fuel-time: 150 + model: + type: minecraft:model + path: minecraft:item/custom/palm_slab + generation: + parent: minecraft:block/custom/palm_slab + behavior: + type: block_item + block: + behaviors: + type: slab_block + loot: + template: default:loot_table/self + settings: + template: + - default:sound/wood + - default:burn_data/planks + overrides: + map-color: 2 + instrument: bass + hardness: 2.0 + resistance: 3.0 + tags: + - minecraft:wooden_slabs + - minecraft:slabs + - minecraft:mineable/axe + states: + template: default:block_state/slab + arguments: + base_block: petrified_oak_slab + model_bottom_path: minecraft:block/custom/palm_slab + model_bottom_generation: + parent: minecraft:block/slab + textures: + bottom: minecraft:block/custom/palm_planks + side: minecraft:block/custom/palm_planks + top: minecraft:block/custom/palm_planks + model_top_path: minecraft:block/custom/palm_slab_top + model_top_generation: + parent: minecraft:block/slab_top + textures: + bottom: minecraft:block/custom/palm_planks + side: minecraft:block/custom/palm_planks + top: minecraft:block/custom/palm_planks + model_double_path: minecraft:block/custom/palm_planks recipes: default:palm_planks: template: default:recipe/planks @@ -498,4 +556,35 @@ recipes: A: default:palm_planks result: id: default:palm_trapdoor - count: 2 \ No newline at end of file + count: 2 + default:palm_fence_gate: + type: shaped + pattern: + - ABA + - ABA + ingredients: + A: minecraft:stick + B: default:palm_planks + result: + id: default:palm_fence_gate + count: 1 + default:palm_slab: + type: shaped + pattern: + - AAA + ingredients: + A: default:palm_planks + result: + id: default:palm_slab + count: 6 +# default:palm_stairs: +# type: shaped +# pattern: +# - A +# - AA +# - AAA +# ingredients: +# A: default:palm_planks +# result: +# id: default:palm_stairs +# count: 4 \ No newline at end of file diff --git a/common-files/src/main/resources/resources/default/configuration/templates.yml b/common-files/src/main/resources/resources/default/configuration/templates.yml index 8db5c7d7d..44af75694 100644 --- a/common-files/src/main/resources/resources/default/configuration/templates.yml +++ b/common-files/src/main/resources/resources/default/configuration/templates.yml @@ -2039,6 +2039,74 @@ templates#block_states: facing=north,in_wall=true,open=true,powered=false: appearance: facing=north,in_wall=true,open=true id: 31 + # slab block + default:block_state/slab: + properties: + type: + type: slab_type + default: bottom + waterlogged: + type: boolean + default: false + appearances: + type=top,waterlogged=false: + state: ${base_block}[type=top,waterlogged=false] + model: + path: ${model_top_path} + generation: ${model_top_generation} + type=bottom,waterlogged=false: + state: ${base_block}[type=bottom,waterlogged=false] + model: + path: ${model_bottom_path} + generation: ${model_bottom_generation} + type=double,waterlogged=false: + state: ${base_block}[type=double,waterlogged=false] + model: + path: ${model_double_path} + generation: ${model_double_generation} + type=top,waterlogged=true: + state: ${base_block}[type=top,waterlogged=true] + model: + path: ${model_top_path} + type=bottom,waterlogged=true: + state: ${base_block}[type=bottom,waterlogged=true] + model: + path: ${model_bottom_path} + type=double,waterlogged=true: + state: ${base_block}[type=double,waterlogged=true] + model: + path: ${model_double_path} + variants: + type=top,waterlogged=false: + appearance: type=top,waterlogged=false + id: 0 + type=bottom,waterlogged=false: + appearance: type=bottom,waterlogged=false + id: 1 + type=double,waterlogged=false: + appearance: type=double,waterlogged=false + id: 2 + type=top,waterlogged=true: + appearance: type=top,waterlogged=true + id: 3 + settings: + resistance: 1200.0 + burnable: false + fluid-state: water + type=bottom,waterlogged=true: + appearance: type=bottom,waterlogged=true + id: 4 + settings: + resistance: 1200.0 + burnable: false + fluid-state: water + type=double,waterlogged=true: + appearance: type=double,waterlogged=true + id: 5 + settings: + resistance: 1200.0 + burnable: false + fluid-state: water # recipes templates#recipes: 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 caf215f40..5fcff8d89 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 @@ -1,8 +1,14 @@ package net.momirealms.craftengine.core.block; import net.momirealms.craftengine.core.entity.player.InteractionResult; +import net.momirealms.craftengine.core.item.CustomItem; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.behavior.BlockBoundItemBehavior; +import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.item.context.UseOnContext; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.Key; import java.util.Optional; import java.util.concurrent.Callable; @@ -91,10 +97,44 @@ public abstract class BlockBehavior { public void onExplosionHit(Object thisBlock, Object[] args, Callable superMethod) { } + // LevelAccessor level, BlockPos pos, BlockState state, FluidState fluidState + public boolean placeLiquid(Object thisObj, Object[] args, Callable superMethod) { + return false; + } + + // 1.20.1 BlockGetter world, BlockPos pos, BlockState state, Fluid fluid + // 1.20.2+ LivingEntity owner, BlockGetter level, BlockPos pos, BlockState state, Fluid fluid + public boolean canPlaceLiquid(Object thisObj, Object[] args, Callable superMethod) { + return false; + } + + // 1.20.1 LivingEntity owner, LevelAccessor level, BlockPos pos, BlockState state + // 1.20.2+ LevelAccessor world, BlockPos pos, BlockState state + public Object pickupBlock(Object thisObj, Object[] args, Callable superMethod) throws Exception { + return superMethod.call(); + } + public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) { return state; } + public boolean canBeReplaced(BlockPlaceContext context, ImmutableBlockState state) { + Key clickedBlockId = state.owner().value().id(); + Item item = context.getItem(); + Optional> customItem = CraftEngine.instance().itemManager().getCustomItem(item.id()); + if (customItem.isEmpty()) return state.settings().replaceable(); + CustomItem custom = customItem.get(); + for (ItemBehavior behavior : custom.behaviors()) { + if (behavior instanceof BlockBoundItemBehavior blockItemBehavior) { + Key blockId = blockItemBehavior.block(); + if (blockId.equals(clickedBlockId)) { + return false; + } + } + } + return state.settings().replaceable(); + } + public void setPlacedBy(BlockPlaceContext context, ImmutableBlockState state) { } @@ -106,15 +146,5 @@ public abstract class BlockBehavior { 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; - } + public abstract CustomBlock block(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/EmptyBlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/EmptyBlockBehavior.java index 69fe5b246..bbc069d8a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/EmptyBlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/EmptyBlockBehavior.java @@ -1,6 +1,10 @@ package net.momirealms.craftengine.core.block; public class EmptyBlockBehavior extends BlockBehavior { - public static final EmptyBlockBehavior INSTANCE = new EmptyBlockBehavior(); + + @Override + public CustomBlock block() { + return EmptyBlock.INSTANCE; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/AbstractBlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/AbstractBlockBehavior.java index 6890677cf..dfd7f3b05 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/AbstractBlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/AbstractBlockBehavior.java @@ -10,6 +10,7 @@ public abstract class AbstractBlockBehavior extends BlockBehavior { this.customBlock = customBlock; } + @Override public CustomBlock block() { return this.customBlock; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/properties/Properties.java b/core/src/main/java/net/momirealms/craftengine/core/block/properties/Properties.java index c1a917dde..4edc88ae1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/properties/Properties.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/properties/Properties.java @@ -1,9 +1,6 @@ package net.momirealms.craftengine.core.block.properties; -import net.momirealms.craftengine.core.block.state.properties.DoorHinge; -import net.momirealms.craftengine.core.block.state.properties.DoubleBlockHalf; -import net.momirealms.craftengine.core.block.state.properties.SingleBlockHalf; -import net.momirealms.craftengine.core.block.state.properties.StairsShape; +import net.momirealms.craftengine.core.block.state.properties.*; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; @@ -24,6 +21,7 @@ public class Properties { public static final Key DOUBLE_BLOCK_HALF = Key.of("craftengine:double_block_half"); public static final Key HINGE = Key.of("craftengine:hinge"); public static final Key STAIRS_SHAPE = Key.of("craftengine:stairs_shape"); + public static final Key SLAB_TYPE = Key.of("craftengine:slab_type"); static { register(BOOLEAN, BooleanProperty.FACTORY); @@ -38,6 +36,7 @@ public class Properties { register(DOUBLE_BLOCK_HALF, new EnumProperty.Factory<>(DoubleBlockHalf.class)); register(HINGE, new EnumProperty.Factory<>(DoorHinge.class)); register(STAIRS_SHAPE, new EnumProperty.Factory<>(StairsShape.class)); + register(SLAB_TYPE, new EnumProperty.Factory<>(SlabType.class)); } public static void register(Key key, PropertyFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/state/properties/SlabType.java b/core/src/main/java/net/momirealms/craftengine/core/block/state/properties/SlabType.java new file mode 100644 index 000000000..09f4fbbfb --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/block/state/properties/SlabType.java @@ -0,0 +1,7 @@ +package net.momirealms.craftengine.core.block.state.properties; + +public enum SlabType { + TOP, + BOTTOM, + DOUBLE +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/behavior/BlockBoundItemBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/item/behavior/BlockBoundItemBehavior.java new file mode 100644 index 000000000..ee8da0cb6 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/behavior/BlockBoundItemBehavior.java @@ -0,0 +1,8 @@ +package net.momirealms.craftengine.core.item.behavior; + +import net.momirealms.craftengine.core.util.Key; + +public abstract class BlockBoundItemBehavior extends ItemBehavior { + + public abstract Key block(); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/behavior/ItemBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/item/behavior/ItemBehavior.java index cd243ad72..3c73c14e7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/behavior/ItemBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/behavior/ItemBehavior.java @@ -15,9 +15,4 @@ public abstract class ItemBehavior { public InteractionResult use(World world, Player player, InteractionHand hand) { return InteractionResult.PASS; } - - // TODO - public InteractionResult useOnEntity() { - return InteractionResult.PASS; - } }