mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-30 12:29:15 +00:00
初步实现台阶
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<SlabType> typeProperty;
|
||||
|
||||
public SlabBlockBehavior(CustomBlock block, Property<SlabType> typeProperty) {
|
||||
super(block);
|
||||
this.typeProperty = typeProperty;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean canBeReplaced(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
SlabType type = state.get(this.typeProperty);
|
||||
Item<ItemStack> item = (Item<ItemStack>) context.getItem();
|
||||
if (type == SlabType.DOUBLE) return false;
|
||||
Optional<CustomItem<ItemStack>> itemInHand = item.getCustomItem();
|
||||
if (itemInHand.isEmpty()) return false;
|
||||
CustomItem<ItemStack> 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<Object> 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<Object> 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<Object> 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<Object> 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<String, Object> arguments) {
|
||||
Property<SlabType> type = (Property<SlabType>) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("type"), "warning.config.block.behavior.trapdoor.missing_type");
|
||||
|
||||
return new SlabBlockBehavior(block, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, Object> arguments) {
|
||||
return new StairsBlockBehavior(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ItemStack> item = (Item<ItemStack>) context.getPlayer().getItemInHand(context.getHand());
|
||||
Optional<CustomItem<ItemStack>> customItem = BukkitItemManager.instance().getCustomItem(item.id());
|
||||
if (customItem.isPresent()) {
|
||||
CustomItem<ItemStack> 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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user