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) { private static List<BlockPos> getPotentialNeighbourLocations(KineticBlockEntity be) {
List<BlockPos> neighbours = new LinkedList<>(); List<BlockPos> neighbours = new LinkedList<>();
BlockPos blockPos = be.getBlockPos();
Level level = be.getLevel();
if (!be.getLevel() if (!level.isLoaded(blockPos))
.isAreaLoaded(be.getBlockPos(), 1))
return neighbours; return neighbours;
for (Direction facing : Iterate.directions) for (Direction facing : Iterate.directions) {
neighbours.add(be.getBlockPos() BlockPos relative = blockPos.relative(facing);
.relative(facing)); if (level.isLoaded(relative))
neighbours.add(relative);
}
BlockState blockState = be.getBlockState(); BlockState blockState = be.getBlockState();
if (!(blockState.getBlock() instanceof IRotate)) 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.base.IRotate.StressImpact;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation; 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.elementary.ICogWheel;
import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock; import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock;
import com.simibubi.create.foundation.block.BlockStressValues; import com.simibubi.create.foundation.block.BlockStressValues;
@ -68,6 +69,8 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
protected float lastStressApplied; protected float lastStressApplied;
protected float lastCapacityProvided; protected float lastCapacityProvided;
public SequenceContext sequenceContext;
public KineticBlockEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) { public KineticBlockEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) {
super(typeIn, pos, state); super(typeIn, pos, state);
effects = new KineticEffectHandler(this); effects = new KineticEffectHandler(this);
@ -197,6 +200,8 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
@Override @Override
protected void write(CompoundTag compound, boolean clientPacket) { protected void write(CompoundTag compound, boolean clientPacket) {
compound.putFloat("Speed", speed); compound.putFloat("Speed", speed);
if (sequenceContext != null && (!clientPacket || syncSequenceContext()))
compound.put("Sequence", sequenceContext.serializeNBT());
if (needsSpeedUpdate()) if (needsSpeedUpdate())
compound.putBoolean("NeedsSpeedUpdate", true); compound.putBoolean("NeedsSpeedUpdate", true);
@ -238,6 +243,7 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
} }
speed = compound.getFloat("Speed"); speed = compound.getFloat("Speed");
sequenceContext = SequenceContext.fromNBT(compound.getCompound("Sequence"));
if (compound.contains("Source")) if (compound.contains("Source"))
source = NbtUtils.readBlockPos(compound.getCompound("Source")); source = NbtUtils.readBlockPos(compound.getCompound("Source"));
@ -294,13 +300,17 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
return; return;
BlockEntity blockEntity = level.getBlockEntity(source); BlockEntity blockEntity = level.getBlockEntity(source);
if (!(blockEntity instanceof KineticBlockEntity)) { if (!(blockEntity instanceof KineticBlockEntity sourceBE)) {
removeSource(); removeSource();
return; return;
} }
KineticBlockEntity sourceBE = (KineticBlockEntity) blockEntity;
setNetwork(sourceBE.network); setNetwork(sourceBE.network);
copySequenceContextFrom(sourceBE);
}
protected void copySequenceContextFrom(KineticBlockEntity sourceBE) {
sequenceContext = sourceBE.sequenceContext;
} }
public void removeSource() { public void removeSource() {
@ -309,6 +319,7 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
speed = 0; speed = 0;
source = null; source = null;
setNetwork(null); setNetwork(null);
sequenceContext = null;
onSpeedChanged(prevSpeed); onSpeedChanged(prevSpeed);
} }
@ -593,4 +604,8 @@ public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleI
return 0; 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.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; 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.advancement.AllAdvancements;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollOptionBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
@ -35,12 +36,14 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
protected boolean assembleNextTick; protected boolean assembleNextTick;
protected float clientAngleDiff; protected float clientAngleDiff;
protected AssemblyException lastException; protected AssemblyException lastException;
protected double sequencedAngleLimit;
private float prevAngle; private float prevAngle;
public MechanicalBearingBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) { public MechanicalBearingBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); super(type, pos, state);
setLazyTickRate(3); setLazyTickRate(3);
sequencedAngleLimit = -1;
} }
@Override @Override
@ -48,11 +51,16 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
return false; return false;
} }
@Override
protected boolean syncSequenceContext() {
return true;
}
@Override @Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) { public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
super.addBehaviours(behaviours); super.addBehaviours(behaviours);
movementMode = new ScrollOptionBehaviour<>(RotationMode.class, Lang.translateDirect("contraptions.movement_mode"), movementMode = new ScrollOptionBehaviour<>(RotationMode.class,
this, getMovementModeSlot()); Lang.translateDirect("contraptions.movement_mode"), this, getMovementModeSlot());
behaviours.add(movementMode); behaviours.add(movementMode);
registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS);
} }
@ -68,6 +76,8 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
public void write(CompoundTag compound, boolean clientPacket) { public void write(CompoundTag compound, boolean clientPacket) {
compound.putBoolean("Running", running); compound.putBoolean("Running", running);
compound.putFloat("Angle", angle); compound.putFloat("Angle", angle);
if (sequencedAngleLimit >= 0)
compound.putDouble("SequencedAngleLimit", sequencedAngleLimit);
AssemblyException.write(compound, lastException); AssemblyException.write(compound, lastException);
super.write(compound, clientPacket); super.write(compound, clientPacket);
} }
@ -82,6 +92,7 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
float angleBefore = angle; float angleBefore = angle;
running = compound.getBoolean("Running"); running = compound.getBoolean("Running");
angle = compound.getFloat("Angle"); angle = compound.getFloat("Angle");
sequencedAngleLimit = compound.contains("SequencedAngleLimit") ? compound.getDouble("SequencedAngleLimit") : -1;
lastException = AssemblyException.read(compound); lastException = AssemblyException.read(compound);
super.read(compound, clientPacket); super.read(compound, clientPacket);
if (!clientPacket) if (!clientPacket)
@ -101,18 +112,30 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
return Mth.lerp(partialTicks + .5f, prevAngle, angle); return Mth.lerp(partialTicks + .5f, prevAngle, angle);
if (movedContraption == null || movedContraption.isStalled() || !running) if (movedContraption == null || movedContraption.isStalled() || !running)
partialTicks = 0; 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 @Override
public void onSpeedChanged(float prevSpeed) { public void onSpeedChanged(float prevSpeed) {
super.onSpeedChanged(prevSpeed); super.onSpeedChanged(prevSpeed);
assembleNextTick = true; assembleNextTick = true;
sequencedAngleLimit = -1;
if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) {
if (!movedContraption.isStalled()) {
angle = Math.round(angle);
applyRotation();
}
movedContraption.getContraption() movedContraption.getContraption()
.stop(level); .stop(level);
} }
if (!isWindmill() && sequenceContext != null
&& sequenceContext.instruction() == SequencerInstructions.TURN_ANGLE)
sequencedAngleLimit = sequenceContext.getEffectiveValue(getTheoreticalSpeed());
} }
public float getAngularSpeed() { public float getAngularSpeed() {
@ -185,6 +208,7 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
if (!running && movedContraption == null) if (!running && movedContraption == null)
return; return;
angle = 0; angle = 0;
sequencedAngleLimit = -1;
if (isWindmill()) if (isWindmill())
applyRotation(); applyRotation();
if (movedContraption != null) { if (movedContraption != null) {
@ -233,6 +257,10 @@ public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity
if (!(movedContraption != null && movedContraption.isStalled())) { if (!(movedContraption != null && movedContraption.isStalled())) {
float angularSpeed = getAngularSpeed(); 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; float newAngle = angle + angularSpeed;
angle = (float) (newAngle % 360); 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.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; 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.GantryShaftBlockEntity;
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencerInstructions;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
@ -83,14 +84,14 @@ public class GantryCarriageBlockEntity extends KineticBlockEntity implements IDi
Direction direction = blockState.getValue(GantryCarriageBlock.FACING); Direction direction = blockState.getValue(GantryCarriageBlock.FACING);
GantryContraption contraption = new GantryContraption(direction); GantryContraption contraption = new GantryContraption(direction);
BlockEntity shaftBE = level.getBlockEntity(worldPosition.relative(direction.getOpposite())); BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(direction.getOpposite()));
if (!(shaftBE instanceof GantryShaftBlockEntity)) if (!(blockEntity instanceof GantryShaftBlockEntity shaftBE))
return; return;
BlockState shaftState = shaftBE.getBlockState(); BlockState shaftState = shaftBE.getBlockState();
if (!AllBlocks.GANTRY_SHAFT.has(shaftState)) if (!AllBlocks.GANTRY_SHAFT.has(shaftState))
return; return;
float pinionMovementSpeed = ((GantryShaftBlockEntity) shaftBE).getPinionMovementSpeed(); float pinionMovementSpeed = shaftBE.getPinionMovementSpeed();
Direction shaftOrientation = shaftState.getValue(GantryShaftBlock.FACING); Direction shaftOrientation = shaftState.getValue(GantryShaftBlock.FACING);
Direction movementDirection = shaftOrientation; Direction movementDirection = shaftOrientation;
if (pinionMovementSpeed < 0) if (pinionMovementSpeed < 0)
@ -121,6 +122,10 @@ public class GantryCarriageBlockEntity extends KineticBlockEntity implements IDi
movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ());
AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition);
level.addFreshEntity(movedContraption); level.addFreshEntity(movedContraption);
if (shaftBE.sequenceContext != null
&& shaftBE.sequenceContext.instruction() == SequencerInstructions.TURN_DISTANCE)
movedContraption.limitMovement(shaftBE.sequenceContext.getEffectiveValue(shaftBE.getTheoreticalSpeed()));
} }
@Override @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.networking.AllPackets;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -34,8 +35,11 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
double clientOffsetDiff; double clientOffsetDiff;
double axisMotion; double axisMotion;
public double sequencedOffsetLimit;
public GantryContraptionEntity(EntityType<?> entityTypeIn, Level worldIn) { public GantryContraptionEntity(EntityType<?> entityTypeIn, Level worldIn) {
super(entityTypeIn, worldIn); super(entityTypeIn, worldIn);
sequencedOffsetLimit = -1;
} }
public static GantryContraptionEntity create(Level world, Contraption contraption, Direction movementAxis) { public static GantryContraptionEntity create(Level world, Contraption contraption, Direction movementAxis) {
@ -45,6 +49,10 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
return entity; return entity;
} }
public void limitMovement(double maxOffset) {
sequencedOffsetLimit = maxOffset;
}
@Override @Override
protected void tickContraption() { protected void tickContraption() {
if (!(contraption instanceof GantryContraption)) if (!(contraption instanceof GantryContraption))
@ -66,8 +74,13 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
return; 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); 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) if (Math.signum(prevAxisMotion) != Math.signum(axisMotion) && prevAxisMotion != 0)
contraption.stop(level); contraption.stop(level);
@ -75,6 +88,12 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
sendPacket(); sendPacket();
} }
@Override
public void disassemble() {
sequencedOffsetLimit = -1;
super.disassemble();
}
protected void checkPinionShaft() { protected void checkPinionShaft() {
Vec3 movementVec; Vec3 movementVec;
Direction facing = ((GantryContraption) contraption).getFacing(); Direction facing = ((GantryContraption) contraption).getFacing();
@ -95,8 +114,6 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
GantryShaftBlockEntity gantryShaftBlockEntity = (GantryShaftBlockEntity) be; GantryShaftBlockEntity gantryShaftBlockEntity = (GantryShaftBlockEntity) be;
float pinionMovementSpeed = gantryShaftBlockEntity.getPinionMovementSpeed(); float pinionMovementSpeed = gantryShaftBlockEntity.getPinionMovementSpeed();
movementVec = Vec3.atLowerCornerOf(direction.getNormal()).scale(pinionMovementSpeed);
if (blockState.getValue(GantryShaftBlock.POWERED) || pinionMovementSpeed == 0) { if (blockState.getValue(GantryShaftBlock.POWERED) || pinionMovementSpeed == 0) {
setContraptionMotion(Vec3.ZERO); setContraptionMotion(Vec3.ZERO);
if (!level.isClientSide) if (!level.isClientSide)
@ -104,6 +121,11 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
return; return;
} }
if (sequencedOffsetLimit >= 0)
pinionMovementSpeed = (float) Mth.clamp(pinionMovementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit);
movementVec = Vec3.atLowerCornerOf(direction.getNormal())
.scale(pinionMovementSpeed);
Vec3 nextPosition = currentPosition.add(movementVec); Vec3 nextPosition = currentPosition.add(movementVec);
double currentCoord = direction.getAxis() double currentCoord = direction.getAxis()
.choose(currentPosition.x, currentPosition.y, currentPosition.z); .choose(currentPosition.x, currentPosition.y, currentPosition.z);
@ -129,11 +151,15 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
@Override @Override
protected void writeAdditional(CompoundTag compound, boolean spawnPacket) { protected void writeAdditional(CompoundTag compound, boolean spawnPacket) {
NBTHelper.writeEnum(compound, "GantryAxis", movementAxis); NBTHelper.writeEnum(compound, "GantryAxis", movementAxis);
if (sequencedOffsetLimit >= 0)
compound.putDouble("SequencedOffsetLimit", sequencedOffsetLimit);
super.writeAdditional(compound, spawnPacket); super.writeAdditional(compound, spawnPacket);
} }
protected void readAdditional(CompoundTag compound, boolean spawnData) { protected void readAdditional(CompoundTag compound, boolean spawnData) {
movementAxis = NBTHelper.readEnum(compound, "GantryAxis", Direction.class); movementAxis = NBTHelper.readEnum(compound, "GantryAxis", Direction.class);
sequencedOffsetLimit =
compound.contains("SequencedOffsetLimit") ? compound.getDouble("SequencedOffsetLimit") : -1;
super.readAdditional(compound, spawnData); super.readAdditional(compound, spawnData);
} }
@ -176,13 +202,16 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
} }
@Override @Override
public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) { } public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) {}
public void updateClientMotion() { public void updateClientMotion() {
float modifier = movementAxis.getAxisDirection() float modifier = movementAxis.getAxisDirection()
.getStep(); .getStep();
setContraptionMotion(Vec3.atLowerCornerOf(movementAxis.getNormal()) Vec3 motion = Vec3.atLowerCornerOf(movementAxis.getNormal())
.scale((axisMotion + clientOffsetDiff * modifier / 2f) * ServerSpeedProvider.get())); .scale((axisMotion + clientOffsetDiff * modifier / 2f) * ServerSpeedProvider.get());
if (sequencedOffsetLimit >= 0)
motion = VecHelper.clampComponentWise(motion, (float) sequencedOffsetLimit);
setContraptionMotion(motion);
} }
public double getAxisCoord() { public double getAxisCoord() {
@ -192,8 +221,9 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
} }
public void sendPacket() { public void sendPacket() {
AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> this), AllPackets.getChannel()
new GantryContraptionUpdatePacket(getId(), getAxisCoord(), axisMotion)); .send(PacketDistributor.TRACKING_ENTITY.with(() -> this),
new GantryContraptionUpdatePacket(getId(), getAxisCoord(), axisMotion, sequencedOffsetLimit));
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
@ -204,6 +234,7 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
GantryContraptionEntity ce = (GantryContraptionEntity) entity; GantryContraptionEntity ce = (GantryContraptionEntity) entity;
ce.axisMotion = packet.motion; ce.axisMotion = packet.motion;
ce.clientOffsetDiff = packet.coord - ce.getAxisCoord(); ce.clientOffsetDiff = packet.coord - ce.getAxisCoord();
ce.sequencedOffsetLimit = packet.sequenceLimit;
} }
} }

