| package mekanism.common.content.boiler; |
| |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import mekanism.api.Coord4D; |
| import mekanism.common.Mekanism; |
| import mekanism.common.block.states.BlockStateBasic.BasicBlockType; |
| import mekanism.common.content.tank.SynchronizedTankData.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; |
| import net.minecraft.util.math.BlockPos; |
| |
| public class BoilerUpdateProtocol extends UpdateProtocol<SynchronizedBoilerData> |
| { |
| public static final int WATER_PER_TANK = 16000; |
| public static final int STEAM_PER_TANK = 160000; |
| |
| public BoilerUpdateProtocol(TileEntityBoilerCasing tileEntity) |
| { |
| super(tileEntity); |
| } |
| |
| @Override |
| protected boolean isValidFrame(int x, int y, int z) |
| { |
| return BasicBlockType.get(pointer.getWorld().getBlockState(new BlockPos(x, y, z))) == BasicBlockType.BOILER_CASING; |
| } |
| |
| @Override |
| protected boolean isValidInnerNode(int x, int y, int z) |
| { |
| if(super.isValidInnerNode(x, y, z)) |
| { |
| return true; |
| } |
| |
| TileEntity tile = new Coord4D(x, y, z, pointer.getWorld().provider.getDimensionId()).getTileEntity(pointer.getWorld()); |
| |
| 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.getWorld()); |
| |
| if(tile instanceof TileEntityPressureDisperser) |
| { |
| dispersers.add(coord); |
| } |
| else if(tile instanceof TileEntitySuperheatingElement) |
| { |
| structure.internalLocations.add(coord); |
| 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 |
| final Coord4D initDisperser = dispersers.iterator().next(); |
| |
| //Ensure that a full horizontal plane of dispersers exist, surrounding the found disperser |
| Coord4D pos = new Coord4D(structure.renderLocation.xCoord, initDisperser.yCoord, structure.renderLocation.zCoord, pointer.getWorld().provider.getDimensionId()); |
| for(int x = 1; x < structure.volLength-1; x++) |
| { |
| for(int z = 1; z < structure.volWidth-1; z++) |
| { |
| Coord4D coord4D = pos.translate(x, 0, z); |
| TileEntity tile = coord4D.getTileEntity(pointer.getWorld()); |
| |
| if(!(tile instanceof TileEntityPressureDisperser)) |
| { |
| return false; |
| } |
| |
| dispersers.remove(coord4D); |
| } |
| } |
| |
| //If there are more dispersers than those on the plane found, the structure is invalid |
| if(dispersers.size() > 0) |
| { |
| return false; |
| } |
| |
| if(elements.size() > 0) |
| { |
| structure.superheatingElements = new NodeCounter(new NodeChecker() { |
| @Override |
| public boolean isValid(Coord4D coord) |
| { |
| return coord.getTileEntity(pointer.getWorld()) 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.getWorld().isAirBlock(new BlockPos(x, y, z)) || isViableNode(x, y, z)) |
| { |
| initAir = new Coord4D(x, y, z, pointer.getWorld().provider.getDimensionId()); |
| totalAir++; |
| } |
| } |
| } |
| } |
| |
| //Some air must exist for the structure to be valid |
| if(initAir == null) |
| { |
| return false; |
| } |
| |
| //Gradle build requires these fields to be final |
| final Coord4D renderLocation = structure.renderLocation; |
| final int volLength = structure.volLength; |
| final int volWidth = structure.volWidth; |
| |
| structure.waterVolume = new NodeCounter(new NodeChecker() { |
| @Override |
| public final boolean isValid(Coord4D coord) |
| { |
| return coord.yCoord >= renderLocation.yCoord-1 && coord.yCoord < initDisperser.yCoord && |
| coord.xCoord >= renderLocation.xCoord && coord.xCoord < renderLocation.xCoord+volLength && |
| coord.zCoord >= renderLocation.zCoord && coord.zCoord < renderLocation.zCoord+volWidth && |
| (coord.isAirBlock(pointer.getWorld()) || isViableNode(coord.getPos())); |
| } |
| }).calculate(initAir); |
| |
| //Make sure all air blocks are connected |
| if(totalAir > structure.waterVolume) |
| { |
| return false; |
| } |
| |
| int steamHeight = (structure.renderLocation.yCoord+structure.volHeight-2)-initDisperser.yCoord; |
| structure.steamVolume = structure.volWidth*structure.volLength*steamHeight; |
| |
| structure.upperRenderLocation = new Coord4D(structure.renderLocation.xCoord, initDisperser.yCoord+1, structure.renderLocation.zCoord); |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| @Override |
| protected BoilerCache getNewCache() |
| { |
| return new BoilerCache(); |
| } |
| |
| @Override |
| protected SynchronizedBoilerData getNewStructure() |
| { |
| return new SynchronizedBoilerData(); |
| } |
| |
| @Override |
| protected MultiblockManager<SynchronizedBoilerData> getManager() |
| { |
| return Mekanism.boilerManager; |
| } |
| |
| @Override |
| protected void mergeCaches(List<ItemStack> rejectedItems, MultiblockCache<SynchronizedBoilerData> cache, MultiblockCache<SynchronizedBoilerData> merge) |
| { |
| if(((BoilerCache)cache).water == null) |
| { |
| ((BoilerCache)cache).water = ((BoilerCache)merge).water; |
| } |
| else if(((BoilerCache)merge).water != null && ((BoilerCache)cache).water.isFluidEqual(((BoilerCache)merge).water)) |
| { |
| ((BoilerCache)cache).water.amount += ((BoilerCache)merge).water.amount; |
| } |
| |
| if(((BoilerCache)cache).steam == null) |
| { |
| ((BoilerCache)cache).steam = ((BoilerCache)merge).steam; |
| } |
| else if(((BoilerCache)merge).steam != null && ((BoilerCache)cache).steam.isFluidEqual(((BoilerCache)merge).steam)) |
| { |
| ((BoilerCache)cache).steam.amount += ((BoilerCache)merge).steam.amount; |
| } |
| |
| ((BoilerCache)cache).temperature = Math.max(((BoilerCache)cache).temperature, ((BoilerCache)merge).temperature); |
| } |
| |
| @Override |
| protected void onFormed() |
| { |
| super.onFormed(); |
| |
| if((structureFound).waterStored != null) |
| { |
| (structureFound).waterStored.amount = Math.min((structureFound).waterStored.amount, structureFound.waterVolume*WATER_PER_TANK); |
| } |
| |
| if((structureFound).steamStored != null) |
| { |
| (structureFound).steamStored.amount = Math.min((structureFound).steamStored.amount, structureFound.steamVolume*STEAM_PER_TANK); |
| } |
| } |
| |
| @Override |
| protected void onStructureCreated(SynchronizedBoilerData structure, int origX, int origY, int origZ, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax) |
| { |
| for(Coord4D obj : structure.locations) |
| { |
| if(obj.getTileEntity(pointer.getWorld()) instanceof TileEntityBoilerValve) |
| { |
| ValveData data = new ValveData(); |
| data.location = obj; |
| data.side = getSide(obj, origX+xmin, origX+xmax, origY+ymin, origY+ymax, origZ+zmin, origZ+zmax); |
| |
| structure.valves.add(data); |
| } |
| } |
| } |
| } |