Create/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java
2022-01-11 13:04:08 -05:00

130 lines
3.3 KiB
Java

package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
import java.util.Optional;
import java.util.Vector;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
public class Instruction {
SequencerInstructions instruction;
InstructionSpeedModifiers speedModifier;
int value;
public Instruction(SequencerInstructions instruction) {
this(instruction, 1);
}
public Instruction(SequencerInstructions instruction, int value) {
this.instruction = instruction;
speedModifier = InstructionSpeedModifiers.FORWARD;
this.value = value;
}
int getDuration(float currentProgress, float speed) {
speed *= speedModifier.value;
speed = Math.abs(speed);
double target = value - currentProgress;
switch (instruction) {
case TURN_ANGLE:
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:
double metersPerTick = KineticTileEntity.convertToLinear(speed);
int offset = speed > 0 && speedModifier.value < 0 ? 1 : 2;
return (int) (target / metersPerTick + offset);
case DELAY:
return (int) target;
case AWAIT:
return -1;
case END:
default:
break;
}
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;
}
float getSpeedModifier() {
return switch (instruction) {
case TURN_ANGLE, TURN_DISTANCE -> speedModifier.value;
default -> 0;
};
}
OnIsPoweredResult onRedstonePulse() {
return instruction == SequencerInstructions.AWAIT ? OnIsPoweredResult.CONTINUE : OnIsPoweredResult.NOTHING;
}
public static ListTag serializeAll(Vector<Instruction> instructions) {
ListTag list = new ListTag();
instructions.forEach(i -> list.add(i.serialize()));
return list;
}
public static Vector<Instruction> deserializeAll(ListTag list) {
if (list.isEmpty())
return createDefault();
Vector<Instruction> instructions = new Vector<>(5);
list.forEach(inbt -> instructions.add(deserialize((CompoundTag) inbt)));
return instructions;
}
public static Vector<Instruction> createDefault() {
Vector<Instruction> instructions = new Vector<>(5);
instructions.add(new Instruction(SequencerInstructions.TURN_ANGLE, 90));
instructions.add(new Instruction(SequencerInstructions.END));
return instructions;
}
CompoundTag serialize() {
CompoundTag tag = new CompoundTag();
NBTHelper.writeEnum(tag, "Type", instruction);
NBTHelper.writeEnum(tag, "Modifier", speedModifier);
tag.putInt("Value", value);
return tag;
}
static Instruction deserialize(CompoundTag tag) {
Instruction instruction = new Instruction(NBTHelper.readEnum(tag, "Type", SequencerInstructions.class));
instruction.speedModifier = NBTHelper.readEnum(tag, "Modifier", InstructionSpeedModifiers.class);
instruction.value = tag.getInt("Value");
return instruction;
}
}