View file

@ -12,17 +12,20 @@ public class GantryContraptionUpdatePacket extends SimplePacketBase {
int entityID; int entityID;
double coord; double coord;
double motion; 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.entityID = entityID;
this.coord = coord; this.coord = coord;
this.motion = motion; this.motion = motion;
this.sequenceLimit = sequenceLimit;
} }
public GantryContraptionUpdatePacket(FriendlyByteBuf buffer) { public GantryContraptionUpdatePacket(FriendlyByteBuf buffer) {
entityID = buffer.readInt(); entityID = buffer.readInt();
coord = buffer.readFloat(); coord = buffer.readFloat();
motion = buffer.readFloat(); motion = buffer.readFloat();
sequenceLimit = buffer.readFloat();
} }
@Override @Override
@ -30,6 +33,7 @@ public class GantryContraptionUpdatePacket extends SimplePacketBase {
buffer.writeInt(entityID); buffer.writeInt(entityID);
buffer.writeFloat((float) coord); buffer.writeFloat((float) coord);
buffer.writeFloat((float) motion); buffer.writeFloat((float) motion);
buffer.writeFloat((float) sequenceLimit);
} }
@Override @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.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption; import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; 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.advancement.AllAdvancements;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform;
@ -35,6 +36,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
protected ScrollOptionBehaviour<MovementMode> movementMode; protected ScrollOptionBehaviour<MovementMode> movementMode;
protected boolean waitingForSpeedChange; protected boolean waitingForSpeedChange;
protected AssemblyException lastException; protected AssemblyException lastException;
protected double sequencedOffsetLimit;
// Custom position sync // Custom position sync
protected float clientOffsetDiff; protected float clientOffsetDiff;
@ -44,6 +46,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
setLazyTickRate(3); setLazyTickRate(3);
forceMove = true; forceMove = true;
needsContraption = true; needsContraption = true;
sequencedOffsetLimit = -1;
} }
@Override @Override
@ -56,6 +59,11 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS);
} }
@Override
protected boolean syncSequenceContext() {
return true;
}
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
@ -112,10 +120,21 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
return; return;
float movementSpeed = getMovementSpeed(); float movementSpeed = getMovementSpeed();
boolean locked = false;
if (sequencedOffsetLimit > 0) {
sequencedOffsetLimit = Math.max(0, sequencedOffsetLimit - Math.abs(movementSpeed));
locked = sequencedOffsetLimit == 0;
}
float newOffset = offset + movementSpeed; float newOffset = offset + movementSpeed;
if ((int) newOffset != (int) offset) if ((int) newOffset != (int) offset)
visitNewPosition(); visitNewPosition();
if (locked) {
forceMove = true;
resetContraptionToOffset();
sendData();
}
if (contraptionPresent) { if (contraptionPresent) {
if (moveAndCollideContraption()) { if (moveAndCollideContraption()) {
movedContraption.setContraptionMotion(Vec3.ZERO); movedContraption.setContraptionMotion(Vec3.ZERO);
@ -169,6 +188,7 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
@Override @Override
public void onSpeedChanged(float prevSpeed) { public void onSpeedChanged(float prevSpeed) {
super.onSpeedChanged(prevSpeed); super.onSpeedChanged(prevSpeed);
sequencedOffsetLimit = -1;
if (isPassive()) if (isPassive())
return; return;
@ -177,9 +197,16 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
waitingForSpeedChange = false; waitingForSpeedChange = false;
if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) {
if (!movedContraption.isStalled()) {
offset = Math.round(offset * 16) / 16;
resetContraptionToOffset();
}
movedContraption.getContraption() movedContraption.getContraption()
.stop(level); .stop(level);
} }
if (sequenceContext != null && sequenceContext.instruction() == SequencerInstructions.TURN_DISTANCE)
sequencedOffsetLimit = sequenceContext.getEffectiveValue(getTheoreticalSpeed());
} }
@Override @Override
@ -195,6 +222,8 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
compound.putBoolean("Running", running); compound.putBoolean("Running", running);
compound.putBoolean("Waiting", waitingForSpeedChange); compound.putBoolean("Waiting", waitingForSpeedChange);
compound.putFloat("Offset", offset); compound.putFloat("Offset", offset);
if (sequencedOffsetLimit >= 0)
compound.putDouble("SequencedOffsetLimit", sequencedOffsetLimit);
AssemblyException.write(compound, lastException); AssemblyException.write(compound, lastException);
super.write(compound, clientPacket); super.write(compound, clientPacket);
@ -212,6 +241,8 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
running = compound.getBoolean("Running"); running = compound.getBoolean("Running");
waitingForSpeedChange = compound.getBoolean("Waiting"); waitingForSpeedChange = compound.getBoolean("Waiting");
offset = compound.getFloat("Offset"); offset = compound.getFloat("Offset");
sequencedOffsetLimit =
compound.contains("SequencedOffsetLimit") ? compound.getDouble("SequencedOffsetLimit") : -1;
lastException = AssemblyException.read(compound); lastException = AssemblyException.read(compound);
super.read(compound, clientPacket); super.read(compound, clientPacket);
@ -308,6 +339,8 @@ public abstract class LinearActuatorBlockEntity extends KineticBlockEntity
float movementSpeed = Mth.clamp(convertToLinear(getSpeed()), -.49f, .49f) + clientOffsetDiff / 2f; float movementSpeed = Mth.clamp(convertToLinear(getSpeed()), -.49f, .49f) + clientOffsetDiff / 2f;
if (level.isClientSide) if (level.isClientSide)
movementSpeed *= ServerSpeedProvider.get(); movementSpeed *= ServerSpeedProvider.get();
if (sequencedOffsetLimit >= 0)
movementSpeed = (float) Mth.clamp(movementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit);
return movementSpeed; return movementSpeed;
} }

