mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-04 15:41:38 +00:00
@@ -36,6 +36,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key LIQUID_FLOWABLE_BLOCK = Key.from("craftengine:liquid_flowable_block");
|
||||
public static final Key SIMPLE_PARTICLE_BLOCK = Key.from("craftengine:simple_particle_block");
|
||||
public static final Key WALL_TORCH_PARTICLE_BLOCK = Key.from("craftengine:wall_torch_particle_block");
|
||||
public static final Key FENCE_BLOCK = Key.from("craftengine:fence_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -70,5 +71,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(LIQUID_FLOWABLE_BLOCK, LiquidFlowableBlockBehavior.FACTORY);
|
||||
register(SIMPLE_PARTICLE_BLOCK, SimpleParticleBlockBehavior.FACTORY);
|
||||
register(WALL_TORCH_PARTICLE_BLOCK, WallTorchParticleBlockBehavior.FACTORY);
|
||||
register(FENCE_BLOCK, FenceBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ 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.BlockTags;
|
||||
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.core.block.BlockBehavior;
|
||||
@@ -13,24 +14,41 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class DirectionalAttachedBlockBehavior extends BukkitBlockBehavior {
|
||||
public class DirectionalAttachedBlockBehavior extends AbstractCanSurviveBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final Property<?> facingProperty;
|
||||
private final boolean isSixDirection;
|
||||
private final List<Object> tagsCanSurviveOn;
|
||||
private final Set<Object> blockStatesCanSurviveOn;
|
||||
private final Set<String> customBlocksCansSurviveOn;
|
||||
private final boolean blacklistMode;
|
||||
|
||||
public DirectionalAttachedBlockBehavior(CustomBlock customBlock, Property<?> facingProperty, boolean isSixDirection) {
|
||||
super(customBlock);
|
||||
public DirectionalAttachedBlockBehavior(CustomBlock customBlock,
|
||||
Property<?> facingProperty,
|
||||
boolean isSixDirection,
|
||||
int delay,
|
||||
boolean blacklist,
|
||||
List<Object> tagsCanSurviveOn,
|
||||
Set<Object> blockStatesCanSurviveOn,
|
||||
Set<String> customBlocksCansSurviveOn) {
|
||||
super(customBlock, delay);
|
||||
this.facingProperty = facingProperty;
|
||||
this.isSixDirection = isSixDirection;
|
||||
this.tagsCanSurviveOn = tagsCanSurviveOn;
|
||||
this.blockStatesCanSurviveOn = blockStatesCanSurviveOn;
|
||||
this.customBlocksCansSurviveOn = customBlocksCansSurviveOn;
|
||||
this.blacklistMode = blacklist;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,8 +69,8 @@ public class DirectionalAttachedBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(args[0]).orElse(null);
|
||||
protected boolean canSurvive(Object thisBlock, Object blockState, Object world, Object pos) throws Exception {
|
||||
ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(blockState).orElse(null);
|
||||
if (state == null) return false;
|
||||
DirectionalAttachedBlockBehavior behavior = state.behavior().getAs(DirectionalAttachedBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) return false;
|
||||
@@ -62,10 +80,34 @@ public class DirectionalAttachedBlockBehavior extends BukkitBlockBehavior {
|
||||
} else {
|
||||
direction = ((HorizontalDirection) state.get(behavior.facingProperty)).opposite().toDirection();
|
||||
}
|
||||
BlockPos blockPos = LocationUtils.fromBlockPos(args[2]).relative(direction);
|
||||
BlockPos blockPos = LocationUtils.fromBlockPos(pos).relative(direction);
|
||||
Object nmsPos = LocationUtils.toBlockPos(blockPos);
|
||||
Object nmsState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(args[1], nmsPos);
|
||||
return FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy(nmsState, args[1], nmsPos, DirectionUtils.toNMSDirection(direction), CoreReflections.instance$SupportType$FULL);
|
||||
Object nmsState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, nmsPos);
|
||||
return FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy(nmsState, world, nmsPos, DirectionUtils.toNMSDirection(direction), CoreReflections.instance$SupportType$FULL)
|
||||
&& mayPlaceOn(nmsState);
|
||||
}
|
||||
|
||||
private boolean mayPlaceOn(Object state) {
|
||||
for (Object tag : this.tagsCanSurviveOn) {
|
||||
if (FastNMS.INSTANCE.method$BlockStateBase$is(state, tag)) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
}
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(state);
|
||||
if (optionalCustomState.isEmpty()) {
|
||||
if (!this.blockStatesCanSurviveOn.isEmpty() && this.blockStatesCanSurviveOn.contains(state)) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
} else {
|
||||
ImmutableBlockState belowCustomState = optionalCustomState.get();
|
||||
if (this.customBlocksCansSurviveOn.contains(belowCustomState.owner().value().id().toString())) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
if (this.customBlocksCansSurviveOn.contains(belowCustomState.toString())) {
|
||||
return !this.blacklistMode;
|
||||
}
|
||||
}
|
||||
return this.blacklistMode;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -101,7 +143,37 @@ public class DirectionalAttachedBlockBehavior extends BukkitBlockBehavior {
|
||||
if (!(isHorizontalDirection || isDirection)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.behavior.surface_attached.missing_facing");
|
||||
}
|
||||
return new DirectionalAttachedBlockBehavior(block, facing, isDirection);
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments);
|
||||
int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay");
|
||||
boolean blacklistMode = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("blacklist", true), "blacklist");
|
||||
return new DirectionalAttachedBlockBehavior(block, facing, isDirection, delay, blacklistMode, tuple.left(), tuple.mid(), tuple.right());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private static Tuple<List<Object>, Set<Object>, Set<String>> readTagsAndState(Map<String, Object> arguments) {
|
||||
List<Object> mcTags = new ArrayList<>();
|
||||
for (String tag : MiscUtils.getAsStringList(arguments.getOrDefault("attached-block-tags", List.of()))) {
|
||||
mcTags.add(BlockTags.getOrCreate(Key.of(tag)));
|
||||
}
|
||||
Set<Object> mcBlocks = new HashSet<>();
|
||||
Set<String> customBlocks = new HashSet<>();
|
||||
for (String blockStateStr : MiscUtils.getAsStringList(arguments.getOrDefault("attached-blocks", List.of()))) {
|
||||
int index = blockStateStr.indexOf('[');
|
||||
Key blockType = index != -1 ? Key.from(blockStateStr.substring(0, index)) : Key.from(blockStateStr);
|
||||
Material material = Registry.MATERIAL.get(new NamespacedKey(blockType.namespace(), blockType.value()));
|
||||
if (material != null) {
|
||||
if (index == -1) {
|
||||
// vanilla
|
||||
mcBlocks.addAll(BlockStateUtils.getAllVanillaBlockStates(blockType));
|
||||
} else {
|
||||
mcBlocks.add(BlockStateUtils.blockDataToBlockState(Bukkit.createBlockData(blockStateStr)));
|
||||
}
|
||||
} else {
|
||||
// custom maybe
|
||||
customBlocks.add(blockStateStr);
|
||||
}
|
||||
}
|
||||
return new Tuple<>(mcTags, mcBlocks, customBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
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.MRegistries;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MTagKeys;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.core.block.*;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.BooleanProperty;
|
||||
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.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.HorizontalDirection;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class FenceBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final BooleanProperty northProperty;
|
||||
private final BooleanProperty eastProperty;
|
||||
private final BooleanProperty southProperty;
|
||||
private final BooleanProperty westProperty;
|
||||
private final Object connectableBlockTag;
|
||||
private final boolean canLeash;
|
||||
|
||||
public FenceBlockBehavior(CustomBlock customBlock,
|
||||
BooleanProperty northProperty,
|
||||
BooleanProperty eastProperty,
|
||||
BooleanProperty southProperty,
|
||||
BooleanProperty westProperty,
|
||||
Object connectableBlockTag,
|
||||
boolean canLeash) {
|
||||
super(customBlock);
|
||||
this.northProperty = northProperty;
|
||||
this.eastProperty = eastProperty;
|
||||
this.southProperty = southProperty;
|
||||
this.westProperty = westProperty;
|
||||
this.connectableBlockTag = connectableBlockTag;
|
||||
this.canLeash = canLeash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPathFindable(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean connectsTo(BlockStateWrapper state, boolean isSideSolid, HorizontalDirection direction) {
|
||||
boolean isSameFence = this.isSameFence(state);
|
||||
boolean flag = CoreReflections.clazz$FenceGateBlock.isInstance(BlockStateUtils.getBlockOwner(state.literalObject()))
|
||||
? FastNMS.INSTANCE.method$FenceGateBlock$connectsToDirection(state.literalObject(), DirectionUtils.toNMSDirection(direction.toDirection()))
|
||||
: FenceGateBlockBehavior.connectsToDirection(state, direction);
|
||||
return !BlockUtils.isExceptionForConnection(state) && isSideSolid || isSameFence || flag;
|
||||
}
|
||||
|
||||
private boolean isSameFence(BlockStateWrapper state) {
|
||||
Object blockState = state.literalObject();
|
||||
return FastNMS.INSTANCE.method$BlockStateBase$is(blockState, MTagKeys.Block$FENCES)
|
||||
&& FastNMS.INSTANCE.method$BlockStateBase$is(blockState, this.connectableBlockTag)
|
||||
== FastNMS.INSTANCE.method$BlockStateBase$is(this.customBlock.defaultState().customBlockState().literalObject(), this.connectableBlockTag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) {
|
||||
if (!this.canLeash) return InteractionResult.PASS;
|
||||
Player player = context.getPlayer();
|
||||
if (player == null) return InteractionResult.PASS;
|
||||
if (FastNMS.INSTANCE.method$LeadItem$bindPlayerMobs(player.serverPlayer(), context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()))) {
|
||||
player.swingHand(InteractionHand.MAIN_HAND);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
World level = context.getLevel();
|
||||
BlockPos clickedPos = context.getClickedPos();
|
||||
Object fluidState = FastNMS.INSTANCE.method$BlockGetter$getFluidState(level.serverWorld(), LocationUtils.toBlockPos(clickedPos));
|
||||
BlockPos blockPos = clickedPos.north();
|
||||
BlockPos blockPos1 = clickedPos.east();
|
||||
BlockPos blockPos2 = clickedPos.south();
|
||||
BlockPos blockPos3 = clickedPos.west();
|
||||
BlockStateWrapper blockState = level.getBlockAt(blockPos).blockState();
|
||||
BlockStateWrapper blockState1 = level.getBlockAt(blockPos1).blockState();
|
||||
BlockStateWrapper blockState2 = level.getBlockAt(blockPos2).blockState();
|
||||
BlockStateWrapper blockState3 = level.getBlockAt(blockPos3).blockState();
|
||||
BooleanProperty waterlogged = (BooleanProperty) state.owner().value().getProperty("waterlogged");
|
||||
if (waterlogged != null) {
|
||||
state = state.with(waterlogged, FastNMS.INSTANCE.method$FluidState$getType(fluidState) == MFluids.WATER);
|
||||
}
|
||||
return state
|
||||
.with(this.northProperty, this.connectsTo(blockState, FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy(blockState.literalObject(), level.serverWorld(), LocationUtils.toBlockPos(blockPos), CoreReflections.instance$Direction$SOUTH, CoreReflections.instance$SupportType$FULL), HorizontalDirection.SOUTH))
|
||||
.with(this.eastProperty, this.connectsTo(blockState1, FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy(blockState1.literalObject(), level.serverWorld(), LocationUtils.toBlockPos(blockPos1), CoreReflections.instance$Direction$WEST, CoreReflections.instance$SupportType$FULL), HorizontalDirection.WEST))
|
||||
.with(this.southProperty, this.connectsTo(blockState2, FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy(blockState2.literalObject(), level.serverWorld(), LocationUtils.toBlockPos(blockPos2), CoreReflections.instance$Direction$NORTH, CoreReflections.instance$SupportType$FULL), HorizontalDirection.NORTH))
|
||||
.with(this.westProperty, this.connectsTo(blockState3, FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy(blockState3.literalObject(), level.serverWorld(), LocationUtils.toBlockPos(blockPos3), CoreReflections.instance$Direction$EAST, CoreReflections.instance$SupportType$FULL), HorizontalDirection.EAST));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Optional<ImmutableBlockState> optionalState = BlockStateUtils.getOptionalCustomBlockState(args[0]);
|
||||
BooleanProperty waterlogged = (BooleanProperty) optionalState
|
||||
.map(BlockStateHolder::owner)
|
||||
.map(Holder::value)
|
||||
.map(block -> block.getProperty("waterlogged"))
|
||||
.orElse(null);
|
||||
if (waterlogged != null) {
|
||||
FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleFluidTick(args[updateShape$level], args[updateShape$blockPos], MFluids.WATER, 5);
|
||||
}
|
||||
if (DirectionUtils.fromNMSDirection(args[updateShape$direction]).axis().isHorizontal() && optionalState.isPresent()) {
|
||||
Direction direction = DirectionUtils.fromNMSDirection(args[updateShape$direction]);
|
||||
ImmutableBlockState state = optionalState.get();
|
||||
if (state.owner() != null) {
|
||||
BooleanProperty booleanProperty = (BooleanProperty) state.owner().value().getProperty(direction.name().toLowerCase(Locale.ROOT));
|
||||
if (booleanProperty != null) {
|
||||
BlockStateWrapper wrapper = BlockStateUtils.toBlockStateWrapper(args[updateShape$neighborState]);
|
||||
return state.with(booleanProperty, this.connectsTo(wrapper, FastNMS.INSTANCE.method$BlockStateBase$isFaceSturdy(wrapper.literalObject(), args[updateShape$level], args[5], DirectionUtils.toNMSDirection(direction.opposite()), CoreReflections.instance$SupportType$FULL), direction.opposite().toHorizontalDirection())).customBlockState().literalObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
return superMethod.call();
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
BooleanProperty north = (BooleanProperty) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("north"), "warning.config.block.behavior.fence.missing_north");
|
||||
BooleanProperty east = (BooleanProperty) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("east"), "warning.config.block.behavior.fence.missing_east");
|
||||
BooleanProperty south = (BooleanProperty) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("south"), "warning.config.block.behavior.fence.missing_south");
|
||||
BooleanProperty west = (BooleanProperty) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("west"), "warning.config.block.behavior.fence.missing_west");
|
||||
Object connectableBlockTag = FastNMS.INSTANCE.method$TagKey$create(MRegistries.BLOCK, KeyUtils.toResourceLocation(Key.of(arguments.getOrDefault("connectable-block-tag", "minecraft:wooden_fences").toString())));
|
||||
connectableBlockTag = connectableBlockTag != null ? connectableBlockTag : MTagKeys.Block$WOODEN_FENCES;
|
||||
boolean canLeash = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("can-leash", false), "can-leash");
|
||||
return new FenceBlockBehavior(block, north, east, south, west, connectableBlockTag, canLeash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,7 @@ import net.momirealms.craftengine.bukkit.util.DirectionUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.InteractUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
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.*;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
@@ -262,6 +259,22 @@ public class FenceGateBlockBehavior extends BukkitBlockBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean connectsToDirection(BlockStateWrapper state, HorizontalDirection direction) {
|
||||
FenceGateBlockBehavior fence = BlockStateUtils.getOptionalCustomBlockState(state.literalObject())
|
||||
.map(ImmutableBlockState::behavior)
|
||||
.flatMap(behavior -> behavior.getAs(FenceGateBlockBehavior.class))
|
||||
.orElse(null);
|
||||
if (fence == null) return false;
|
||||
Direction facing = null;
|
||||
ImmutableBlockState customState = BlockStateUtils.getOptionalCustomBlockState(state.literalObject()).orElse(null);
|
||||
if (customState == null) return false;
|
||||
Property<?> facingProperty = customState.owner().value().getProperty("facing");
|
||||
if (facingProperty != null && facingProperty.valueClass() == HorizontalDirection.class) {
|
||||
facing = ((HorizontalDirection) customState.get(facingProperty)).toDirection();
|
||||
}
|
||||
return facing != null && facing.axis() == direction.toDirection().clockWise().axis();
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4393,4 +4393,11 @@ public final class CoreReflections {
|
||||
public static final Constructor<?> constructor$AdvancementHolder = Optional.ofNullable(clazz$AdvancementHolder)
|
||||
.map(it -> ReflectionUtils.getConstructor(it, clazz$ResourceLocation, clazz$Advancement))
|
||||
.orElse(null);
|
||||
|
||||
public static final Class<?> clazz$FenceGateBlock = requireNonNull(
|
||||
BukkitReflectionUtils.findReobfOrMojmapClass(
|
||||
"world.level.block.BlockFenceGate",
|
||||
"world.level.block.FenceGateBlock"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ public final class MBlocks {
|
||||
public static final Object WATER$defaultState;
|
||||
public static final Object TNT;
|
||||
public static final Object TNT$defaultState;
|
||||
public static final Object BARRIER;
|
||||
public static final Object CARVED_PUMPKIN;
|
||||
public static final Object JACK_O_LANTERN;
|
||||
public static final Object MELON;
|
||||
public static final Object PUMPKIN;
|
||||
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
@@ -45,5 +50,10 @@ public final class MBlocks {
|
||||
WATER$defaultState = FastNMS.INSTANCE.method$Block$defaultState(WATER);
|
||||
TNT = getById("tnt");
|
||||
TNT$defaultState = FastNMS.INSTANCE.method$Block$defaultState(TNT);
|
||||
BARRIER = getById("barrier");
|
||||
CARVED_PUMPKIN = getById("carved_pumpkin");
|
||||
JACK_O_LANTERN = getById("jack_o_lantern");
|
||||
MELON = getById("melon");
|
||||
PUMPKIN = getById("pumpkin");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ public final class MTagKeys {
|
||||
|
||||
public static final Object Item$WOOL = create(MRegistries.ITEM, "wool");
|
||||
public static final Object Block$WALLS = create(MRegistries.BLOCK, "walls");
|
||||
public static final Object Block$SHULKER_BOXES = create(MRegistries.BLOCK, "shulker_boxes");
|
||||
public static final Object Block$FENCES = create(MRegistries.BLOCK, "fences");
|
||||
public static final Object Block$WOODEN_FENCES = create(MRegistries.BLOCK, "wooden_fences");
|
||||
|
||||
private static Object create(Object registry, String location) {
|
||||
Object resourceLocation = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", location);
|
||||
|
||||
@@ -45,8 +45,12 @@ public final class BlockStateUtils {
|
||||
|
||||
public static BlockStateWrapper toBlockStateWrapper(BlockData blockData) {
|
||||
Object state = blockDataToBlockState(blockData);
|
||||
int id = blockStateToId(state);
|
||||
return new BukkitBlockStateWrapper(state, id);
|
||||
return toBlockStateWrapper(state);
|
||||
}
|
||||
|
||||
public static BlockStateWrapper toBlockStateWrapper(Object blockState) {
|
||||
int id = blockStateToId(blockState);
|
||||
return new BukkitBlockStateWrapper(blockState, id);
|
||||
}
|
||||
|
||||
public static boolean isCorrectTool(@NotNull ImmutableBlockState state, @Nullable Item<ItemStack> itemInHand) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
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.plugin.reflection.minecraft.MTagKeys;
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
|
||||
public final class BlockUtils {
|
||||
private BlockUtils() {}
|
||||
|
||||
public static boolean isExceptionForConnection(BlockStateWrapper state) {
|
||||
Object blockState = state.literalObject();
|
||||
return CoreReflections.clazz$LeavesBlock.isInstance(BlockStateUtils.getBlockOwner(blockState))
|
||||
|| FastNMS.INSTANCE.method$BlockStateBase$isBlock(blockState, MBlocks.BARRIER)
|
||||
|| FastNMS.INSTANCE.method$BlockStateBase$isBlock(blockState, MBlocks.CARVED_PUMPKIN)
|
||||
|| FastNMS.INSTANCE.method$BlockStateBase$isBlock(blockState, MBlocks.JACK_O_LANTERN)
|
||||
|| FastNMS.INSTANCE.method$BlockStateBase$isBlock(blockState, MBlocks.MELON)
|
||||
|| FastNMS.INSTANCE.method$BlockStateBase$isBlock(blockState, MBlocks.PUMPKIN)
|
||||
|| FastNMS.INSTANCE.method$BlockStateBase$is(blockState, MTagKeys.Block$SHULKER_BOXES);
|
||||
}
|
||||
}
|
||||
@@ -321,6 +321,10 @@ warning.config.block.behavior.double_high.missing_half: "<yellow>Issue found in
|
||||
warning.config.block.behavior.change_over_time.missing_next_block: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'next_block' argument for 'change_over_time_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.surface_attached.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'surface_attached_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.wall_torch_particle.missing_facing: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'facing' property for 'wall_torch_particle_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.fence.missing_north: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'north' property for 'fence_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.fence.missing_east: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'east' property for 'fence_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.fence.missing_south: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'south' property for 'fence_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.fence.missing_west: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'west' property for 'fence_block' behavior.</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is missing the required 'parent' argument in 'generation' section.</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>Issue found in file <arg:0> - Failed to generate model for '<arg:1>' as two or more configurations attempt to generate different json models with the same path: '<arg:2>'.</yellow>"
|
||||
warning.config.model.generation.invalid_display_position: "<yellow>Issue found in file <arg:0> - The config '<arg:1>' is using an invalid display position '<arg:2>' in 'generation.display' section. Allowed display positions: [<arg:3>]</yellow>"
|
||||
|
||||
@@ -315,6 +315,10 @@ warning.config.block.behavior.double_high.missing_half: "<yellow>在文件 <arg:
|
||||
warning.config.block.behavior.change_over_time.missing_next_block: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'change_over_time_block' 行为缺少必需的 'next-block' 参数</yellow>"
|
||||
warning.config.block.behavior.surface_attached.missing_facing: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'surface_attached_block' 行为缺少必需的 'facing' 属性</yellow>"
|
||||
warning.config.block.behavior.wall_torch_particle.missing_facing: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'wall_torch_particle_block' 行为缺少必需的 'facing' 属性</yellow>"
|
||||
warning.config.block.behavior.fence.missing_north: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'fence_block' 行为缺少必需的 'north' 属性</yellow>"
|
||||
warning.config.block.behavior.fence.missing_east: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'fence_block' 行为缺少必需的 'east' 属性</yellow>"
|
||||
warning.config.block.behavior.fence.missing_south: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'fence_block' 行为缺少必需的 'south' 属性</yellow>"
|
||||
warning.config.block.behavior.fence.missing_west: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'fence_block' 行为缺少必需的 'west' 属性</yellow>"
|
||||
warning.config.model.generation.missing_parent: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 的 'generation' 段落缺少必需的 'parent' 参数</yellow>"
|
||||
warning.config.model.generation.conflict: "<yellow>在文件 <arg:0> 发现问题 - 无法为 '<arg:1>' 生成模型 存在多个配置尝试使用相同路径 '<arg:2>' 生成不同的 JSON 模型</yellow>"
|
||||
warning.config.model.generation.invalid_display_position: "<yellow>在文件 <arg:0> 发现问题 - 配置项 '<arg:1>' 在 'generation.display' 区域使用了无效的 display 位置类型 '<arg:2>'. 可用展示类型: [<arg:3>]</yellow>"
|
||||
|
||||
@@ -55,4 +55,48 @@ public class BlockPos extends Vec3i {
|
||||
public BlockPos offset(int x, int y, int z) {
|
||||
return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.x() + x, this.y() + y, this.z() + z);
|
||||
}
|
||||
|
||||
public BlockPos immutable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos north() {
|
||||
return new BlockPos(this.x(), this.y(), this.z() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos north(int distance) {
|
||||
return distance == 0 ? this.immutable() : new BlockPos(this.x(), this.y(), this.z() - distance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos south() {
|
||||
return new BlockPos(this.x(), this.y(), this.z() + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos south(int distance) {
|
||||
return distance == 0 ? this.immutable() : new BlockPos(this.x(), this.y(), this.z() + distance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos west() {
|
||||
return new BlockPos(this.x() - 1, this.y(), this.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos west(int distance) {
|
||||
return distance == 0 ? this.immutable() : new BlockPos(this.x() - distance, this.y(), this.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos east() {
|
||||
return new BlockPos(this.x() + 1, this.y(), this.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos east(int distance) {
|
||||
return distance == 0 ? this.immutable() : new BlockPos(this.x() + distance, this.y(), this.z());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,4 +92,37 @@ public class Vec3i implements Comparable<Vec3i> {
|
||||
return this.y() - vec3i.y();
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3i north() {
|
||||
return this.north(1);
|
||||
}
|
||||
|
||||
public Vec3i north(int distance) {
|
||||
return this.relative(Direction.NORTH, distance);
|
||||
}
|
||||
|
||||
public Vec3i south() {
|
||||
return this.south(1);
|
||||
}
|
||||
|
||||
public Vec3i south(int distance) {
|
||||
return this.relative(Direction.SOUTH, distance);
|
||||
}
|
||||
|
||||
public Vec3i west() {
|
||||
return this.west(1);
|
||||
}
|
||||
|
||||
public Vec3i west(int distance) {
|
||||
return this.relative(Direction.WEST, distance);
|
||||
}
|
||||
|
||||
public Vec3i east() {
|
||||
return this.east(1);
|
||||
}
|
||||
|
||||
public Vec3i east(int distance) {
|
||||
return this.relative(Direction.EAST, distance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ org.gradle.jvmargs=-Xmx1G
|
||||
# Project settings
|
||||
# Rule: [major update].[feature update].[bug fix]
|
||||
project_version=0.0.63.3
|
||||
config_version=45
|
||||
lang_version=29
|
||||
config_version=46
|
||||
lang_version=30
|
||||
project_group=net.momirealms
|
||||
latest_supported_version=1.21.8
|
||||
|
||||
@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
|
||||
ahocorasick_version=0.6.3
|
||||
snake_yaml_version=2.5
|
||||
anti_grief_version=0.20
|
||||
nms_helper_version=1.0.90
|
||||
nms_helper_version=1.0.91
|
||||
evalex_version=3.5.0
|
||||
reactive_streams_version=1.0.4
|
||||
amazon_awssdk_version=2.33.1
|
||||
|
||||
Reference in New Issue
Block a user