Add multiblock creation algorithm for boiler

This commit is contained in:
aidancbrady 2016-02-11 19:35:02 -05:00
parent e23409e2a5
commit 3a2eeac52d
4 changed files with 203 additions and 46 deletions

View file

@ -1,19 +1,22 @@
package mekanism.common.content.boiler;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mekanism.api.Coord4D;
import mekanism.api.util.StackUtils;
import mekanism.common.Mekanism;
import mekanism.common.MekanismBlocks;
import mekanism.common.content.boiler.SynchronizedBoilerData.ValveData;
import mekanism.common.multiblock.MultiblockCache;
import mekanism.common.multiblock.MultiblockManager;
import mekanism.common.multiblock.UpdateProtocol;
import mekanism.common.tile.TileEntityBoilerCasing;
import mekanism.common.tile.TileEntityBoilerValve;
import mekanism.common.tile.TileEntityPressureDisperser;
import mekanism.common.tile.TileEntitySuperheatingElement;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
public class BoilerUpdateProtocol extends UpdateProtocol<SynchronizedBoilerData>
{
@ -28,7 +31,137 @@ public class BoilerUpdateProtocol extends UpdateProtocol<SynchronizedBoilerData>
@Override
protected boolean isValidFrame(int x, int y, int z)
{
return pointer.getWorldObj().getBlock(x, y, z) == MekanismBlocks.BasicBlock2 && pointer.getWorldObj().getBlockMetadata(x, y, z) == 1;
return false;
//return BasicType.get(pointer.getWorldObj().getBlock(x, y, z), pointer.getWorldObj().getBlockMetadata(x, y, z)) == BasicType.BOILER_CASING;
}
@Override
protected boolean isValidInnerNode(int x, int y, int z)
{
if(super.isValidInnerNode(x, y, z))
{
return true;
}
TileEntity tile = pointer.getWorldObj().getTileEntity(x, y, z);
return tile instanceof TileEntityPressureDisperser || tile instanceof TileEntitySuperheatingElement;
}
@Override
protected boolean canForm(SynchronizedBoilerData structure)
{
if(structure.volHeight >= 3)
{
Set<Coord4D> dispersers = new HashSet<Coord4D>();
Set<Coord4D> elements = new HashSet<Coord4D>();
for(Coord4D coord : innerNodes)
{
TileEntity tile = coord.getTileEntity(pointer.getWorldObj());
if(tile instanceof TileEntityPressureDisperser)
{
dispersers.add(coord);
}
else if(tile instanceof TileEntitySuperheatingElement)
{
elements.add(coord);
}
}
int prevDispersers = dispersers.size();
//Ensure at least one disperser exists
if(dispersers.size() == 0)
{
return false;
}
//Find a single disperser contained within this multiblock
Coord4D initDisperser = dispersers.iterator().next();
//Ensure that a full horizontal plane of dispersers exist, surrounding the found disperser
for(int x = structure.renderLocation.xCoord+1; x < structure.renderLocation.xCoord+structure.volLength-1; x++)
{
for(int z = structure.renderLocation.zCoord+1; z < structure.renderLocation.zCoord+structure.volWidth-1; z++)
{
TileEntity tile = pointer.getWorldObj().getTileEntity(x, initDisperser.yCoord, z);
if(!(tile instanceof TileEntityPressureDisperser))
{
return false;
}
dispersers.remove(new Coord4D(x, initDisperser.yCoord, z, pointer.getWorldObj().provider.dimensionId));
}
}
//If there are more dispersers than those on the plane found, the structure is invalid
if(dispersers.size() > 0)
{
return false;
}
structure.superheatingElements = new NodeCounter(new NodeChecker() {
@Override
public boolean isValid(Coord4D coord)
{
return coord.getTileEntity(pointer.getWorldObj()) instanceof TileEntitySuperheatingElement;
}
}).calculate(elements.iterator().next());
if(elements.size() > structure.superheatingElements)
{
return false;
}
Coord4D initAir = null;
int totalAir = 0;
//Find the first available block in the structure for water storage (including casings)
for(int x = structure.renderLocation.xCoord; x < structure.renderLocation.xCoord+structure.volLength; x++)
{
for(int y = structure.renderLocation.yCoord; y < initDisperser.yCoord; y++)
{
for(int z = structure.renderLocation.zCoord; z < structure.renderLocation.zCoord+structure.volWidth; z++)
{
if(pointer.getWorldObj().isAirBlock(x, y, z) || isViableNode(x, y, z))
{
initAir = new Coord4D(x, y, z, pointer.getWorldObj().provider.dimensionId);
totalAir++;
}
}
}
}
//Some air must exist for the structure to be valid
if(initAir == null)
{
return false;
}
structure.waterVolume = new NodeCounter(new NodeChecker() {
@Override
public boolean isValid(Coord4D coord)
{
return coord.yCoord < initDisperser.yCoord && (coord.isAirBlock(pointer.getWorldObj()) || isViableNode(coord.xCoord, coord.yCoord, coord.zCoord));
}
}).calculate(initAir);
//Make sure all air blocks are connected
if(totalAir > structure.waterVolume)
{
return false;
}
int steamHeight = (structure.renderLocation.yCoord+structure.volHeight)-initDisperser.yCoord;
structure.steamVolume = structure.volWidth*structure.volLength*steamHeight;
return true;
}
return false;
}
@Override
@ -85,11 +218,12 @@ public class BoilerUpdateProtocol extends UpdateProtocol<SynchronizedBoilerData>
{
if((structureFound).waterStored != null)
{
(structureFound).waterStored.amount = Math.min((structureFound).waterStored.amount, structureFound.volume*WATER_PER_TANK);
(structureFound).waterStored.amount = Math.min((structureFound).waterStored.amount, structureFound.waterVolume*WATER_PER_TANK);
}
if((structureFound).steamStored != null)
{
(structureFound).steamStored.amount = Math.min((structureFound).waterStored.amount, structureFound.volume*STEAM_PER_TANK);
(structureFound).steamStored.amount = Math.min((structureFound).steamStored.amount, structureFound.steamVolume*STEAM_PER_TANK);
}
}

View file

@ -7,7 +7,6 @@ import mekanism.api.Coord4D;
import mekanism.api.IHeatTransfer;
import mekanism.common.multiblock.SynchronizedData;
import mekanism.common.util.FluidContainerUtils.ContainerEditMode;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidRegistry;
@ -27,6 +26,12 @@ public class SynchronizedBoilerData extends SynchronizedData<SynchronizedBoilerD
public double enthalpyOfVaporization = 10;
public int superheatingElements;
public int waterVolume;
public int steamVolume;
public ContainerEditMode editMode = ContainerEditMode.BOTH;
public ItemStack[] inventory = new ItemStack[2];

View file

@ -289,7 +289,7 @@ public abstract class UpdateProtocol<T extends SynchronizedData<T>>
* @param z - z coordinate
* @return
*/
private boolean isViableNode(int x, int y, int z)
public boolean isViableNode(int x, int y, int z)
{
TileEntity tile = pointer.getWorldObj().getTileEntity(x, y, z);
@ -534,4 +534,48 @@ public abstract class UpdateProtocol<T extends SynchronizedData<T>>
}
}
}
public class NodeCounter
{
public Set<Coord4D> iterated = new HashSet<Coord4D>();
public NodeChecker checker;
public NodeCounter(NodeChecker c)
{
checker = c;
}
public void loop(Coord4D pos)
{
iterated.add(pos);
for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS)
{
Coord4D coord = pos.getFromSide(side);
if(!iterated.contains(coord) && checker.isValid(coord))
{
loop(coord);
}
}
}
public int calculate(Coord4D coord)
{
if(!checker.isValid(coord))
{
return 0;
}
loop(coord);
return iterated.size();
}
}
public static interface NodeChecker
{
public boolean isValid(Coord4D coord);
}
}

