Gantry improvements

- Fixed gantry shafts not locking to correct orientations when placed near others
- Gantry pinions can now be kickstarted by player interaction
- Gantry pinions now update properly after being moved onto different gantry shafts
- Fixed Encased Fans not providing kinetic power after being moved by contraption
- Sticky Mechanical Pistons now drag attached structures with them
- Mechanical piston heads and poles now drag their entire piston multiblock with them
This commit is contained in:
simibubi 2021-02-06 16:07:22 +01:00
parent ff96e80d81
commit 3d8b10d9a7
5 changed files with 173 additions and 74 deletions

View file

@ -1,6 +1,5 @@
package com.simibubi.create.content.contraptions.components.fan;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock;
@ -33,9 +32,16 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
@Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
super.onBlockAdded(state, worldIn, pos, oldState, isMoving);
blockUpdate(state, worldIn, pos);
}
@Override
public void updateNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags) {
super.updateNeighbors(stateIn, worldIn, pos, flags);
blockUpdate(stateIn, worldIn, pos);
}
@Override
public void onReplaced(BlockState state, World world, BlockPos pos, BlockState p_196243_4_, boolean p_196243_5_) {
if (state.hasTileEntity() && (state.getBlock() != p_196243_4_.getBlock() || !p_196243_4_.hasTileEntity())) {
@ -70,13 +76,13 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
.isSneaking() ? preferredFacing : preferredFacing.getOpposite());
}
protected void blockUpdate(BlockState state, World worldIn, BlockPos pos) {
protected void blockUpdate(BlockState state, IWorld worldIn, BlockPos pos) {
if (worldIn instanceof WrappedWorld)
return;
notifyFanTile(worldIn, pos);
if (worldIn.isRemote)
if (worldIn.isRemote())
return;
withTileEntityDo(worldIn, pos, te -> te.updateGenerator(state.get(FACING)));
withTileEntityDo(worldIn, pos, te -> te.queueGeneratorUpdate());
}
protected void notifyFanTile(IWorld world, BlockPos pos) {

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.fan;
import javax.annotation.Nullable;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
@ -18,7 +19,6 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@MethodsReturnNonnullByDefault
public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements IAirCurrentSource {
@ -27,17 +27,20 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
protected int entitySearchCooldown;
protected boolean isGenerator;
protected boolean updateAirFlow;
protected boolean updateGenerator;
public EncasedFanTileEntity(TileEntityType<? extends EncasedFanTileEntity> type) {
super(type);
isGenerator = false;
airCurrent = new AirCurrent(this);
updateAirFlow = true;
updateGenerator = false;
}
@Override
protected void read(CompoundNBT compound, boolean clientPacket) {
super.read(compound, clientPacket);
if (!wasMoved)
isGenerator = compound.getBoolean("Generating");
if (clientPacket)
airCurrent.rebuild();
@ -64,12 +67,20 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
return isGenerator ? AllConfigs.SERVER.kinetics.generatingFanSpeed.get() : 0;
}
public void updateGenerator(Direction facing) {
boolean shouldGenerate = world.isBlockPowered(pos) && facing == Direction.DOWN
&& world.isBlockPresent(pos.down()) && blockBelowIsHot();
if (shouldGenerate == isGenerator)
public void queueGeneratorUpdate() {
updateGenerator = true;
}
public void updateGenerator() {
BlockState blockState = getBlockState();
if (!AllBlocks.ENCASED_FAN.has(blockState))
return;
if (blockState.get(EncasedFanBlock.FACING) != Direction.DOWN)
return;
boolean shouldGenerate = world.isBlockPowered(pos) && world.isBlockPresent(pos.down()) && blockBelowIsHot();
if (shouldGenerate == isGenerator)
return;
isGenerator = shouldGenerate;
updateGeneratedRotation();
}
@ -171,6 +182,11 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
sendData();
}
if (updateGenerator) {
updateGenerator = false;
updateGenerator();
}
if (getSpeed() == 0 || isGenerator)
return;

View file

@ -23,6 +23,7 @@ import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.actors.SeatBlock;
import com.simibubi.create.content.contraptions.components.actors.SeatEntity;
@ -35,6 +36,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.glu
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueHandler;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonHeadBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.MagnetBlock;
@ -71,6 +73,7 @@ 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.state.properties.PistonType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
@ -266,25 +269,11 @@ public abstract class Contraption {
if (AllBlocks.BELT.has(state))
moveBelt(pos, frontier, visited, state);
if (AllBlocks.GANTRY_PINION.has(state)) {
BlockPos offset = pos.offset(state.get(GantryPinionBlock.FACING));
if (!visited.contains(offset))
frontier.add(offset);
}
if (AllBlocks.GANTRY_PINION.has(state))
moveGantryPinion(world, pos, frontier, visited, state);
if (AllBlocks.GANTRY_SHAFT.has(state))
for (Direction d : Iterate.directions) {
BlockPos offset = pos.offset(d);
if (!visited.contains(offset)) {
BlockState offsetState = world.getBlockState(offset);
Direction facing = state.get(GantryShaftBlock.FACING);
if (d.getAxis() == facing.getAxis() && AllBlocks.GANTRY_SHAFT.has(offsetState)
&& offsetState.get(GantryShaftBlock.FACING) == facing)
frontier.add(offset);
else if (AllBlocks.GANTRY_PINION.has(offsetState) && offsetState.get(GantryPinionBlock.FACING) == d)
frontier.add(offset);
}
}
moveGantryShaft(world, pos, frontier, visited, state);
// Bearings potentially create stabilized sub-contraptions
if (AllBlocks.MECHANICAL_BEARING.has(state))
@ -302,6 +291,10 @@ public abstract class Contraption {
if (state.getBlock() instanceof MechanicalPistonBlock)
if (!moveMechanicalPiston(world, pos, frontier, visited, state))
return false;
if (isExtensionPole(state))
movePistonPole(world, pos, frontier, visited, state);
if (isPistonHead(state))
movePistonHead(world, pos, frontier, visited, state);
// Doors try to stay whole
if (state.getBlock() instanceof DoorBlock) {
@ -346,6 +339,83 @@ public abstract class Contraption {
return blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get();
}
protected void movePistonHead(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
Direction direction = state.get(MechanicalPistonHeadBlock.FACING);
BlockPos offset = pos.offset(direction.getOpposite());
if (!visited.contains(offset)) {
BlockState blockState = world.getBlockState(offset);
if (isExtensionPole(blockState) && blockState.get(PistonExtensionPoleBlock.FACING)
.getAxis() == direction.getAxis())
frontier.add(offset);
if (blockState.getBlock() instanceof MechanicalPistonBlock) {
Direction pistonFacing = blockState.get(MechanicalPistonBlock.FACING);
if (pistonFacing == direction && blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED)
frontier.add(offset);
}
}
if (state.get(MechanicalPistonHeadBlock.TYPE) == PistonType.STICKY) {
BlockPos attached = pos.offset(direction);
if (!visited.contains(attached))
frontier.add(attached);
}
}
protected void movePistonPole(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
for (Direction d : Iterate.directionsInAxis(state.get(PistonExtensionPoleBlock.FACING)
.getAxis())) {
BlockPos offset = pos.offset(d);
if (!visited.contains(offset)) {
BlockState blockState = world.getBlockState(offset);
if (isExtensionPole(blockState) && blockState.get(PistonExtensionPoleBlock.FACING)
.getAxis() == d.getAxis())
frontier.add(offset);
if (isPistonHead(blockState) && blockState.get(MechanicalPistonHeadBlock.FACING)
.getAxis() == d.getAxis())
frontier.add(offset);
if (blockState.getBlock() instanceof MechanicalPistonBlock) {
Direction pistonFacing = blockState.get(MechanicalPistonBlock.FACING);
if (pistonFacing == d || pistonFacing == d.getOpposite()
&& blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED)
frontier.add(offset);
}
}
}
}
protected void moveGantryPinion(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
BlockPos offset = pos.offset(state.get(GantryPinionBlock.FACING));
if (!visited.contains(offset))
frontier.add(offset);
Axis rotationAxis = ((IRotate) state.getBlock()).getRotationAxis(state);
for (Direction d : Iterate.directionsInAxis(rotationAxis)) {
offset = pos.offset(d);
BlockState offsetState = world.getBlockState(offset);
if (AllBlocks.GANTRY_SHAFT.has(offsetState) && offsetState.get(GantryShaftBlock.FACING)
.getAxis() == d.getAxis())
if (!visited.contains(offset))
frontier.add(offset);
}
}
protected void moveGantryShaft(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
for (Direction d : Iterate.directions) {
BlockPos offset = pos.offset(d);
if (!visited.contains(offset)) {
BlockState offsetState = world.getBlockState(offset);
Direction facing = state.get(GantryShaftBlock.FACING);
if (d.getAxis() == facing.getAxis() && AllBlocks.GANTRY_SHAFT.has(offsetState)
&& offsetState.get(GantryShaftBlock.FACING) == facing)
frontier.add(offset);
else if (AllBlocks.GANTRY_PINION.has(offsetState) && offsetState.get(GantryPinionBlock.FACING) == d)
frontier.add(offset);
}
}
}
private void moveBearing(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, BlockState state) {
Direction facing = state.get(MechanicalBearingBlock.FACING);
if (!canAxisBeStabilized(facing.getAxis())) {
@ -398,47 +468,25 @@ public abstract class Contraption {
private boolean moveMechanicalPiston(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
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)
PistonState pistonState = state.get(MechanicalPistonBlock.STATE);
if (pistonState == PistonState.MOVING)
return false;
BlockPos offset = pos.offset(direction.getOpposite());
if (!visited.contains(offset)) {
BlockState poleState = world.getBlockState(offset);
if (AllBlocks.PISTON_EXTENSION_POLE.has(poleState) && poleState.get(PistonExtensionPoleBlock.FACING)
.getAxis() == direction.getAxis())
frontier.add(offset);
}
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 (pistonState == PistonState.EXTENDED || MechanicalPistonBlock.isStickyPiston(state)) {
offset = pos.offset(direction);
if (!visited.contains(offset))
frontier.add(offset);
}
if (limit <= -1)
return false;
return true;
}

View file

@ -10,11 +10,15 @@ import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
@ -34,10 +38,15 @@ public class GantryPinionBlock extends DirectionalAxisKineticBlock implements IT
.getAxis() != direction.getAxis();
}
@Override
public void updateNeighbors(BlockState stateIn, IWorld worldIn, BlockPos pos, int flags) {
super.updateNeighbors(stateIn, worldIn, pos, flags);
withTileEntityDo(worldIn, pos, GantryPinionTileEntity::checkValidGantryShaft);
}
@Override
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
super.onBlockAdded(state, worldIn, pos, oldState, isMoving);
withTileEntityDo(worldIn, pos, GantryPinionTileEntity::checkValidGantryShaft);
}
@Override
@ -50,6 +59,18 @@ public class GantryPinionBlock extends DirectionalAxisKineticBlock implements IT
return context.getFace();
}
public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
if (!player.isAllowEdit() || player.isSneaking())
return ActionResultType.PASS;
if (player.getHeldItem(handIn)
.isEmpty()) {
withTileEntityDo(worldIn, pos, te -> te.checkValidGantryShaft());
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS;
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState stateForPlacement = super.getStateForPlacement(context);

View file

@ -113,17 +113,25 @@ public class GantryShaftBlock extends DirectionalKineticBlock {
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockState state = super.getStateForPlacement(context);
BlockPos pos = context.getPos();
World world = context.getWorld();
Direction face = context.getFace();
BlockState blockState = context.getWorld()
.getBlockState(context.getPos()
.offset(face.getOpposite()));
if (AllBlocks.GANTRY_SHAFT.has(blockState) && blockState.get(FACING)
.getAxis() == face.getAxis()) {
Direction facing = blockState.get(FACING);
BlockState neighbour = world.getBlockState(pos.offset(state.get(FACING)
.getOpposite()));
BlockState clickedState =
AllBlocks.GANTRY_SHAFT.has(neighbour) ? neighbour : world.getBlockState(pos.offset(face.getOpposite()));
if (AllBlocks.GANTRY_SHAFT.has(clickedState) && clickedState.get(FACING)
.getAxis() == state.get(FACING)
.getAxis()) {
Direction facing = clickedState.get(FACING);
state = state.with(FACING, context.getPlayer() == null || !context.getPlayer()
.isSneaking() ? facing : facing.getOpposite());
}
return state.with(POWERED, shouldBePowered(state, context.getWorld(), context.getPos()));
return state.with(POWERED, shouldBePowered(state, world, pos));
}
@Override