From 88fc285be743bc9e9c53a549362896afeecbbf26 Mon Sep 17 00:00:00 2001 From: Allmoz Date: Fri, 11 Jul 2025 05:23:16 -0400 Subject: [PATCH 1/4] give me all your items! MKII --- .../content/contraptions/Contraption.java | 18 +++++- .../contraptions/SingleBlockServerLevel.java | 56 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/SingleBlockServerLevel.java diff --git a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java index d3a8d748f7..f08bf5b603 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java @@ -1144,6 +1144,8 @@ public void addBlocksToWorld(Level world, StructureTransform transform) { translateMultiblockControllers(transform); + SingleBlockServerLevel popChamber = null; + for (boolean nonBrittles : Iterate.trueAndFalse) { for (StructureBlockInfo block : blocks.values()) { if (nonBrittles == BlockMovementChecks.isBrittle(block.state())) @@ -1167,8 +1169,22 @@ public void addBlocksToWorld(Level world, StructureTransform transform) { .isEmpty())) { if (targetPos.getY() == world.getMinBuildHeight()) targetPos = targetPos.above(); + + if(popChamber == null && world instanceof ServerLevel serverWorld) + popChamber = new SingleBlockServerLevel(serverWorld); + + if(popChamber != null){ + popChamber.setBlock(targetPos, state, Block.UPDATE_NONE); + BlockEntity be = popChamber.getBlockEntity(targetPos); + if (be != null) { + CompoundTag tag = block.nbt(); + tag = NBTProcessors.process(state, be, tag, false); + if (tag != null) + be.load(tag); + } + popChamber.destroyBlock(targetPos, true); + } world.levelEvent(2001, targetPos, Block.getId(state)); - Block.dropResources(state, world, targetPos, null); continue; } if (state.getBlock() instanceof SimpleWaterloggedBlock diff --git a/src/main/java/com/simibubi/create/content/contraptions/SingleBlockServerLevel.java b/src/main/java/com/simibubi/create/content/contraptions/SingleBlockServerLevel.java new file mode 100644 index 0000000000..abc3bcec31 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/SingleBlockServerLevel.java @@ -0,0 +1,56 @@ +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; + +public class SingleBlockServerLevel extends WrappedServerLevel { + + public BlockState blockState; + public @Nullable BlockEntity blockEntity; + + public SingleBlockServerLevel(ServerLevel level) { + super(level); + blockState = Blocks.AIR.defaultBlockState(); + blockEntity = null; + } + + @Override + public boolean setBlock(BlockPos pos, BlockState newState, int flags) { + blockState.onRemove(this, pos, newState, (flags & 64) != 0); + blockState = newState; + blockEntity = null; + return true; + } + + @Override + public BlockState getBlockState(BlockPos pos) { + return blockState; + } + + @Nullable + public BlockEntity getBlockEntity(BlockPos pos) { + if (blockState.hasBlockEntity() && blockEntity == null) + blockEntity = ((EntityBlock) blockState.getBlock()).newBlockEntity(pos, blockState); + return blockEntity; + } + + @Override + public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft){ + if (blockState.isAir()) + return false; + if (dropBlock) + Block.dropResources(blockState, this, pos, blockEntity, entity, ItemStack.EMPTY); + setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_NONE); + return true; + } +} From 0d275fc16a8d3ddf51b9c037be4cf8e4d09b132c Mon Sep 17 00:00:00 2001 From: Allmoz Date: Sat, 19 Jul 2025 02:01:29 -0400 Subject: [PATCH 2/4] better name, extended storage, building height case --- .../content/contraptions/Contraption.java | 22 +++++------ ...el.java => GhostPlacementServerLevel.java} | 38 +++++++++++++------ 2 files changed, 37 insertions(+), 23 deletions(-) rename src/main/java/com/simibubi/create/content/contraptions/{SingleBlockServerLevel.java => GhostPlacementServerLevel.java} (53%) diff --git a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java index f08bf5b603..29758d871c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java @@ -1144,7 +1144,7 @@ public void addBlocksToWorld(Level world, StructureTransform transform) { translateMultiblockControllers(transform); - SingleBlockServerLevel popChamber = null; + GhostPlacementServerLevel ghostLevel = null; for (boolean nonBrittles : Iterate.trueAndFalse) { for (StructureBlockInfo block : blocks.values()) { @@ -1163,26 +1163,26 @@ public void addBlocksToWorld(Level world, StructureTransform transform) { targetPos.relative(face)); BlockState blockState = world.getBlockState(targetPos); - if (blockState.getDestroySpeed(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) - .isEmpty() - && !blockState.getCollisionShape(world, targetPos) - .isEmpty())) { + if (world.isOutsideBuildHeight(targetPos) || + blockState.getDestroySpeed(world, targetPos) == -1 || + (state.getCollisionShape(world, targetPos).isEmpty() && + !blockState.getCollisionShape(world, targetPos).isEmpty())) { if (targetPos.getY() == world.getMinBuildHeight()) targetPos = targetPos.above(); - if(popChamber == null && world instanceof ServerLevel serverWorld) - popChamber = new SingleBlockServerLevel(serverWorld); + if(ghostLevel == null && world instanceof ServerLevel serverWorld) + ghostLevel = new GhostPlacementServerLevel(serverWorld); - if(popChamber != null){ - popChamber.setBlock(targetPos, state, Block.UPDATE_NONE); - BlockEntity be = popChamber.getBlockEntity(targetPos); + 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); } - popChamber.destroyBlock(targetPos, true); + ghostLevel.destroyBlock(targetPos, true); } world.levelEvent(2001, targetPos, Block.getId(state)); continue; diff --git a/src/main/java/com/simibubi/create/content/contraptions/SingleBlockServerLevel.java b/src/main/java/com/simibubi/create/content/contraptions/GhostPlacementServerLevel.java similarity index 53% rename from src/main/java/com/simibubi/create/content/contraptions/SingleBlockServerLevel.java rename to src/main/java/com/simibubi/create/content/contraptions/GhostPlacementServerLevel.java index abc3bcec31..3df836b41d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/SingleBlockServerLevel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/GhostPlacementServerLevel.java @@ -13,43 +13,57 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; -public class SingleBlockServerLevel extends WrappedServerLevel { +import java.util.HashMap; +import java.util.Map; - public BlockState blockState; - public @Nullable BlockEntity blockEntity; +public class GhostPlacementServerLevel extends WrappedServerLevel { - public SingleBlockServerLevel(ServerLevel level) { + protected final Map blockStates = new HashMap<>(); + protected final Map blockEntities = new HashMap<>(); + + public GhostPlacementServerLevel(ServerLevel level) { super(level); - blockState = Blocks.AIR.defaultBlockState(); - blockEntity = null; } @Override public boolean setBlock(BlockPos pos, BlockState newState, int flags) { - blockState.onRemove(this, pos, newState, (flags & 64) != 0); - blockState = newState; - blockEntity = null; + pos = pos.immutable(); + getBlockState(pos).onRemove(this, pos, newState,false); + blockStates.put(pos, newState); return true; } @Override public BlockState getBlockState(BlockPos pos) { - return blockState; + return blockStates.getOrDefault(pos, Blocks.AIR.defaultBlockState()); } @Nullable public BlockEntity getBlockEntity(BlockPos pos) { - if (blockState.hasBlockEntity() && blockEntity == null) + 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, blockEntity, entity, ItemStack.EMPTY); + Block.dropResources(blockState, this, pos, getBlockEntity(pos), entity, ItemStack.EMPTY); setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_NONE); return true; } From 579758bf6461c3b1865a73b30703762ac092deeb Mon Sep 17 00:00:00 2001 From: Allmoz Date: Wed, 10 Sep 2025 22:29:15 -0300 Subject: [PATCH 3/4] format cosmetic fix --- .../content/contraptions/Contraption.java | 21 +++++++------------ .../GhostPlacementServerLevel.java | 4 ++-- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java index bc8c690c8b..dd9a197222 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java @@ -1169,22 +1169,18 @@ public void addBlocksToWorld(Level world, StructureTransform transform) { targetPos.relative(face)); BlockState blockState = world.getBlockState(targetPos); - if (world.isOutsideBuildHeight(targetPos) || - blockState.getDestroySpeed(world, targetPos) == -1 || - (state.getCollisionShape(world, targetPos).isEmpty() && - !blockState.getCollisionShape(world, targetPos).isEmpty())) { + if (blockState.getDestroySpeed(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) + .isEmpty() + && !blockState.getCollisionShape(world, targetPos) + .isEmpty()) || world.isOutsideBuildHeight(targetPos)) { if (targetPos.getY() == world.getMinBuildHeight()) targetPos = targetPos.above(); - world.levelEvent(2001, targetPos, Block.getId(state)); - - if (!shouldDropBlocks) - continue; - - if(ghostLevel == null && world instanceof ServerLevel serverWorld) + if (!shouldDropBlocks) + continue; + if (ghostLevel == null && world instanceof ServerLevel serverWorld) ghostLevel = new GhostPlacementServerLevel(serverWorld); - - if(ghostLevel != null){ + if (ghostLevel != null) { ghostLevel.setBlock(targetPos, state, Block.UPDATE_NONE); BlockEntity be = ghostLevel.getBlockEntity(targetPos); if (be != null) { @@ -1195,7 +1191,6 @@ public void addBlocksToWorld(Level world, StructureTransform transform) { } ghostLevel.destroyBlock(targetPos, true); } - continue; } if (state.getBlock() instanceof SimpleWaterloggedBlock diff --git a/src/main/java/com/simibubi/create/content/contraptions/GhostPlacementServerLevel.java b/src/main/java/com/simibubi/create/content/contraptions/GhostPlacementServerLevel.java index 3df836b41d..bd04ad0394 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/GhostPlacementServerLevel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/GhostPlacementServerLevel.java @@ -44,7 +44,7 @@ public BlockEntity getBlockEntity(BlockPos pos) { BlockEntity blockEntity = blockEntities.getOrDefault(pos, null); if (blockState.hasBlockEntity() && blockEntity == null) { blockEntity = ((EntityBlock) blockState.getBlock()).newBlockEntity(pos, blockState); - if(blockEntity != null) + if (blockEntity != null) blockEntity.setLevel(this); pos = pos.immutable(); blockEntities.put(pos, blockEntity); @@ -58,7 +58,7 @@ public void removeBlockEntity(BlockPos pos) { } @Override - public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft){ + public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft) { BlockState blockState = getBlockState(pos); if (blockState.isAir()) return false; From 2a6fb0c1150c65d4435ff75b72fd27870a84d840 Mon Sep 17 00:00:00 2001 From: Allmoz Date: Thu, 11 Sep 2025 11:31:11 -0300 Subject: [PATCH 4/4] added case for updateShape returning AIR --- .../com/simibubi/create/content/contraptions/Contraption.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java index dd9a197222..09761a3178 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java @@ -1172,7 +1172,8 @@ public void addBlocksToWorld(Level world, StructureTransform transform) { if (blockState.getDestroySpeed(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) .isEmpty() && !blockState.getCollisionShape(world, targetPos) - .isEmpty()) || world.isOutsideBuildHeight(targetPos)) { + .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));