package mods.eln.sixnode.lampsocket;
import mods.eln.Eln;
import mods.eln.generic.GenericItemUsingDamage;
import mods.eln.generic.GenericItemUsingDamageDescriptor;
import mods.eln.item.LampDescriptor;
import mods.eln.item.LampDescriptor.Type;
import mods.eln.misc.Coordonate;
import mods.eln.misc.INBTTReady;
import mods.eln.misc.Utils;
import mods.eln.server.SaveConfig;
import mods.eln.sim.IProcess;
import mods.eln.sixnode.lampsupply.LampSupplyElement;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
public class LampSocketProcess implements IProcess, INBTTReady /*,LightBlockObserver*/ {
double time = 0;
double deltaTBase = 0.2;
double deltaT = deltaTBase;
public double invulerabilityTimeLeft = 2;
boolean overPoweredInvulerabilityArmed = true;
LampSocketElement lamp;
int light = 0; // 0..15
double alphaZ = 0.0;
double stableProb = 0;
ItemStack lampStackLast = null;
boolean boot = true;
double vp[] = new double[3];
private LampSupplyElement oldLampSupply;
double updateLifeTimeout = 0, updateLifeTimeoutMax = 5;
Coordonate lbCoord;
public LampSocketProcess(LampSocketElement l) {
this.lamp = l;
lbCoord = new Coordonate(l.sixNode.coordonate);
}
@Override
public void process(double time) {
ItemStack lampStack = lamp.getInventory().getStackInSlot(0);
if (!lamp.poweredByLampSupply || lamp.getInventory().getStackInSlot(LampSocketContainer.cableSlotId) == null) {
lamp.setIsConnectedToLampSupply(false);
oldLampSupply = null;
} else {
Coordonate myCoord = lamp.sixNode.coordonate;
LampSupplyElement.PowerSupplyChannelHandle best = null;
float bestDistance = 10000;
List<LampSupplyElement.PowerSupplyChannelHandle> list = LampSupplyElement.channelMap.get(lamp.channel);
if (list != null) {
for (LampSupplyElement.PowerSupplyChannelHandle s : list) {
float distance = (float) s.element.sixNode.coordonate.trueDistanceTo(myCoord);
if (distance < bestDistance && distance <= s.element.getRange()) {
bestDistance = distance;
best = s;
}
}
}
if (best != null && best.element.getChannelState(best.id)) {
if (lampStack != null) {
LampDescriptor lampDescriptor = (LampDescriptor) ((GenericItemUsingDamage<GenericItemUsingDamageDescriptor>) lampStack.getItem()).getDescriptor(lampStack);
best.element.addToRp(lampDescriptor.getR());
}
lamp.positiveLoad.state = best.element.powerLoad.state;
oldLampSupply = best.element;
} else {
lamp.positiveLoad.state = 0;
oldLampSupply = null;
}
lamp.setIsConnectedToLampSupply(best != null);
}
if (lampStack != null) {
LampDescriptor lampDescriptor = (LampDescriptor) ((GenericItemUsingDamage<GenericItemUsingDamageDescriptor>) lampStack.getItem()).getDescriptor(lampStack);
if (lamp.getCoordonate().getBlockExist() && lampDescriptor.vegetableGrowRate != 0.0) {
double randTarget = 1.0 / lampDescriptor.vegetableGrowRate * time * (1.0 * light / lampDescriptor.nominalLight / 15.0);
if (randTarget > Math.random()) {
boolean exit = false;
Vec3 vv = Vec3.createVectorHelper(1, 0, 0);
Vec3 vp = Vec3.createVectorHelper(myCoord().x + 0.5, myCoord().y + 0.5, myCoord().z + 0.5);
vv.rotateAroundZ((float) (alphaZ * Math.PI / 180.0));
vv.rotateAroundY((float) ((Math.random() - 0.5) * 2 * Math.PI / 4));
vv.rotateAroundZ((float) ((Math.random() - 0.5) * 2 * Math.PI / 4));
lamp.front.rotateOnXnLeft(vv);
lamp.side.rotateFromXN(vv);
Coordonate c = new Coordonate(myCoord());
for (int idx = 0; idx < lamp.socketDescriptor.range + light; idx++) {
// newCoord.move(lamp.side.getInverse());
vp.xCoord += vv.xCoord;
vp.yCoord += vv.yCoord;
vp.zCoord += vv.zCoord;
c.setPosition(vp);
Block b = c.getBlock();
if (!c.getBlockExist()) {
exit = true;
break;
}
if (isOpaque(c)) {
vp.xCoord -= vv.xCoord;
vp.yCoord -= vv.yCoord;
vp.zCoord -= vv.zCoord;
c.setPosition(vp);
b = c.getBlock();
break;
}
}
if (!exit) {
Block b = c.getBlock();
if (b != Blocks.air) {
b.updateTick(c.world(), c.x, c.y, c.z, c.world().rand);
}
}
}
}
}
this.time += time;
if (this.time < deltaT)
return;
this.time -= deltaT;
lamp.computeElectricalLoad();
int oldLight = light;
int newLight = 0;
if (!boot && (lampStack != lampStackLast || lampStack == null)) {
stableProb = 0;
}
if (lampStack != null) {
LampDescriptor lampDescriptor = (LampDescriptor) ((GenericItemUsingDamage<GenericItemUsingDamageDescriptor>) lampStack.getItem()).getDescriptor(lampStack);
if (stableProb < 0)
stableProb = 0;
double lightDouble = 0;
switch (lampDescriptor.type) {
case Incandescent:
case LED:
lightDouble = lampDescriptor.nominalLight * (Math.abs(lamp.lampResistor.getU()) - lampDescriptor.minimalU) / (lampDescriptor.nominalU - lampDescriptor.minimalU);
lightDouble = (lightDouble * 16);
break;
case eco:
double U = Math.abs(lamp.lampResistor.getU());
if (U < lampDescriptor.minimalU) {
stableProb = 0;
lightDouble = 0;
} else {
double powerFactor = U / lampDescriptor.nominalU;
stableProb += U / lampDescriptor.stableU * deltaT / lampDescriptor.stableTime * lampDescriptor.stableUNormalised;
if (stableProb > U / lampDescriptor.stableU)
stableProb = U / lampDescriptor.stableU;
if (Math.random() > stableProb) {
lightDouble = 0;
} else {
lightDouble = lampDescriptor.nominalLight * powerFactor;
lightDouble = (lightDouble * 16);
}
}
break;
default:
break;
}
if (lightDouble - oldLight > 1.0) {
newLight = (int) lightDouble;
} else if (lightDouble - oldLight < -0.3) {
newLight = (int) lightDouble;
} else {
newLight = oldLight;
}
if (newLight < 0)
newLight = 0;
if (newLight > 14)
newLight = 14;
/*
* double overFactor = (lamp.electricalLoad.Uc-lampDescriptor.minimalU) /(lampDescriptor.nominalU-lampDescriptor.minimalU);
*/
double overFactor = (lamp.lampResistor.getP()) / (lampDescriptor.nominalP);
if (overFactor < 0)
overFactor = 0;
if (overFactor < 1.3)
overPoweredInvulerabilityArmed = true;
if (overFactor > 1.5 && overPoweredInvulerabilityArmed) {
invulerabilityTimeLeft = 2;
overPoweredInvulerabilityArmed = false;
}
if (invulerabilityTimeLeft != 0 && overFactor > 1.5)
overFactor = 1.5;
updateLifeTimeout += deltaT;
if (updateLifeTimeout > updateLifeTimeoutMax &&
!(lampDescriptor.type == Type.LED && Eln.ledLampInfiniteLife)) {
// Utils.println("aging");
updateLifeTimeout -= updateLifeTimeoutMax;
double lifeLost = overFactor * updateLifeTimeoutMax / lampDescriptor.nominalLife;
lifeLost = Utils.voltageMargeFactorSub(lifeLost);
if (overFactor >= 1.21) {
lifeLost *= overFactor;
}
// lifeLost *= overFactor;
// lifeLost *= overFactor;
double life = lampDescriptor.getLifeInTag(lampStack) - lifeLost;
if (SaveConfig.instance.electricalLampAging) {
lampDescriptor.setLifeInTag(lampStack, life);
}
if (life < 0 || overFactor > 3) {
lamp.getInventory().setInventorySlotContents(0, null);
light = 0;
}
}
boot = false;
}
if (invulerabilityTimeLeft != 0) {
invulerabilityTimeLeft -= deltaT;
if (invulerabilityTimeLeft < 0)
invulerabilityTimeLeft = 0;
}
deltaT = deltaTBase + deltaTBase * (-0.1 + 0.2 * Math.random());
lampStackLast = lampStack;
placeSpot(newLight);
}
// ElectricalConnectionOneWay connection = null;
public void rotateAroundZ(Vec3 v, float par1) {
float f1 = MathHelper.cos(par1);
float f2 = MathHelper.sin(par1);
double d0 = v.xCoord * (double) f1 + v.yCoord * (double) f2;
double d1 = v.yCoord * (double) f1 - v.xCoord * (double) f2;
double d2 = v.zCoord;
v.xCoord = d0;
v.yCoord = d1;
v.zCoord = d2;
}
void placeSpot(int newLight) {
boolean exit = false;
if (!lbCoord.getBlockExist())
return;
Vec3 vv = Vec3.createVectorHelper(1, 0, 0);
Vec3 vp = Utils.getVec05(myCoord());
rotateAroundZ(vv, (float) (alphaZ * Math.PI / 180.0));
lamp.front.rotateOnXnLeft(vv);
lamp.side.rotateFromXN(vv);
Coordonate newCoord = new Coordonate(myCoord());
for (int idx = 0; idx < lamp.socketDescriptor.range; idx++) {
// newCoord.move(lamp.side.getInverse());
vp.xCoord += vv.xCoord;
vp.yCoord += vv.yCoord;
vp.zCoord += vv.zCoord;
newCoord.setPosition(vp);
if (!newCoord.getBlockExist()) {
exit = true;
break;
}
if (isOpaque(newCoord)) {
vp.xCoord -= vv.xCoord;
vp.yCoord -= vv.yCoord;
vp.zCoord -= vv.zCoord;
newCoord.setPosition(vp);
break;
}
}
if (!exit) {
int count = 0;
while (!newCoord.equals(myCoord())) {
Block block = newCoord.getBlock();
if (block == Blocks.air || block == Eln.lightBlock) {
count++;
if (count == 2)
break;
}
vp.xCoord -= vv.xCoord;
vp.yCoord -= vv.yCoord;
vp.zCoord -= vv.zCoord;
newCoord.setPosition(vp);
}
}
if (!exit)
setLightAt(newCoord, newLight);
}
public boolean isOpaque(Coordonate coord) {
Block block = coord.getBlock();
boolean isNotOpaque = block == Blocks.air || !block.isOpaqueCube();
if (block == Blocks.farmland)
isNotOpaque = false;
return !isNotOpaque;
}
public void publish() {
Utils.print("Light published");
}
public void setLightAt(Coordonate coord, int value) {
Coordonate oldLbCoord = lbCoord;
lbCoord = new Coordonate(coord);
int oldLight = light;
boolean same = coord.equals(oldLbCoord);
light = value;
if (!same && oldLbCoord.equals(myCoord())) {
lamp.sixNode.recalculateLightValue();
}
if (lbCoord.equals(myCoord())) {
if (light != oldLight || !same)
lamp.sixNode.recalculateLightValue();
} else {
/*
* if(same) LightBlockEntity.remplaceLight(lbCoord, oldLight, light); else LightBlockEntity.addLight(lbCoord, light);
*/
LightBlockEntity.addLight(lbCoord, light, 5);
}
if (light != oldLight) {
ByteArrayOutputStream bos = new ByteArrayOutputStream(64);
DataOutputStream packet = new DataOutputStream(bos);
lamp.preparePacketForClient(packet);
try {
packet.writeByte(light);
} catch (IOException e) {
e.printStackTrace();
}
lamp.sendPacketToAllClient(bos);
}
}
Coordonate myCoord() {
return lamp.sixNode.coordonate;
}
public void destructor() {
// if(lbCoord.equals(myCoord()) == false && lbCoord.getBlockId() ==
// Eln.lightBlockId)
// lbCoord.setBlock(0,0);
// TODO
/*
* LightBlockEntity.removeObserver(this); if(lbCoord.equals(myCoord()) == false) LightBlockEntity.removeLight(lbCoord, light);
*/
}
@Override
public void readFromNBT(NBTTagCompound nbt, String str) {
stableProb = nbt.getDouble(str + "LSP" + "stableProb");
lbCoord.readFromNBT(nbt, str + "lbCoordInst");
alphaZ = nbt.getFloat(str + "alphaZ");
light = nbt.getInteger(str + "light");
}
@Override
public void writeToNBT(NBTTagCompound nbt, String str) {
nbt.setDouble(str + "LSP" + "stableProb", stableProb);
lbCoord.writeToNBT(nbt, str + "lbCoordInst");
nbt.setFloat(str + "alphaZ", (float) alphaZ);
nbt.setInteger(str + "light", light);
}
public int getBlockLight() {
if (lbCoord.equals(myCoord())) {
return light;
} else {
return 0;
}
}
/*
*
* @Override public void lightBlockDestructor(Coordonate coord) { if(coord.equals(lbCoord)) { light = 0; lbCoord = new Coordonate(myCoord()); //placeSpot(light); } }
*/
}