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:
simibubi 2023-03-28 17:45:13 +02:00
parent 1c81c6c12a
commit f45e22496e
13 changed files with 197 additions and 35 deletions

View file

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

View file

@ -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;
@ -67,6 +68,8 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
private int validationCountdown;
protected float lastStressApplied;
protected float lastCapacityProvided;
public SequenceContext sequenceContext;
public KineticBlockEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) {
super(typeIn, pos, state);
@ -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);
}
@ -592,5 +603,9 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
public int getRotationAngleOffset(Axis axis) {
return 0;
}
protected boolean syncSequenceContext() {
return false;
}
}

View file

@ -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() {
@ -172,7 +195,7 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
level.addFreshEntity(movedContraption);
AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition);
if (contraption.containsBlockBreakers())
award(AllAdvancements.CONTRAPTION_ACTORS);
@ -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);
}

View file

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

View file

@ -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);
@ -121,7 +143,7 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
if (level.isClientSide)
return;
axisMotion = pinionMovementSpeed;
setContraptionMotion(movementVec);
}
@ -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;
}
}

View file

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

View file

@ -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
@ -56,6 +59,11 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
behaviours.add(movementMode);
registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS);
}
@Override
protected boolean syncSequenceContext() {
return true;
}
@Override
public void 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;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -44,6 +44,10 @@ public enum SequencerInstructions {
descriptiveTranslationKey = translationKey + ".descriptive";
parameterKey = translationKey + "." + parameterName;
}
public boolean needsPropagation() {
return this == TURN_ANGLE || this == TURN_DISTANCE;
}
static List<Component> getOptions() {
List<Component> options = new ArrayList<>();