mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-27 02:49:15 +00:00
添加多高方块及物品行为
This commit is contained in:
@@ -49,6 +49,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key HANGABLE_BLOCK = Key.from("craftengine:hangable_block");
|
||||
public static final Key DROP_EXPERIENCE_BLOCK = Key.from("craftengine:drop_experience_block");
|
||||
public static final Key DROP_EXP_BLOCK = Key.from("craftengine:drop_exp_block");
|
||||
public static final Key MULTI_HIGH_BLOCK = Key.from("craftengine:multi_high_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -96,5 +97,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(HANGABLE_BLOCK, HangableBlockBehavior.FACTORY);
|
||||
register(DROP_EXPERIENCE_BLOCK, DropExperienceBlockBehavior.FACTORY);
|
||||
register(DROP_EXP_BLOCK, DropExperienceBlockBehavior.FACTORY);
|
||||
register(MULTI_HIGH_BLOCK, MultiHighBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,11 +114,7 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior implement
|
||||
} else {
|
||||
if (half == DoubleBlockHalf.LOWER && direction == CoreReflections.instance$Direction$DOWN
|
||||
&& !canSurvive(thisBlock, blockState, level, blockPos)) {
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
world.playBlockSound(position, customState.settings().sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
MultiHighBlockBehavior.playBreakEffect(customState, blockPos, level);
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
return blockState;
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.BukkitAdaptors;
|
||||
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.MFluids;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.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.IntegerProperty;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.*;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class MultiHighBlockBehavior extends BukkitBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public final IntegerProperty highProperty;
|
||||
|
||||
public MultiHighBlockBehavior(CustomBlock customBlock, IntegerProperty highProperty) {
|
||||
super(customBlock);
|
||||
this.highProperty = highProperty;
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
@Override
|
||||
public Object updateShape(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object blockState = args[0];
|
||||
ImmutableBlockState customState = BlockStateUtils.getOptionalCustomBlockState(blockState).orElse(null);
|
||||
if (customState == null || customState.isEmpty()) {
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
MultiHighBlockBehavior behavior = customState.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) {
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
IntegerProperty property = behavior.highProperty;
|
||||
int high = customState.get(property);
|
||||
Object direction = args[updateShape$direction];
|
||||
Object level = args[updateShape$level];
|
||||
Object blockPos = args[updateShape$blockPos];
|
||||
if (direction == CoreReflections.instance$Direction$UP && high != property.max) {
|
||||
Object abovePos = LocationUtils.above(blockPos);
|
||||
Object aboveState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, abovePos);
|
||||
ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(aboveState).orElse(null);
|
||||
if (state == null) {
|
||||
playBreakEffect(customState, blockPos, level);
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
MultiHighBlockBehavior aboveBehavior = state.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (aboveBehavior == null || aboveBehavior.highProperty != property) {
|
||||
playBreakEffect(customState, blockPos, level);
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
Integer aboveHigh = state.get(property);
|
||||
if (high + 1 != aboveHigh) {
|
||||
playBreakEffect(customState, blockPos, level);
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
} else if (direction == CoreReflections.instance$Direction$DOWN && high != property.min) {
|
||||
Object belowPos = LocationUtils.below(blockPos);
|
||||
Object belowState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, belowPos);
|
||||
ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(belowState).orElse(null);
|
||||
if (state == null) {
|
||||
playBreakEffect(customState, blockPos, level);
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
MultiHighBlockBehavior belowBehavior = state.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (belowBehavior == null || belowBehavior.highProperty != property) {
|
||||
playBreakEffect(customState, blockPos, level);
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
Integer belowHigh = state.get(property);
|
||||
if (high - 1 != belowHigh) {
|
||||
playBreakEffect(customState, blockPos, level);
|
||||
return MBlocks.AIR$defaultState;
|
||||
}
|
||||
}
|
||||
return blockState;
|
||||
}
|
||||
|
||||
public static void playBreakEffect(ImmutableBlockState customState, Object blockPos, Object level) {
|
||||
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
|
||||
net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level));
|
||||
WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos));
|
||||
world.playBlockSound(position, customState.settings().sounds().breakSound());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object playerWillDestroy(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object player = args[3];
|
||||
ImmutableBlockState blockState = BlockStateUtils.getOptionalCustomBlockState(args[2]).orElse(null);
|
||||
if (blockState == null || blockState.isEmpty()) {
|
||||
return superMethod.call();
|
||||
}
|
||||
BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(FastNMS.INSTANCE.method$ServerPlayer$getBukkitEntity(player));
|
||||
if (serverPlayer == null) {
|
||||
return superMethod.call();
|
||||
}
|
||||
Item<ItemStack> item = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
|
||||
if (serverPlayer.canInstabuild() || !BlockStateUtils.isCorrectTool(blockState, item)) {
|
||||
preventDropFromBasePart(args[0], args[1], blockState, player);
|
||||
}
|
||||
return superMethod.call();
|
||||
}
|
||||
|
||||
private void preventDropFromBasePart(Object level, Object pos, ImmutableBlockState state, Object player) {
|
||||
MultiHighBlockBehavior behavior = state.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) {
|
||||
return;
|
||||
}
|
||||
IntegerProperty property = behavior.highProperty;
|
||||
int high = state.get(property);
|
||||
if (high == property.min) {
|
||||
return;
|
||||
}
|
||||
Object basePos = LocationUtils.below(pos, high - property.min);
|
||||
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, basePos);
|
||||
ImmutableBlockState baseState = BlockStateUtils.getOptionalCustomBlockState(blockState).orElse(null);
|
||||
if (baseState == null || baseState.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Optional<MultiHighBlockBehavior> baseBehavior = baseState.behavior().getAs(MultiHighBlockBehavior.class);
|
||||
if (baseBehavior.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
IntegerProperty baseProperty = baseBehavior.get().highProperty;
|
||||
if (baseState.get(baseProperty) != baseProperty.min) {
|
||||
return;
|
||||
}
|
||||
Object emptyState = FastNMS.INSTANCE.method$FluidState$getType(FastNMS.INSTANCE.field$BlockBehaviour$BlockStateBase$fluidState(blockState)) == MFluids.WATER
|
||||
? MBlocks.WATER$defaultState
|
||||
: MBlocks.AIR$defaultState;
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, basePos, emptyState, UpdateOption.builder().updateSuppressDrops().updateClients().updateNeighbors().build().flags());
|
||||
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, player, WorldEvents.BLOCK_BREAK_EFFECT, basePos, baseState.customBlockState().registryId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSurvive(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
|
||||
Object state = args[0];
|
||||
Object world = args[1];
|
||||
Object blockPos = args[2];
|
||||
ImmutableBlockState customState = BlockStateUtils.getOptionalCustomBlockState(state).orElse(null);
|
||||
if (customState == null || customState.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
MultiHighBlockBehavior behavior = customState.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) {
|
||||
return false;
|
||||
}
|
||||
IntegerProperty property = behavior.highProperty;
|
||||
int high = customState.get(property);
|
||||
if (high != property.min && high != property.max) {
|
||||
Object aboveState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, LocationUtils.above(blockPos));
|
||||
Object belowState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, LocationUtils.below(blockPos));
|
||||
CustomBlock aboveCustomBlock = BlockStateUtils.getOptionalCustomBlockState(aboveState).map(blockState -> blockState.owner().value()).orElse(null);
|
||||
CustomBlock belowCustomBlock = BlockStateUtils.getOptionalCustomBlockState(belowState).map(blockState -> blockState.owner().value()).orElse(null);
|
||||
return aboveCustomBlock == behavior.customBlock && belowCustomBlock == behavior.customBlock;
|
||||
} else if (high == property.max) {
|
||||
Object belowState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, LocationUtils.below(blockPos));
|
||||
CustomBlock belowCustomBlock = BlockStateUtils.getOptionalCustomBlockState(belowState).map(blockState -> blockState.owner().value()).orElse(null);
|
||||
return belowCustomBlock == behavior.customBlock;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placeMultiState(Object thisBlock, Object[] args, Callable<Object> superMethod) {
|
||||
Object blockState = args[2];
|
||||
Object pos = args[1];
|
||||
ImmutableBlockState state = BlockStateUtils.getOptionalCustomBlockState(blockState).orElse(null);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
MultiHighBlockBehavior behavior = state.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) {
|
||||
return;
|
||||
}
|
||||
IntegerProperty property = behavior.highProperty;
|
||||
for (int i = property.min + 1; i <= property.max; i++) {
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(args[0], LocationUtils.above(pos, i), state.with(property, i).customBlockState().literalObject(), UpdateOption.UPDATE_ALL.flags());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMultiState(ImmutableBlockState baseState) {
|
||||
return this.highProperty.max - this.highProperty.min > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceMultiState(BlockAccessor accessor, BlockPos pos, ImmutableBlockState state) {
|
||||
MultiHighBlockBehavior behavior = state.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) {
|
||||
return false;
|
||||
}
|
||||
IntegerProperty property = behavior.highProperty;
|
||||
if (pos.y() >= accessor.worldHeight().getMaxBuildHeight() - property.max) {
|
||||
return false;
|
||||
}
|
||||
for (int i = property.min + 1; i <= property.max; i++) {
|
||||
if (!accessor.getBlockState(pos.relative(Direction.UP, i)).isAir()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableBlockState updateStateForPlacement(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
World world = context.getLevel();
|
||||
BlockPos pos = context.getClickedPos();
|
||||
MultiHighBlockBehavior behavior = state.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) {
|
||||
return null;
|
||||
}
|
||||
IntegerProperty property = behavior.highProperty;
|
||||
if (pos.y() >= context.getLevel().worldHeight().getMaxBuildHeight() - property.max) {
|
||||
return null;
|
||||
}
|
||||
for (int i = property.min + 1; i <= property.max; i++) {
|
||||
if (!world.getBlock(pos.relative(Direction.UP, i)).canBeReplaced(context)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return state.with(property, 0);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
IntegerProperty high = (IntegerProperty) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("high"), "warning.config.block.behavior.multi_high.missing_high");
|
||||
return new MultiHighBlockBehavior(block, high);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ public class BukkitItemBehaviors extends ItemBehaviors {
|
||||
public static final Key WALL_BLOCK_ITEM = Key.from("craftengine:wall_block_item");
|
||||
public static final Key CEILING_BLOCK_ITEM = Key.from("craftengine:ceiling_block_item");
|
||||
public static final Key GROUND_BLOCK_ITEM = Key.from("craftengine:ground_block_item");
|
||||
public static final Key MULTI_HIGH_BLOCK_ITEM = Key.from("craftengine:multi_high_block_item");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, EmptyItemBehavior.FACTORY);
|
||||
@@ -30,5 +31,6 @@ public class BukkitItemBehaviors extends ItemBehaviors {
|
||||
register(WALL_BLOCK_ITEM, WallBlockItemBehavior.FACTORY);
|
||||
register(CEILING_BLOCK_ITEM, CeilingBlockItemBehavior.FACTORY);
|
||||
register(GROUND_BLOCK_ITEM, GroundBlockItemBehavior.FACTORY);
|
||||
register(MULTI_HIGH_BLOCK_ITEM, MultiHighBlockItemBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.behavior.MultiHighBlockBehavior;
|
||||
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.MFluids;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.block.BlockCanBuildEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MultiHighBlockItemBehavior extends BlockItemBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
|
||||
public MultiHighBlockItemBehavior(Key blockId) {
|
||||
super(blockId);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnstableApiUsage", "DuplicatedCode"})
|
||||
@Override
|
||||
protected boolean canPlace(BlockPlaceContext context, ImmutableBlockState state) {
|
||||
if (!super.canPlace(context, state)) {
|
||||
return false;
|
||||
}
|
||||
MultiHighBlockBehavior behavior = state.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) {
|
||||
return false;
|
||||
}
|
||||
IntegerProperty property = behavior.highProperty;
|
||||
Player cePlayer = context.getPlayer();
|
||||
Object player = cePlayer != null ? cePlayer.serverPlayer() : null;
|
||||
Object blockState = state.customBlockState().literalObject();
|
||||
for (int i = property.min + 1; i <= property.max; i++) {
|
||||
Object blockPos = LocationUtils.toBlockPos(context.getClickedPos().relative(Direction.UP, i));
|
||||
try {
|
||||
Object voxelShape;
|
||||
if (VersionHelper.isOrAbove1_21_6()) {
|
||||
voxelShape = CoreReflections.method$CollisionContext$placementContext.invoke(null, player);
|
||||
} else if (player != null) {
|
||||
voxelShape = CoreReflections.method$CollisionContext$of.invoke(null, player);
|
||||
} else {
|
||||
voxelShape = CoreReflections.instance$CollisionContext$empty;
|
||||
}
|
||||
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel((World) context.getLevel().platformWorld());
|
||||
boolean defaultReturn = (boolean) CoreReflections.method$ServerLevel$checkEntityCollision.invoke(world, blockState, player, voxelShape, blockPos, true); // paper only
|
||||
Block block = FastNMS.INSTANCE.method$CraftBlock$at(world, blockPos);
|
||||
BlockData blockData = FastNMS.INSTANCE.method$CraftBlockData$fromData(blockState);
|
||||
BlockCanBuildEvent canBuildEvent = new BlockCanBuildEvent(
|
||||
block, cePlayer != null ? (org.bukkit.entity.Player) cePlayer.platformPlayer() : null, blockData, defaultReturn,
|
||||
context.getHand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND
|
||||
);
|
||||
Bukkit.getPluginManager().callEvent(canBuildEvent);
|
||||
if (!canBuildEvent.isBuildable()) {
|
||||
return false;
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to check canPlace", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean placeBlock(Location location, ImmutableBlockState blockState, List<BlockState> revertState) {
|
||||
MultiHighBlockBehavior behavior = blockState.behavior().getAs(MultiHighBlockBehavior.class).orElse(null);
|
||||
if (behavior == null) {
|
||||
return false;
|
||||
}
|
||||
IntegerProperty property = behavior.highProperty;
|
||||
for (int i = property.min + 1; i <= property.max; i++) {
|
||||
Object level = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld());
|
||||
Object blockPos = FastNMS.INSTANCE.constructor$BlockPos(location.getBlockX(), location.getBlockY() + i, location.getBlockZ());
|
||||
UpdateOption option = UpdateOption.builder().updateNeighbors().updateClients().updateImmediate().updateKnownShape().build();
|
||||
Object fluidData = FastNMS.INSTANCE.method$BlockGetter$getFluidState(level, blockPos);
|
||||
Object stateToPlace = fluidData == MFluids.WATER$defaultState ? MBlocks.WATER$defaultState : MBlocks.AIR$defaultState;
|
||||
revertState.add(location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() + i, location.getBlockZ()).getState());
|
||||
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, stateToPlace, option.flags());
|
||||
}
|
||||
return super.placeBlock(location, blockState, revertState);
|
||||
}
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
@Override
|
||||
public ItemBehavior create(Pack pack, Path path, String node, Key key, Map<String, Object> arguments) {
|
||||
Object id = arguments.get("block");
|
||||
if (id == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.item.behavior.multi_high.missing_block");
|
||||
}
|
||||
if (id instanceof Map<?, ?> map) {
|
||||
addPendingSection(pack, path, node, key, map);
|
||||
return new MultiHighBlockItemBehavior(key);
|
||||
} else {
|
||||
return new MultiHighBlockItemBehavior(Key.of(id.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,10 +45,18 @@ public final class LocationUtils {
|
||||
return toBlockPos(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos) + 1, FastNMS.INSTANCE.field$Vec3i$z(blockPos));
|
||||
}
|
||||
|
||||
public static Object above(Object blockPos, int y) {
|
||||
return toBlockPos(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos) + y, FastNMS.INSTANCE.field$Vec3i$z(blockPos));
|
||||
}
|
||||
|
||||
public static Object below(Object blockPos) {
|
||||
return toBlockPos(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos) - 1, FastNMS.INSTANCE.field$Vec3i$z(blockPos));
|
||||
}
|
||||
|
||||
public static Object below(Object blockPos, int y) {
|
||||
return toBlockPos(FastNMS.INSTANCE.field$Vec3i$x(blockPos), FastNMS.INSTANCE.field$Vec3i$y(blockPos) - y, FastNMS.INSTANCE.field$Vec3i$z(blockPos));
|
||||
}
|
||||
|
||||
public static Object toBlockPos(int x, int y, int z) {
|
||||
return FastNMS.INSTANCE.constructor$BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@@ -289,6 +289,7 @@ warning.config.item.behavior.ground_block.missing_block: "<yellow>Issue found in
|
||||
warning.config.item.behavior.furniture.missing_furniture: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'furniture' argument for 'furniture_item' behavior.</yellow>"
|
||||
warning.config.item.behavior.liquid_collision.missing_block: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'block' argument for 'liquid_collision_block_item' behavior.</yellow>"
|
||||
warning.config.item.behavior.double_high.missing_block: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'block' argument for 'double_high_block_item' behavior.</yellow>"
|
||||
warning.config.item.behavior.multi_high.missing_block: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the required 'block' argument for 'multi_high_block_item' behavior.</yellow>"
|
||||
warning.config.item.legacy_model.missing_path: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the require 'path' argument for legacy-model.</yellow>"
|
||||
warning.config.item.legacy_model.overrides.missing_path: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the require 'path' argument for legacy-model overrides.</yellow>"
|
||||
warning.config.item.legacy_model.overrides.missing_predicate: "<yellow>Issue found in file <arg:0> - The item '<arg:1>' is missing the require 'predicate' argument for legacy-model overrides.</yellow>"
|
||||
@@ -433,6 +434,7 @@ warning.config.block.behavior.chime.missing_sounds_projectile_hit: "<yellow>Issu
|
||||
warning.config.block.behavior.surface_spreading.missing_base_block: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'base-block' argument for 'surface_spreading_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.snowy.missing_snowy: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'snowy' property for 'snowy_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.hangable.missing_hanging: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'hanging' property for 'hangable_block' behavior.</yellow>"
|
||||
warning.config.block.behavior.multi_high.missing_high: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'high' property for 'multi_high_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>"
|
||||
|
||||
@@ -289,6 +289,7 @@ warning.config.item.behavior.ground_block.missing_block: "<yellow>在文件 <arg
|
||||
warning.config.item.behavior.furniture.missing_furniture: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'furniture_item' 行为缺少必需的 'furniture' 参数</yellow>"
|
||||
warning.config.item.behavior.liquid_collision.missing_block: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'liquid_collision_block_item' 行为缺少必需的 'block' 参数</yellow>"
|
||||
warning.config.item.behavior.double_high.missing_block: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'double_high_block_item' 行为缺少必需的 'block' 参数</yellow>"
|
||||
warning.config.item.behavior.multi_high.missing_block: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的 'multi_high_block_item' 行为缺少必需的 'block' 参数</yellow>"
|
||||
warning.config.item.legacy_model.missing_path: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的旧版模型(legacy-model)缺少必需的 'path' 参数</yellow>"
|
||||
warning.config.item.legacy_model.overrides.missing_path: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的旧版模型覆写规则(overrides)缺少必需的 'path' 参数</yellow>"
|
||||
warning.config.item.legacy_model.overrides.missing_predicate: "<yellow>在文件 <arg:0> 发现问题 - 物品 '<arg:1>' 的旧版模型覆写规则(overrides)缺少必需的 'predicate' 参数</yellow>"
|
||||
@@ -433,6 +434,7 @@ warning.config.block.behavior.chime.missing_sounds_projectile_hit: "<yellow>在
|
||||
warning.config.block.behavior.surface_spreading.missing_base_block: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'surface_spreading_block' 行为缺少必需的 'base-block' 选项</yellow>"
|
||||
warning.config.block.behavior.snowy.missing_snowy: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'snowy_block' 行为缺少必需的 'snowy' 属性</yellow>"
|
||||
warning.config.block.behavior.hangable.missing_hanging: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'hangable_block' 行为缺少必需的 'hanging' 属性</yellow>"
|
||||
warning.config.block.behavior.multi_high.missing_high: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'multi_high_block' 行为缺少必需的 'high' 属性</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>"
|
||||
|
||||
Reference in New Issue
Block a user