diff --git a/build.gradle b/build.gradle index afa8a08c3..57ab30767 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = 'mc1.14.4_v0.1.1' +version = 'mc1.14.4_v0.2' group = 'com.simibubi.create' archivesBaseName = 'create' diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..878bf1f7e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,4 @@ +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/modules/contraptions/generators/WaterWheelBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/generators/WaterWheelBlock.java index 374e568e9..25dfc1928 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/generators/WaterWheelBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/generators/WaterWheelBlock.java @@ -83,22 +83,23 @@ public class WaterWheelBlock extends HorizontalKineticBlock { flowVec = flowVec.scale(f.getAxisDirection().getOffset()); boolean clockwise = wf.getAxisDirection() == AxisDirection.POSITIVE; + int clockwiseMultiplier = 1; // No difference. Causes confusion if (wf.getAxis() == Axis.Z) { if (f.getAxis() == Axis.Y) - flow = flowVec.x > 0 ^ !clockwise ? -flowVec.x * 2 : -flowVec.x; + flow = flowVec.x > 0 ^ !clockwise ? -flowVec.x * clockwiseMultiplier : -flowVec.x; if (f.getAxis() == Axis.X) - flow = flowVec.y < 0 ^ !clockwise ? flowVec.y * 2 : flowVec.y; + flow = flowVec.y < 0 ^ !clockwise ? flowVec.y * clockwiseMultiplier : flowVec.y; } if (wf.getAxis() == Axis.X) { if (f.getAxis() == Axis.Y) - flow = flowVec.z < 0 ^ !clockwise ? flowVec.z * 2 : flowVec.z; + flow = flowVec.z < 0 ^ !clockwise ? flowVec.z * clockwiseMultiplier : flowVec.z; if (f.getAxis() == Axis.Z) - flow = flowVec.y > 0 ^ !clockwise ? -flowVec.y * 2 : -flowVec.y; + flow = flowVec.y > 0 ^ !clockwise ? -flowVec.y * clockwiseMultiplier : -flowVec.y; } - te.setFlow(f, (int) (flow * 10)); + te.setFlow(f, (int) (flow * 20)); } private void updateWheelSpeed(IWorld world, BlockPos pos) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillBlock.java index 8fe0ec51b..110aed8d9 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/DrillBlock.java @@ -140,18 +140,20 @@ public class DrillBlock extends DirectionalKineticBlock implements IHaveMovement } @Override - public boolean visitPosition(World world, BlockPos pos, BlockState block, Direction movement, + public IMovementContext visitPosition(World world, BlockPos pos, BlockState block, Direction movement, MechanicalPistonTileEntity piston) { + IMovementContext context = IdleMovementContext.INSTANCE; + if (movement != block.get(FACING)) - return false; + return context; pos = pos.offset(movement); BlockState stateVisited = world.getBlockState(pos); if (stateVisited.getCollisionShape(world, pos).isEmpty()) - return false; + return context; if (stateVisited.getBlockHardness(world, pos) == -1) - return false; + return context; world.playEvent(2001, pos, Block.getStateId(stateVisited)); List drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null); @@ -164,7 +166,7 @@ public class DrillBlock extends DirectionalKineticBlock implements IHaveMovement world.addEntity(itemEntity); } - return false; + return context; } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java index d0cbb36d7..04a7a9347 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/HarvesterBlock.java @@ -93,10 +93,12 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha } @Override - public boolean visitPosition(World world, BlockPos pos, BlockState block, Direction movement, + public IMovementContext visitPosition(World world, BlockPos pos, BlockState block, Direction movement, MechanicalPistonTileEntity piston) { + IMovementContext context = IdleMovementContext.INSTANCE; + if (movement != block.get(HORIZONTAL_FACING)) - return false; + return context; BlockState stateVisited = world.getBlockState(pos); boolean notCropButCuttable = false; @@ -111,7 +113,7 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha if (isValidOther(world, pos, stateVisited)) notCropButCuttable = true; else - return false; + return context; } List drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null); @@ -130,7 +132,7 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha world.addEntity(itemEntity); } - return false; + return context; } private boolean isValidCrop(World world, BlockPos pos, BlockState state) { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/IHaveMovementBehavior.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/IHaveMovementBehavior.java index ed4db34bb..d7902f70f 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/IHaveMovementBehavior.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/IHaveMovementBehavior.java @@ -7,6 +7,26 @@ import net.minecraft.world.World; public interface IHaveMovementBehavior { - public boolean visitPosition(World world, BlockPos pos, BlockState block, Direction movement, MechanicalPistonTileEntity piston); - + default IMovementContext visitPosition(World world, BlockPos pos, BlockState block, Direction movement, + MechanicalPistonTileEntity piston) { + return IdleMovementContext.INSTANCE; + } + + default void tick(MechanicalPistonTileEntity piston) { + } + + default boolean hasSpecialRenderer() { + return false; + } + + public interface IMovementContext { + default boolean isBlocking() { + return false; + } + } + + public static class IdleMovementContext implements IMovementContext { + public static IdleMovementContext INSTANCE = new IdleMovementContext(); + } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonBlock.java index 32fc8531d..0dd807fc2 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonBlock.java @@ -10,6 +10,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BlockItemUseContext; +import net.minecraft.particles.ParticleTypes; import net.minecraft.state.BooleanProperty; import net.minecraft.state.DirectionProperty; import net.minecraft.state.EnumProperty; @@ -18,13 +19,19 @@ import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Hand; import net.minecraft.util.IStringSerializable; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; +import net.minecraftforge.common.Tags; public class MechanicalPistonBlock extends KineticBlock { @@ -110,6 +117,33 @@ public class MechanicalPistonBlock extends KineticBlock { .with(AXIS_ALONG_FIRST_COORDINATE, alongFirst); } + @Override + public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + if (state.get(STATE) != PistonState.RETRACTED) + return false; + if (!player.isAllowEdit()) + return false; + if (!player.getHeldItem(handIn).getItem().isIn(Tags.Items.SLIMEBALLS)) + return false; + Direction direction = state.get(FACING); + if (hit.getFace() != direction) + return false; + if (((MechanicalPistonBlock) state.getBlock()).isSticky) + return false; + if (worldIn.isRemote) { + Vec3d vec = hit.getHitVec(); + worldIn.addParticle(ParticleTypes.ITEM_SLIME, vec.x, vec.y, vec.z, 0, 0, 0); + return true; + } + worldIn.playSound(null, pos, SoundEvents.BLOCK_SLIME_BLOCK_PLACE, SoundCategory.BLOCKS, .5f, 1); + if (!player.isCreative()) + player.getHeldItem(handIn).shrink(1); + worldIn.setBlockState(pos, AllBlocks.STICKY_MECHANICAL_PISTON.get().getDefaultState().with(FACING, direction) + .with(AXIS_ALONG_FIRST_COORDINATE, state.get(AXIS_ALONG_FIRST_COORDINATE))); + return true; + } + @Override public TileEntity createTileEntity(BlockState state, IBlockReader world) { return new MechanicalPistonTileEntity(); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonTileEntity.java index 36d75fd8f..77478d89e 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/MechanicalPistonTileEntity.java @@ -255,10 +255,10 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection, getModulatedOffset(otherPiston.offset)); - for (AxisAlignedBB tBB : Arrays.asList(movingConstruct.collisionBoxFront, - movingConstruct.collisionBoxBack)) { - for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movingConstruct.collisionBoxFront, - otherPiston.movingConstruct.collisionBoxBack)) { + for (AxisAlignedBB tBB : Arrays.asList(movingConstruct.constructCollisionBox, + movingConstruct.pistonCollisionBox)) { + for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movingConstruct.constructCollisionBox, + otherPiston.movingConstruct.pistonCollisionBox)) { if (tBB == null || oBB == null) continue; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/TranslationConstruct.java b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/TranslationConstruct.java index 0603e50cc..0ad174b00 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/TranslationConstruct.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/receivers/constructs/TranslationConstruct.java @@ -3,7 +3,9 @@ package com.simibubi.create.modules.contraptions.receivers.constructs; import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD; import static com.simibubi.create.AllBlocks.PISTON_POLE; import static com.simibubi.create.AllBlocks.STICKY_MECHANICAL_PISTON; +import static com.simibubi.create.AllBlocks.TRANSLATION_CHASSIS; import static com.simibubi.create.CreateConfig.parameters; +import static net.minecraft.state.properties.BlockStateProperties.AXIS; import static net.minecraft.state.properties.BlockStateProperties.FACING; import java.util.ArrayList; @@ -23,14 +25,17 @@ import net.minecraft.block.BlockState; import net.minecraft.block.FallingBlock; import net.minecraft.block.PistonBlock; import net.minecraft.block.ShulkerBoxBlock; +import net.minecraft.block.SlimeBlock; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.FloatNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.PistonType; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -41,14 +46,15 @@ public class TranslationConstruct { protected Map blocks; protected List actors; - protected AxisAlignedBB collisionBoxFront; - protected AxisAlignedBB collisionBoxBack; + protected AxisAlignedBB constructCollisionBox; + protected AxisAlignedBB pistonCollisionBox; protected Set cachedColliders; protected Direction cachedColliderDirection; protected int extensionLength; protected int initialExtensionProgress; + protected Axis movementAxis; public TranslationConstruct() { blocks = new HashMap<>(); @@ -157,12 +163,12 @@ public class TranslationConstruct { extensionLength = extensionsInBack + extensionsInFront; initialExtensionProgress = extensionsInFront; - collisionBoxBack = new AxisAlignedBB(end.offset(direction, -extensionsInFront)); + pistonCollisionBox = new AxisAlignedBB(end.offset(direction, -extensionsInFront)); for (BlockInfo pole : poles) { BlockPos polePos = pole.pos.offset(direction, -extensionsInFront); blocks.put(polePos, new BlockInfo(polePos, pole.state, null)); - collisionBoxBack = collisionBoxBack.union(new AxisAlignedBB(polePos)); + pistonCollisionBox = pistonCollisionBox.union(new AxisAlignedBB(polePos)); } return true; @@ -189,7 +195,7 @@ public class TranslationConstruct { BlockPos blockPos = pos.offset(direction).offset(direction, -offset); blocks.put(blockPos, new BlockInfo(blockPos, state, null)); - collisionBoxFront = new AxisAlignedBB(blockPos); + constructCollisionBox = new AxisAlignedBB(blockPos); } else { for (int distance = 1; distance <= parameters.maxChassisRange.get() + 1; distance++) { @@ -213,10 +219,10 @@ public class TranslationConstruct { BlockPos blockPos = currentPos.offset(direction, -offset); blocks.put(blockPos, new BlockInfo(blockPos, state, null)); - if (collisionBoxFront == null) - collisionBoxFront = new AxisAlignedBB(blockPos); + if (constructCollisionBox == null) + constructCollisionBox = new AxisAlignedBB(blockPos); else - collisionBoxFront = collisionBoxFront.union(new AxisAlignedBB(blockPos)); + constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(blockPos)); // Don't collect in front of drills if (AllBlocks.DRILL.typeOf(state) && state.get(FACING) == direction) @@ -227,14 +233,14 @@ public class TranslationConstruct { // Get attached blocks by chassis else { - collisionBoxFront = new AxisAlignedBB(pos.offset(direction, -offset + 1)); + constructCollisionBox = new AxisAlignedBB(pos.offset(direction, -offset + 1)); List attachedBlocksByChassis = getAttachedBlocksByChassis(world, direction, chassis, movementDirection, offset); if (attachedBlocksByChassis == null) return false; attachedBlocksByChassis.forEach(info -> { blocks.put(info.pos, info); - collisionBoxFront = collisionBoxFront.union(new AxisAlignedBB(info.pos)); + constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(info.pos)); }); } @@ -296,11 +302,11 @@ public class TranslationConstruct { // Skip if pushed column ended already if (!currentPos.equals(currentChassisPos)) { - + // Don't pull if not sticky if (!chassisSticky && !pushing) continue; - + for (BlockPos p = currentPos; !p.equals(currentChassisPos); p = p.offset(direction.getOpposite())) { BlockState blockState = world.getBlockState(p); @@ -328,7 +334,7 @@ public class TranslationConstruct { CompoundNBT nbt = new CompoundNBT(); nbt.putInt("Range", chassisRange); blocks.add(new BlockInfo(currentPos.offset(direction, -offset), state, - AllBlocks.TRANSLATION_CHASSIS.typeOf(state) ? nbt : null)); + TRANSLATION_CHASSIS.typeOf(state) ? nbt : null)); // Expand search for (Direction facing : Direction.values()) { @@ -346,7 +352,7 @@ public class TranslationConstruct { private static boolean canPush(World world, BlockPos pos, Direction direction) { BlockState blockState = world.getBlockState(pos); - if (AllBlocks.TRANSLATION_CHASSIS.typeOf(blockState)) + if (TRANSLATION_CHASSIS.typeOf(blockState)) return true; if (blockState.getBlock() instanceof ShulkerBoxBlock) return false; @@ -373,7 +379,7 @@ public class TranslationConstruct { BlockState blockState = world.getBlockState(current); if (!(blockState.getBlock() instanceof TranslationChassisBlock)) continue; - if (blockState.get(BlockStateProperties.AXIS) != direction.getAxis()) + if (blockState.get(AXIS) != direction.getAxis()) continue; visited.add(current); @@ -388,12 +394,260 @@ public class TranslationConstruct { return chassis; } + ///////////////////////// + + public static TranslationConstruct moveConstructAt(World world, BlockPos pos, Direction direction) { + if (isFrozen()) + return null; + TranslationConstruct construct = new TranslationConstruct(); + construct.movementAxis = direction.getAxis(); + + // collect piston extensions + + if (!construct.searchMovedStructure(world, pos, direction)) + return null; + return construct; + } + + private boolean searchMovedStructure(World world, BlockPos pos, Direction direction) { + List frontier = new ArrayList<>(); + Set visited = new HashSet<>(); + constructCollisionBox = new AxisAlignedBB(pos); + frontier.add(pos); + + for (int offset = 1; offset <= parameters.maxChassisRange.get(); offset++) { + BlockPos currentPos = pos.offset(direction, offset); + if (!world.isAreaLoaded(currentPos, 1)) + return false; + if (!world.isBlockPresent(currentPos)) + continue; + BlockState state = world.getBlockState(currentPos); + if (state.getMaterial().isReplaceable()) + break; + if (state.getCollisionShape(world, currentPos).isEmpty()) + break; + if (!canPush(world, currentPos, direction)) + return false; + + } + + for (int limit = 1000; limit > 0; limit--) { + if (frontier.isEmpty()) + return true; + if (!moveBlock(world, frontier.remove(0), direction, frontier, visited)) + return false; + + } + return false; + } + + private boolean moveBlock(World world, BlockPos pos, Direction direction, List frontier, + Set visited) { + visited.add(pos); + frontier.remove(pos); + + if (!world.isBlockPresent(pos)) + return false; + BlockState state = world.getBlockState(pos); + if (state.getMaterial().isReplaceable()) + return true; + if (state.getCollisionShape(world, pos).isEmpty()) + return true; + if (!canPush(world, pos, direction)) + return false; + if (TRANSLATION_CHASSIS.typeOf(state) && !moveChassis(world, pos, direction, frontier, visited)) + return false; + if (state.getBlock() instanceof SlimeBlock) + for (Direction offset : Direction.values()) + frontier.add(pos.offset(offset)); + + add(pos, capture(world, pos)); + return true; + } + + private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, List frontier, + Set visited) { + List cluster = getChassisClusterAt(world, pos); + if (cluster == null) + return false; + if (cluster.isEmpty()) + return true; + + BlockInfo anchorChassis = cluster.get(0); + Axis chassisAxis = anchorChassis.state.get(AXIS); + List chassisFrontier = new LinkedList<>(); + Set chassisVisited = new HashSet<>(); + cluster.forEach(c -> frontier.add(c.pos)); + int chassisCoord = chassisAxis.getCoordinate(anchorChassis.pos.getX(), anchorChassis.pos.getY(), + anchorChassis.pos.getZ()); + + Function getChassisPos = position -> new BlockPos( + chassisAxis == Axis.X ? chassisCoord : position.getX(), + chassisAxis == Axis.Y ? chassisCoord : position.getY(), + chassisAxis == Axis.Z ? chassisCoord : position.getZ()); + + // Collect blocks on both sides + for (AxisDirection axisDirection : AxisDirection.values()) { + Direction chassisDirection = Direction.getFacingFromAxis(axisDirection, chassisAxis); + boolean pushing = chassisDirection == movementDirection; + + Search: while (!chassisFrontier.isEmpty()) { + BlockPos currentPos = chassisFrontier.remove(0); + if (!world.isAreaLoaded(currentPos, 1)) + return false; + if (!world.isBlockPresent(currentPos)) + continue; + if (chassisVisited.contains(currentPos)) + continue; + chassisVisited.add(currentPos); + + BlockState state = world.getBlockState(currentPos); + BlockPos currentChassisPos = getChassisPos.apply(currentPos); + BlockState chassisState = world.getBlockState(currentChassisPos); + + // Not attached to a chassis + if (!AllBlocks.TRANSLATION_CHASSIS.typeOf(chassisState) || chassisState.get(AXIS) != chassisAxis) + continue; + + int chassisRange = ((ChassisTileEntity) world.getTileEntity(currentChassisPos)).getRange(); + boolean chassisSticky = chassisState.get(((AbstractChassisBlock) chassisState.getBlock()) + .getGlueableSide(chassisState, chassisDirection)); + + // Ignore replaceable Blocks and Air-like + if (state.getMaterial().isReplaceable() || state.isAir(world, currentPos)) + continue; + if (state.getCollisionShape(world, currentPos).isEmpty()) + continue; + + // Too many Blocks + boolean notInRange = !currentChassisPos.withinDistance(currentPos, chassisRange + 1); + if (pushing && notInRange) + return false; + if (!pushing && notInRange) + continue; + + boolean isBaseChassis = currentPos.equals(currentChassisPos); + if (!isBaseChassis) { + // Don't pull if chassis not sticky + if (!chassisSticky && !pushing) + continue; + + // Skip if pushed column ended already + for (BlockPos posInbetween = currentPos; !posInbetween.equals( + currentChassisPos); posInbetween = posInbetween.offset(chassisDirection.getOpposite())) { + BlockState blockState = world.getBlockState(posInbetween); + + if (!chassisSticky && (blockState.getMaterial().isReplaceable())) + continue Search; + if (!pushing && chassisSticky && !canPush(world, posInbetween, movementDirection)) + continue Search; + } + } + + // Ignore sand and co. + if (chassisSticky && !pushing && state.getBlock() instanceof FallingBlock) + continue; + + // Structure is immobile + boolean cannotPush = !canPush(world, currentPos, movementDirection); + if (pushing && cannotPush) + return false; + if (!pushing && cannotPush) + continue; + + if (isBaseChassis) { + add(currentPos, capture(world, currentPos)); + visited.add(currentPos); + } else { + frontier.add(currentPos); + } + + // Expand search + for (Direction facing : Direction.values()) { + if (isBaseChassis && facing == chassisDirection.getOpposite()) + continue; + if (notSupportive(world, pos, facing)) + continue; + chassisFrontier.add(currentPos.offset(facing)); + } + } + } + + return true; + } + + private static List getChassisClusterAt(World world, BlockPos pos) { + List search = new LinkedList<>(); + Set visited = new HashSet<>(); + List chassis = new LinkedList<>(); + Axis axis = world.getBlockState(pos).get(AXIS); + search.add(pos); + + while (!search.isEmpty()) { + if (chassis.size() > parameters.maxChassisForTranslation.get()) + return null; + + BlockPos current = search.remove(0); + if (visited.contains(current)) + continue; + if (!world.isAreaLoaded(current, 1)) + return null; + + BlockState state = world.getBlockState(current); + if (!TRANSLATION_CHASSIS.typeOf(state)) + continue; + if (state.get(AXIS) != axis) + continue; + + visited.add(current); + chassis.add(capture(world, current)); + + for (Direction offset : Direction.values()) { + if (offset.getAxis() == axis) + continue; + search.add(current.offset(offset)); + } + } + return chassis; + } + + private boolean notSupportive(World world, BlockPos pos, Direction facing) { + BlockState state = world.getBlockState(pos); + if (AllBlocks.DRILL.typeOf(state)) + return state.get(BlockStateProperties.FACING) == facing; + if (AllBlocks.HARVESTER.typeOf(state)) + return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing; + return false; + } + + private void add(BlockPos pos, BlockInfo block) { + BlockPos localPos = pos.offset(Direction.getFacingFromAxisDirection(movementAxis, AxisDirection.POSITIVE), + -initialExtensionProgress); + blocks.put(localPos, block); + if (block.state.getBlock() instanceof IHaveMovementBehavior) + actors.add(block); + constructCollisionBox.union(new AxisAlignedBB(pos)); + } + + private static BlockInfo capture(World world, BlockPos pos) { + BlockState blockstate = world.getBlockState(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 new BlockInfo(pos, blockstate, compoundnbt); + } + public AxisAlignedBB getCollisionBoxFront() { - return collisionBoxFront; + return constructCollisionBox; } public AxisAlignedBB getCollisionBoxBack() { - return collisionBoxBack; + return pistonCollisionBox; } public CompoundNBT writeNBT() { @@ -408,13 +662,13 @@ public class TranslationConstruct { blocks.add(c); } - if (collisionBoxFront != null) { - ListNBT bb = writeAABB(collisionBoxFront); + if (constructCollisionBox != null) { + ListNBT bb = writeAABB(constructCollisionBox); nbt.put("BoundsFront", bb); } - if (collisionBoxBack != null) { - ListNBT bb = writeAABB(collisionBoxBack); + if (pistonCollisionBox != null) { + ListNBT bb = writeAABB(pistonCollisionBox); nbt.put("BoundsBack", bb); } @@ -454,9 +708,9 @@ public class TranslationConstruct { construct.extensionLength = nbt.getInt("ExtensionLength"); if (nbt.contains("BoundsFront")) - construct.collisionBoxFront = construct.readAABB(nbt.getList("BoundsFront", 5)); + construct.constructCollisionBox = construct.readAABB(nbt.getList("BoundsFront", 5)); if (nbt.contains("BoundsBack")) - construct.collisionBoxBack = construct.readAABB(nbt.getList("BoundsBack", 5)); + construct.pistonCollisionBox = construct.readAABB(nbt.getList("BoundsBack", 5)); // Find blocks with special movement behaviour construct.blocks.values().forEach(block -> { diff --git a/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java index 067bd6d94..db3d23170 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/redstone/ContactBlock.java @@ -101,16 +101,16 @@ public class ContactBlock extends ProperDirectionalBlock implements IHaveMovemen } @Override - public boolean visitPosition(World world, BlockPos pos, BlockState block, Direction movement, + public IMovementContext visitPosition(World world, BlockPos pos, BlockState block, Direction movement, MechanicalPistonTileEntity piston) { Direction direction = block.get(FACING); if (!hasValidContact(world, pos, direction)) - return false; + return IdleMovementContext.INSTANCE; int ticksToStayActive = (int) Math.ceil(1 / Math.abs(piston.getMovementSpeed())); world.setBlockState(pos.offset(direction), world.getBlockState(pos.offset(direction)).with(POWERED, true)); world.getPendingBlockTicks().scheduleTick(pos.offset(direction), this, ticksToStayActive, TickPriority.NORMAL); - return false; + return IdleMovementContext.INSTANCE; } }