Add a second RS channel for each voltage signal to allow precise control

This commit is contained in:
malte0811 2017-08-16 21:15:26 +02:00
parent a61639052e
commit 2f609e9026

View file

@ -77,7 +77,18 @@ import java.util.function.BiConsumer;
import static malte0811.industrialWires.blocks.hv.TileEntityMarx.FiringState.FIRE;
import static malte0811.industrialWires.util.MiscUtils.getOffset;
import static malte0811.industrialWires.util.MiscUtils.offset;
import static net.minecraft.item.EnumDyeColor.*;
/**
* Channel: Purpose
* White: Coarse Vcharge
* Orange: Coarse bottom cap voltage
* Magenta: Coarse top voltage
* LBlue: Firing trigger
* Yellow: Fine Vcharge
* Lime: Fine bottom cap voltage
* Pink: Fine top cap voltage
*/
@Mod.EventBusSubscriber
public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable, ISyncReceiver, IBlockBoundsIW, IImmersiveConnectable, IIC2Connector,
IRedstoneConnector {
@ -93,7 +104,6 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
private double timeFactorBottom;
private final static double CAPACITANCE = 0.000_001_6;
private final static double MAX_VOLTAGE = 250_000;
private boolean allowSlowDischarge = true;
public IWProperties.MarxType type = IWProperties.MarxType.NO_MODEL;
private int stageCount = 0;
@ -104,10 +114,10 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
private DualEnergyStorage storage = new DualEnergyStorage(50_000, 32_000);
private boolean hasConnection;
private double[] capVoltages;
//RS channel 1/white
private int voltageControl = 0;
private boolean loaded = false;
private double leftover;
private long lastUpdate = -1;
TileEntityMarx(EnumFacing facing, IWProperties.MarxType type, boolean mirrored) {
this.facing = facing;
@ -223,43 +233,42 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
break;
}
if (!world.isRemote&&type== IWProperties.MarxType.BOTTOM) {
if (capVoltages==null||capVoltages.length!=stageCount) {
if (capVoltages == null || capVoltages.length != stageCount) {
capVoltages = new double[stageCount];
}
final double oldTopVoltage = capVoltages[stageCount-1];
final double oldTopVoltage = capVoltages[stageCount - 1];
final double oldBottomVoltage = capVoltages[0];
for (int i = stageCount-1;i>0;i--) {
for (int i = stageCount - 1; i > 0; i--) {
double oldVoltage = capVoltages[i];
double u0 = capVoltages[i-1];
capVoltages[i] = u0-(u0-oldVoltage)*timeFactor;
capVoltages[i-1] -= capVoltages[i]-oldVoltage;
double u0 = capVoltages[i - 1];
capVoltages[i] = u0 - (u0 - oldVoltage) * timeFactor;
capVoltages[i - 1] -= capVoltages[i] - oldVoltage;
}
//charge bottom cap from storage
double setVoltage = MAX_VOLTAGE * voltageControl / 15D;
double setVoltage = MAX_VOLTAGE * voltageControl / 255F;
double u0 = Math.min(setVoltage, 100 * storage.getEnergyStoredEU());
if (u0<0) {
if (u0 < 0) {
u0 = 0;
}
if (u0 < capVoltages[0] && setVoltage > capVoltages[0]) {
u0 = capVoltages[0];
}
if (allowSlowDischarge || u0 > capVoltages[0]) {
double tmp = u0 - (u0 - oldBottomVoltage) * timeFactorBottom;
double energyUsed = .5*(tmp * tmp - oldBottomVoltage * oldBottomVoltage)*CAPACITANCE;
if (energyUsed > 0 && storage.extractEU(energyUsed, false)==energyUsed) {// energyUsed can be negative when discharging the caps
storage.extractEU(energyUsed, true);
capVoltages[0] = tmp;
} else if (energyUsed<=0) {
capVoltages[0] = tmp;
}
if (Math.round(15*oldBottomVoltage/MAX_VOLTAGE)!=Math.round(15*capVoltages[0]/MAX_VOLTAGE)) {
net.updateValues();
} else if (Math.round(15*oldTopVoltage/MAX_VOLTAGE)!=Math.round(15*capVoltages[stageCount-1]/MAX_VOLTAGE)) {
net.updateValues();
}
if (capVoltages[0] > MAX_VOLTAGE * 14 / 15) {
state = FiringState.NEXT_TICK;
}
double tmp = u0 - (u0 - oldBottomVoltage) * timeFactorBottom;
double energyUsed = .5 * (tmp * tmp - oldBottomVoltage * oldBottomVoltage) * CAPACITANCE;
if (energyUsed > 0 && storage.extractEU(energyUsed, false) == energyUsed) {// energyUsed can be negative when discharging the caps
storage.extractEU(energyUsed, true);
capVoltages[0] = tmp;
} else if (energyUsed <= 0) {
capVoltages[0] = tmp;
}
int delta = (int) (lastUpdate+15-world.getTotalWorldTime());
if (Math.abs(getRSSignalFromVoltage(oldBottomVoltage)-getRSSignalFromVoltage(capVoltages[0]))>delta) {
net.updateValues();
} else if (Math.abs(getRSSignalFromVoltage(oldTopVoltage)-getRSSignalFromVoltage(capVoltages[stageCount-1]))>delta) {
net.updateValues();
}
if (capVoltages[0] > MAX_VOLTAGE * 14.5 / 15) {
state = FiringState.NEXT_TICK;
}
}
leftover = storage.getMaxInputIF();
@ -394,6 +403,10 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
return Math.abs(offset.getX())>Math.abs(offset.getY());
}
private int getRSSignalFromVoltage(double voltage) {
return (int) (Math.round(255 * voltage / MAX_VOLTAGE)&0xff);
}
@Override
public Vec3i getSize() {
return new Vec3i(stageCount, 8, 2);
@ -630,12 +643,11 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
@Override
public void onChange() {
TileEntityMarx master = masterOr(this, this);
master.voltageControl = master.net.channelValues[0];
if (master.net.channelValues[3]!=0) {//light blue is firing trigger
master.voltageControl = (master.net.channelValues[WHITE.getMetadata()]<<4)|master.net.channelValues[YELLOW.getMetadata()];
if (master.net.channelValues[LIGHT_BLUE.getMetadata()]!=0) {
master.tryTriggeredDischarge();
}
//yellow determines whether a lower charge- than cap0-voltage will discharge the generator
master.allowSlowDischarge = master.net.channelValues[4] == 0;
master.lastUpdate = world.getTotalWorldTime();
}
private void tryTriggeredDischarge() {
state = FiringState.NEXT_TICK;
@ -650,15 +662,19 @@ public class TileEntityMarx extends TileEntityIWMultiblock implements ITickable,
public void updateInput(byte[] signals) {
TileEntityMarx master = masterOr(this, this);
if (master.capVoltages!=null&&master.capVoltages.length==stageCount) {
//1/orange is voltage measurement from the top cap
//2/magenta is for the bottom one
byte signal1 = (byte)(Math.round(15*master.capVoltages[stageCount-1]/ MAX_VOLTAGE));
byte signal2 = (byte)(Math.round(15*master.capVoltages[0]/ MAX_VOLTAGE));
signals[1] = (byte) Math.max(signals[1], signal1);
signals[2] = (byte) Math.max(signals[2], signal2);
int signalTop = getRSSignalFromVoltage(master.capVoltages[stageCount-1]);
int signalBottom = getRSSignalFromVoltage(master.capVoltages[0]);
setSignal(ORANGE.getMetadata(), (signalBottom>>4)&0xf, signals);
setSignal(MAGENTA.getMetadata(), (signalTop>>4)&0xf, signals);
setSignal(LIME.getMetadata(), signalBottom&0xf, signals);
setSignal(PINK.getMetadata(), signalTop&0xf, signals);
}
}
private void setSignal(int channel, int value, byte[] signals) {
signals[channel] = (byte) Math.max(value, signals[channel]);
}
void setStageCount(int stageCount) {
this.stageCount = stageCount;
rcTimeConst = 5D/stageCount;