Addressing Todos

- Started work on changing how moving constructs are assembled and ticked
This commit is contained in:
simibubi 2019-10-13 21:30:25 +02:00
parent 488a9f63a9
commit 98f568f887
10 changed files with 364 additions and 47 deletions

View file

@ -13,7 +13,7 @@ apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'eclipse' apply plugin: 'eclipse'
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
version = 'mc1.14.4_v0.1.1' version = 'mc1.14.4_v0.2'
group = 'com.simibubi.create' group = 'com.simibubi.create'
archivesBaseName = 'create' archivesBaseName = 'create'

4
gradle.properties Normal file
View file

@ -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

View file

@ -83,22 +83,23 @@ public class WaterWheelBlock extends HorizontalKineticBlock {
flowVec = flowVec.scale(f.getAxisDirection().getOffset()); flowVec = flowVec.scale(f.getAxisDirection().getOffset());
boolean clockwise = wf.getAxisDirection() == AxisDirection.POSITIVE; boolean clockwise = wf.getAxisDirection() == AxisDirection.POSITIVE;
int clockwiseMultiplier = 1; // No difference. Causes confusion
if (wf.getAxis() == Axis.Z) { if (wf.getAxis() == Axis.Z) {
if (f.getAxis() == Axis.Y) 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) 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 (wf.getAxis() == Axis.X) {
if (f.getAxis() == Axis.Y) 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) 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) { private void updateWheelSpeed(IWorld world, BlockPos pos) {

View file

@ -140,18 +140,20 @@ public class DrillBlock extends DirectionalKineticBlock implements IHaveMovement
} }
@Override @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) { MechanicalPistonTileEntity piston) {
IMovementContext context = IdleMovementContext.INSTANCE;
if (movement != block.get(FACING)) if (movement != block.get(FACING))
return false; return context;
pos = pos.offset(movement); pos = pos.offset(movement);
BlockState stateVisited = world.getBlockState(pos); BlockState stateVisited = world.getBlockState(pos);
if (stateVisited.getCollisionShape(world, pos).isEmpty()) if (stateVisited.getCollisionShape(world, pos).isEmpty())
return false; return context;
if (stateVisited.getBlockHardness(world, pos) == -1) if (stateVisited.getBlockHardness(world, pos) == -1)
return false; return context;
world.playEvent(2001, pos, Block.getStateId(stateVisited)); world.playEvent(2001, pos, Block.getStateId(stateVisited));
List<ItemStack> drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null); List<ItemStack> drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null);
@ -164,7 +166,7 @@ public class DrillBlock extends DirectionalKineticBlock implements IHaveMovement
world.addEntity(itemEntity); world.addEntity(itemEntity);
} }
return false; return context;
} }
} }

View file

@ -93,10 +93,12 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
} }
@Override @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) { MechanicalPistonTileEntity piston) {
IMovementContext context = IdleMovementContext.INSTANCE;
if (movement != block.get(HORIZONTAL_FACING)) if (movement != block.get(HORIZONTAL_FACING))
return false; return context;
BlockState stateVisited = world.getBlockState(pos); BlockState stateVisited = world.getBlockState(pos);
boolean notCropButCuttable = false; boolean notCropButCuttable = false;
@ -111,7 +113,7 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
if (isValidOther(world, pos, stateVisited)) if (isValidOther(world, pos, stateVisited))
notCropButCuttable = true; notCropButCuttable = true;
else else
return false; return context;
} }
List<ItemStack> drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null); List<ItemStack> drops = Block.getDrops(stateVisited, (ServerWorld) world, pos, null);
@ -130,7 +132,7 @@ public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBeha
world.addEntity(itemEntity); world.addEntity(itemEntity);
} }
return false; return context;
} }
private boolean isValidCrop(World world, BlockPos pos, BlockState state) { private boolean isValidCrop(World world, BlockPos pos, BlockState state) {

View file

@ -7,6 +7,26 @@ import net.minecraft.world.World;
public interface IHaveMovementBehavior { 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();
}
} }

View file

