diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java index a34df62e1..f89f05aa0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java @@ -1,25 +1,5 @@ package com.simibubi.create.content.contraptions.components.structureMovement; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BiPredicate; -import java.util.stream.Collectors; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.tuple.MutablePair; -import org.apache.commons.lang3.tuple.Pair; - import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.saw.SawBlock; @@ -42,20 +22,15 @@ import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; - -import net.minecraft.block.AbstractButtonBlock; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.ChestBlock; -import net.minecraft.block.DoorBlock; -import net.minecraft.block.PressurePlateBlock; -import net.minecraft.block.SlimeBlock; +import net.minecraft.block.*; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderTypeLookup; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.ChestType; import net.minecraft.state.properties.DoubleBlockHalf; import net.minecraft.tileentity.TileEntity; @@ -72,651 +47,666 @@ import net.minecraft.world.gen.feature.template.Template.BlockInfo; import net.minecraftforge.common.util.Constants.BlockFlags; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.wrapper.CombinedInvWrapper; +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.BiPredicate; +import java.util.stream.Collectors; + +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; public abstract class Contraption { - public Map blocks; - public Map storage; - public List> actors; - public CombinedInvWrapper inventory; - public List customRenderTEs; - public Set> superglue; + public Map blocks; + public Map storage; + public List> actors; + public CombinedInvWrapper inventory; + public List customRenderTEs; + public Set> superglue; - public AxisAlignedBB bounds; - public boolean stalled; + public AxisAlignedBB bounds; + public boolean stalled; - protected Set cachedColliders; - protected Direction cachedColliderDirection; - protected BlockPos anchor; + protected Set cachedColliders; + protected Direction cachedColliderDirection; + protected BlockPos anchor; + protected List glueToRemove; + List renderOrder; - List renderOrder; - protected List glueToRemove; + public Contraption() { + blocks = new HashMap<>(); + storage = new HashMap<>(); + actors = new ArrayList<>(); + superglue = new HashSet<>(); + renderOrder = new ArrayList<>(); + customRenderTEs = new ArrayList<>(); + glueToRemove = new ArrayList<>(); + } - public Contraption() { - blocks = new HashMap<>(); - storage = new HashMap<>(); - actors = new ArrayList<>(); - superglue = new HashSet<>(); - renderOrder = new ArrayList<>(); - customRenderTEs = new ArrayList<>(); - glueToRemove = new ArrayList<>(); + protected static boolean isChassis(BlockState state) { + return state.getBlock() instanceof AbstractChassisBlock; + } + + public static CompoundNBT getTileEntityNBT(World world, BlockPos pos) { + TileEntity tileentity = world.getTileEntity(pos); + CompoundNBT compoundnbt = null; + if (tileentity != null) { + compoundnbt = tileentity.write(new CompoundNBT()); + compoundnbt.remove("x"); + compoundnbt.remove("y"); + compoundnbt.remove("z"); + } + return compoundnbt; + } + + public static Contraption fromNBT(World world, CompoundNBT nbt) { + String type = nbt.getString("Type"); + Contraption contraption = AllContraptionTypes.fromType(type); + contraption.readNBT(world, nbt); + return contraption; + } + + public static boolean isFrozen() { + return AllConfigs.SERVER.control.freezeContraptions.get(); + } + + protected static MovementBehaviour getMovement(BlockState state) { + Block block = state.getBlock(); + if (!(block instanceof IPortableBlock)) + return null; + return ((IPortableBlock) block).getMovementBehaviour(); + } + + public Set getColliders(World world, Direction movementDirection) { + if (blocks == null) + return null; + if (cachedColliders == null || cachedColliderDirection != movementDirection) { + cachedColliders = new HashSet<>(); + cachedColliderDirection = movementDirection; + + for (BlockInfo info : blocks.values()) { + BlockPos offsetPos = info.pos.offset(movementDirection); + if (info.state.getCollisionShape(world, offsetPos) + .isEmpty()) + continue; + if (blocks.containsKey(offsetPos) && !blocks.get(offsetPos).state.getCollisionShape(world, offsetPos) + .isEmpty()) + continue; + cachedColliders.add(info.pos); + } + + } + return cachedColliders; + } + + public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) { + List frontier = new ArrayList<>(); + Set visited = new HashSet<>(); + anchor = pos; + + if (bounds == null) + bounds = new AxisAlignedBB(BlockPos.ZERO); + + if (!BlockMovementTraits.isBrittle(world.getBlockState(pos))) + frontier.add(pos); + if (!addToInitialFrontier(world, pos, forcedDirection, frontier)) + return false; + for (int limit = 100000; limit > 0; limit--) { + if (frontier.isEmpty()) + return true; + if (!moveBlock(world, frontier.remove(0), forcedDirection, frontier, visited)) + return false; + } + return false; + } + + public void gatherStoredItems() { + List list = storage.values() + .stream() + .map(MountedStorage::getItemHandler) + .collect(Collectors.toList()); + inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); + } + + protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection, + List frontier) { + return true; + } + + protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List frontier, + Set visited) { + visited.add(pos); + frontier.remove(pos); + + if (!world.isBlockPresent(pos)) + return false; + if (isAnchoringBlockAt(pos)) + return true; + if (!BlockMovementTraits.movementNecessary(world, pos)) + return true; + if (!BlockMovementTraits.movementAllowed(world, pos)) + return false; + BlockState state = world.getBlockState(pos); + if (isChassis(state) && !moveChassis(world, pos, forcedDirection, frontier, visited)) + return false; + + if (AllBlocks.ADJUSTABLE_CRATE.has(state)) + AdjustableCrateBlock.splitCrate(world, pos); + if (AllBlocks.BELT.has(state)) { + BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true); + BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false); + if (nextPos != null && !visited.contains(nextPos)) + frontier.add(nextPos); + if (prevPos != null && !visited.contains(prevPos)) + frontier.add(prevPos); + } + + // Pulleys drag their rope and their attached structure + if (state.getBlock() instanceof PulleyBlock) { + int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get(); + BlockPos ropePos = pos; + while (limit-- >= 0) { + ropePos = ropePos.down(); + if (!world.isBlockPresent(ropePos)) + break; + BlockState ropeState = world.getBlockState(ropePos); + Block block = ropeState.getBlock(); + if (!(block instanceof RopeBlock) && !(block instanceof MagnetBlock)) { + if (!visited.contains(ropePos)) + frontier.add(ropePos); + break; + } + add(ropePos, capture(world, ropePos)); + } + } + + // Pistons drag their attaches poles and extension + if (state.getBlock() instanceof MechanicalPistonBlock) { + int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get(); + Direction direction = state.get(MechanicalPistonBlock.FACING); + if (state.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) { + BlockPos searchPos = pos; + while (limit-- >= 0) { + searchPos = searchPos.offset(direction); + BlockState blockState = world.getBlockState(searchPos); + if (isExtensionPole(blockState)) { + if (blockState.get(PistonExtensionPoleBlock.FACING) + .getAxis() != direction.getAxis()) + break; + if (!visited.contains(searchPos)) + frontier.add(searchPos); + continue; + } + if (isPistonHead(blockState)) + if (!visited.contains(searchPos)) + frontier.add(searchPos); + break; + } + if (limit <= -1) + return false; + } + + BlockPos searchPos = pos; + while (limit-- >= 0) { + searchPos = searchPos.offset(direction.getOpposite()); + BlockState blockState = world.getBlockState(searchPos); + if (isExtensionPole(blockState)) { + if (blockState.get(PistonExtensionPoleBlock.FACING) + .getAxis() != direction.getAxis()) + break; + if (!visited.contains(searchPos)) + frontier.add(searchPos); + continue; + } + break; + } + + if (limit <= -1) + return false; + } + + // Doors try to stay whole + if (state.getBlock() instanceof DoorBlock) { + BlockPos otherPartPos = pos.up(state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 1 : -1); + if (!visited.contains(otherPartPos)) + frontier.add(otherPartPos); + } + + Map superglue = SuperGlueHandler.gatherGlue(world, pos); + + // Slime blocks drag adjacent blocks if possible + boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock; + for (Direction offset : Direction.values()) { + BlockPos offsetPos = pos.offset(offset); + BlockState blockState = world.getBlockState(offsetPos); + if (isAnchoringBlockAt(offsetPos)) + continue; + if (!BlockMovementTraits.movementAllowed(world, offsetPos)) { + if (offset == forcedDirection && isSlimeBlock) + return false; + continue; + } + + boolean wasVisited = visited.contains(offsetPos); + boolean faceHasGlue = superglue.containsKey(offset); + boolean blockAttachedTowardsFace = + BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite()); + boolean brittle = BlockMovementTraits.isBrittle(blockState); + + if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue)) + frontier.add(offsetPos); + + if (faceHasGlue) + addGlue(superglue.get(offset)); + } + + add(pos, capture(world, pos)); + return blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get(); } - public Set getColliders(World world, Direction movementDirection) { - if (blocks == null) - return null; - if (cachedColliders == null || cachedColliderDirection != movementDirection) { - cachedColliders = new HashSet<>(); - cachedColliderDirection = movementDirection; - - for (BlockInfo info : blocks.values()) { - BlockPos offsetPos = info.pos.offset(movementDirection); - if (info.state.getCollisionShape(world, offsetPos) - .isEmpty()) - continue; - if (blocks.containsKey(offsetPos) && !blocks.get(offsetPos).state.getCollisionShape(world, offsetPos) - .isEmpty()) - continue; - cachedColliders.add(info.pos); - } - - } - return cachedColliders; - } - - public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) { - List frontier = new ArrayList<>(); - Set visited = new HashSet<>(); - anchor = pos; - - if (bounds == null) - bounds = new AxisAlignedBB(BlockPos.ZERO); - - if (!BlockMovementTraits.isBrittle(world.getBlockState(pos))) - frontier.add(pos); - if (!addToInitialFrontier(world, pos, forcedDirection, frontier)) - return false; - for (int limit = 100000; limit > 0; limit--) { - if (frontier.isEmpty()) - return true; - if (!moveBlock(world, frontier.remove(0), forcedDirection, frontier, visited)) - return false; - } - return false; - } - - public void gatherStoredItems() { - List list = storage.values() - .stream() - .map(MountedStorage::getItemHandler) - .collect(Collectors.toList()); - inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); - } - - protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection, - List frontier) { - return true; - } - - protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List frontier, - Set visited) { - visited.add(pos); - frontier.remove(pos); - - if (!world.isBlockPresent(pos)) - return false; - if (isAnchoringBlockAt(pos)) - return true; - if (!BlockMovementTraits.movementNecessary(world, pos)) - return true; - if (!BlockMovementTraits.movementAllowed(world, pos)) - return false; - BlockState state = world.getBlockState(pos); - if (isChassis(state) && !moveChassis(world, pos, forcedDirection, frontier, visited)) - return false; - - if (AllBlocks.ADJUSTABLE_CRATE.has(state)) - AdjustableCrateBlock.splitCrate(world, pos); - if (AllBlocks.BELT.has(state)) { - BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true); - BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false); - if (nextPos != null && !visited.contains(nextPos)) - frontier.add(nextPos); - if (prevPos != null && !visited.contains(prevPos)) - frontier.add(prevPos); - } - - // Pulleys drag their rope and their attached structure - if (state.getBlock() instanceof PulleyBlock) { - int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get(); - BlockPos ropePos = pos; - while (limit-- >= 0) { - ropePos = ropePos.down(); - if (!world.isBlockPresent(ropePos)) - break; - BlockState ropeState = world.getBlockState(ropePos); - Block block = ropeState.getBlock(); - if (!(block instanceof RopeBlock) && !(block instanceof MagnetBlock)) { - if (!visited.contains(ropePos)) - frontier.add(ropePos); - break; - } - add(ropePos, capture(world, ropePos)); - } - } - - // Pistons drag their attaches poles and extension - if (state.getBlock() instanceof MechanicalPistonBlock) { - int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get(); - Direction direction = state.get(MechanicalPistonBlock.FACING); - if (state.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) { - BlockPos searchPos = pos; - while (limit-- >= 0) { - searchPos = searchPos.offset(direction); - BlockState blockState = world.getBlockState(searchPos); - if (isExtensionPole(blockState)) { - if (blockState.get(PistonExtensionPoleBlock.FACING) - .getAxis() != direction.getAxis()) - break; - if (!visited.contains(searchPos)) - frontier.add(searchPos); - continue; - } - if (isPistonHead(blockState)) - if (!visited.contains(searchPos)) - frontier.add(searchPos); - break; - } - if (limit <= -1) - return false; - } - - BlockPos searchPos = pos; - while (limit-- >= 0) { - searchPos = searchPos.offset(direction.getOpposite()); - BlockState blockState = world.getBlockState(searchPos); - if (isExtensionPole(blockState)) { - if (blockState.get(PistonExtensionPoleBlock.FACING) - .getAxis() != direction.getAxis()) - break; - if (!visited.contains(searchPos)) - frontier.add(searchPos); - continue; - } - break; - } - - if (limit <= -1) - return false; - } - - // Doors try to stay whole - if (state.getBlock() instanceof DoorBlock) { - BlockPos otherPartPos = pos.up(state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 1 : -1); - if (!visited.contains(otherPartPos)) - frontier.add(otherPartPos); - } - - Map superglue = SuperGlueHandler.gatherGlue(world, pos); - - // Slime blocks drag adjacent blocks if possible - boolean isSlimeBlock = state.getBlock() instanceof SlimeBlock; - for (Direction offset : Direction.values()) { - BlockPos offsetPos = pos.offset(offset); - BlockState blockState = world.getBlockState(offsetPos); - if (isAnchoringBlockAt(offsetPos)) - continue; - if (!BlockMovementTraits.movementAllowed(world, offsetPos)) { - if (offset == forcedDirection && isSlimeBlock) - return false; - continue; - } - - boolean wasVisited = visited.contains(offsetPos); - boolean faceHasGlue = superglue.containsKey(offset); - boolean blockAttachedTowardsFace = - BlockMovementTraits.isBlockAttachedTowards(blockState, offset.getOpposite()); - boolean brittle = BlockMovementTraits.isBrittle(blockState); - - if (!wasVisited && ((isSlimeBlock && !brittle) || blockAttachedTowardsFace || faceHasGlue)) - frontier.add(offsetPos); - - if (faceHasGlue) - addGlue(superglue.get(offset)); - } - - add(pos, capture(world, pos)); - if (blocks.size() > AllConfigs.SERVER.kinetics.maxBlocksMoved.get()) - return false; - - return true; - } - - protected boolean isAnchoringBlockAt(BlockPos pos) { - return pos.equals(anchor); - } - - protected static boolean isChassis(BlockState state) { - return state.getBlock() instanceof AbstractChassisBlock; - } - - private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, List frontier, - Set visited) { - TileEntity te = world.getTileEntity(pos); - if (!(te instanceof ChassisTileEntity)) - return false; - ChassisTileEntity chassis = (ChassisTileEntity) te; - chassis.addAttachedChasses(frontier, visited); - List includedBlockPositions = chassis.getIncludedBlockPositions(movementDirection, false); - if (includedBlockPositions == null) - return false; - for (BlockPos blockPos : includedBlockPositions) - if (!visited.contains(blockPos)) - frontier.add(blockPos); - return true; - } - - protected Pair capture(World world, BlockPos pos) { - BlockState blockstate = world.getBlockState(pos); - if (AllBlocks.MECHANICAL_SAW.has(blockstate)) - blockstate = blockstate.with(SawBlock.RUNNING, true); - if (blockstate.getBlock() instanceof ChestBlock) - blockstate = blockstate.with(ChestBlock.TYPE, ChestType.SINGLE); - if (AllBlocks.ADJUSTABLE_CRATE.has(blockstate)) - blockstate = blockstate.with(AdjustableCrateBlock.DOUBLE, false); - if (AllBlocks.REDSTONE_CONTACT.has(blockstate)) - blockstate = blockstate.with(RedstoneContactBlock.POWERED, true); - if (blockstate.getBlock() instanceof AbstractButtonBlock) { - blockstate = blockstate.with(AbstractButtonBlock.POWERED, false); - world.getPendingBlockTicks() - .scheduleTick(pos, blockstate.getBlock(), -1); - } - if (blockstate.getBlock() instanceof PressurePlateBlock) { - blockstate = blockstate.with(PressurePlateBlock.POWERED, false); - world.getPendingBlockTicks() - .scheduleTick(pos, blockstate.getBlock(), -1); - } - CompoundNBT compoundnbt = getTileEntityNBT(world, pos); - TileEntity tileentity = world.getTileEntity(pos); - return Pair.of(new BlockInfo(pos, blockstate, compoundnbt), tileentity); - } - - public static CompoundNBT getTileEntityNBT(World world, BlockPos pos) { - TileEntity tileentity = world.getTileEntity(pos); - CompoundNBT compoundnbt = null; - if (tileentity != null) { - compoundnbt = tileentity.write(new CompoundNBT()); - compoundnbt.remove("x"); - compoundnbt.remove("y"); - compoundnbt.remove("z"); - } - return compoundnbt; - } - - public void addGlue(SuperGlueEntity entity) { - BlockPos pos = entity.getHangingPosition(); - Direction direction = entity.getFacingDirection(); - BlockPos localPos = pos.subtract(anchor); - this.superglue.add(Pair.of(localPos, direction)); - glueToRemove.add(entity); - } - - public void add(BlockPos pos, Pair pair) { - BlockInfo captured = pair.getKey(); - BlockPos localPos = pos.subtract(anchor); - BlockInfo blockInfo = new BlockInfo(localPos, captured.state, captured.nbt); - - if (blocks.put(localPos, blockInfo) != null) - return; - bounds = bounds.union(new AxisAlignedBB(localPos)); - - TileEntity te = pair.getValue(); - if (te != null && MountedStorage.canUseAsStorage(te)) - storage.put(localPos, new MountedStorage(te)); - if (captured.state.getBlock() instanceof IPortableBlock) - getActors().add(MutablePair.of(blockInfo, null)); - } - - public static Contraption fromNBT(World world, CompoundNBT nbt) { - String type = nbt.getString("Type"); - Contraption contraption = AllContraptionTypes.fromType(type); - contraption.readNBT(world, nbt); - return contraption; - } - - public void readNBT(World world, CompoundNBT nbt) { - blocks.clear(); - renderOrder.clear(); - customRenderTEs.clear(); - - nbt.getList("Blocks", 10) - .forEach(c -> { - CompoundNBT comp = (CompoundNBT) c; - BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")), - NBTUtil.readBlockState(comp.getCompound("Block")), - comp.contains("Data") ? comp.getCompound("Data") : null); - blocks.put(info.pos, info); - - if (world.isRemote) { - Block block = info.state.getBlock(); - if (RenderTypeLookup.canRenderInLayer(info.state, RenderType.getTranslucent())) - renderOrder.add(info.pos); - else - renderOrder.add(0, info.pos); - CompoundNBT tag = info.nbt; - if (tag == null || block instanceof IPortableBlock) - return; - - tag.putInt("x", info.pos.getX()); - tag.putInt("y", info.pos.getY()); - tag.putInt("z", info.pos.getZ()); - - TileEntity te = TileEntity.create(tag); - te.setLocation(new WrappedWorld(world) { - - @Override - public BlockState getBlockState(BlockPos pos) { - if (!pos.equals(te.getPos())) - return Blocks.AIR.getDefaultState(); - return info.state; - } - - }, te.getPos()); - if (te instanceof KineticTileEntity) - ((KineticTileEntity) te).setSpeed(0); - te.getBlockState(); - customRenderTEs.add(te); - } - }); - - actors.clear(); - nbt.getList("Actors", 10) - .forEach(c -> { - CompoundNBT comp = (CompoundNBT) c; - BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos"))); - MovementContext context = MovementContext.readNBT(world, info, comp); - context.contraption = this; - getActors().add(MutablePair.of(info, context)); - }); - - superglue.clear(); - nbt.getList("Superglue", 10) - .forEach(c -> { - CompoundNBT comp = (CompoundNBT) c; - superglue.add(Pair.of(NBTUtil.readBlockPos(comp.getCompound("Pos")), - Direction.byIndex(comp.getByte("Direction")))); - }); - - storage.clear(); - nbt.getList("Storage", 10) - .forEach(c -> { - CompoundNBT comp = (CompoundNBT) c; - storage.put(NBTUtil.readBlockPos(comp.getCompound("Pos")), - new MountedStorage(comp.getCompound("Data"))); - }); - List list = storage.values() - .stream() - .map(MountedStorage::getItemHandler) - .collect(Collectors.toList()); - inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); - - if (nbt.contains("BoundsFront")) - bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5)); - - stalled = nbt.getBoolean("Stalled"); - anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor")); - } - - public CompoundNBT writeNBT() { - CompoundNBT nbt = new CompoundNBT(); - nbt.putString("Type", getType().id); - ListNBT blocksNBT = new ListNBT(); - for (BlockInfo block : this.blocks.values()) { - CompoundNBT c = new CompoundNBT(); - c.put("Block", NBTUtil.writeBlockState(block.state)); - c.put("Pos", NBTUtil.writeBlockPos(block.pos)); - if (block.nbt != null) - c.put("Data", block.nbt); - blocksNBT.add(c); - } - - ListNBT actorsNBT = new ListNBT(); - for (MutablePair actor : getActors()) { - CompoundNBT compound = new CompoundNBT(); - compound.put("Pos", NBTUtil.writeBlockPos(actor.left.pos)); - getMovement(actor.left.state).writeExtraData(actor.right); - actor.right.writeToNBT(compound); - actorsNBT.add(compound); - } - - ListNBT superglueNBT = new ListNBT(); - for (Pair glueEntry : superglue) { - CompoundNBT c = new CompoundNBT(); - c.put("Pos", NBTUtil.writeBlockPos(glueEntry.getKey())); - c.putByte("Direction", (byte) glueEntry.getValue() - .getIndex()); - superglueNBT.add(c); - } - - ListNBT storageNBT = new ListNBT(); - for (BlockPos pos : storage.keySet()) { - CompoundNBT c = new CompoundNBT(); - MountedStorage mountedStorage = storage.get(pos); - if (!mountedStorage.isWorking()) - continue; - c.put("Pos", NBTUtil.writeBlockPos(pos)); - c.put("Data", mountedStorage.serialize()); - storageNBT.add(c); - } - - nbt.put("Blocks", blocksNBT); - nbt.put("Actors", actorsNBT); - nbt.put("Superglue", superglueNBT); - nbt.put("Storage", storageNBT); - nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); - nbt.putBoolean("Stalled", stalled); - - if (bounds != null) { - ListNBT bb = NBTHelper.writeAABB(bounds); - nbt.put("BoundsFront", bb); - } - - return nbt; - } - - public static boolean isFrozen() { - return AllConfigs.SERVER.control.freezeContraptions.get(); - } - - public void removeBlocksFromWorld(IWorld world, BlockPos offset) { - removeBlocksFromWorld(world, offset, (pos, state) -> false); - } - - public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate customRemoval) { - storage.values() - .forEach(MountedStorage::empty); - glueToRemove.forEach(SuperGlueEntity::remove); - - for (boolean brittles : Iterate.trueAndFalse) { - for (Iterator iterator = blocks.values() - .iterator(); iterator.hasNext();) { - BlockInfo block = iterator.next(); - if (brittles != BlockMovementTraits.isBrittle(block.state)) - continue; - - BlockPos add = block.pos.add(anchor) - .add(offset); - if (customRemoval.test(add, block.state)) - continue; - Block blockIn = world.getBlockState(add) - .getBlock(); - if (block.state.getBlock() != blockIn) - iterator.remove(); - world.getWorld() - .removeTileEntity(add); - int flags = 67; - if (blockIn instanceof DoorBlock) - flags = flags | 32 | 16; - world.setBlockState(add, Blocks.AIR.getDefaultState(), flags); - } - } - } - - public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) { - addBlocksToWorld(world, offset, rotation, (pos, state) -> false); - } - - public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation, - BiPredicate customPlacement) { - stop(world); - - StructureTransform transform = new StructureTransform(offset, rotation); - - for (boolean nonBrittles : Iterate.trueAndFalse) { - for (BlockInfo block : blocks.values()) { - if (nonBrittles == BlockMovementTraits.isBrittle(block.state)) - continue; - - BlockPos targetPos = transform.apply(block.pos); - BlockState state = transform.apply(block.state); - - if (customPlacement.test(targetPos, state)) - continue; - - if (nonBrittles) - for (Direction face : Direction.values()) - state = state.updatePostPlacement(face, world.getBlockState(targetPos.offset(face)), world, - targetPos, targetPos.offset(face)); - - if (AllBlocks.MECHANICAL_SAW.has(state)) - state = state.with(SawBlock.RUNNING, false); - - BlockState blockState = world.getBlockState(targetPos); - if (blockState.getBlockHardness(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) - .isEmpty() - && !blockState.getCollisionShape(world, targetPos) - .isEmpty())) { - if (targetPos.getY() == 0) - targetPos = targetPos.up(); - world.playEvent(2001, targetPos, Block.getStateId(state)); - Block.spawnDrops(state, world, targetPos, null); - continue; - } - - world.destroyBlock(targetPos, true); - world.setBlockState(targetPos, state, 3 | BlockFlags.IS_MOVING); - - boolean verticalRotation = transform.rotationAxis == null || transform.rotationAxis.isHorizontal(); - verticalRotation = verticalRotation && transform.rotation != Rotation.NONE; - if (verticalRotation) { - if (state.getBlock() instanceof RopeBlock || state.getBlock() instanceof MagnetBlock) - world.destroyBlock(targetPos, true); - } - - TileEntity tileEntity = world.getTileEntity(targetPos); - CompoundNBT tag = block.nbt; - if (tileEntity != null && tag != null) { - tag.putInt("x", targetPos.getX()); - tag.putInt("y", targetPos.getY()); - tag.putInt("z", targetPos.getZ()); - - if (verticalRotation && tileEntity instanceof PulleyTileEntity) { - tag.remove("Offset"); - tag.remove("InitialOffset"); - } - - tileEntity.read(tag); - - if (storage.containsKey(block.pos)) { - MountedStorage mountedStorage = storage.get(block.pos); - if (mountedStorage.isWorking()) - mountedStorage.fill(tileEntity); - } - } - } - } - - for (Pair pair : superglue) { - BlockPos targetPos = transform.apply(pair.getKey()); - Direction targetFacing = transform.transformFacing(pair.getValue()); - - SuperGlueEntity entity = new SuperGlueEntity(world, targetPos, targetFacing); - if (entity.onValidSurface()) { - if (!world.isRemote) - world.addEntity(entity); - } - - } - - } - - public void initActors(World world) { - for (MutablePair pair : actors) { - MovementContext context = new MovementContext(world, pair.left); - context.contraption = this; - getMovement(pair.left.state).startMoving(context); - pair.setRight(context); - } - } - - public AxisAlignedBB getBoundingBox() { - return bounds; - } - - public List> getActors() { - return actors; - } - - public BlockPos getAnchor() { - return anchor; - } - - public void stop(World world) { - foreachActor(world, (behaviour, ctx) -> { - behaviour.stopMoving(ctx); - ctx.position = null; - ctx.motion = Vec3d.ZERO; - ctx.relativeMotion = Vec3d.ZERO; - ctx.rotation = Vec3d.ZERO; - }); - } - - public void foreachActor(World world, BiConsumer callBack) { - for (MutablePair pair : actors) - callBack.accept(getMovement(pair.getLeft().state), pair.getRight()); - } - - protected static MovementBehaviour getMovement(BlockState state) { - Block block = state.getBlock(); - if (!(block instanceof IPortableBlock)) - return null; - return ((IPortableBlock) block).getMovementBehaviour(); - } - - public void expandBoundsAroundAxis(Axis axis) { - AxisAlignedBB bb = bounds; - double maxXDiff = Math.max(bb.maxX - 1, -bb.minX); - double maxYDiff = Math.max(bb.maxY - 1, -bb.minY); - double maxZDiff = Math.max(bb.maxZ - 1, -bb.minZ); - double maxDiff = 0; - - if (axis == Axis.X) - maxDiff = Math.max(maxZDiff, maxYDiff); - if (axis == Axis.Y) - maxDiff = Math.max(maxZDiff, maxXDiff); - if (axis == Axis.Z) - maxDiff = Math.max(maxXDiff, maxYDiff); - - Vec3d vec = new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis) - .getDirectionVec()); - Vec3d planeByNormal = VecHelper.planeByNormal(vec); - Vec3d min = vec.mul(bb.minX, bb.minY, bb.minZ) - .add(planeByNormal.scale(-maxDiff)); - Vec3d max = vec.mul(bb.maxX, bb.maxY, bb.maxZ) - .add(planeByNormal.scale(maxDiff + 1)); - bounds = new AxisAlignedBB(min, max); - } - - protected abstract AllContraptionTypes getType(); + protected boolean isAnchoringBlockAt(BlockPos pos) { + return pos.equals(anchor); + } + + private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, List frontier, + Set visited) { + TileEntity te = world.getTileEntity(pos); + if (!(te instanceof ChassisTileEntity)) + return false; + ChassisTileEntity chassis = (ChassisTileEntity) te; + chassis.addAttachedChasses(frontier, visited); + List includedBlockPositions = chassis.getIncludedBlockPositions(movementDirection, false); + if (includedBlockPositions == null) + return false; + for (BlockPos blockPos : includedBlockPositions) + if (!visited.contains(blockPos)) + frontier.add(blockPos); + return true; + } + + protected Pair capture(World world, BlockPos pos) { + BlockState blockstate = world.getBlockState(pos); + if (AllBlocks.MECHANICAL_SAW.has(blockstate)) + blockstate = blockstate.with(SawBlock.RUNNING, true); + if (blockstate.getBlock() instanceof ChestBlock) + blockstate = blockstate.with(ChestBlock.TYPE, ChestType.SINGLE); + if (AllBlocks.ADJUSTABLE_CRATE.has(blockstate)) + blockstate = blockstate.with(AdjustableCrateBlock.DOUBLE, false); + if (AllBlocks.REDSTONE_CONTACT.has(blockstate)) + blockstate = blockstate.with(RedstoneContactBlock.POWERED, true); + if (blockstate.getBlock() instanceof AbstractButtonBlock) { + blockstate = blockstate.with(AbstractButtonBlock.POWERED, false); + world.getPendingBlockTicks() + .scheduleTick(pos, blockstate.getBlock(), -1); + } + if (blockstate.getBlock() instanceof PressurePlateBlock) { + blockstate = blockstate.with(PressurePlateBlock.POWERED, false); + world.getPendingBlockTicks() + .scheduleTick(pos, blockstate.getBlock(), -1); + } + CompoundNBT compoundnbt = getTileEntityNBT(world, pos); + TileEntity tileentity = world.getTileEntity(pos); + return Pair.of(new BlockInfo(pos, blockstate, compoundnbt), tileentity); + } + + public void addGlue(SuperGlueEntity entity) { + BlockPos pos = entity.getHangingPosition(); + Direction direction = entity.getFacingDirection(); + BlockPos localPos = pos.subtract(anchor); + this.superglue.add(Pair.of(localPos, direction)); + glueToRemove.add(entity); + } + + public void add(BlockPos pos, Pair pair) { + BlockInfo captured = pair.getKey(); + BlockPos localPos = pos.subtract(anchor); + BlockInfo blockInfo = new BlockInfo(localPos, captured.state, captured.nbt); + + if (blocks.put(localPos, blockInfo) != null) + return; + bounds = bounds.union(new AxisAlignedBB(localPos)); + + TileEntity te = pair.getValue(); + if (te != null && MountedStorage.canUseAsStorage(te)) + storage.put(localPos, new MountedStorage(te)); + if (captured.state.getBlock() instanceof IPortableBlock) + getActors().add(MutablePair.of(blockInfo, null)); + } + + public void readNBT(World world, CompoundNBT nbt) { + blocks.clear(); + renderOrder.clear(); + customRenderTEs.clear(); + + nbt.getList("Blocks", 10) + .forEach(c -> { + CompoundNBT comp = (CompoundNBT) c; + BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")), + NBTUtil.readBlockState(comp.getCompound("Block")), + comp.contains("Data") ? comp.getCompound("Data") : null); + blocks.put(info.pos, info); + + if (world.isRemote) { + Block block = info.state.getBlock(); + if (RenderTypeLookup.canRenderInLayer(info.state, RenderType.getTranslucent())) + renderOrder.add(info.pos); + else + renderOrder.add(0, info.pos); + CompoundNBT tag = info.nbt; + if (tag == null || block instanceof IPortableBlock) + return; + + tag.putInt("x", info.pos.getX()); + tag.putInt("y", info.pos.getY()); + tag.putInt("z", info.pos.getZ()); + + TileEntity te = TileEntity.create(tag); + te.setLocation(new WrappedWorld(world) { + + @Override + public BlockState getBlockState(BlockPos pos) { + if (!pos.equals(te.getPos())) + return Blocks.AIR.getDefaultState(); + return info.state; + } + + }, te.getPos()); + if (te instanceof KineticTileEntity) + ((KineticTileEntity) te).setSpeed(0); + te.getBlockState(); + customRenderTEs.add(te); + } + }); + + actors.clear(); + nbt.getList("Actors", 10) + .forEach(c -> { + CompoundNBT comp = (CompoundNBT) c; + BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos"))); + MovementContext context = MovementContext.readNBT(world, info, comp); + context.contraption = this; + getActors().add(MutablePair.of(info, context)); + }); + + superglue.clear(); + nbt.getList("Superglue", 10) + .forEach(c -> { + CompoundNBT comp = (CompoundNBT) c; + superglue.add(Pair.of(NBTUtil.readBlockPos(comp.getCompound("Pos")), + Direction.byIndex(comp.getByte("Direction")))); + }); + + storage.clear(); + nbt.getList("Storage", 10) + .forEach(c -> { + CompoundNBT comp = (CompoundNBT) c; + storage.put(NBTUtil.readBlockPos(comp.getCompound("Pos")), + new MountedStorage(comp.getCompound("Data"))); + }); + List list = storage.values() + .stream() + .map(MountedStorage::getItemHandler) + .collect(Collectors.toList()); + inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); + + if (nbt.contains("BoundsFront")) + bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5)); + + stalled = nbt.getBoolean("Stalled"); + anchor = NBTUtil.readBlockPos(nbt.getCompound("Anchor")); + } + + public CompoundNBT writeNBT() { + CompoundNBT nbt = new CompoundNBT(); + nbt.putString("Type", getType().id); + ListNBT blocksNBT = new ListNBT(); + for (BlockInfo block : this.blocks.values()) { + CompoundNBT c = new CompoundNBT(); + c.put("Block", NBTUtil.writeBlockState(block.state)); + c.put("Pos", NBTUtil.writeBlockPos(block.pos)); + if (block.nbt != null) + c.put("Data", block.nbt); + blocksNBT.add(c); + } + + ListNBT actorsNBT = new ListNBT(); + for (MutablePair actor : getActors()) { + CompoundNBT compound = new CompoundNBT(); + compound.put("Pos", NBTUtil.writeBlockPos(actor.left.pos)); + getMovement(actor.left.state).writeExtraData(actor.right); + actor.right.writeToNBT(compound); + actorsNBT.add(compound); + } + + ListNBT superglueNBT = new ListNBT(); + for (Pair glueEntry : superglue) { + CompoundNBT c = new CompoundNBT(); + c.put("Pos", NBTUtil.writeBlockPos(glueEntry.getKey())); + c.putByte("Direction", (byte) glueEntry.getValue() + .getIndex()); + superglueNBT.add(c); + } + + ListNBT storageNBT = new ListNBT(); + for (BlockPos pos : storage.keySet()) { + CompoundNBT c = new CompoundNBT(); + MountedStorage mountedStorage = storage.get(pos); + if (!mountedStorage.isWorking()) + continue; + c.put("Pos", NBTUtil.writeBlockPos(pos)); + c.put("Data", mountedStorage.serialize()); + storageNBT.add(c); + } + + nbt.put("Blocks", blocksNBT); + nbt.put("Actors", actorsNBT); + nbt.put("Superglue", superglueNBT); + nbt.put("Storage", storageNBT); + nbt.put("Anchor", NBTUtil.writeBlockPos(anchor)); + nbt.putBoolean("Stalled", stalled); + + if (bounds != null) { + ListNBT bb = NBTHelper.writeAABB(bounds); + nbt.put("BoundsFront", bb); + } + + return nbt; + } + + public void removeBlocksFromWorld(IWorld world, BlockPos offset) { + removeBlocksFromWorld(world, offset, (pos, state) -> false); + } + + public void removeBlocksFromWorld(IWorld world, BlockPos offset, BiPredicate customRemoval) { + storage.values() + .forEach(MountedStorage::empty); + glueToRemove.forEach(SuperGlueEntity::remove); + + for (boolean brittles : Iterate.trueAndFalse) { + for (Iterator iterator = blocks.values() + .iterator(); iterator.hasNext(); ) { + BlockInfo block = iterator.next(); + if (brittles != BlockMovementTraits.isBrittle(block.state)) + continue; + + BlockPos add = block.pos.add(anchor) + .add(offset); + if (customRemoval.test(add, block.state)) + continue; + BlockState oldState = world.getBlockState(add); + Block blockIn = oldState.getBlock(); + if (block.state.getBlock() != blockIn) + iterator.remove(); + world.getWorld() + .removeTileEntity(add); + int flags = 67; + if (blockIn instanceof DoorBlock) + flags = flags | 32 | 16; + if (blockIn instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED) && oldState.get(BlockStateProperties.WATERLOGGED).booleanValue()) { + world.setBlockState(add, Blocks.WATER.getDefaultState(), flags); + continue; + } + world.setBlockState(add, Blocks.AIR.getDefaultState(), flags); + } + } + } + + public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation) { + addBlocksToWorld(world, offset, rotation, (pos, state) -> false); + } + + public void addBlocksToWorld(World world, BlockPos offset, Vec3d rotation, + BiPredicate customPlacement) { + stop(world); + StructureTransform transform = new StructureTransform(offset, rotation); + + for (boolean nonBrittles : Iterate.trueAndFalse) { + for (BlockInfo block : blocks.values()) { + if (nonBrittles == BlockMovementTraits.isBrittle(block.state)) + continue; + + BlockPos targetPos = transform.apply(block.pos); + + BlockState state = transform.apply(block.state); + + if (customPlacement.test(targetPos, state)) + continue; + + if (nonBrittles) + for (Direction face : Direction.values()) + state = state.updatePostPlacement(face, world.getBlockState(targetPos.offset(face)), world, + targetPos, targetPos.offset(face)); + + if (AllBlocks.MECHANICAL_SAW.has(state)) + state = state.with(SawBlock.RUNNING, false); + + BlockState blockState = world.getBlockState(targetPos); + if (blockState.getBlockHardness(world, targetPos) == -1 || (state.getCollisionShape(world, targetPos) + .isEmpty() + && !blockState.getCollisionShape(world, targetPos) + .isEmpty())) { + if (targetPos.getY() == 0) + targetPos = targetPos.up(); + world.playEvent(2001, targetPos, Block.getStateId(state)); + Block.spawnDrops(state, world, targetPos, null); + continue; + } + if (state.getBlock() instanceof IWaterLoggable && state.has(BlockStateProperties.WATERLOGGED)) { + IFluidState ifluidstate = world.getFluidState(targetPos); + state = state.with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + } + + world.destroyBlock(targetPos, true); + world.setBlockState(targetPos, state, 3 | BlockFlags.IS_MOVING); + + boolean verticalRotation = transform.rotationAxis == null || transform.rotationAxis.isHorizontal(); + verticalRotation = verticalRotation && transform.rotation != Rotation.NONE; + if (verticalRotation) { + if (state.getBlock() instanceof RopeBlock || state.getBlock() instanceof MagnetBlock) + world.destroyBlock(targetPos, true); + } + + TileEntity tileEntity = world.getTileEntity(targetPos); + CompoundNBT tag = block.nbt; + if (tileEntity != null && tag != null) { + tag.putInt("x", targetPos.getX()); + tag.putInt("y", targetPos.getY()); + tag.putInt("z", targetPos.getZ()); + + if (verticalRotation && tileEntity instanceof PulleyTileEntity) { + tag.remove("Offset"); + tag.remove("InitialOffset"); + } + + tileEntity.read(tag); + + if (storage.containsKey(block.pos)) { + MountedStorage mountedStorage = storage.get(block.pos); + if (mountedStorage.isWorking()) + mountedStorage.fill(tileEntity); + } + } + } + } + + for (Pair pair : superglue) { + BlockPos targetPos = transform.apply(pair.getKey()); + Direction targetFacing = transform.transformFacing(pair.getValue()); + + SuperGlueEntity entity = new SuperGlueEntity(world, targetPos, targetFacing); + if (entity.onValidSurface()) { + if (!world.isRemote) + world.addEntity(entity); + } + + } + + } + + public void initActors(World world) { + for (MutablePair pair : actors) { + MovementContext context = new MovementContext(world, pair.left); + context.contraption = this; + getMovement(pair.left.state).startMoving(context); + pair.setRight(context); + } + } + + public AxisAlignedBB getBoundingBox() { + return bounds; + } + + public List> getActors() { + return actors; + } + + public BlockPos getAnchor() { + return anchor; + } + + public void stop(World world) { + foreachActor(world, (behaviour, ctx) -> { + behaviour.stopMoving(ctx); + ctx.position = null; + ctx.motion = Vec3d.ZERO; + ctx.relativeMotion = Vec3d.ZERO; + ctx.rotation = Vec3d.ZERO; + }); + } + + public void foreachActor(World world, BiConsumer callBack) { + for (MutablePair pair : actors) + callBack.accept(getMovement(pair.getLeft().state), pair.getRight()); + } + + public void expandBoundsAroundAxis(Axis axis) { + AxisAlignedBB bb = bounds; + double maxXDiff = Math.max(bb.maxX - 1, -bb.minX); + double maxYDiff = Math.max(bb.maxY - 1, -bb.minY); + double maxZDiff = Math.max(bb.maxZ - 1, -bb.minZ); + double maxDiff = 0; + + if (axis == Axis.X) + maxDiff = Math.max(maxZDiff, maxYDiff); + if (axis == Axis.Y) + maxDiff = Math.max(maxZDiff, maxXDiff); + if (axis == Axis.Z) + maxDiff = Math.max(maxXDiff, maxYDiff); + + Vec3d vec = new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis) + .getDirectionVec()); + Vec3d planeByNormal = VecHelper.planeByNormal(vec); + Vec3d min = vec.mul(bb.minX, bb.minY, bb.minZ) + .add(planeByNormal.scale(-maxDiff)); + Vec3d max = vec.mul(bb.maxX, bb.maxY, bb.maxZ) + .add(planeByNormal.scale(maxDiff + 1)); + bounds = new AxisAlignedBB(min, max); + } + + protected abstract AllContraptionTypes getType(); } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java index fa3c241f7..5c21f6c80 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java @@ -1,16 +1,17 @@ package com.simibubi.create.content.contraptions.components.structureMovement.piston; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; - import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.foundation.block.ProperDirectionalBlock; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.IWaterLoggable; import net.minecraft.block.material.PushReaction; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.state.EnumProperty; import net.minecraft.state.StateContainer.Builder; @@ -22,67 +23,91 @@ import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; import net.minecraft.world.World; -public class MechanicalPistonHeadBlock extends ProperDirectionalBlock { +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; - public static final EnumProperty TYPE = BlockStateProperties.PISTON_TYPE; +public class MechanicalPistonHeadBlock extends ProperDirectionalBlock implements IWaterLoggable { - public MechanicalPistonHeadBlock(Properties p_i48415_1_) { - super(p_i48415_1_); - } + public static final EnumProperty TYPE = BlockStateProperties.PISTON_TYPE; - @Override - protected void fillStateContainer(Builder builder) { - builder.add(TYPE); - super.fillStateContainer(builder); - } + public MechanicalPistonHeadBlock(Properties p_i48415_1_) { + super(p_i48415_1_); + setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); + } - @Override - public PushReaction getPushReaction(BlockState state) { - return PushReaction.NORMAL; - } + @Override + protected void fillStateContainer(Builder builder) { + builder.add(TYPE, BlockStateProperties.WATERLOGGED); + super.fillStateContainer(builder); + } - @Override - public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos, - PlayerEntity player) { - return AllBlocks.PISTON_EXTENSION_POLE.asStack(); - } + @Override + public PushReaction getPushReaction(BlockState state) { + return PushReaction.NORMAL; + } - @Override - public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { - Direction direction = state.get(FACING); - BlockPos pistonHead = pos; - BlockPos pistonBase = null; + @Override + public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos, + PlayerEntity player) { + return AllBlocks.PISTON_EXTENSION_POLE.asStack(); + } - for (int offset = 1; offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset++) { - BlockPos currentPos = pos.offset(direction.getOpposite(), offset); - BlockState block = worldIn.getBlockState(currentPos); + @Override + public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { + Direction direction = state.get(FACING); + BlockPos pistonHead = pos; + BlockPos pistonBase = null; - if (isExtensionPole(block) && direction.getAxis() == block.get(BlockStateProperties.FACING) - .getAxis()) - continue; + for (int offset = 1; offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset++) { + BlockPos currentPos = pos.offset(direction.getOpposite(), offset); + BlockState block = worldIn.getBlockState(currentPos); - if (MechanicalPistonBlock.isPiston(block) && block.get(BlockStateProperties.FACING) == direction) - pistonBase = currentPos; + if (isExtensionPole(block) && direction.getAxis() == block.get(BlockStateProperties.FACING) + .getAxis()) + continue; - break; - } + if (MechanicalPistonBlock.isPiston(block) && block.get(BlockStateProperties.FACING) == direction) + pistonBase = currentPos; - if (pistonHead != null && pistonBase != null) { - final BlockPos basePos = pistonBase; - BlockPos.getAllInBox(pistonBase, pistonHead) - .filter(p -> !p.equals(pos) && !p.equals(basePos)) - .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); - worldIn.setBlockState(basePos, worldIn.getBlockState(basePos) - .with(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); - } + break; + } - super.onBlockHarvested(worldIn, pos, state, player); - } + if (pistonHead != null && pistonBase != null) { + final BlockPos basePos = pistonBase; + BlockPos.getAllInBox(pistonBase, pistonHead) + .filter(p -> !p.equals(pos) && !p.equals(basePos)) + .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); + worldIn.setBlockState(basePos, worldIn.getBlockState(basePos) + .with(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.MECHANICAL_PISTON_HEAD.get(state.get(FACING)); - } + super.onBlockHarvested(worldIn, pos, state, player); + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return AllShapes.MECHANICAL_PISTON_HEAD.get(state.get(FACING)); + } + + @Override + public IFluidState getFluidState(BlockState state) { + return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState(); + } + + @Override + public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + IWorld world, BlockPos pos, BlockPos neighbourPos) { + if (state.get(BlockStateProperties.WATERLOGGED)) { + world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + } + return state; + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos()); + return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java index 8c05ac120..379d3c202 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java @@ -1,18 +1,18 @@ package com.simibubi.create.content.contraptions.components.structureMovement.piston; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPiston; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; - import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.foundation.block.ProperDirectionalBlock; - +import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.IWaterLoggable; import net.minecraft.block.material.PushReaction; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; import net.minecraft.item.BlockItemUseContext; +import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -21,75 +21,98 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; import net.minecraft.world.World; -public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements IWrenchable { +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*; - public PistonExtensionPoleBlock(Properties properties) { - super(properties); - setDefaultState(getDefaultState().with(FACING, Direction.UP)); - } +public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements IWrenchable, IWaterLoggable { - @Override - public PushReaction getPushReaction(BlockState state) { - return PushReaction.NORMAL; - } + public PistonExtensionPoleBlock(Properties properties) { + super(properties); + setDefaultState(getDefaultState().with(FACING, Direction.UP).with(BlockStateProperties.WATERLOGGED, false)); + } - @Override - public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { - Axis axis = state.get(FACING) - .getAxis(); - Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); - BlockPos pistonHead = null; - BlockPos pistonBase = null; + @Override + public PushReaction getPushReaction(BlockState state) { + return PushReaction.NORMAL; + } - for (int modifier : new int[] { 1, -1 }) { - for (int offset = modifier; modifier * offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset += - modifier) { - BlockPos currentPos = pos.offset(direction, offset); - BlockState block = worldIn.getBlockState(currentPos); + @Override + public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { + Axis axis = state.get(FACING) + .getAxis(); + Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis); + BlockPos pistonHead = null; + BlockPos pistonBase = null; - if (isExtensionPole(block) && axis == block.get(FACING) - .getAxis()) - continue; + for (int modifier : new int[]{1, -1}) { + for (int offset = modifier; modifier * offset < MechanicalPistonBlock.maxAllowedPistonPoles(); offset += + modifier) { + BlockPos currentPos = pos.offset(direction, offset); + BlockState block = worldIn.getBlockState(currentPos); - if (isPiston(block) && block.get(BlockStateProperties.FACING) - .getAxis() == axis) - pistonBase = currentPos; + if (isExtensionPole(block) && axis == block.get(FACING) + .getAxis()) + continue; - if (isPistonHead(block) && block.get(BlockStateProperties.FACING) - .getAxis() == axis) - pistonHead = currentPos; + if (isPiston(block) && block.get(BlockStateProperties.FACING) + .getAxis() == axis) + pistonBase = currentPos; - break; - } - } + if (isPistonHead(block) && block.get(BlockStateProperties.FACING) + .getAxis() == axis) + pistonHead = currentPos; - if (pistonHead != null && pistonBase != null && worldIn.getBlockState(pistonHead) - .get(BlockStateProperties.FACING) == worldIn.getBlockState(pistonBase) - .get(BlockStateProperties.FACING)) { + break; + } + } - final BlockPos basePos = pistonBase; - BlockPos.getAllInBox(pistonBase, pistonHead) - .filter(p -> !p.equals(pos) && !p.equals(basePos)) - .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); - worldIn.setBlockState(basePos, worldIn.getBlockState(basePos) - .with(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); - } + if (pistonHead != null && pistonBase != null && worldIn.getBlockState(pistonHead) + .get(BlockStateProperties.FACING) == worldIn.getBlockState(pistonBase) + .get(BlockStateProperties.FACING)) { - super.onBlockHarvested(worldIn, pos, state, player); - } + final BlockPos basePos = pistonBase; + BlockPos.getAllInBox(pistonBase, pistonHead) + .filter(p -> !p.equals(pos) && !p.equals(basePos)) + .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); + worldIn.setBlockState(basePos, worldIn.getBlockState(basePos) + .with(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.FOUR_VOXEL_POLE.get(state.get(FACING) - .getAxis()); - } + super.onBlockHarvested(worldIn, pos, state, player); + } - @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - return getDefaultState().with(FACING, context.getFace() - .getOpposite()); - } + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return AllShapes.FOUR_VOXEL_POLE.get(state.get(FACING) + .getAxis()); + } + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos()); + return getDefaultState().with(FACING, context.getFace().getOpposite()) + .with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + } + + @Override + public IFluidState getFluidState(BlockState state) { + return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState(); + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(BlockStateProperties.WATERLOGGED); + super.fillStateContainer(builder); + } + + @Override + public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + IWorld world, BlockPos pos, BlockPos neighbourPos) { + if (state.get(BlockStateProperties.WATERLOGGED)) { + world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + } + return state; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java index d1c889fc8..2f650d4e9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java @@ -5,13 +5,17 @@ import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock; import com.simibubi.create.foundation.block.ITE; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.IWaterLoggable; import net.minecraft.block.material.PushReaction; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.state.EnumProperty; +import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; @@ -24,128 +28,156 @@ import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; import net.minecraft.world.World; public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE { - public static EnumProperty HORIZONTAL_AXIS = BlockStateProperties.HORIZONTAL_AXIS; + public static EnumProperty HORIZONTAL_AXIS = BlockStateProperties.HORIZONTAL_AXIS; - public PulleyBlock(Properties properties) { - super(properties); - } + public PulleyBlock(Properties properties) { + super(properties); + } - @Override - public TileEntity createTileEntity(BlockState state, IBlockReader world) { - return AllTileEntities.ROPE_PULLEY.create(); - } + private static void onRopeBroken(World world, BlockPos pulleyPos) { + TileEntity te = world.getTileEntity(pulleyPos); + if (!(te instanceof PulleyTileEntity)) + return; + PulleyTileEntity pulley = (PulleyTileEntity) te; + pulley.offset = 0; + pulley.sendData(); + } - @Override - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (state.getBlock() != newState.getBlock()) { - if (!worldIn.isRemote) { - BlockState below = worldIn.getBlockState(pos.down()); - if (below.getBlock() instanceof RopeBlockBase) - worldIn.destroyBlock(pos.down(), true); - } - if (state.hasTileEntity()) - worldIn.removeTileEntity(pos); - } - } + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return AllTileEntities.ROPE_PULLEY.create(); + } - public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, - BlockRayTraceResult hit) { - if (!player.isAllowEdit()) - return ActionResultType.PASS; - if (player.isSneaking()) - return ActionResultType.PASS; - if (player.getHeldItem(handIn) - .isEmpty()) { - withTileEntityDo(worldIn, pos, te -> te.assembleNextTick = true); - return ActionResultType.SUCCESS; - } - return ActionResultType.PASS; - } + @Override + public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (state.getBlock() != newState.getBlock()) { + if (!worldIn.isRemote) { + BlockState below = worldIn.getBlockState(pos.down()); + if (below.getBlock() instanceof RopeBlockBase) + worldIn.destroyBlock(pos.down(), true); + } + if (state.hasTileEntity()) + worldIn.removeTileEntity(pos); + } + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.PULLEY.get(state.get(HORIZONTAL_AXIS)); - } + public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + if (!player.isAllowEdit()) + return ActionResultType.PASS; + if (player.isSneaking()) + return ActionResultType.PASS; + if (player.getHeldItem(handIn) + .isEmpty()) { + withTileEntityDo(worldIn, pos, te -> te.assembleNextTick = true); + return ActionResultType.SUCCESS; + } + return ActionResultType.PASS; + } - private static void onRopeBroken(World world, BlockPos pulleyPos) { - TileEntity te = world.getTileEntity(pulleyPos); - if (!(te instanceof PulleyTileEntity)) - return; - PulleyTileEntity pulley = (PulleyTileEntity) te; - pulley.offset = 0; - pulley.sendData(); - } + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return AllShapes.PULLEY.get(state.get(HORIZONTAL_AXIS)); + } - private static class RopeBlockBase extends Block { + @Override + public Class getTileEntityClass() { + return PulleyTileEntity.class; + } - public RopeBlockBase(Properties properties) { - super(properties); - } + private static class RopeBlockBase extends Block implements IWaterLoggable { - @Override - public PushReaction getPushReaction(BlockState state) { - return PushReaction.BLOCK; - } + public RopeBlockBase(Properties properties) { + super(properties); + setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); + } - @Override - public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos, - PlayerEntity player) { - return AllBlocks.ROPE_PULLEY.asStack(); - } + @Override + public PushReaction getPushReaction(BlockState state) { + return PushReaction.BLOCK; + } - @Override - public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (!isMoving) { - onRopeBroken(worldIn, pos.up()); - if (!worldIn.isRemote) { - BlockState above = worldIn.getBlockState(pos.up()); - BlockState below = worldIn.getBlockState(pos.down()); - if (above.getBlock() instanceof RopeBlockBase) - worldIn.destroyBlock(pos.up(), true); - if (below.getBlock() instanceof RopeBlockBase) - worldIn.destroyBlock(pos.down(), true); - } - } - if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) { - worldIn.removeTileEntity(pos); - } - } + @Override + public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos, + PlayerEntity player) { + return AllBlocks.ROPE_PULLEY.asStack(); + } - } + @Override + public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (!isMoving && (!state.has(BlockStateProperties.WATERLOGGED) || !newState.has(BlockStateProperties.WATERLOGGED) || state.get(BlockStateProperties.WATERLOGGED) == newState.get(BlockStateProperties.WATERLOGGED))) { + onRopeBroken(worldIn, pos.up()); + if (!worldIn.isRemote) { + BlockState above = worldIn.getBlockState(pos.up()); + BlockState below = worldIn.getBlockState(pos.down()); + if (above.getBlock() instanceof RopeBlockBase) + worldIn.destroyBlock(pos.up(), true); + if (below.getBlock() instanceof RopeBlockBase) + worldIn.destroyBlock(pos.down(), true); + } + } + if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) { + worldIn.removeTileEntity(pos); + } + } - public static class MagnetBlock extends RopeBlockBase { - public MagnetBlock(Properties properties) { - super(properties); - } + @Override + public IFluidState getFluidState(BlockState state) { + return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState(); + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.PULLEY_MAGNET; - } + @Override + protected void fillStateContainer(Builder builder) { + builder.add(BlockStateProperties.WATERLOGGED); + super.fillStateContainer(builder); + } - } + @Override + public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + IWorld world, BlockPos pos, BlockPos neighbourPos) { + if (state.get(BlockStateProperties.WATERLOGGED)) { + world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + } + return state; + } - public static class RopeBlock extends RopeBlockBase { + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos()); + return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + } - public RopeBlock(Properties properties) { - super(properties); - } + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.FOUR_VOXEL_POLE.get(Direction.UP); - } + public static class MagnetBlock extends RopeBlockBase { - } + public MagnetBlock(Properties properties) { + super(properties); + } - @Override - public Class getTileEntityClass() { - return PulleyTileEntity.class; - } + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return AllShapes.PULLEY_MAGNET; + } + + } + + public static class RopeBlock extends RopeBlockBase { + + public RopeBlock(Properties properties) { + super(properties); + } + + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return AllShapes.FOUR_VOXEL_POLE.get(Direction.UP); + } + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java index 3642285e8..122d7be6c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java @@ -8,9 +8,13 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pis import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; - +import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.block.IWaterLoggable; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.math.AxisAlignedBB; @@ -19,170 +23,180 @@ import net.minecraft.util.math.Vec3d; public class PulleyTileEntity extends LinearActuatorTileEntity { - protected int initialOffset; + protected int initialOffset; - public PulleyTileEntity(TileEntityType type) { - super(type); - } + public PulleyTileEntity(TileEntityType type) { + super(type); + } - @Override - public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().expand(0, -offset, 0); - } + @Override + public AxisAlignedBB getRenderBoundingBox() { + return super.getRenderBoundingBox().expand(0, -offset, 0); + } - @Override - public double getMaxRenderDistanceSquared() { - return super.getMaxRenderDistanceSquared() + offset * offset; - } + @Override + public double getMaxRenderDistanceSquared() { + return super.getMaxRenderDistanceSquared() + offset * offset; + } - @Override - protected void assemble() { - if (!(world.getBlockState(pos) - .getBlock() instanceof PulleyBlock)) - return; - if (speed == 0) - return; - if (offset >= getExtensionRange() && getSpeed() > 0) - return; - if (offset <= 0 && getSpeed() < 0) - return; + @Override + protected void assemble() { + if (!(world.getBlockState(pos) + .getBlock() instanceof PulleyBlock)) + return; + if (speed == 0) + return; + if (offset >= getExtensionRange() && getSpeed() > 0) + return; + if (offset <= 0 && getSpeed() < 0) + return; - // Collect Construct - if (!world.isRemote) { - BlockPos anchor = pos.down((int) (offset + 1)); - initialOffset = (int) (offset); - PulleyContraption contraption = PulleyContraption.assemblePulleyAt(world, anchor, (int) offset); + // Collect Construct + if (!world.isRemote) { + BlockPos anchor = pos.down((int) (offset + 1)); + initialOffset = (int) (offset); + PulleyContraption contraption = PulleyContraption.assemblePulleyAt(world, anchor, (int) offset); - if (contraption != null) { - Direction movementDirection = getSpeed() > 0 ? Direction.DOWN : Direction.UP; - if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection), - movementDirection)) - contraption = null; - } + if (contraption != null) { + Direction movementDirection = getSpeed() > 0 ? Direction.DOWN : Direction.UP; + if (ContraptionCollider.isCollidingWithWorld(world, contraption, anchor.offset(movementDirection), + movementDirection)) + contraption = null; + } - if (contraption == null && getSpeed() > 0) - return; + if (contraption == null && getSpeed() > 0) + return; - for (int i = ((int) offset); i > 0; i--) { - BlockPos offset = pos.down(i); - world.setBlockState(offset, Blocks.AIR.getDefaultState(), 66); - } + for (int i = ((int) offset); i > 0; i--) { + BlockPos offset = pos.down(i); + BlockState oldState = world.getBlockState(offset); + if (oldState.getBlock() instanceof IWaterLoggable && oldState.has(BlockStateProperties.WATERLOGGED) && oldState.get(BlockStateProperties.WATERLOGGED)) { + world.setBlockState(offset, Blocks.WATER.getDefaultState(), 66); + continue; + } + world.setBlockState(offset, Blocks.AIR.getDefaultState(), 66); + } - if (contraption != null && !contraption.blocks.isEmpty()) { - contraption.removeBlocksFromWorld(world, BlockPos.ZERO); - movedContraption = ContraptionEntity.createStationary(world, contraption) - .controlledBy(this); - movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); - world.addEntity(movedContraption); - forceMove = true; - } - } + if (contraption != null && !contraption.blocks.isEmpty()) { + contraption.removeBlocksFromWorld(world, BlockPos.ZERO); + movedContraption = ContraptionEntity.createStationary(world, contraption) + .controlledBy(this); + movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); + world.addEntity(movedContraption); + forceMove = true; + } + } - clientOffsetDiff = 0; - running = true; - sendData(); - } + clientOffsetDiff = 0; + running = true; + sendData(); + } - @Override - public void disassemble() { - if (!running && movedContraption == null) - return; - offset = getGridOffset(offset); - if (movedContraption != null) - applyContraptionPosition(); + @Override + public void disassemble() { + if (!running && movedContraption == null) + return; + offset = getGridOffset(offset); + if (movedContraption != null) + applyContraptionPosition(); - if (!world.isRemote) { - if (!removed) { - if (offset > 0) { - BlockPos magnetPos = pos.down((int) offset); - world.destroyBlock(magnetPos, world.getBlockState(magnetPos) - .getCollisionShape(world, magnetPos) - .isEmpty()); - world.setBlockState(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState(), 66); - } - - for (int i = 1; i <= ((int) offset) - 1; i++) { - BlockPos ropePos = pos.down(i); - world.destroyBlock(ropePos, world.getBlockState(ropePos) - .getCollisionShape(world, ropePos) - .isEmpty()); - } - for (int i = 1; i <= ((int) offset) - 1; i++) - world.setBlockState(pos.down(i), AllBlocks.ROPE.getDefaultState(), 66); - } + if (!world.isRemote) { + if (!removed) { + if (offset > 0) { + BlockPos magnetPos = pos.down((int) offset); + IFluidState ifluidstate = world.getFluidState(magnetPos); + world.destroyBlock(magnetPos, world.getBlockState(magnetPos) + .getCollisionShape(world, magnetPos) + .isEmpty()); + world.setBlockState(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState().with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)), 66); + } - if (movedContraption != null) - movedContraption.disassemble(); - } + boolean[] waterlog = new boolean[(int) offset]; - if (movedContraption != null) - movedContraption.remove(); - movedContraption = null; - initialOffset = 0; - running = false; - sendData(); - } + for (int i = 1; i <= ((int) offset) - 1; i++) { + BlockPos ropePos = pos.down(i); + IFluidState ifluidstate = world.getFluidState(ropePos); + waterlog[i] = ifluidstate.getFluid() == Fluids.WATER; + world.destroyBlock(ropePos, world.getBlockState(ropePos) + .getCollisionShape(world, ropePos) + .isEmpty()); + } + for (int i = 1; i <= ((int) offset) - 1; i++) + world.setBlockState(pos.down(i), AllBlocks.ROPE.getDefaultState().with(BlockStateProperties.WATERLOGGED, waterlog[i]), 66); + } - @Override - protected Vec3d toPosition(float offset) { - if (movedContraption.getContraption() instanceof PulleyContraption) { - PulleyContraption contraption = (PulleyContraption) movedContraption.getContraption(); - return new Vec3d(contraption.getAnchor()).add(0, contraption.initialOffset - offset, 0); + if (movedContraption != null) + movedContraption.disassemble(); + } - } - return Vec3d.ZERO; - } + if (movedContraption != null) + movedContraption.remove(); + movedContraption = null; + initialOffset = 0; + running = false; + sendData(); + } - @Override - protected void visitNewPosition() { - super.visitNewPosition(); - if (world.isRemote) - return; - if (movedContraption != null) - return; - if (getSpeed() <= 0) - return; + @Override + protected Vec3d toPosition(float offset) { + if (movedContraption.getContraption() instanceof PulleyContraption) { + PulleyContraption contraption = (PulleyContraption) movedContraption.getContraption(); + return new Vec3d(contraption.getAnchor()).add(0, contraption.initialOffset - offset, 0); - BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1); - if (!BlockMovementTraits.movementNecessary(world, posBelow)) - return; - if (BlockMovementTraits.isBrittle(world.getBlockState(posBelow))) - return; + } + return Vec3d.ZERO; + } - disassemble(); - assembleNextTick = true; - } + @Override + protected void visitNewPosition() { + super.visitNewPosition(); + if (world.isRemote) + return; + if (movedContraption != null) + return; + if (getSpeed() <= 0) + return; - @Override - public void read(CompoundNBT tag) { - initialOffset = tag.getInt("InitialOffset"); - super.read(tag); - } + BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1); + if (!BlockMovementTraits.movementNecessary(world, posBelow)) + return; + if (BlockMovementTraits.isBrittle(world.getBlockState(posBelow))) + return; - @Override - public CompoundNBT write(CompoundNBT tag) { - tag.putInt("InitialOffset", initialOffset); - return super.write(tag); - } + disassemble(); + assembleNextTick = true; + } - @Override - protected int getExtensionRange() { - return Math.max(0, Math.min(AllConfigs.SERVER.kinetics.maxRopeLength.get(), pos.getY() - 1)); - } + @Override + public void read(CompoundNBT tag) { + initialOffset = tag.getInt("InitialOffset"); + super.read(tag); + } - @Override - protected int getInitialOffset() { - return initialOffset; - } + @Override + public CompoundNBT write(CompoundNBT tag) { + tag.putInt("InitialOffset", initialOffset); + return super.write(tag); + } - @Override - protected Vec3d toMotionVector(float speed) { - return new Vec3d(0, -speed, 0); - } + @Override + protected int getExtensionRange() { + return Math.max(0, Math.min(AllConfigs.SERVER.kinetics.maxRopeLength.get(), pos.getY() - 1)); + } - @Override - protected ValueBoxTransform getMovementModeSlot() { - return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP); - } + @Override + protected int getInitialOffset() { + return initialOffset; + } + + @Override + protected Vec3d toMotionVector(float speed) { + return new Vec3d(0, -speed, 0); + } + + @Override + protected ValueBoxTransform getMovementModeSlot() { + return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPipeBlock.java index f9a05f43f..5df66aead 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPipeBlock.java @@ -104,6 +104,7 @@ public class FluidPipeBlock extends SixWayBlock implements IWaterLoggable { @Override protected void fillStateContainer(Builder builder) { builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN, BlockStateProperties.WATERLOGGED); + super.fillStateContainer(builder); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java index bcef27b33..788dcee2f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java @@ -3,8 +3,14 @@ package com.simibubi.create.content.contraptions.fluids; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; - +import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.IWaterLoggable; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.state.StateContainer.Builder; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -12,45 +18,73 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; -public class PumpBlock extends DirectionalKineticBlock { +public class PumpBlock extends DirectionalKineticBlock implements IWaterLoggable { - public PumpBlock(Properties p_i48415_1_) { - super(p_i48415_1_); - } + public PumpBlock(Properties p_i48415_1_) { + super(p_i48415_1_); + setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); + } - @Override - public boolean hasTileEntity(BlockState state) { - return true; - } + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } - @Override - public TileEntity createTileEntity(BlockState state, IBlockReader world) { - return AllTileEntities.MECHANICAL_PUMP.create(); - } + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return AllTileEntities.MECHANICAL_PUMP.create(); + } - @Override - public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { - return originalState.with(FACING, originalState.get(FACING) - .getOpposite()); - } + @Override + public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { + return originalState.with(FACING, originalState.get(FACING) + .getOpposite()); + } - @Override - public Axis getRotationAxis(BlockState state) { - return state.get(FACING) - .getAxis(); - } + @Override + public Axis getRotationAxis(BlockState state) { + return state.get(FACING) + .getAxis(); + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, - ISelectionContext p_220053_4_) { - return AllShapes.PUMP.get(state.get(FACING)); - } + @Override + public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, + ISelectionContext p_220053_4_) { + return AllShapes.PUMP.get(state.get(FACING)); + } - @Override - public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) { - return true; - } + @Override + public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) { + return true; + } + + @Override + public IFluidState getFluidState(BlockState state) { + return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState(); + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(BlockStateProperties.WATERLOGGED); + super.fillStateContainer(builder); + } + + @Override + public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + IWorld world, BlockPos pos, BlockPos neighbourPos) { + if (state.get(BlockStateProperties.WATERLOGGED)) { + world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + } + return state; + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos()); + return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java index 55d2299e5..e8d7e1310 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java @@ -4,12 +4,14 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.NonNullList; @@ -22,95 +24,96 @@ import net.minecraft.world.World; public class CogWheelBlock extends ShaftBlock { - boolean isLarge; + boolean isLarge; - public static CogWheelBlock small(Properties properties) { - return new CogWheelBlock(false, properties); - } + private CogWheelBlock(boolean large, Properties properties) { + super(properties); + isLarge = large; + } - public static CogWheelBlock large(Properties properties) { - return new CogWheelBlock(true, properties); - } + public static CogWheelBlock small(Properties properties) { + return new CogWheelBlock(false, properties); + } - private CogWheelBlock(boolean large, Properties properties) { - super(properties); - isLarge = large; - } + public static CogWheelBlock large(Properties properties) { + return new CogWheelBlock(true, properties); + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return (isLarge ? AllShapes.LARGE_GEAR : AllShapes.SMALL_GEAR).get(state.get(AXIS)); - } + public static boolean isSmallCog(BlockState state) { + return AllBlocks.COGWHEEL.has(state); + } - @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - for (Direction facing : Direction.values()) { - if (facing.getAxis() == state.get(AXIS)) - continue; + public static boolean isLargeCog(BlockState state) { + return AllBlocks.LARGE_COGWHEEL.has(state); + } - BlockState blockState = worldIn.getBlockState(pos.offset(facing)); - if (isLargeCog(blockState) || isLarge && isSmallCog(blockState)) - return false; - } - return true; - } + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return (isLarge ? AllShapes.LARGE_GEAR : AllShapes.SMALL_GEAR).get(state.get(AXIS)); + } - @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - BlockPos placedOnPos = context.getPos() - .offset(context.getFace() - .getOpposite()); - World world = context.getWorld(); - BlockState placedAgainst = world.getBlockState(placedOnPos); - Block block = placedAgainst.getBlock(); + @Override + public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { + for (Direction facing : Direction.values()) { + if (facing.getAxis() == state.get(AXIS)) + continue; - BlockState stateBelow = world.getBlockState(context.getPos() - .down()); - if (AllBlocks.ROTATION_SPEED_CONTROLLER.has(stateBelow) && isLarge) { - return this.getDefaultState() - .with(AXIS, stateBelow.get(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X); - } + BlockState blockState = worldIn.getBlockState(pos.offset(facing)); + if (isLargeCog(blockState) || isLarge && isSmallCog(blockState)) + return false; + } + return true; + } - if (!(block instanceof IRotate) - || !(((IRotate) block).hasIntegratedCogwheel(world, placedOnPos, placedAgainst))) { - Axis preferredAxis = getPreferredAxis(context); - if (preferredAxis != null) - return this.getDefaultState() - .with(AXIS, preferredAxis); - return this.getDefaultState() - .with(AXIS, context.getFace() - .getAxis()); - } + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + BlockPos placedOnPos = context.getPos() + .offset(context.getFace() + .getOpposite()); + World world = context.getWorld(); + BlockState placedAgainst = world.getBlockState(placedOnPos); + Block block = placedAgainst.getBlock(); - return getDefaultState().with(AXIS, ((IRotate) block).getRotationAxis(placedAgainst)); - } + BlockState stateBelow = world.getBlockState(context.getPos() + .down()); + IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos()); + if (AllBlocks.ROTATION_SPEED_CONTROLLER.has(stateBelow) && isLarge) { + return this.getDefaultState().with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)) + .with(AXIS, stateBelow.get(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X); + } - @Override - public float getParticleTargetRadius() { - return isLarge ? 1.125f : .65f; - } + if (!(block instanceof IRotate) + || !(((IRotate) block).hasIntegratedCogwheel(world, placedOnPos, placedAgainst))) { + Axis preferredAxis = getPreferredAxis(context); + if (preferredAxis != null) + return this.getDefaultState() + .with(AXIS, preferredAxis).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + return this.getDefaultState() + .with(AXIS, context.getFace() + .getAxis()).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + } - @Override - public float getParticleInitialRadius() { - return isLarge ? 1f : .75f; - } + return getDefaultState().with(AXIS, ((IRotate) block).getRotationAxis(placedAgainst)); + } - public static boolean isSmallCog(BlockState state) { - return AllBlocks.COGWHEEL.has(state); - } + @Override + public float getParticleTargetRadius() { + return isLarge ? 1.125f : .65f; + } - public static boolean isLargeCog(BlockState state) { - return AllBlocks.LARGE_COGWHEEL.has(state); - } + @Override + public float getParticleInitialRadius() { + return isLarge ? 1f : .75f; + } - public void fillItemGroup(ItemGroup group, NonNullList items) { - items.add(new ItemStack(this)); - } + public void fillItemGroup(ItemGroup group, NonNullList items) { + items.add(new ItemStack(this)); + } - // IRotate + // IRotate - @Override - public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) { - return !isLarge; - } + @Override + public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) { + return !isLarge; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java index 56a291984..e13efbdd8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java @@ -4,12 +4,18 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; - +import net.minecraft.block.Block; import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; +import net.minecraft.block.IWaterLoggable; import net.minecraft.block.material.PushReaction; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; +import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; +import net.minecraft.state.StateContainer.Builder; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -18,63 +24,90 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; -public class ShaftBlock extends RotatedPillarKineticBlock { +public class ShaftBlock extends RotatedPillarKineticBlock implements IWaterLoggable { - public ShaftBlock(Properties properties) { - super(properties); - } - - @Override - public PushReaction getPushReaction(BlockState state) { - return PushReaction.NORMAL; - } + public ShaftBlock(Properties properties) { + super(properties); + setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); + } - @Override - public BlockRenderType getRenderType(BlockState state) { - return BlockRenderType.ENTITYBLOCK_ANIMATED; - } - - @Override - public TileEntity createTileEntity(BlockState state, IBlockReader world) { - return AllTileEntities.SIMPLE_KINETIC.create(); - } + public static boolean isShaft(BlockState state) { + return AllBlocks.SHAFT.has(state); + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS)); - } + @Override + public PushReaction getPushReaction(BlockState state) { + return PushReaction.NORMAL; + } - @Override - public float getParticleTargetRadius() { - return .25f; - } + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.ENTITYBLOCK_ANIMATED; + } - @Override - public float getParticleInitialRadius() { - return 0f; - } - - @Override - public void fillItemGroup(ItemGroup group, NonNullList items) { - super.fillItemGroup(group, items); - } - - public static boolean isShaft(BlockState state) { - return AllBlocks.SHAFT.has(state); - } + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return AllTileEntities.SIMPLE_KINETIC.create(); + } - // IRotate: + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS)); + } - @Override - public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.get(AXIS); - } + @Override + public float getParticleTargetRadius() { + return .25f; + } - @Override - public Axis getRotationAxis(BlockState state) { - return state.get(AXIS); - } + @Override + public float getParticleInitialRadius() { + return 0f; + } + @Override + public void fillItemGroup(ItemGroup group, NonNullList items) { + super.fillItemGroup(group, items); + } + + // IRotate: + + @Override + public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { + return face.getAxis() == state.get(AXIS); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return state.get(AXIS); + } + + @Override + public IFluidState getFluidState(BlockState state) { + return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState(); + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(BlockStateProperties.WATERLOGGED); + super.fillStateContainer(builder); + } + + @Override + public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, + IWorld world, BlockPos pos, BlockPos neighbourPos) { + if (state.get(BlockStateProperties.WATERLOGGED)) { + world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); + } + return state; + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + IFluidState ifluidstate = context.getWorld().getFluidState(context.getPos()); + return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER)); + } }