Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,8 @@ public void addBlocksToWorld(Level world, StructureTransform transform) {

translateMultiblockControllers(transform);

GhostPlacementServerLevel ghostLevel = null;

for (boolean nonBrittles : Iterate.trueAndFalse) {
for (StructureBlockInfo block : blocks.values()) {
if (nonBrittles == BlockMovementChecks.isBrittle(block.state()))
Expand All @@ -1170,12 +1172,25 @@ public void addBlocksToWorld(Level world, StructureTransform transform) {
if (blockState.getDestroySpeed(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos)
.isEmpty()
&& !blockState.getCollisionShape(world, targetPos)
.isEmpty())) {
.isEmpty()) || world.isOutsideBuildHeight(targetPos) || (state.isAir() && !block.state().isAir())) {
state = block.state();
if (targetPos.getY() == world.getMinBuildHeight())
targetPos = targetPos.above();
world.levelEvent(2001, targetPos, Block.getId(state));
if (shouldDropBlocks) {
Block.dropResources(state, world, targetPos, null);
if (!shouldDropBlocks)
continue;
if (ghostLevel == null && world instanceof ServerLevel serverWorld)
ghostLevel = new GhostPlacementServerLevel(serverWorld);
if (ghostLevel != null) {
ghostLevel.setBlock(targetPos, state, Block.UPDATE_NONE);
BlockEntity be = ghostLevel.getBlockEntity(targetPos);
if (be != null) {
CompoundTag tag = block.nbt();
tag = NBTProcessors.process(state, be, tag, false);
if (tag != null)
be.load(tag);
}
ghostLevel.destroyBlock(targetPos, true);
}
continue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.simibubi.create.content.contraptions;

import javax.annotation.Nullable;

import net.createmod.catnip.levelWrappers.WrappedServerLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;

import java.util.HashMap;
import java.util.Map;

public class GhostPlacementServerLevel extends WrappedServerLevel {

protected final Map<BlockPos, BlockState> blockStates = new HashMap<>();
protected final Map<BlockPos, BlockEntity> blockEntities = new HashMap<>();

public GhostPlacementServerLevel(ServerLevel level) {
super(level);
}

@Override
public boolean setBlock(BlockPos pos, BlockState newState, int flags) {
pos = pos.immutable();
getBlockState(pos).onRemove(this, pos, newState,false);
blockStates.put(pos, newState);
return true;
}

@Override
public BlockState getBlockState(BlockPos pos) {
return blockStates.getOrDefault(pos, Blocks.AIR.defaultBlockState());
}

@Nullable
public BlockEntity getBlockEntity(BlockPos pos) {
BlockState blockState = getBlockState(pos);
BlockEntity blockEntity = blockEntities.getOrDefault(pos, null);
if (blockState.hasBlockEntity() && blockEntity == null) {
blockEntity = ((EntityBlock) blockState.getBlock()).newBlockEntity(pos, blockState);
if (blockEntity != null)
blockEntity.setLevel(this);
pos = pos.immutable();
blockEntities.put(pos, blockEntity);
}
return blockEntity;
}

@Override
public void removeBlockEntity(BlockPos pos) {
blockEntities.remove(pos);
}

@Override
public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft) {
BlockState blockState = getBlockState(pos);
if (blockState.isAir())
return false;
if (dropBlock)
Block.dropResources(blockState, this, pos, getBlockEntity(pos), entity, ItemStack.EMPTY);
setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_NONE);
return true;
}
}