@ -10,6 +10,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.state.DirectionProperty; import net.minecraft.state.DirectionProperty;
import net.minecraft.state.EnumProperty; import net.minecraft.state.EnumProperty;
@ -18,13 +19,19 @@ import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.IStringSerializable; 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.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.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.Tags;
public class MechanicalPistonBlock extends KineticBlock { public class MechanicalPistonBlock extends KineticBlock {
@ -110,6 +117,33 @@ public class MechanicalPistonBlock extends KineticBlock {
.with(AXIS_ALONG_FIRST_COORDINATE, alongFirst); .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 @Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) { public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new MechanicalPistonTileEntity(); return new MechanicalPistonTileEntity();

View file

@ -255,10 +255,10 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection, BlockPos otherRelativePos = BlockPos.ZERO.offset(otherMovementDirection,
getModulatedOffset(otherPiston.offset)); getModulatedOffset(otherPiston.offset));
for (AxisAlignedBB tBB : Arrays.asList(movingConstruct.collisionBoxFront, for (AxisAlignedBB tBB : Arrays.asList(movingConstruct.constructCollisionBox,
movingConstruct.collisionBoxBack)) { movingConstruct.pistonCollisionBox)) {
for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movingConstruct.collisionBoxFront, for (AxisAlignedBB oBB : Arrays.asList(otherPiston.movingConstruct.constructCollisionBox,
otherPiston.movingConstruct.collisionBoxBack)) { otherPiston.movingConstruct.pistonCollisionBox)) {
if (tBB == null || oBB == null) if (tBB == null || oBB == null)
continue; continue;

View file

@ -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.MECHANICAL_PISTON_HEAD;
import static com.simibubi.create.AllBlocks.PISTON_POLE; import static com.simibubi.create.AllBlocks.PISTON_POLE;
import static com.simibubi.create.AllBlocks.STICKY_MECHANICAL_PISTON; 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 com.simibubi.create.CreateConfig.parameters;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.state.properties.BlockStateProperties.FACING; import static net.minecraft.state.properties.BlockStateProperties.FACING;
import java.util.ArrayList; import java.util.ArrayList;
@ -23,14 +25,17 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.FallingBlock; import net.minecraft.block.FallingBlock;
import net.minecraft.block.PistonBlock; import net.minecraft.block.PistonBlock;
import net.minecraft.block.ShulkerBoxBlock; import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.block.SlimeBlock;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.FloatNBT; import net.minecraft.nbt.FloatNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.PistonType; import net.minecraft.state.properties.PistonType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -41,14 +46,15 @@ public class TranslationConstruct {
protected Map<BlockPos, BlockInfo> blocks; protected Map<BlockPos, BlockInfo> blocks;
protected List<BlockInfo> actors; protected List<BlockInfo> actors;
protected AxisAlignedBB collisionBoxFront; protected AxisAlignedBB constructCollisionBox;
protected AxisAlignedBB collisionBoxBack; protected AxisAlignedBB pistonCollisionBox;
protected Set<BlockPos> cachedColliders; protected Set<BlockPos> cachedColliders;
protected Direction cachedColliderDirection; protected Direction cachedColliderDirection;
protected int extensionLength; protected int extensionLength;
protected int initialExtensionProgress; protected int initialExtensionProgress;
protected Axis movementAxis;
public TranslationConstruct() { public TranslationConstruct() {
blocks = new HashMap<>(); blocks = new HashMap<>();
@ -157,12 +163,12 @@ public class TranslationConstruct {
extensionLength = extensionsInBack + extensionsInFront; extensionLength = extensionsInBack + extensionsInFront;
initialExtensionProgress = extensionsInFront; initialExtensionProgress = extensionsInFront;
collisionBoxBack = new AxisAlignedBB(end.offset(direction, -extensionsInFront)); pistonCollisionBox = new AxisAlignedBB(end.offset(direction, -extensionsInFront));
for (BlockInfo pole : poles) { for (BlockInfo pole : poles) {
BlockPos polePos = pole.pos.offset(direction, -extensionsInFront); BlockPos polePos = pole.pos.offset(direction, -extensionsInFront);
blocks.put(polePos, new BlockInfo(polePos, pole.state, null)); blocks.put(polePos, new BlockInfo(polePos, pole.state, null));
collisionBoxBack = collisionBoxBack.union(new AxisAlignedBB(polePos)); pistonCollisionBox = pistonCollisionBox.union(new AxisAlignedBB(polePos));
} }
return true; return true;
@ -189,7 +195,7 @@ public class TranslationConstruct {
BlockPos blockPos = pos.offset(direction).offset(direction, -offset); BlockPos blockPos = pos.offset(direction).offset(direction, -offset);
blocks.put(blockPos, new BlockInfo(blockPos, state, null)); blocks.put(blockPos, new BlockInfo(blockPos, state, null));
collisionBoxFront = new AxisAlignedBB(blockPos); constructCollisionBox = new AxisAlignedBB(blockPos);
} else { } else {
for (int distance = 1; distance <= parameters.maxChassisRange.get() + 1; distance++) { for (int distance = 1; distance <= parameters.maxChassisRange.get() + 1; distance++) {
@ -213,10 +219,10 @@ public class TranslationConstruct {
BlockPos blockPos = currentPos.offset(direction, -offset); BlockPos blockPos = currentPos.offset(direction, -offset);
blocks.put(blockPos, new BlockInfo(blockPos, state, null)); blocks.put(blockPos, new BlockInfo(blockPos, state, null));
if (collisionBoxFront == null) if (constructCollisionBox == null)
collisionBoxFront = new AxisAlignedBB(blockPos); constructCollisionBox = new AxisAlignedBB(blockPos);
else else
collisionBoxFront = collisionBoxFront.union(new AxisAlignedBB(blockPos)); constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(blockPos));
// Don't collect in front of drills // Don't collect in front of drills
if (AllBlocks.DRILL.typeOf(state) && state.get(FACING) == direction) if (AllBlocks.DRILL.typeOf(state) && state.get(FACING) == direction)
@ -227,14 +233,14 @@ public class TranslationConstruct {
// Get attached blocks by chassis // Get attached blocks by chassis
else { else {
collisionBoxFront = new AxisAlignedBB(pos.offset(direction, -offset + 1)); constructCollisionBox = new AxisAlignedBB(pos.offset(direction, -offset + 1));
List<BlockInfo> attachedBlocksByChassis = getAttachedBlocksByChassis(world, direction, chassis, List<BlockInfo> attachedBlocksByChassis = getAttachedBlocksByChassis(world, direction, chassis,
movementDirection, offset); movementDirection, offset);
if (attachedBlocksByChassis == null) if (attachedBlocksByChassis == null)
return false; return false;
attachedBlocksByChassis.forEach(info -> { attachedBlocksByChassis.forEach(info -> {
blocks.put(info.pos, info); blocks.put(info.pos, info);
collisionBoxFront = collisionBoxFront.union(new AxisAlignedBB(info.pos)); constructCollisionBox = constructCollisionBox.union(new AxisAlignedBB(info.pos));
}); });
} }
@ -328,7 +334,7 @@ public class TranslationConstruct {
CompoundNBT nbt = new CompoundNBT(); CompoundNBT nbt = new CompoundNBT();
nbt.putInt("Range", chassisRange); nbt.putInt("Range", chassisRange);
blocks.add(new BlockInfo(currentPos.offset(direction, -offset), state, blocks.add(new BlockInfo(currentPos.offset(direction, -offset), state,
AllBlocks.TRANSLATION_CHASSIS.typeOf(state) ? nbt : null)); TRANSLATION_CHASSIS.typeOf(state) ? nbt : null));
// Expand search // Expand search
for (Direction facing : Direction.values()) { for (Direction facing : Direction.values()) {
@ -346,7 +352,7 @@ public class TranslationConstruct {
private static boolean canPush(World world, BlockPos pos, Direction direction) { private static boolean canPush(World world, BlockPos pos, Direction direction) {
BlockState blockState = world.getBlockState(pos); BlockState blockState = world.getBlockState(pos);
if (AllBlocks.TRANSLATION_CHASSIS.typeOf(blockState)) if (TRANSLATION_CHASSIS.typeOf(blockState))
return true; return true;
if (blockState.getBlock() instanceof ShulkerBoxBlock) if (blockState.getBlock() instanceof ShulkerBoxBlock)
return false; return false;
@ -373,7 +379,7 @@ public class TranslationConstruct {
BlockState blockState = world.getBlockState(current); BlockState blockState = world.getBlockState(current);
if (!(blockState.getBlock() instanceof TranslationChassisBlock)) if (!(blockState.getBlock() instanceof TranslationChassisBlock))
continue; continue;
if (blockState.get(BlockStateProperties.AXIS) != direction.getAxis()) if (blockState.get(AXIS) != direction.getAxis())
continue; continue;
visited.add(current); visited.add(current);
@ -388,12 +394,260 @@ public class TranslationConstruct {
return chassis; 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<BlockPos> frontier = new ArrayList<>();
Set<BlockPos> 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<BlockPos> frontier,
Set<BlockPos> 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<BlockPos> frontier,
Set<BlockPos> visited) {
List<BlockInfo> 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<BlockPos> chassisFrontier = new LinkedList<>();
Set<BlockPos> chassisVisited = new HashSet<>();
cluster.forEach(c -> frontier.add(c.pos));
int chassisCoord = chassisAxis.getCoordinate(anchorChassis.pos.getX(), anchorChassis.pos.getY(),
anchorChassis.pos.getZ());
Function<BlockPos, BlockPos> 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<BlockInfo> getChassisClusterAt(World world, BlockPos pos) {
List<BlockPos> search = new LinkedList<>();
Set<BlockPos> visited = new HashSet<>();
List<BlockInfo> 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() { public AxisAlignedBB getCollisionBoxFront() {
return collisionBoxFront; return constructCollisionBox;
} }
public AxisAlignedBB getCollisionBoxBack() { public AxisAlignedBB getCollisionBoxBack() {
return collisionBoxBack; return pistonCollisionBox;
} }
public CompoundNBT writeNBT() { public CompoundNBT writeNBT() {
@ -408,13 +662,13 @@ public class TranslationConstruct {
blocks.add(c); blocks.add(c);
} }
if (collisionBoxFront != null) { if (constructCollisionBox != null) {
ListNBT bb = writeAABB(collisionBoxFront); ListNBT bb = writeAABB(constructCollisionBox);
nbt.put("BoundsFront", bb); nbt.put("BoundsFront", bb);
} }
if (collisionBoxBack != null) { if (pistonCollisionBox != null) {
ListNBT bb = writeAABB(collisionBoxBack); ListNBT bb = writeAABB(pistonCollisionBox);
nbt.put("BoundsBack", bb); nbt.put("BoundsBack", bb);
} }
@ -454,9 +708,9 @@ public class TranslationConstruct {
construct.extensionLength = nbt.getInt("ExtensionLength"); construct.extensionLength = nbt.getInt("ExtensionLength");
if (nbt.contains("BoundsFront")) if (nbt.contains("BoundsFront"))
construct.collisionBoxFront = construct.readAABB(nbt.getList("BoundsFront", 5)); construct.constructCollisionBox = construct.readAABB(nbt.getList("BoundsFront", 5));
if (nbt.contains("BoundsBack")) 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 // Find blocks with special movement behaviour
construct.blocks.values().forEach(block -> { construct.blocks.values().forEach(block -> {

View file

@ -101,16 +101,16 @@ public class ContactBlock extends ProperDirectionalBlock implements IHaveMovemen
} }
@Override @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) { MechanicalPistonTileEntity piston) {
Direction direction = block.get(FACING); Direction direction = block.get(FACING);
if (!hasValidContact(world, pos, direction)) if (!hasValidContact(world, pos, direction))
return false; return IdleMovementContext.INSTANCE;
int ticksToStayActive = (int) Math.ceil(1 / Math.abs(piston.getMovementSpeed())); int ticksToStayActive = (int) Math.ceil(1 / Math.abs(piston.getMovementSpeed()));
world.setBlockState(pos.offset(direction), world.getBlockState(pos.offset(direction)).with(POWERED, true)); world.setBlockState(pos.offset(direction), world.getBlockState(pos.offset(direction)).with(POWERED, true));
world.getPendingBlockTicks().scheduleTick(pos.offset(direction), this, ticksToStayActive, TickPriority.NORMAL); world.getPendingBlockTicks().scheduleTick(pos.offset(direction), this, ticksToStayActive, TickPriority.NORMAL);
return false; return IdleMovementContext.INSTANCE;
} }
} }