mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-27 15:36:43 +01:00
Secret Spinformation
- Fixed Bearings, Pistons, Pulleys and Gantries powered by a Sequenced Gearshift not moving precisely to its instructions at high speeds - Minecart contraptions no longer visually jump to a location when stalled - Mechanical bearings now snap to a rounded angle when stopped
This commit is contained in:
parent
1c81c6c12a
commit
f45e22496e
13 changed files with 197 additions and 35 deletions
|
@ -426,14 +426,17 @@ public class RotationPropagator {
|
|||
|
||||
private static List<BlockPos> getPotentialNeighbourLocations(KineticBlockEntity be) {
|
||||
List<BlockPos> neighbours = new LinkedList<>();
|
||||
BlockPos blockPos = be.getBlockPos();
|
||||
Level level = be.getLevel();
|
||||
|
||||
if (!be.getLevel()
|
||||
.isAreaLoaded(be.getBlockPos(), 1))
|
||||
if (!level.isLoaded(blockPos))
|
||||
return neighbours;
|
||||
|
||||
for (Direction facing : Iterate.directions)
|
||||
neighbours.add(be.getBlockPos()
|
||||
.relative(facing));
|
||||
for (Direction facing : Iterate.directions) {
|
||||
BlockPos relative = blockPos.relative(facing);
|
||||
if (level.isLoaded(relative))
|
||||
neighbours.add(relative);
|
||||
}
|
||||
|
||||
BlockState blockState = be.getBlockState();
|
||||
if (!(blockState.getBlock() instanceof IRotate))
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel;
|
|||
import com.simibubi.create.content.contraptions.base.IRotate.StressImpact;
|
||||
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
|
||||
import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation;
|
||||
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftBlockEntity.SequenceContext;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
|
||||
import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock;
|
||||
import com.simibubi.create.foundation.block.BlockStressValues;
|
||||
|
@ -68,6 +69,8 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
|
|||
protected float lastStressApplied;
|
||||
protected float lastCapacityProvided;
|
||||
|
||||
public SequenceContext sequenceContext;
|
||||
|
||||
public KineticBlockEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) {
|
||||
super(typeIn, pos, state);
|
||||
effects = new KineticEffectHandler(this);
|
||||
|
@ -197,6 +200,8 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
|
|||
@Override
|
||||
protected void write(CompoundTag compound, boolean clientPacket) {
|
||||
compound.putFloat("Speed", speed);
|
||||
if (sequenceContext != null && (!clientPacket || syncSequenceContext()))
|
||||
compound.put("Sequence", sequenceContext.serializeNBT());
|
||||
|
||||
if (needsSpeedUpdate())
|
||||
compound.putBoolean("NeedsSpeedUpdate", true);
|
||||
|
@ -238,6 +243,7 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
|
|||
}
|
||||
|
||||
speed = compound.getFloat("Speed");
|
||||
sequenceContext = SequenceContext.fromNBT(compound.getCompound("Sequence"));
|
||||
|
||||
if (compound.contains("Source"))
|
||||
source = NbtUtils.readBlockPos(compound.getCompound("Source"));
|
||||
|
@ -294,13 +300,17 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
|
|||
return;
|
||||
|
||||
BlockEntity blockEntity = level.getBlockEntity(source);
|
||||
if (!(blockEntity instanceof KineticBlockEntity)) {
|
||||
if (!(blockEntity instanceof KineticBlockEntity sourceBE)) {
|
||||
removeSource();
|
||||
return;
|
||||
}
|
||||
|
||||
KineticBlockEntity sourceBE = (KineticBlockEntity) blockEntity;
|
||||
setNetwork(sourceBE.network);
|
||||
copySequenceContextFrom(sourceBE);
|
||||
}
|
||||
|
||||
protected void copySequenceContextFrom(KineticBlockEntity sourceBE) {
|
||||
sequenceContext = sourceBE.sequenceContext;
|
||||
}
|
||||
|
||||
public void removeSource() {
|
||||
|
@ -309,6 +319,7 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
|
|||
speed = 0;
|
||||
source = null;
|
||||
setNetwork(null);
|
||||
sequenceContext = null;
|
||||
|
||||
onSpeedChanged(prevSpeed);
|
||||
}
|
||||
|
@ -593,4 +604,8 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected boolean syncSequenceContext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Abs
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
|
||||
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencerInstructions;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
|
||||
|
@ -35,12 +36,14 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
|
|||
protected boolean assembleNextTick;
|
||||
protected float clientAngleDiff;
|
||||
protected AssemblyException lastException;
|
||||
protected double sequencedAngleLimit;
|
||||
|
||||
private float prevAngle;
|
||||
|
||||
public MechanicalBearingBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
setLazyTickRate(3);
|
||||
sequencedAngleLimit = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,11 +51,16 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean syncSequenceContext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||
super.addBehaviours(behaviours);
|
||||
movementMode = new ScrollOptionBehaviour<>(RotationMode.class, Lang.translateDirect("contraptions.movement_mode"),
|
||||
this, getMovementModeSlot());
|
||||
movementMode = new ScrollOptionBehaviour<>(RotationMode.class,
|
||||
Lang.translateDirect("contraptions.movement_mode"), this, getMovementModeSlot());
|
||||
movementMode.requiresWrench();
|
||||
behaviours.add(movementMode);
|
||||
registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS);
|
||||
|
@ -69,6 +77,8 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
|
|||
public void write(CompoundTag compound, boolean clientPacket) {
|
||||
compound.putBoolean("Running", running);
|
||||
compound.putFloat("Angle", angle);
|
||||
if (sequencedAngleLimit >= 0)
|
||||
compound.putDouble("SequencedAngleLimit", sequencedAngleLimit);
|
||||
AssemblyException.write(compound, lastException);
|
||||
super.write(compound, clientPacket);
|
||||
}
|
||||
|
@ -83,6 +93,7 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
|
|||
float angleBefore = angle;
|
||||
running = compound.getBoolean("Running");
|
||||
angle = compound.getFloat("Angle");
|
||||
sequencedAngleLimit = compound.contains("SequencedAngleLimit") ? compound.getDouble("SequencedAngleLimit") : -1;
|
||||
lastException = AssemblyException.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
if (!clientPacket)
|
||||
|
@ -102,18 +113,30 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
|
|||
return Mth.lerp(partialTicks + .5f, prevAngle, angle);
|
||||
if (movedContraption == null || movedContraption.isStalled() || !running)
|
||||
partialTicks = 0;
|
||||
return Mth.lerp(partialTicks, angle, angle + getAngularSpeed());
|
||||
float angularSpeed = getAngularSpeed();
|
||||
if (sequencedAngleLimit >= 0)
|
||||
angularSpeed = (float) Mth.clamp(angularSpeed, -sequencedAngleLimit, sequencedAngleLimit);
|
||||
return Mth.lerp(partialTicks, angle, angle + angularSpeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpeedChanged(float prevSpeed) {
|
||||
super.onSpeedChanged(prevSpeed);
|
||||
assembleNextTick = true;
|
||||
sequencedAngleLimit = -1;
|
||||
|
||||
if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) {
|
||||
if (!movedContraption.isStalled()) {
|
||||
angle = Math.round(angle);
|
||||
applyRotation();
|
||||
}
|
||||
movedContraption.getContraption()
|
||||
.stop(level);
|
||||
}
|
||||
|
||||
if (!isWindmill() && sequenceContext != null
|
||||
&& sequenceContext.instruction() == SequencerInstructions.TURN_ANGLE)
|
||||
sequencedAngleLimit = sequenceContext.getEffectiveValue(getTheoreticalSpeed());
|
||||
}
|
||||
|
||||
public float getAngularSpeed() {
|
||||
|
@ -186,6 +209,7 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
|
|||
if (!running && movedContraption == null)
|
||||
return;
|
||||
angle = 0;
|
||||
sequencedAngleLimit = -1;
|
||||
if (isWindmill())
|
||||
applyRotation();
|
||||
if (movedContraption != null) {
|
||||
|
@ -234,6 +258,10 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
|
|||
|
||||
if (!(movedContraption != null && movedContraption.isStalled())) {
|
||||
float angularSpeed = getAngularSpeed();
|
||||
if (sequencedAngleLimit >= 0) {
|
||||
angularSpeed = (float) Mth.clamp(angularSpeed, -sequencedAngleLimit, sequencedAngleLimit);
|
||||
sequencedAngleLimit = Math.max(0, sequencedAngleLimit - Math.abs(angularSpeed));
|
||||
}
|
||||
float newAngle = angle + angularSpeed;
|
||||
angle = (float) (newAngle % 360);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
|
||||
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock;
|
||||
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlockEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencerInstructions;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
|
||||
|
@ -83,14 +84,14 @@ public class GantryCarriageBlockEntity extends KineticBlockEntity implements IDi
|
|||
Direction direction = blockState.getValue(GantryCarriageBlock.FACING);
|
||||
GantryContraption contraption = new GantryContraption(direction);
|
||||
|
||||
BlockEntity shaftBE = level.getBlockEntity(worldPosition.relative(direction.getOpposite()));
|
||||
if (!(shaftBE instanceof GantryShaftBlockEntity))
|
||||
BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(direction.getOpposite()));
|
||||
if (!(blockEntity instanceof GantryShaftBlockEntity shaftBE))
|
||||
return;
|
||||
BlockState shaftState = shaftBE.getBlockState();
|
||||
if (!AllBlocks.GANTRY_SHAFT.has(shaftState))
|
||||
return;
|
||||
|
||||
float pinionMovementSpeed = ((GantryShaftBlockEntity) shaftBE).getPinionMovementSpeed();
|
||||
float pinionMovementSpeed = shaftBE.getPinionMovementSpeed();
|
||||
Direction shaftOrientation = shaftState.getValue(GantryShaftBlock.FACING);
|
||||
Direction movementDirection = shaftOrientation;
|
||||
if (pinionMovementSpeed < 0)
|
||||
|
@ -121,6 +122,10 @@ public class GantryCarriageBlockEntity extends KineticBlockEntity implements IDi
|
|||
movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ());
|
||||
AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition);
|
||||
level.addFreshEntity(movedContraption);
|
||||
|
||||
if (shaftBE.sequenceContext != null
|
||||
&& shaftBE.sequenceContext.instruction() == SequencerInstructions.TURN_DISTANCE)
|
||||
movedContraption.limitMovement(shaftBE.sequenceContext.getEffectiveValue(shaftBE.getTheoreticalSpeed()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock
|
|||
import com.simibubi.create.foundation.networking.AllPackets;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -34,8 +35,11 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
double clientOffsetDiff;
|
||||
double axisMotion;
|
||||
|
||||
public double sequencedOffsetLimit;
|
||||
|
||||
public GantryContraptionEntity(EntityType<?> entityTypeIn, Level worldIn) {
|
||||
super(entityTypeIn, worldIn);
|
||||
sequencedOffsetLimit = -1;
|
||||
}
|
||||
|
||||
public static GantryContraptionEntity create(Level world, Contraption contraption, Direction movementAxis) {
|
||||
|
@ -45,6 +49,10 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
return entity;
|
||||
}
|
||||
|
||||
public void limitMovement(double maxOffset) {
|
||||
sequencedOffsetLimit = maxOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tickContraption() {
|
||||
if (!(contraption instanceof GantryContraption))
|
||||
|
@ -66,8 +74,13 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!isStalled() && tickCount > 2)
|
||||
if (!isStalled() && tickCount > 2) {
|
||||
if (sequencedOffsetLimit >= 0)
|
||||
movementVec = VecHelper.clampComponentWise(movementVec, (float) sequencedOffsetLimit);
|
||||
move(movementVec.x, movementVec.y, movementVec.z);
|
||||
if (sequencedOffsetLimit > 0)
|
||||
sequencedOffsetLimit = Math.max(0, sequencedOffsetLimit - movementVec.length());
|
||||
}
|
||||
|
||||
if (Math.signum(prevAxisMotion) != Math.signum(axisMotion) && prevAxisMotion != 0)
|
||||
contraption.stop(level);
|
||||
|
@ -75,6 +88,12 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
sendPacket();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disassemble() {
|
||||
sequencedOffsetLimit = -1;
|
||||
super.disassemble();
|
||||
}
|
||||
|
||||
protected void checkPinionShaft() {
|
||||
Vec3 movementVec;
|
||||
Direction facing = ((GantryContraption) contraption).getFacing();
|
||||
|
@ -95,8 +114,6 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
GantryShaftBlockEntity gantryShaftBlockEntity = (GantryShaftBlockEntity) be;
|
||||
|
||||
float pinionMovementSpeed = gantryShaftBlockEntity.getPinionMovementSpeed();
|
||||
movementVec = Vec3.atLowerCornerOf(direction.getNormal()).scale(pinionMovementSpeed);
|
||||
|
||||
if (blockState.getValue(GantryShaftBlock.POWERED) || pinionMovementSpeed == 0) {
|
||||
setContraptionMotion(Vec3.ZERO);
|
||||
if (!level.isClientSide)
|
||||
|
@ -104,6 +121,11 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
return;
|
||||
}
|
||||
|
||||
if (sequencedOffsetLimit >= 0)
|
||||
pinionMovementSpeed = (float) Mth.clamp(pinionMovementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit);
|
||||
movementVec = Vec3.atLowerCornerOf(direction.getNormal())
|
||||
.scale(pinionMovementSpeed);
|
||||
|
||||
Vec3 nextPosition = currentPosition.add(movementVec);
|
||||
double currentCoord = direction.getAxis()
|
||||
.choose(currentPosition.x, currentPosition.y, currentPosition.z);
|
||||
|
@ -129,11 +151,15 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
@Override
|
||||
protected void writeAdditional(CompoundTag compound, boolean spawnPacket) {
|
||||
NBTHelper.writeEnum(compound, "GantryAxis", movementAxis);
|
||||
if (sequencedOffsetLimit >= 0)
|
||||
compound.putDouble("SequencedOffsetLimit", sequencedOffsetLimit);
|
||||
super.writeAdditional(compound, spawnPacket);
|
||||
}
|
||||
|
||||
protected void readAdditional(CompoundTag compound, boolean spawnData) {
|
||||
movementAxis = NBTHelper.readEnum(compound, "GantryAxis", Direction.class);
|
||||
sequencedOffsetLimit =
|
||||
compound.contains("SequencedOffsetLimit") ? compound.getDouble("SequencedOffsetLimit") : -1;
|
||||
super.readAdditional(compound, spawnData);
|
||||
}
|
||||
|
||||
|
@ -176,13 +202,16 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) { }
|
||||
public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) {}
|
||||
|
||||
public void updateClientMotion() {
|
||||
float modifier = movementAxis.getAxisDirection()
|
||||
.getStep();
|
||||
setContraptionMotion(Vec3.atLowerCornerOf(movementAxis.getNormal())
|
||||
.scale((axisMotion + clientOffsetDiff * modifier / 2f) * ServerSpeedProvider.get()));
|
||||
Vec3 motion = Vec3.atLowerCornerOf(movementAxis.getNormal())
|
||||
.scale((axisMotion + clientOffsetDiff * modifier / 2f) * ServerSpeedProvider.get());
|
||||
if (sequencedOffsetLimit >= 0)
|
||||
motion = VecHelper.clampComponentWise(motion, (float) sequencedOffsetLimit);
|
||||
setContraptionMotion(motion);
|
||||
}
|
||||
|
||||
public double getAxisCoord() {
|
||||
|
@ -192,8 +221,9 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
}
|
||||
|
||||
public void sendPacket() {
|
||||
AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||
new GantryContraptionUpdatePacket(getId(), getAxisCoord(), axisMotion));
|
||||
AllPackets.getChannel()
|
||||
.send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
|
||||
new GantryContraptionUpdatePacket(getId(), getAxisCoord(), axisMotion, sequencedOffsetLimit));
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
|
@ -204,6 +234,7 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
|||
GantryContraptionEntity ce = (GantryContraptionEntity) entity;
|
||||
ce.axisMotion = packet.motion;
|
||||
ce.clientOffsetDiff = packet.coord - ce.getAxisCoord();
|
||||
ce.sequencedOffsetLimit = packet.sequenceLimit;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,17 +12,20 @@ public class GantryContraptionUpdatePacket extends SimplePacketBase {
|
|||
int entityID;
|
||||
double coord;
|
||||
double motion;
|
||||
double sequenceLimit;
|
||||
|
||||
public GantryContraptionUpdatePacket(int entityID, double coord, double motion) {
|
||||
public GantryContraptionUpdatePacket(int entityID, double coord, double motion, double sequenceLimit) {
|
||||
this.entityID = entityID;
|
||||
this.coord = coord;
|
||||
this.motion = motion;
|
||||
this.sequenceLimit = sequenceLimit;
|
||||
}
|
||||
|
||||
public GantryContraptionUpdatePacket(FriendlyByteBuf buffer) {
|
||||
entityID = buffer.readInt();
|
||||
coord = buffer.readFloat();
|
||||
motion = buffer.readFloat();
|
||||
sequenceLimit = buffer.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,6 +33,7 @@ public class GantryContraptionUpdatePacket extends SimplePacketBase {
|
|||
buffer.writeInt(entityID);
|
||||
buffer.writeFloat((float) coord);
|
||||
buffer.writeFloat((float) motion);
|
||||
buffer.writeFloat((float) sequenceLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
|
|||
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
|
||||
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencerInstructions;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
|
||||
|
@ -35,6 +36,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
protected ScrollOptionBehaviour<MovementMode> movementMode;
|
||||
protected boolean waitingForSpeedChange;
|
||||
protected AssemblyException lastException;
|
||||
protected double sequencedOffsetLimit;
|
||||
|
||||
// Custom position sync
|
||||
protected float clientOffsetDiff;
|
||||
|
@ -44,6 +46,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
setLazyTickRate(3);
|
||||
forceMove = true;
|
||||
needsContraption = true;
|
||||
sequencedOffsetLimit = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,6 +60,11 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean syncSequenceContext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
@ -113,10 +121,21 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
return;
|
||||
|
||||
float movementSpeed = getMovementSpeed();
|
||||
boolean locked = false;
|
||||
if (sequencedOffsetLimit > 0) {
|
||||
sequencedOffsetLimit = Math.max(0, sequencedOffsetLimit - Math.abs(movementSpeed));
|
||||
locked = sequencedOffsetLimit == 0;
|
||||
}
|
||||
float newOffset = offset + movementSpeed;
|
||||
if ((int) newOffset != (int) offset)
|
||||
visitNewPosition();
|
||||
|
||||
if (locked) {
|
||||
forceMove = true;
|
||||
resetContraptionToOffset();
|
||||
sendData();
|
||||
}
|
||||
|
||||
if (contraptionPresent) {
|
||||
if (moveAndCollideContraption()) {
|
||||
movedContraption.setContraptionMotion(Vec3.ZERO);
|
||||
|
@ -170,6 +189,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
@Override
|
||||
public void onSpeedChanged(float prevSpeed) {
|
||||
super.onSpeedChanged(prevSpeed);
|
||||
sequencedOffsetLimit = -1;
|
||||
|
||||
if (isPassive())
|
||||
return;
|
||||
|
@ -178,9 +198,16 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
waitingForSpeedChange = false;
|
||||
|
||||
if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) {
|
||||
if (!movedContraption.isStalled()) {
|
||||
offset = Math.round(offset * 16) / 16;
|
||||
resetContraptionToOffset();
|
||||
}
|
||||
movedContraption.getContraption()
|
||||
.stop(level);
|
||||
}
|
||||
|
||||
if (sequenceContext != null && sequenceContext.instruction() == SequencerInstructions.TURN_DISTANCE)
|
||||
sequencedOffsetLimit = sequenceContext.getEffectiveValue(getTheoreticalSpeed());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -196,6 +223,8 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
compound.putBoolean("Running", running);
|
||||
compound.putBoolean("Waiting", waitingForSpeedChange);
|
||||
compound.putFloat("Offset", offset);
|
||||
if (sequencedOffsetLimit >= 0)
|
||||
compound.putDouble("SequencedOffsetLimit", sequencedOffsetLimit);
|
||||
AssemblyException.write(compound, lastException);
|
||||
super.write(compound, clientPacket);
|
||||
|
||||
|
@ -213,6 +242,8 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
running = compound.getBoolean("Running");
|
||||
waitingForSpeedChange = compound.getBoolean("Waiting");
|
||||
offset = compound.getFloat("Offset");
|
||||
sequencedOffsetLimit =
|
||||
compound.contains("SequencedOffsetLimit") ? compound.getDouble("SequencedOffsetLimit") : -1;
|
||||
lastException = AssemblyException.read(compound);
|
||||
super.read(compound, clientPacket);
|
||||
|
||||
|
@ -309,6 +340,8 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
|
|||
float movementSpeed = Mth.clamp(convertToLinear(getSpeed()), -.49f, .49f) + clientOffsetDiff / 2f;
|
||||
if (level.isClientSide)
|
||||
movementSpeed *= ServerSpeedProvider.get();
|
||||
if (sequencedOffsetLimit >= 0)
|
||||
movementSpeed = (float) Mth.clamp(movementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit);
|
||||
return movementSpeed;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,6 +132,8 @@ public class MechanicalPistonBlockEntity extends LinearActuatorBlockEntity {
|
|||
|
||||
int extensionRange = getExtensionRange();
|
||||
movementSpeed = Mth.clamp(movementSpeed, 0 - offset, extensionRange - offset);
|
||||
if (sequencedOffsetLimit >= 0)
|
||||
movementSpeed = (float) Mth.clamp(movementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit);
|
||||
return movementSpeed;
|
||||
}
|
||||
|
||||
|
|
|
@ -404,7 +404,7 @@ public class MinecartController implements INBTSerializable<CompoundTag> {
|
|||
}
|
||||
|
||||
void tick(AbstractMinecart entity) {
|
||||
entity.setPos(position.x, position.y, position.z);
|
||||
// entity.setPos(position.x, position.y, position.z);
|
||||
entity.setDeltaMovement(Vec3.ZERO);
|
||||
entity.setYRot(yaw);
|
||||
entity.setXRot(pitch);
|
||||
|
|
|
@ -19,6 +19,11 @@ public class GantryShaftBlockEntity extends KineticBlockEntity {
|
|||
super(typeIn, pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean syncSequenceContext() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void checkAttachedCarriageBlocks() {
|
||||
if (!canAssembleOn())
|
||||
return;
|
||||
|
|
|
@ -27,28 +27,23 @@ public class Instruction {
|
|||
int getDuration(float currentProgress, float speed) {
|
||||
speed *= speedModifier.value;
|
||||
speed = Math.abs(speed);
|
||||
|
||||
double target = value - currentProgress;
|
||||
|
||||
switch (instruction) {
|
||||
|
||||
// Always overshoot, target will stop early
|
||||
case TURN_ANGLE:
|
||||
double degreesPerTick = KineticBlockEntity.convertToAngular(speed);
|
||||
int ticks = (int) (target / degreesPerTick);
|
||||
double degreesErr = target - degreesPerTick*ticks;
|
||||
return ticks + (degreesPerTick > 2*degreesErr ? 0 : 1);
|
||||
|
||||
return (int) Math.ceil(target / degreesPerTick) + 2;
|
||||
case TURN_DISTANCE:
|
||||
double metersPerTick = KineticBlockEntity.convertToLinear(speed);
|
||||
int offset = speed > 0 && speedModifier.value < 0 ? 1 : 2;
|
||||
return (int) (target / metersPerTick + offset);
|
||||
return (int) Math.ceil(target / metersPerTick) + 2;
|
||||
|
||||
// Timing instructions
|
||||
case DELAY:
|
||||
return (int) target;
|
||||
|
||||
case AWAIT:
|
||||
return -1;
|
||||
|
||||
case END:
|
||||
default:
|
||||
break;
|
||||
|
@ -58,7 +53,7 @@ public class Instruction {
|
|||
}
|
||||
|
||||
float getTickProgress(float speed) {
|
||||
switch(instruction) {
|
||||
switch (instruction) {
|
||||
|
||||
case TURN_ANGLE:
|
||||
return KineticBlockEntity.convertToAngular(speed);
|
||||
|
|
|
@ -2,7 +2,9 @@ package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
|
|||
|
||||
import java.util.Vector;
|
||||
|
||||
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.SplitShaftBlockEntity;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -20,6 +22,35 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
|||
int timer;
|
||||
boolean poweredPreviously;
|
||||
|
||||
public record SequenceContext(SequencerInstructions instruction, double relativeValue) {
|
||||
|
||||
static SequenceContext fromGearshift(SequencerInstructions instruction, double kineticSpeed,
|
||||
int absoluteValue) {
|
||||
return instruction.needsPropagation()
|
||||
? new SequenceContext(instruction, kineticSpeed == 0 ? 0 : absoluteValue / kineticSpeed)
|
||||
: null;
|
||||
}
|
||||
|
||||
public double getEffectiveValue(double speedAtTarget) {
|
||||
return Math.abs(relativeValue * speedAtTarget);
|
||||
}
|
||||
|
||||
public CompoundTag serializeNBT() {
|
||||
CompoundTag nbt = new CompoundTag();
|
||||
NBTHelper.writeEnum(nbt, "Mode", instruction);
|
||||
nbt.putDouble("Value", relativeValue);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public static SequenceContext fromNBT(CompoundTag nbt) {
|
||||
if (nbt.isEmpty())
|
||||
return null;
|
||||
return new SequenceContext(NBTHelper.readEnum(nbt, "Mode", SequencerInstructions.class),
|
||||
nbt.getDouble("Value"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SequencedGearshiftBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
instructions = Instruction.createDefault();
|
||||
|
@ -113,6 +144,7 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
|||
currentInstruction = -1;
|
||||
currentInstructionDuration = -1;
|
||||
currentInstructionProgress = 0;
|
||||
sequenceContext = null;
|
||||
timer = 0;
|
||||
if (!level.hasNeighborSignal(worldPosition))
|
||||
level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3);
|
||||
|
@ -125,6 +157,8 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
|||
currentInstructionDuration = instruction.getDuration(0, getTheoreticalSpeed());
|
||||
currentInstruction = instructionIndex;
|
||||
currentInstructionProgress = 0;
|
||||
sequenceContext = SequenceContext.fromGearshift(instruction.instruction, getTheoreticalSpeed() * getModifier(),
|
||||
instruction.value);
|
||||
timer = 0;
|
||||
level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3);
|
||||
}
|
||||
|
@ -134,6 +168,9 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
|||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void copySequenceContextFrom(KineticBlockEntity sourceBE) {}
|
||||
|
||||
@Override
|
||||
public void write(CompoundTag compound, boolean clientPacket) {
|
||||
compound.putInt("InstructionIndex", currentInstruction);
|
||||
|
|
|
@ -45,6 +45,10 @@ public enum SequencerInstructions {
|
|||
parameterKey = translationKey + "." + parameterName;
|
||||
}
|
||||
|
||||
public boolean needsPropagation() {
|
||||
return this == TURN_ANGLE || this == TURN_DISTANCE;
|
||||
}
|
||||
|
||||
static List<Component> getOptions() {
|
||||
List<Component> options = new ArrayList<>();
|
||||
for (SequencerInstructions entry : values())
|
||||
|
|
Loading…
Reference in a new issue