View file

@ -132,6 +132,8 @@ public class MechanicalPistonBlockEntity extends LinearActuatorBlockEntity {
int extensionRange = getExtensionRange(); int extensionRange = getExtensionRange();
movementSpeed = Mth.clamp(movementSpeed, 0 - offset, extensionRange - offset); movementSpeed = Mth.clamp(movementSpeed, 0 - offset, extensionRange - offset);
if (sequencedOffsetLimit >= 0)
movementSpeed = (float) Mth.clamp(movementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit);
return movementSpeed; return movementSpeed;
} }

View file

@ -404,7 +404,7 @@ public class MinecartController implements INBTSerializable<CompoundTag> {
} }
void tick(AbstractMinecart entity) { 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.setDeltaMovement(Vec3.ZERO);
entity.setYRot(yaw); entity.setYRot(yaw);
entity.setXRot(pitch); entity.setXRot(pitch);

View file

@ -19,6 +19,11 @@ public class GantryShaftBlockEntity extends KineticBlockEntity {
super(typeIn, pos, state); super(typeIn, pos, state);
} }
@Override
protected boolean syncSequenceContext() {
return true;
}
public void checkAttachedCarriageBlocks() { public void checkAttachedCarriageBlocks() {
if (!canAssembleOn()) if (!canAssembleOn())
return; return;

View file

@ -27,28 +27,23 @@ public class Instruction {
int getDuration(float currentProgress, float speed) { int getDuration(float currentProgress, float speed) {
speed *= speedModifier.value; speed *= speedModifier.value;
speed = Math.abs(speed); speed = Math.abs(speed);
double target = value - currentProgress; double target = value - currentProgress;
switch (instruction) { switch (instruction) {
// Always overshoot, target will stop early
case TURN_ANGLE: case TURN_ANGLE:
double degreesPerTick = KineticBlockEntity.convertToAngular(speed); double degreesPerTick = KineticBlockEntity.convertToAngular(speed);
int ticks = (int) (target / degreesPerTick); return (int) Math.ceil(target / degreesPerTick) + 2;
double degreesErr = target - degreesPerTick*ticks;
return ticks + (degreesPerTick > 2*degreesErr ? 0 : 1);
case TURN_DISTANCE: case TURN_DISTANCE:
double metersPerTick = KineticBlockEntity.convertToLinear(speed); double metersPerTick = KineticBlockEntity.convertToLinear(speed);
int offset = speed > 0 && speedModifier.value < 0 ? 1 : 2; return (int) Math.ceil(target / metersPerTick) + 2;
return (int) (target / metersPerTick + offset);
// Timing instructions
case DELAY: case DELAY:
return (int) target; return (int) target;
case AWAIT: case AWAIT:
return -1; return -1;
case END: case END:
default: default:
break; break;
@ -58,7 +53,7 @@ public class Instruction {
} }
float getTickProgress(float speed) { float getTickProgress(float speed) {
switch(instruction) { switch (instruction) {
case TURN_ANGLE: case TURN_ANGLE:
return KineticBlockEntity.convertToAngular(speed); return KineticBlockEntity.convertToAngular(speed);

View file

@ -2,7 +2,9 @@ package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
import java.util.Vector; 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.content.contraptions.relays.encased.SplitShaftBlockEntity;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -20,6 +22,35 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
int timer; int timer;
boolean poweredPreviously; 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) { public SequencedGearshiftBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); super(type, pos, state);
instructions = Instruction.createDefault(); instructions = Instruction.createDefault();
@ -113,6 +144,7 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
currentInstruction = -1; currentInstruction = -1;
currentInstructionDuration = -1; currentInstructionDuration = -1;
currentInstructionProgress = 0; currentInstructionProgress = 0;
sequenceContext = null;
timer = 0; timer = 0;
if (!level.hasNeighborSignal(worldPosition)) if (!level.hasNeighborSignal(worldPosition))
level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3); level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3);
@ -125,6 +157,8 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
currentInstructionDuration = instruction.getDuration(0, getTheoreticalSpeed()); currentInstructionDuration = instruction.getDuration(0, getTheoreticalSpeed());
currentInstruction = instructionIndex; currentInstruction = instructionIndex;
currentInstructionProgress = 0; currentInstructionProgress = 0;
sequenceContext = SequenceContext.fromGearshift(instruction.instruction, getTheoreticalSpeed() * getModifier(),
instruction.value);
timer = 0; timer = 0;
level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3); level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3);
} }
@ -134,6 +168,9 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
: null; : null;
} }
@Override
protected void copySequenceContextFrom(KineticBlockEntity sourceBE) {}
@Override @Override
public void write(CompoundTag compound, boolean clientPacket) { public void write(CompoundTag compound, boolean clientPacket) {
compound.putInt("InstructionIndex", currentInstruction); compound.putInt("InstructionIndex", currentInstruction);

View file

@ -45,6 +45,10 @@ public enum SequencerInstructions {
parameterKey = translationKey + "." + parameterName; parameterKey = translationKey + "." + parameterName;
} }
public boolean needsPropagation() {
return this == TURN_ANGLE || this == TURN_DISTANCE;
}
static List<Component> getOptions() { static List<Component> getOptions() {
List<Component> options = new ArrayList<>(); List<Component> options = new ArrayList<>();
for (SequencerInstructions entry : values()) 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.DirectionalAxisKineticBlock;
import com.simibubi.create.content.contraptions.base.KineticBlockEntity; import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; 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.block.IBE;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang; 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.LevelAccessor;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; 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.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition.Builder; 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.block.state.properties.Property;
import net.minecraft.world.level.material.PushReaction; 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 Property<Part> PART = EnumProperty.create("part", Part.class);
public static final BooleanProperty CONNECTED_ALONG_FIRST_COORDINATE = 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(); 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);
}
} }