From 53ba59c0828f446a6ce0305c74dd38fe12773e97 Mon Sep 17 00:00:00 2001 From: reidbhuntley Date: Mon, 31 May 2021 15:42:12 -0400 Subject: [PATCH] Improve stability of sequenced gearshift (esp. for rotations) (#1695) --- .../contraptions/base/KineticTileEntity.java | 4 ++ .../bearing/MechanicalBearingTileEntity.java | 12 +++--- .../piston/LinearActuatorTileEntity.java | 2 +- .../piston/MechanicalPistonTileEntity.java | 4 +- .../fluids/actors/HosePulleyTileEntity.java | 2 +- .../advanced/GantryShaftTileEntity.java | 2 +- .../advanced/sequencer/Instruction.java | 40 +++++++++++++++---- .../SequencedGearshiftTileEntity.java | 11 ++++- 8 files changed, 57 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java index 385c12815..a0fe6a992 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java @@ -477,6 +477,10 @@ public abstract class KineticTileEntity extends SmartTileEntity return d.getAxisDirection() == AxisDirection.POSITIVE ? axisSpeed : -axisSpeed; } + public static float convertToLinear(float speed) { return speed / 512f; } + + public static float convertToAngular(float speed) { return speed * 3 / 10f; } + public boolean isOverStressed() { return overStressed; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java index d7ed6958b..5c27c6576 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java @@ -6,6 +6,7 @@ import java.util.List; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; @@ -80,7 +81,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity super.fromTag(state, compound, clientPacket); return; } - + float angleBefore = angle; running = compound.getBoolean("Running"); angle = compound.getFloat("Angle"); @@ -108,7 +109,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity public void onSpeedChanged(float prevSpeed) { super.onSpeedChanged(prevSpeed); assembleNextTick = true; - + if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { movedContraption.getContraption() .stop(world); @@ -116,7 +117,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity } public float getAngularSpeed() { - float speed = (isWindmill() ? getGeneratedSpeed() : getSpeed()) * 3 / 10f; + float speed = convertToAngular(isWindmill() ? getGeneratedSpeed() : getSpeed()); if (getSpeed() == 0) speed = 0; if (world.isRemote) { @@ -169,7 +170,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); movedContraption.setRotationAxis(direction.getAxis()); world.addEntity(movedContraption); - + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(world, pos); running = true; @@ -216,14 +217,13 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity movedContraption.getContraption() .stop(world); disassemble(); + return; } - return; } else { if (speed == 0 && !isWindmill()) return; assemble(); } - return; } if (!running) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java index 300f17aab..35dfac048 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java @@ -270,7 +270,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity } public float getMovementSpeed() { - float movementSpeed = MathHelper.clamp(getSpeed() / 512f, -.49f, .49f) + clientOffsetDiff / 2f; + float movementSpeed = MathHelper.clamp(convertToLinear(getSpeed()), -.49f, .49f) + clientOffsetDiff / 2f; if (world.isRemote) movementSpeed *= ServerSpeedProvider.get(); return movementSpeed; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java index bad9651ef..8297c9b20 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java @@ -84,7 +84,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { applyContraptionPosition(); forceMove = true; world.addEntity(movedContraption); - + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(world, pos); } @@ -118,7 +118,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { @Override public float getMovementSpeed() { - float movementSpeed = MathHelper.clamp(getSpeed() / 512f, -.49f, .49f); + float movementSpeed = MathHelper.clamp(convertToLinear(getSpeed()), -.49f, .49f); if (world.isRemote) movementSpeed *= ServerSpeedProvider.get(); Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java index 7871b9e10..574b76f83 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java @@ -175,7 +175,7 @@ public class HosePulleyTileEntity extends KineticTileEntity { } public float getMovementSpeed() { - float movementSpeed = getSpeed() / 512f; + float movementSpeed = convertToLinear(getSpeed()); if (world.isRemote) movementSpeed *= ServerSpeedProvider.get(); return movementSpeed; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java index 2f9fe658a..4cd68bcbf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java @@ -99,7 +99,7 @@ public class GantryShaftTileEntity extends KineticTileEntity { BlockState blockState = getBlockState(); if (!AllBlocks.GANTRY_SHAFT.has(blockState)) return 0; - return MathHelper.clamp(-getSpeed() / 512f, -.49f, .49f); + return MathHelper.clamp(convertToLinear(-getSpeed()), -.49f, .49f); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java index 2bf09acea..2ffbcae4d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.relays.advanced.sequencer; import java.util.Vector; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.nbt.CompoundNBT; @@ -23,23 +24,27 @@ public class Instruction { this.value = value; } - int getDuration(float initialProgress, float speed) { - int offset = speed > 0 && speedModifier.value < 0 ? 1 : 2; + int getDuration(float currentProgress, float speed) { speed *= speedModifier.value; speed = Math.abs(speed); - double degreesPerTick = (speed * 360) / 60 / 20; - double metersPerTick = speed / 512; + double target = value - currentProgress; + switch (instruction) { case TURN_ANGLE: - return (int) ((1 - initialProgress) * value / degreesPerTick + 1); + double degreesPerTick = KineticTileEntity.convertToAngular(speed); + int ticks = (int) (target / degreesPerTick); + double degreesErr = target - degreesPerTick*ticks; + return ticks + (degreesPerTick > 2*degreesErr ? 0 : 1); case TURN_DISTANCE: - return (int) ((1 - initialProgress) * value / metersPerTick + offset); + double metersPerTick = KineticTileEntity.convertToLinear(speed); + int offset = speed > 0 && speedModifier.value < 0 ? 1 : 2; + return (int) (target / metersPerTick + offset); case DELAY: - return (int) ((1 - initialProgress) * value + 1); + return (int) target; case AWAIT: return -1; @@ -52,6 +57,27 @@ public class Instruction { return 0; } + float getTickProgress(float speed) { + switch(instruction) { + + case TURN_ANGLE: + return KineticTileEntity.convertToAngular(speed); + + case TURN_DISTANCE: + return KineticTileEntity.convertToLinear(speed); + + case DELAY: + return 1; + + case AWAIT: + case END: + default: + break; + + } + return 0; + } + int getSpeedModifier() { switch (instruction) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java index 42b961a98..cbd004810 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java @@ -15,6 +15,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { Vector instructions; int currentInstruction; int currentInstructionDuration; + float currentInstructionProgress; int timer; boolean poweredPreviously; @@ -23,6 +24,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { instructions = Instruction.createDefault(); currentInstruction = -1; currentInstructionDuration = -1; + currentInstructionProgress = 0; timer = 0; poweredPreviously = false; } @@ -39,6 +41,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { return; if (timer < currentInstructionDuration) { timer++; + currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(speed); return; } run(currentInstruction + 1); @@ -59,8 +62,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { run(-1); // Update instruction time with regards to new speed - float initialProgress = timer / (float) currentInstructionDuration; - currentInstructionDuration = instruction.getDuration(initialProgress, getTheoreticalSpeed()); + currentInstructionDuration = instruction.getDuration(currentInstructionProgress, getTheoreticalSpeed()); timer = 0; } @@ -109,6 +111,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { detachKinetics(); currentInstruction = -1; currentInstructionDuration = -1; + currentInstructionProgress = 0; timer = 0; if (!world.isBlockPowered(pos)) world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, 0), 3); @@ -119,7 +122,9 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { detachKinetics(); currentInstructionDuration = instruction.getDuration(0, getTheoreticalSpeed()); + System.out.println("Dur.: " + currentInstructionDuration); currentInstruction = instructionIndex; + currentInstructionProgress = 0; timer = 0; world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3); } @@ -133,6 +138,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { public void write(CompoundNBT compound, boolean clientPacket) { compound.putInt("InstructionIndex", currentInstruction); compound.putInt("InstructionDuration", currentInstructionDuration); + compound.putFloat("InstructionProgress", currentInstructionProgress); compound.putInt("Timer", timer); compound.putBoolean("PrevPowered", poweredPreviously); compound.put("Instructions", Instruction.serializeAll(instructions)); @@ -143,6 +149,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { currentInstruction = compound.getInt("InstructionIndex"); currentInstructionDuration = compound.getInt("InstructionDuration"); + currentInstructionProgress = compound.getFloat("InstructionProgress"); poweredPreviously = compound.getBoolean("PrevPowered"); timer = compound.getInt("Timer"); instructions = Instruction.deserializeAll(compound.getList("Instructions", NBT.TAG_COMPOUND));