9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2026-01-06 15:52:03 +00:00

Merge pull request #458 from jhqwqmc/dev

修复meg方块实体渲染
This commit is contained in:
XiaoMoMi
2025-11-14 14:58:10 +08:00
committed by GitHub
2 changed files with 82 additions and 30 deletions

View File

@@ -11,7 +11,6 @@ import net.momirealms.craftengine.core.world.World;
import org.bukkit.Location;
import org.joml.Vector3f;
// TODO not tested yet
public class ModelEngineBlockEntityElement implements BlockEntityElement {
private Dummy<?> dummy;
private final Location location;
@@ -41,14 +40,14 @@ public class ModelEngineBlockEntityElement implements BlockEntityElement {
@Override
public void hide(Player player) {
if (this.dummy != null) {
this.dummy.setForceViewing((org.bukkit.entity.Player) player.platformPlayer(), true);
this.dummy.setForceHidden((org.bukkit.entity.Player) player.platformPlayer(), true);
}
}
@Override
public void show(Player player) {
if (this.dummy != null) {
this.dummy.setForceHidden((org.bukkit.entity.Player) player.platformPlayer(), true);
this.dummy.setForceViewing((org.bukkit.entity.Player) player.platformPlayer(), true);
}
}

View File

@@ -1,31 +1,38 @@
package net.momirealms.craftengine.bukkit.block.behavior;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
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.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.DirectionUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.core.block.*;
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.Property;
import net.momirealms.craftengine.core.block.properties.type.DoubleBlockHalf;
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.BlockPos;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldEvents;
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 DoubleHighBlockBehavior extends BukkitBlockBehavior {
public class DoubleHighBlockBehavior extends AbstractCanSurviveBlockBehavior {
public static final Factory FACTORY = new Factory();
private final Property<DoubleBlockHalf> halfProperty;
public DoubleHighBlockBehavior(CustomBlock customBlock, Property<DoubleBlockHalf> halfProperty) {
super(customBlock);
super(customBlock, 0);
this.halfProperty = halfProperty;
}
@@ -34,33 +41,79 @@ public class DoubleHighBlockBehavior extends BukkitBlockBehavior {
Object level = args[updateShape$level];
Object blockPos = args[updateShape$blockPos];
Object blockState = args[0];
ImmutableBlockState customState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(blockState));
ImmutableBlockState customState = BlockStateUtils.getOptionalCustomBlockState(blockState).orElse(null);
if (customState == null || customState.isEmpty()) return blockState;
DoubleBlockHalf half = customState.get(this.halfProperty);
if (half == null) return blockState;
Object direction = args[updateShape$direction];
if (DirectionUtils.isYAxis(direction) && half == DoubleBlockHalf.LOWER == (direction == CoreReflections.instance$Direction$UP)) {
ImmutableBlockState neighborState = BlockStateUtils.getOptionalCustomBlockState(args[updateShape$neighborState]).orElse(null);
if (neighborState == null || neighborState.isEmpty()) return MBlocks.AIR$defaultState;
DoubleHighBlockBehavior anotherDoorBehavior = neighborState.behavior().getAs(DoubleHighBlockBehavior.class).orElse(null);
if (anotherDoorBehavior == null) return MBlocks.AIR$defaultState;
if (neighborState.get(anotherDoorBehavior.halfProperty) != half) {
return neighborState.with(anotherDoorBehavior.halfProperty, half).customBlockState().literalObject();
}
return MBlocks.AIR$defaultState;
} else if (half == DoubleBlockHalf.LOWER && direction == CoreReflections.instance$Direction$DOWN && !canSurvive(thisBlock, blockState, level, blockPos)) {
BlockPos pos = LocationUtils.fromBlockPos(blockPos);
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());
return MBlocks.AIR$defaultState;
}
return blockState;
}
// 获取另一半
Object anotherHalfPos = FastNMS.INSTANCE.method$BlockPos$relative(blockPos,
half == DoubleBlockHalf.UPPER
? CoreReflections.instance$Direction$DOWN
: CoreReflections.instance$Direction$UP
);
Object anotherHalfState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, anotherHalfPos);
ImmutableBlockState anotherHalfCustomState = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockStateToId(anotherHalfState));
if (anotherHalfCustomState != null && !anotherHalfCustomState.isEmpty()) return blockState;
// 破坏
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId());
return MBlocks.AIR$defaultState;
@Override
public Object playerWillDestroy(Object thisBlock, Object[] args, Callable<Object> superMethod) throws Exception {
Object level = args[0];
Object pos = args[1];
Object state = args[2];
Object player = args[3];
ImmutableBlockState blockState = BlockStateUtils.getOptionalCustomBlockState(state).orElse(null);
if (blockState == null || blockState.isEmpty()) return superMethod.call();
BukkitServerPlayer cePlayer = BukkitAdaptors.adapt(FastNMS.INSTANCE.method$ServerPlayer$getBukkitEntity(player));
Item<ItemStack> item = cePlayer.getItemInHand(InteractionHand.MAIN_HAND);
if (cePlayer.canInstabuild() || !BlockStateUtils.isCorrectTool(blockState, item)) {
preventDropFromBottomPart(level, pos, blockState, player);
}
return superMethod.call();
}
private void preventDropFromBottomPart(Object level, Object pos, ImmutableBlockState state, Object player) {
if (state.get(this.halfProperty) != DoubleBlockHalf.UPPER) return;
Object blockPos = FastNMS.INSTANCE.method$BlockPos$relative(pos, CoreReflections.instance$Direction$DOWN);
Object blockState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(level, blockPos);
ImmutableBlockState belowState = BlockStateUtils.getOptionalCustomBlockState(blockState).orElse(null);
if (belowState == null || belowState.isEmpty()) return;
Optional<DoubleHighBlockBehavior> belowDoubleHighBlockBehavior = belowState.behavior().getAs(DoubleHighBlockBehavior.class);
if (belowDoubleHighBlockBehavior.isEmpty() || belowState.get(this.halfProperty) != DoubleBlockHalf.LOWER) return;
FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, MBlocks.AIR$defaultState, UpdateOption.builder().updateSuppressDrops().updateClients().updateNeighbors().build().flags());
FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, player, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, belowState.customBlockState().registryId());
}
@Override
protected boolean canSurvive(Object thisBlock, Object state, Object world, Object blockPos) throws Exception {
ImmutableBlockState customState = BlockStateUtils.getOptionalCustomBlockState(state).orElse(null);
if (customState == null || customState.isEmpty()) return false;
if (customState.get(this.halfProperty) == DoubleBlockHalf.UPPER) {
int x = FastNMS.INSTANCE.field$Vec3i$x(blockPos);
int y = FastNMS.INSTANCE.field$Vec3i$y(blockPos) - 1;
int z = FastNMS.INSTANCE.field$Vec3i$z(blockPos);
Object belowPos = FastNMS.INSTANCE.constructor$BlockPos(x, y, z);
Object belowState = FastNMS.INSTANCE.method$BlockGetter$getBlockState(world, belowPos);
Optional<ImmutableBlockState> belowCustomState = BlockStateUtils.getOptionalCustomBlockState(belowState);
return belowCustomState.filter(immutableBlockState -> immutableBlockState.owner().value() == super.customBlock).isPresent();
}
return true;
}
@Override
public void setPlacedBy(BlockPlaceContext context, ImmutableBlockState state) {
World level = context.getLevel();
BlockPos anotherHalfPos = context.getClickedPos().relative(Direction.UP);
BlockStateWrapper blockStateWrapper = state.with(this.halfProperty, DoubleBlockHalf.UPPER).customBlockState();
FastNMS.INSTANCE.method$LevelWriter$setBlock(level.serverWorld(), LocationUtils.toBlockPos(anotherHalfPos), blockStateWrapper.literalObject(), UpdateOption.Flags.UPDATE_CLIENTS);
BlockPos pos = context.getClickedPos();
context.getLevel().setBlockAt(pos.x(), pos.y() + 1, pos.z(), state.with(this.halfProperty, DoubleBlockHalf.UPPER).customBlockState(), UpdateOption.UPDATE_ALL.flags());
}
@Override