Merge branch 'mc1.18/0.5.1' into mc1.18/0.5.1-repolish

This commit is contained in:
simibubi 2023-03-29 14:15:57 +02:00
commit 4ca885c933
14 changed files with 252 additions and 36 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;
@ -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;
}
}

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());
behaviours.add(movementMode);
registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS);
}
@ -68,6 +76,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);
}
@ -82,6 +92,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)
@ -101,18 +112,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() {
@ -185,6 +208,7 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
if (!running && movedContraption == null)
return;
angle = 0;
sequencedAngleLimit = -1;
if (isWindmill())
applyRotation();
if (movedContraption != null) {
@ -233,6 +257,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);
@ -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);
}
@ -181,8 +207,11 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
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
registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS);
}
@Override
protected boolean syncSequenceContext() {
return true;
}
@Override
public void tick() {
super.tick();
@ -112,10 +120,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);
@ -169,6 +188,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
@Override
public void onSpeedChanged(float prevSpeed) {
super.onSpeedChanged(prevSpeed);
sequencedOffsetLimit = -1;
if (isPassive())
return;
@ -177,9 +197,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
@ -195,6 +222,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);
@ -212,6 +241,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);
@ -308,6 +339,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;

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

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

View file

@ -4,6 +4,8 @@ import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -18,6 +20,8 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition.Builder;
@ -27,7 +31,8 @@ import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.PushReaction;
public class EncasedBeltBlock extends RotatedPillarKineticBlock implements IBE<KineticBlockEntity> {
public class EncasedBeltBlock extends RotatedPillarKineticBlock
implements IBE<KineticBlockEntity>, ITransformableBlock {
public static final Property<Part> PART = EnumProperty.create("part", Part.class);
public static final BooleanProperty CONNECTED_ALONG_FIRST_COORDINATE =
@ -218,4 +223,53 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock implements IBE<K
return AllBlockEntityTypes.ENCASED_SHAFT.get();
}
@Override
public BlockState rotate(BlockState state, Rotation rot) {
return rotate(state, rot, Axis.Y);
}
protected BlockState rotate(BlockState pState, Rotation rot, Axis rotAxis) {
Axis connectionAxis = getConnectionAxis(pState);
Direction direction = Direction.fromAxisAndDirection(connectionAxis, AxisDirection.POSITIVE);
Direction normal = Direction.fromAxisAndDirection(pState.getValue(AXIS), AxisDirection.POSITIVE);
for (int i = 0; i < rot.ordinal(); i++) {
direction = direction.getClockWise(rotAxis);
normal = normal.getClockWise(rotAxis);
}
if (direction.getAxisDirection() == AxisDirection.NEGATIVE)
pState = reversePart(pState);
Axis newAxis = normal.getAxis();
Axis newConnectingDirection = direction.getAxis();
boolean alongFirst = newAxis == Axis.X && newConnectingDirection == Axis.Y
|| newAxis != Axis.X && newConnectingDirection == Axis.X;
return pState.setValue(AXIS, newAxis)
.setValue(CONNECTED_ALONG_FIRST_COORDINATE, alongFirst);
}
@Override
public BlockState mirror(BlockState pState, Mirror pMirror) {
Axis connectionAxis = getConnectionAxis(pState);
if (pMirror.mirror(Direction.fromAxisAndDirection(connectionAxis, AxisDirection.POSITIVE))
.getAxisDirection() == AxisDirection.POSITIVE)
return pState;
return reversePart(pState);
}
protected BlockState reversePart(BlockState pState) {
Part part = pState.getValue(PART);
if (part == Part.START)
return pState.setValue(PART, Part.END);
if (part == Part.END)
return pState.setValue(PART, Part.START);
return pState;
}
@Override
public BlockState transform(BlockState state, StructureTransform transform) {
return rotate(mirror(state, transform.mirror), transform.rotation, transform.rotationAxis);
}
}