diff --git a/src/main/java/com/ldtteam/structurize/placement/handlers/placement/PlacementHandlers.java b/src/main/java/com/ldtteam/structurize/placement/handlers/placement/PlacementHandlers.java index 7dec53f21..887564db9 100644 --- a/src/main/java/com/ldtteam/structurize/placement/handlers/placement/PlacementHandlers.java +++ b/src/main/java/com/ldtteam/structurize/placement/handlers/placement/PlacementHandlers.java @@ -5,7 +5,6 @@ import com.ldtteam.structurize.api.Log; import com.ldtteam.structurize.api.RotationMirror; import com.ldtteam.structurize.blocks.ModBlocks; -import com.ldtteam.structurize.blocks.schematic.BlockFluidSubstitution; import com.ldtteam.structurize.blueprints.v1.Blueprint; import com.ldtteam.structurize.placement.structure.IStructureHandler; import com.ldtteam.structurize.tag.ModTags; @@ -20,6 +19,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelWriter; import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -27,6 +28,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.block.state.properties.DripstoneThickness; +import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.phys.AABB; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,10 +62,10 @@ public final class PlacementHandlers handlers.add(new FlowerPotPlacementHandler()); handlers.add(new StairBlockPlacementHandler()); handlers.add(new HopperClientLagPlacementHandler()); - handlers.add(new ContainerPlacementHandler()); handlers.add(new DripStoneBlockPlacementHandler()); handlers.add(new FallingBlockPlacementHandler()); handlers.add(new BannerPlacementHandler()); + handlers.add(new ContainerPlacementHandler()); handlers.add(new GeneralBlockPlacementHandler()); } @@ -134,7 +136,7 @@ public static class FluidSubstitutionPlacementHandler implements IPlacementHandl @Override public boolean canHandle(Level world, BlockPos pos, BlockState blockState) { - return blockState.getBlock() instanceof BlockFluidSubstitution; + return blockState.is(ModBlocks.blockFluidSubstitution); } @Override @@ -183,26 +185,27 @@ public void handleRemoval( @Override public ActionProcessingResult handle( - Level world, - BlockPos pos, - BlockState blockState, - @Nullable CompoundTag tileEntityData, - boolean complete, - BlockPos centerPos) + Level world, + BlockPos pos, + BlockState blockState, + @Nullable CompoundTag tileEntityData, + boolean complete, + BlockPos centerPos, + RotationMirror settings) { if (complete) { - world.setBlock(pos, ModBlocks.blockFluidSubstitution.get().defaultBlockState(), UPDATE_FLAG); + handleBlockPlacement(world, pos, ModBlocks.blockFluidSubstitution.get().defaultBlockState()); return ActionProcessingResult.PASS; } if (world.getBlockState(pos).hasProperty(BlockStateProperties.WATERLOGGED)) { - world.setBlock(pos, world.getBlockState(pos).setValue(BlockStateProperties.WATERLOGGED, true), UPDATE_FLAG); + handleBlockPlacement(world, pos, world.getBlockState(pos).setValue(BlockStateProperties.WATERLOGGED, true)); } else { - world.setBlock(pos, BlockUtils.getFluidForDimension(world), UPDATE_FLAG); + handleBlockPlacement(world, pos, BlockUtils.getFluidForDimension(world)); } return ActionProcessingResult.PASS; @@ -214,7 +217,7 @@ public static class FirePlacementHandler implements IPlacementHandler @Override public boolean canHandle(final Level world, final BlockPos pos, final BlockState blockState) { - return blockState.getBlock() instanceof FireBlock; + return blockState.is(Blocks.FIRE); } @Override @@ -239,8 +242,7 @@ public ActionProcessingResult handle( final boolean complete, final BlockPos centerPos) { - world.setBlock(pos, blockState, UPDATE_FLAG); - return ActionProcessingResult.PASS; + return simplePlacement(world, pos, blockState, null, null); } } @@ -314,7 +316,7 @@ public ActionProcessingResult handle( BlockPos posBelow = pos; BlockState supportBlockState = Blocks.DIRT.defaultBlockState(); for (int i = 0; i < 10; i++) // try up to ten blocks below for solid worldgen - { + { posBelow = posBelow.below(); final boolean isFirstTest = i == 0; final BlockState possibleSupport = BlockUtils.getWorldgenBlock(world, posBelow, bp -> isFirstTest ? blockState : null); @@ -324,16 +326,12 @@ public ActionProcessingResult handle( break; } } - world.setBlock(pos.below(), supportBlockState, UPDATE_FLAG); - } - if (!world.setBlock(pos, blockState, UPDATE_FLAG)) - { - return ActionProcessingResult.DENY; + handleBlockPlacement(world, pos.below(), supportBlockState); } - if (tileEntityData != null) + if (!handleBlockPlacement(world, pos, blockState, settings, tileEntityData)) { - handleTileEntityPlacement(tileEntityData, world, pos, settings); + return ActionProcessingResult.DENY; } return ActionProcessingResult.SUCCESS; @@ -357,11 +355,7 @@ public ActionProcessingResult handle( final boolean complete, final BlockPos centerPos) { - if (!world.setBlock(pos, blockState, UPDATE_FLAG)) - { - return ActionProcessingResult.DENY; - } - return ActionProcessingResult.SUCCESS; + return simplePlacement(world, pos, blockState, null, null); } @Override @@ -390,20 +384,20 @@ public boolean canHandle(final Level world, final BlockPos pos, final BlockState @Override public ActionProcessingResult handle( - final Level world, - final BlockPos pos, - final BlockState blockState, - @Nullable final CompoundTag tileEntityData, - final boolean complete, - final BlockPos centerPos) + final Level world, + final BlockPos pos, + final BlockState blockState, + @Nullable final CompoundTag tileEntityData, + final boolean complete, + final BlockPos centerPos, + final RotationMirror settings) { if (blockState.getValue(DoorBlock.HALF).equals(DoubleBlockHalf.LOWER)) { - world.setBlock(pos, blockState.setValue(DoorBlock.HALF, DoubleBlockHalf.LOWER), UPDATE_FLAG); - world.setBlock(pos.above(), blockState.setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER), UPDATE_FLAG); + return simplePlacement(world, pos, blockState, settings, tileEntityData); } - return ActionProcessingResult.SUCCESS; + return ActionProcessingResult.PASS; } @Override @@ -441,20 +435,9 @@ public ActionProcessingResult handle( final BlockPos centerPos, final RotationMirror settings) { - if (blockState.getValue(BedBlock.PART) == BedPart.HEAD) + if (blockState.getValue(BedBlock.PART) == BedPart.FOOT) { - final Direction facing = blockState.getValue(BedBlock.FACING); - - // pos.offset(facing) will get the other part of the bed - world.setBlock(pos.relative(facing.getOpposite()), blockState.setValue(BedBlock.PART, BedPart.FOOT), UPDATE_FLAG); - world.setBlock(pos, blockState.setValue(BedBlock.PART, BedPart.HEAD), UPDATE_FLAG); - - if (tileEntityData != null) - { - handleTileEntityPlacement(tileEntityData, world, pos, settings); - handleTileEntityPlacement(tileEntityData, world, pos.relative(facing.getOpposite()), settings); - } - return ActionProcessingResult.SUCCESS; + return simplePlacement(world, pos, blockState, settings, tileEntityData); } return ActionProcessingResult.PASS; @@ -488,18 +471,17 @@ public boolean canHandle(final Level world, final BlockPos pos, final BlockState @Override public ActionProcessingResult handle( - final Level world, - final BlockPos pos, - final BlockState blockState, - @Nullable final CompoundTag tileEntityData, - final boolean complete, - final BlockPos centerPos) + final Level world, + final BlockPos pos, + final BlockState blockState, + @Nullable final CompoundTag tileEntityData, + final boolean complete, + final BlockPos centerPos, + final RotationMirror settings) { if (blockState.getValue(DoublePlantBlock.HALF).equals(DoubleBlockHalf.LOWER)) { - world.setBlock(pos, blockState.setValue(DoublePlantBlock.HALF, DoubleBlockHalf.LOWER), UPDATE_FLAG); - world.setBlock(pos.above(), blockState.setValue(DoublePlantBlock.HALF, DoubleBlockHalf.UPPER), UPDATE_FLAG); - return ActionProcessingResult.SUCCESS; + return simplePlacement(world, pos, blockState, settings, tileEntityData); } return ActionProcessingResult.PASS; } @@ -569,20 +551,7 @@ public ActionProcessingResult handle( final BlockPos centerPos, final RotationMirror settings) { - if (world.getBlockState(pos).getBlock() == blockState.getBlock()) - { - return ActionProcessingResult.PASS; - } - if (!world.setBlock(pos, blockState, UPDATE_FLAG)) - { - return ActionProcessingResult.DENY; - } - - if (tileEntityData != null) - { - handleTileEntityPlacement(tileEntityData, world, pos, settings); - } - return ActionProcessingResult.SUCCESS; + return simplePlacement(world, pos, blockState, settings, tileEntityData); } @Override @@ -657,19 +626,15 @@ public boolean canHandle(final Level world, final BlockPos pos, final BlockState @Override public ActionProcessingResult handle( - final Level world, - final BlockPos pos, - final BlockState blockState, - @Nullable final CompoundTag tileEntityData, - final boolean complete, - final BlockPos centerPos) + final Level world, + final BlockPos pos, + final BlockState blockState, + @Nullable final CompoundTag tileEntityData, + final boolean complete, + final BlockPos centerPos, + final RotationMirror settings) { - if (!world.setBlock(pos, Blocks.DIRT_PATH.defaultBlockState(), UPDATE_FLAG)) - { - return ActionProcessingResult.DENY; - } - - return ActionProcessingResult.SUCCESS; + return simplePlacement(world, pos, blockState, settings, tileEntityData); } @Override @@ -750,24 +715,15 @@ public ActionProcessingResult handle( if (world.getBlockState(pos).equals(blockState)) { world.removeBlock(pos, false); - world.setBlock(pos, blockState, UPDATE_FLAG); - if (tileEntityData != null) - { - handleTileEntityPlacement(tileEntityData, world, pos, settings); - } + handleBlockPlacement(world, pos, blockState, settings, tileEntityData); return ActionProcessingResult.PASS; } - if (!world.setBlock(pos, blockState, UPDATE_FLAG)) + if (!handleBlockPlacement(world, pos, blockState, settings, tileEntityData)) { return ActionProcessingResult.DENY; } - if (tileEntityData != null) - { - handleTileEntityPlacement(tileEntityData, world, pos, settings); - } - return ActionProcessingResult.SUCCESS; } @@ -806,7 +762,7 @@ public ActionProcessingResult handle( final BlockPos centerPos, final RotationMirror settings) { - if (!world.setBlock(pos, blockState, UPDATE_FLAG)) + if (!handleBlockPlacement(world, pos, blockState)) { return ActionProcessingResult.DENY; } @@ -897,24 +853,15 @@ public ActionProcessingResult handle( { if (world.getBlockState(pos).equals(blockState)) { - if (tileEntityData != null) - { - handleTileEntityPlacement(tileEntityData, world, pos, settings); - } + handleTileEntityPlacement(tileEntityData, world, pos, settings); return ActionProcessingResult.PASS; } - if (!world.setBlock(pos, blockState, UPDATE_FLAG)) + if (!handleBlockPlacement(world, pos, blockState, settings, tileEntityData)) { return ActionProcessingResult.DENY; } - if (tileEntityData != null) - { - handleTileEntityPlacement(tileEntityData, world, pos, settings); - blockState.getBlock().setPlacedBy(world, pos, blockState, null, BlockUtils.getItemStackFromBlockState(blockState)); - } - return ActionProcessingResult.SUCCESS; } @@ -967,14 +914,14 @@ public ActionProcessingResult handle( { placeDripStoneInDir(dir.getOpposite(), blueprint, pos.subtract(centerPos).offset(blueprint.getPrimaryBlockOffset()), pos, blockState, world); placeDripStoneInDir(dir, blueprint, pos.subtract(centerPos).offset(blueprint.getPrimaryBlockOffset()), pos, blockState, world); - world.setBlock(pos, blockState, UPDATE_FLAG); + handleBlockPlacement(world, pos, blockState); // both direction. return ActionProcessingResult.SUCCESS; } placeDripStoneInDir(dir, blueprint, pos.subtract(centerPos).offset(blueprint.getPrimaryBlockOffset()), pos, blockState, world); - world.setBlock(pos, blockState, UPDATE_FLAG); + handleBlockPlacement(world, pos, blockState); return ActionProcessingResult.SUCCESS; } @@ -988,10 +935,10 @@ private static void placeDripStoneInDir(final Direction dir, final Blueprint blu final BlockState secondState = blueprint.getBlockState(blueprintPos.relative(dir, 2)); if (secondState != null && secondState.getBlock() == Blocks.POINTED_DRIPSTONE) { - world.setBlock(worldPos.relative(dir, 2), secondState, UPDATE_FLAG); + handleBlockPlacement(world, worldPos.relative(dir, 2), secondState); } - world.setBlock(worldPos.relative(dir, 1), firstState, UPDATE_FLAG); + handleBlockPlacement(world, worldPos.relative(dir, 1), firstState); } } catch (final Exception ex) @@ -1048,6 +995,81 @@ public List getRequiredItems( } } + /** + * Handles block placement. + * + * @param world the world. + * @param pos the position. + * @param blockState the block state of the block about to be placed. + * @return true if successfully placed. + */ + public static boolean handleBlockPlacement( + final @NotNull Level world, + final @NotNull BlockPos pos, + final @NotNull BlockState blockState) + { + return handleBlockPlacement(world, pos, blockState, null, null); + } + + /** + * Handles block placement. + * + * @param world the world. + * @param pos the position. + * @param blockState the block state of the block about to be placed. + * @param settings the rotation and mirroring settings. + * @return true if successfully placed. + */ + public static boolean handleBlockPlacement( + final @NotNull Level world, + final @NotNull BlockPos pos, + final @NotNull BlockState blockState, + final @Nullable RotationMirror settings, + final @Nullable CompoundTag tileEntityData) + { + return handleBlockPlacement(LevelWriter::setBlock, world, pos, blockState, UPDATE_FLAG, settings, tileEntityData); + } + + /** + * Handles block placement. + * + * @param world the world. + * @param pos the position. + * @param blockState the block state of the block about to be placed. + * @param settings the rotation and mirroring settings. + * @return true if successfully placed. + */ + public static boolean handleBlockPlacement( + final @NotNull BlockPlacementFunction placementFunction, + final @NotNull Level world, + final @NotNull BlockPos pos, + final @NotNull BlockState blockState, + final int flags, + final @Nullable RotationMirror settings, + final @Nullable CompoundTag tileEntityData) + { + final boolean success = placementFunction.execute(world, pos, blockState, flags); + if (success) + { + if (tileEntityData != null && settings != null) + { + handleTileEntityPlacement(tileEntityData, world, pos, settings); + } + + blockState.getBlock().setPlacedBy(world, pos, blockState, null, BlockUtils.getItemStackFromBlockState(blockState)); + world.gameEvent(GameEvent.BLOCK_PLACE, pos, GameEvent.Context.of(null, blockState)); + } + return success; + } + + /** + * Handler for placing the block down into the world. + */ + public interface BlockPlacementFunction + { + boolean execute(LevelAccessor world, BlockPos pos, BlockState state, int flags); + } + /** * Handles tileEntity placement. * @@ -1056,11 +1078,7 @@ public List getRequiredItems( * @param pos the position. * @param settings the placement settings. */ - public static void handleTileEntityPlacement( - final CompoundTag tileEntityData, - final Level world, - final BlockPos pos, - final RotationMirror settings) + public static void handleTileEntityPlacement(@Nullable final CompoundTag tileEntityData, final Level world, final BlockPos pos, final RotationMirror settings) { if (tileEntityData != null) { @@ -1126,4 +1144,36 @@ public static List getItemsFromTileEntity(final CompoundTag tileEntit return Collections.emptyList(); } } + + /** + * Simple block placement that only overwrites the block if the same block is not already present. + * If the block is already present, the tile entity data is updated if necessary. + * If the block is not present, the block is placed down and the tile entity is set down too. + * + * @param world receives the world. + * @param pos the position. + * @param blockState the blockState. + * @param settings the settings to use to rotate or mirror it. + * @param tileEntityData the placer of the block. + * @return ACCEPT, DENY or IGNORE. + */ + public static IPlacementHandler.ActionProcessingResult simplePlacement( + final @NotNull Level world, + final @NotNull BlockPos pos, + final @NotNull BlockState blockState, + final @Nullable RotationMirror settings, + final @Nullable CompoundTag tileEntityData) + { + if (world.getBlockState(pos).is(blockState.getBlock())) + { + handleTileEntityPlacement(tileEntityData, world, pos, settings); + return IPlacementHandler.ActionProcessingResult.PASS; + } + if (!handleBlockPlacement(world, pos, blockState, settings, tileEntityData)) + { + return IPlacementHandler.ActionProcessingResult.DENY; + } + + return IPlacementHandler.ActionProcessingResult.SUCCESS; + } }