package mekanism.generators.common.content.turbine;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mekanism.api.Coord4D;
import mekanism.common.content.tank.TankUpdateProtocol;
import mekanism.common.multiblock.MultiblockCache;
import mekanism.common.multiblock.MultiblockManager;
import mekanism.common.multiblock.UpdateProtocol;
import mekanism.common.tile.TileEntityPressureDisperser;
import mekanism.generators.common.MekanismGenerators;
import mekanism.generators.common.block.states.BlockStateGenerator.GeneratorType;
import mekanism.generators.common.tile.turbine.TileEntityElectromagneticCoil;
import mekanism.generators.common.tile.turbine.TileEntityRotationalComplex;
import mekanism.generators.common.tile.turbine.TileEntitySaturatingCondenser;
import mekanism.generators.common.tile.turbine.TileEntityTurbineCasing;
import mekanism.generators.common.tile.turbine.TileEntityTurbineRotor;
import mekanism.generators.common.tile.turbine.TileEntityTurbineVent;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
public class TurbineUpdateProtocol extends UpdateProtocol<SynchronizedTurbineData>
{
public static final int FLUID_PER_TANK = TankUpdateProtocol.FLUID_PER_TANK;
public static final int MAX_BLADES = 28;
public TurbineUpdateProtocol(TileEntityTurbineCasing tileEntity)
{
super(tileEntity);
}
@Override
protected boolean isValidFrame(int x, int y, int z)
{
return GeneratorType.get(pointer.getWorld().getBlockState(new BlockPos(x, y, z))) == GeneratorType.TURBINE_CASING;
}
@Override
protected boolean isValidInnerNode(int x, int y, int z)
{
if(super.isValidInnerNode(x, y, z))
{
return true;
}
TileEntity tile = pointer.getWorld().getTileEntity(new BlockPos(x, y, z));
return tile instanceof TileEntityTurbineRotor || tile instanceof TileEntityRotationalComplex ||
tile instanceof TileEntityPressureDisperser || tile instanceof TileEntityElectromagneticCoil ||
tile instanceof TileEntitySaturatingCondenser;
}
@Override
protected boolean canForm(SynchronizedTurbineData structure)
{
if(structure.volLength % 2 == 1 && structure.volWidth % 2 == 1)
{
int innerRadius = (Math.min(structure.volLength, structure.volWidth)-3)/2;
if(innerRadius >= Math.ceil((structure.volHeight-2)/4))
{
int centerX = structure.minLocation.xCoord+(structure.volLength-1)/2;
int centerZ = structure.minLocation.zCoord+(structure.volWidth-1)/2;
Coord4D complex = null;
Set<Coord4D> turbines = new HashSet<Coord4D>();
Set<Coord4D> dispersers = new HashSet<Coord4D>();
Set<Coord4D> coils = new HashSet<Coord4D>();
Set<Coord4D> condensers = new HashSet<Coord4D>();
//Scan for complex
for(Coord4D coord : innerNodes)
{
TileEntity tile = coord.getTileEntity(pointer.getWorld());
if(tile instanceof TileEntityRotationalComplex)
{
if(complex != null)
{
return false;
}
else if(coord.xCoord != centerX || coord.zCoord != centerZ)
{
return false;
}
structure.internalLocations.add(coord);
complex = coord;
}
else if(tile instanceof TileEntityTurbineRotor)
{
if(coord.xCoord != centerX || coord.zCoord != centerZ)
{
return false;
}
turbines.add(coord);
}
else if(tile instanceof TileEntityPressureDisperser)
{
dispersers.add(coord);
}
else if(tile instanceof TileEntityElectromagneticCoil)
{
coils.add(coord);
}
else if(tile instanceof TileEntitySaturatingCondenser)
{
condensers.add(coord);
}
}
//Terminate if complex doesn't exist
if(complex == null)
{
return false;
}
//Make sure a flat, horizontal plane of dispersers exists within the multiblock around the complex
for(int x = complex.xCoord-innerRadius; x <= complex.xCoord+innerRadius; x++)
{
for(int z = complex.zCoord-innerRadius; z <= complex.zCoord+innerRadius; z++)
{
if(!(x == centerX && z == centerZ))
{
TileEntity tile = pointer.getWorld().getTileEntity(new BlockPos(x, complex.yCoord, z));
if(!(tile instanceof TileEntityPressureDisperser))
{
return false;
}
dispersers.remove(new Coord4D(x, complex.yCoord, z, pointer.getWorld().provider.getDimension()));
}
}
}
//If any dispersers were not processed, they're in the wrong place
if(dispersers.size() > 0)
{
return false;
}
//Make sure all condensers are in proper locations
for(Coord4D coord : condensers)
{
if(coord.yCoord <= complex.yCoord)
{
return false;
}
}
structure.condensers = condensers.size();
int turbineHeight = 0;
//Make sure a complete line of turbine rotors exist from the complex to the multiblock's base
for(int y = complex.yCoord-1; y > structure.minLocation.yCoord; y--)
{
TileEntity tile = pointer.getWorld().getTileEntity(new BlockPos(centerX, y, centerZ));
if(!(tile instanceof TileEntityTurbineRotor))
{
return false;
}
turbineHeight++;
turbines.remove(new Coord4D(centerX, y, centerZ, pointer.getWorld().provider.getDimension()));
}
//If any turbines were not processed, they're in the wrong place
if(turbines.size() > 0)
{
return false;
}
Coord4D startCoord = complex.offset(EnumFacing.UP);
if(startCoord.getTileEntity(pointer.getWorld()) instanceof TileEntityElectromagneticCoil)
{
structure.coils = new NodeCounter(new NodeChecker() {
@Override
public boolean isValid(Coord4D coord)
{
return coord.getTileEntity(pointer.getWorld()) instanceof TileEntityElectromagneticCoil;
}
}).calculate(startCoord);
}
if(coils.size() > structure.coils)
{
return false;
}
Coord4D turbineCoord = complex.offset(EnumFacing.DOWN);
TileEntity turbineTile = turbineCoord.getTileEntity(pointer.getWorld());
if(turbineTile instanceof TileEntityTurbineRotor)
{
structure.blades = ((TileEntityTurbineRotor)turbineTile).blades;
}
for(Coord4D coord : structure.locations)
{
if(coord.getTileEntity(pointer.getWorld()) instanceof TileEntityTurbineVent)
{
if(coord.yCoord >= complex.yCoord)
{
structure.vents++;
}
else {
return false;
}
}
}
structure.lowerVolume = structure.volLength*structure.volWidth*turbineHeight;
structure.complex = complex;
return true;
}
}
return false;
}
@Override
protected MultiblockCache<SynchronizedTurbineData> getNewCache()
{
return new TurbineCache();
}
@Override
protected SynchronizedTurbineData getNewStructure()
{
return new SynchronizedTurbineData();
}
@Override
protected MultiblockManager<SynchronizedTurbineData> getManager()
{
return MekanismGenerators.turbineManager;
}
@Override
protected void mergeCaches(List<ItemStack> rejectedItems, MultiblockCache<SynchronizedTurbineData> cache, MultiblockCache<SynchronizedTurbineData> merge)
{
if(((TurbineCache)cache).fluid == null)
{
((TurbineCache)cache).fluid = ((TurbineCache)merge).fluid;
}
else if(((TurbineCache)merge).fluid != null && ((TurbineCache)cache).fluid.isFluidEqual(((TurbineCache)merge).fluid))
{
((TurbineCache)cache).fluid.amount += ((TurbineCache)merge).fluid.amount;
}
((TurbineCache)cache).electricity += ((TurbineCache)merge).electricity;
((TurbineCache)cache).dumpMode = ((TurbineCache)merge).dumpMode;
}
@Override
protected void onFormed()
{
super.onFormed();
if(structureFound.fluidStored != null)
{
structureFound.fluidStored.amount = Math.min(structureFound.fluidStored.amount, structureFound.getFluidCapacity());
}
structureFound.electricityStored = Math.min(structureFound.electricityStored, structureFound.getEnergyCapacity());
}
}