View file

@ -183,11 +183,21 @@ public class TurbineUpdateProtocol extends UpdateProtocol<SynchronizedTurbineDat
}
Coord4D startCoord = complex.getFromSide(ForgeDirection.UP);
TileEntity startTile = startCoord.getTileEntity(pointer.getWorldObj());
if(startTile instanceof TileEntityElectromagneticCoil)
if(startCoord.getTileEntity(pointer.getWorldObj()) instanceof TileEntityElectromagneticCoil)
{
structure.coils = new CoilCounter().calculate((TileEntityElectromagneticCoil)startTile);
structure.coils = new NodeCounter(new NodeChecker() {
@Override
public boolean isValid(Coord4D coord)
{
return coord.getTileEntity(pointer.getWorldObj()) instanceof TileEntityElectromagneticCoil;
}
}).calculate(startCoord);
}
if(coils.size() > structure.coils)
{
return false;
}
Coord4D turbineCoord = complex.getFromSide(ForgeDirection.DOWN);
@ -198,11 +208,6 @@ public class TurbineUpdateProtocol extends UpdateProtocol<SynchronizedTurbineDat
structure.blades = ((TileEntityTurbineRotor)turbineTile).blades;
}
if(coils.size() > structure.coils)
{
return false;
}
for(Coord4D coord : structure.locations)
{
if(coord.getTileEntity(pointer.getWorldObj()) instanceof TileEntityTurbineVent)
@ -272,35 +277,4 @@ public class TurbineUpdateProtocol extends UpdateProtocol<SynchronizedTurbineDat
((TileEntityRotationalComplex)structureFound.complex.getTileEntity(pointer.getWorldObj())).setMultiblock(structureFound.inventoryID);
}
public class CoilCounter
{
public Set<Coord4D> iterated = new HashSet<Coord4D>();
public void loop(Coord4D pos)
{
iterated.add(pos);
for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS)
{
Coord4D coord = pos.getFromSide(side);
TileEntity tile = coord.getTileEntity(pointer.getWorldObj());
if(!iterated.contains(coord))
{
if(tile instanceof TileEntityElectromagneticCoil)
{
loop(coord);
}
}
}
}
public int calculate(TileEntityElectromagneticCoil tileEntity)
{
loop(Coord4D.get(tileEntity));
return iterated.size();
}
}
}