package mods.eln.transparentnode.autominer;
import mods.eln.Eln;
import mods.eln.item.ElectricalDrillDescriptor;
import mods.eln.item.MiningPipeDescriptor;
import mods.eln.item.electricalitem.PortableOreScannerItem;
import mods.eln.misc.Coordonate;
import mods.eln.misc.INBTTReady;
import mods.eln.misc.Utils;
import mods.eln.ore.OreBlock;
import mods.eln.sim.IProcess;
import mods.eln.sixnode.lampsocket.LightBlockEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockOre;
import net.minecraft.block.BlockRedstoneOre;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntityChest;
import java.util.List;
public class AutoMinerSlowProcess implements IProcess, INBTTReady {
private final AutoMinerElement miner;
int pipeLength = 0;
private double energyCounter = 0;
private double energyTarget = 0;
private boolean oneJobDone = true;
boolean silkTouch = false;
enum jobType {none, done, full, chestFull, ore, pipeAdd, pipeRemove}
jobType job = jobType.none;
private jobType oldJob = jobType.none;
private final Coordonate jobCoord = new Coordonate();
private int blinkCounter = 0;
private int drillCount = 1;
public AutoMinerSlowProcess(AutoMinerElement autoMiner) {
this.miner = autoMiner;
}
void toggleSilkTouch() {
silkTouch = !silkTouch;
}
private boolean isReadyToDrill() {
ElectricalDrillDescriptor drill = (ElectricalDrillDescriptor) ElectricalDrillDescriptor.getDescriptor(miner.getInventory().getStackInSlot(AutoMinerContainer.electricalDrillSlotId));
if (drill == null) return false;
return isStorageReady();
}
private boolean isStorageReady() {
IInventory i = getDropInventory();
if (i == null) return false;
for (int idx = 0; idx < i.getSizeInventory(); idx++) {
if (i.getStackInSlot(idx) == null)
return true;
}
return false;
}
@Override
public void process(double time) {
ElectricalDrillDescriptor drill = (ElectricalDrillDescriptor) ElectricalDrillDescriptor.getDescriptor(miner.getInventory().getStackInSlot(AutoMinerContainer.electricalDrillSlotId));
if (++blinkCounter >= 9) {
blinkCounter = 0;
if ((miner.inPowerLoad.getU() / miner.descriptor.nominalVoltage - 0.5) * 3 > Math.random()) {
miner.setPowerOk(true);
LightBlockEntity.addLight(miner.lightCoordonate, 12, 11);
} else {
miner.setPowerOk(false);
}
}
energyCounter += miner.powerResistor.getP() * time;
if (job != jobType.none && job != jobType.full && job != jobType.chestFull && job != jobType.done) {
if (energyCounter >= energyTarget || (job == jobType.ore && !isReadyToDrill()) || !miner.powerOk) {
setupJob();
}
if (energyCounter >= energyTarget) {
oneJobDone = true;
switch (job) {
case ore:
drillCount++;
Block block = jobCoord.world().getBlock(jobCoord.x, jobCoord.y, jobCoord.z);
int meta = jobCoord.world().getBlockMetadata(jobCoord.x, jobCoord.y, jobCoord.z);
if (silkTouch) {
drop(new ItemStack(block, 1, meta));
} else {
List<ItemStack> drop = block.getDrops(jobCoord.world(), jobCoord.x, jobCoord.y, jobCoord.z, meta, 0);
for (ItemStack stack : drop) {
drop(stack);
}
}
// Use cobblestone instead of air, everywhere except the mining shaft.
// This is so mobs won't spawn excessively.
int xDist = jobCoord.x - miner.node.coordonate.x, zDist = jobCoord.z - miner.node.coordonate.z;
if (xDist * xDist + zDist * zDist > 25) {
jobCoord.world().setBlock(jobCoord.x, jobCoord.y, jobCoord.z, Blocks.cobblestone);
} else {
jobCoord.world().setBlockToAir(jobCoord.x, jobCoord.y, jobCoord.z);
}
energyCounter -= energyTarget;
setupJob();
break;
case pipeAdd:
// miner.pushLog("Pipe " + (pipeLength + 1) + " added");
Eln.ghostManager.createGhost(jobCoord, miner.node.coordonate, jobCoord.y);
miner.getInventory().decrStackSize(AutoMinerContainer.MiningPipeSlotId, 1);
pipeLength++;
miner.needPublish();
energyCounter -= energyTarget;
setupJob();
break;
case pipeRemove:
// miner.pushLog("Pipe " + pipeLength + " removed");
Eln.ghostManager.removeGhostAndBlock(jobCoord);
if (miner.getInventory().getStackInSlot(AutoMinerContainer.MiningPipeSlotId) == null) {
miner.getInventory().setInventorySlotContents(AutoMinerContainer.MiningPipeSlotId, Eln.miningPipeDescriptor.newItemStack(1));
} else {
miner.getInventory().decrStackSize(AutoMinerContainer.MiningPipeSlotId, -1);
}
pipeLength--;
miner.needPublish();
energyCounter -= energyTarget;
setupJob();
break;
default:
break;
}
}
} else {
setupJob();
}
switch (job) {
default:
miner.powerResistor.highImpedance();
break;
case ore:
if (drill == null) {
miner.powerResistor.highImpedance();
} else {
double p = drill.nominalPower;
if (silkTouch) p *= 3;
miner.powerResistor.setR(Math.pow(miner.descriptor.nominalVoltage, 2.0) / p);
}
break;
case pipeAdd:
miner.powerResistor.setR(miner.descriptor.pipeOperationRp);
break;
case pipeRemove:
miner.powerResistor.setR(miner.descriptor.pipeOperationRp);
break;
}
if (oldJob != job) {
miner.needPublish();
}
if (oneJobDone || oldJob != job) {
switch (job) {
case chestFull:
miner.pushLog("* Storage full!");
break;
case done:
miner.pushLog("- SLEEP");
break;
case full:
miner.pushLog("* Pipe stack full!");
break;
case none:
miner.pushLog("* Waiting opcode.");
break;
case ore:
miner.pushLog("- DRILL #" + drillCount);
break;
case pipeAdd:
miner.pushLog("- ADD PIPE #" + (pipeLength + 1));
break;
case pipeRemove:
miner.pushLog("- REMOVE PIPE #" + (pipeLength));
break;
default:
break;
}
}
oneJobDone = false;
oldJob = job;
}
private IInventory getDropInventory() {
IInventory chestEntity = null;
for (int x = 2; x >= 1; x--) {
Coordonate c = new Coordonate(x, -1, 0, miner.world());
c.applyTransformation(miner.front, miner.coordonate());
if (c.getTileEntity() instanceof IInventory) {
chestEntity = (IInventory) c.getTileEntity();
}
}
return chestEntity;
}
private void drop(ItemStack stack) {
Utils.tryPutStackInInventory(stack, getDropInventory(), 0, 36);
}
private boolean isMinable(Block block) {
return block != Blocks.air
&& (block) != Blocks.flowing_water && (block) != Blocks.water
&& (block) != Blocks.flowing_lava && (block) != Blocks.lava
&& (block) != Blocks.obsidian && (block) != Blocks.bedrock;
}
private void setupJob() {
ElectricalDrillDescriptor drill = (ElectricalDrillDescriptor) ElectricalDrillDescriptor.getDescriptor(miner.getInventory().getStackInSlot(AutoMinerContainer.electricalDrillSlotId));
// OreScanner scanner = (OreScanner) ElectricalDrillDescriptor.getDescriptor(miner.inventory.getStackInSlot(AutoMinerContainer.OreScannerSlotId));
MiningPipeDescriptor pipe = (MiningPipeDescriptor) ElectricalDrillDescriptor.getDescriptor(miner.getInventory().getStackInSlot(AutoMinerContainer.MiningPipeSlotId));
int scannerRadius = Eln.instance.autominerRange;
double scannerEnergy = 0;
jobCoord.dimention = miner.node.coordonate.dimention;
jobCoord.x = miner.node.coordonate.x;
jobCoord.y = miner.node.coordonate.y - pipeLength;
jobCoord.z = miner.node.coordonate.z;
boolean jobFind = false;
if (!miner.node.coordonate.getBlockExist()) {
setJob(jobType.none);
} else if (!miner.powerOk) {
setJob(jobType.none);
} else if (drill == null) {
if (jobCoord.y != miner.node.coordonate.y) {
ItemStack pipeStack = miner.getInventory().getStackInSlot(AutoMinerContainer.MiningPipeSlotId);
if (pipeStack == null || (pipeStack.stackSize != pipeStack.getMaxStackSize() && pipeStack.stackSize != miner.getInventory().getInventoryStackLimit())) {
jobFind = true;
setJob(jobType.pipeRemove);
} else {
jobFind = true;
setJob(jobType.full);
}
}
} else if (!isStorageReady()) {
setJob(jobType.chestFull);
jobFind = true;
} else if (pipe != null) {
if (jobCoord.y < miner.node.coordonate.y - 2) {
int depth = (miner.node.coordonate.y - jobCoord.y);
double miningRay = depth / 10 + 0.1;
miningRay = Math.min(miningRay, 2);
if (depth < scannerRadius) scannerRadius = depth + 1;
miningRay = Math.min(miningRay, scannerRadius - 2);
for (jobCoord.z = miner.node.coordonate.z - scannerRadius; jobCoord.z <= miner.node.coordonate.z + scannerRadius; jobCoord.z++) {
for (jobCoord.x = miner.node.coordonate.x - scannerRadius; jobCoord.x <= miner.node.coordonate.x + scannerRadius; jobCoord.x++) {
double dx = jobCoord.x - miner.node.coordonate.x;
double dy = 0;
double dz = jobCoord.z - miner.node.coordonate.z;
double distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
Block block = jobCoord.world().getBlock(jobCoord.x, jobCoord.y, jobCoord.z);
if (checkIsOre(jobCoord) || (distance > 0.1 && distance < miningRay && isMinable(block))) {
jobFind = true;
setJob(jobType.ore);
break;
}
}
if (jobFind) break;
}
}
if (!jobFind) {
if (jobCoord.y < 3) {
jobFind = true;
setJob(jobType.done);
} else {
jobCoord.x = miner.node.coordonate.x;
jobCoord.y--;
jobCoord.z = miner.node.coordonate.z;
Block block = jobCoord.world().getBlock(jobCoord.x, jobCoord.y, jobCoord.z);
if (block != Blocks.air
&& block != Blocks.flowing_water && block != Blocks.water
&& block != Blocks.flowing_lava && block != Blocks.lava) {
if (block != Blocks.obsidian && block != Blocks.bedrock) {
jobFind = true;
setJob(jobType.ore);
} else {
jobFind = true;
setJob(jobType.done);
}
} else {
jobFind = true;
setJob(jobType.pipeAdd);
}
}
}
}
if (!jobFind) setJob(jobType.none);
switch (job) {
case ore:
energyTarget = drill.OperationEnergy + scannerEnergy;
// Copied from Mekanism. Note that the power demand is tripled, so in effect this doubles time.
if (silkTouch) energyTarget *= 6;
break;
case pipeAdd:
energyTarget = miner.descriptor.pipeOperationEnergy;
break;
case pipeRemove:
energyTarget = miner.descriptor.pipeOperationEnergy;
break;
default:
energyTarget = 0;
break;
}
}
private void setJob(jobType job) {
if (job != this.job) {
miner.needPublish();
energyCounter = 0;
}
this.job = job;
}
private boolean checkIsOre(Coordonate coordonate) {
Block block = coordonate.world().getBlock(coordonate.x, coordonate.y, coordonate.z);
if (block instanceof BlockOre) return true;
if (block instanceof OreBlock) return true;
if (block instanceof BlockRedstoneOre) return true;
if (PortableOreScannerItem.RenderStorage.getBlockKeyFactor()[Block.getIdFromBlock(block) +
(coordonate.world().getBlockMetadata(coordonate.x, coordonate.y, coordonate.z) << 12)] != 0)
return true;
return false;
}
public void onBreakElement() {
destroyPipe();
}
private void destroyPipe() {
dropPipe();
Eln.ghostManager.removeGhostAndBlockWithObserverAndNotUuid(miner.node.coordonate, miner.descriptor.getGhostGroupUuid());
pipeLength = 0;
miner.needPublish();
}
private void dropPipe() {
Coordonate coord = new Coordonate(miner.node.coordonate);
for (coord.y = miner.node.coordonate.y - 1; coord.y >= miner.node.coordonate.y - pipeLength; coord.y--) {
Utils.dropItem(Eln.miningPipeDescriptor.newItemStack(1), coord);
}
}
public void ghostDestroyed() {
destroyPipe();
}
@Override
public void readFromNBT(NBTTagCompound nbt, String str) {
pipeLength = nbt.getInteger(str + "AMSP" + "pipeLength");
drillCount = nbt.getInteger(str + "AMSP" + "drillCount");
if (drillCount == 0) drillCount++;
}
@Override
public void writeToNBT(NBTTagCompound nbt, String str) {
nbt.setInteger(str + "AMSP" + "pipeLength", pipeLength);
nbt.setInteger(str + "AMSP" + "drillCount", drillCount);
}
}