diff --git a/src/main/java/mekanism/common/content/tank/TankUpdateProtocol.java b/src/main/java/mekanism/common/content/tank/TankUpdateProtocol.java index 0e2b80b3d..c95e765ab 100644 --- a/src/main/java/mekanism/common/content/tank/TankUpdateProtocol.java +++ b/src/main/java/mekanism/common/content/tank/TankUpdateProtocol.java @@ -1,466 +1,98 @@ package mekanism.common.content.tank; -import java.util.ArrayList; -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.tank.SynchronizedTankData.ValveData; +import mekanism.common.multiblock.MultiblockCache; +import mekanism.common.multiblock.MultiblockManager; +import mekanism.common.multiblock.SynchronizedData; +import mekanism.common.multiblock.UpdateProtocol; import mekanism.common.tile.TileEntityDynamicTank; import mekanism.common.tile.TileEntityDynamicValve; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; -public class TankUpdateProtocol +public class TankUpdateProtocol extends UpdateProtocol { public static final int FLUID_PER_TANK = 16000; - /** The dynamic tank nodes that have already been iterated over. */ - public Set iteratedNodes = new HashSet(); - - /** The structures found, all connected by some nodes to the pointer. */ - public SynchronizedTankData structureFound = null; - - /** The original block the calculation is getting run from. */ - public TileEntity pointer; - - public TankUpdateProtocol(TileEntity tileEntity) + public TankUpdateProtocol(TileEntityDynamicTank tileEntity) { - pointer = tileEntity; + super(tileEntity); } - /** - * Recursively loops through each node connected to the given TileEntity. - * @param tile - the TileEntity to loop over - */ - public void loopThrough(TileEntity tile) - { - World worldObj = tile.getWorldObj(); - - int origX = tile.xCoord, origY = tile.yCoord, origZ = tile.zCoord; - - boolean isCorner = true; - boolean isHollow = true; - boolean rightBlocks = true; - boolean rightFrame = true; - - Set locations = new HashSet(); - - int xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0; - - int x = 0, y = 0, z = 0; - - int volume = 0; - - if((isViableNode(origX + 1, origY, origZ) && isViableNode(origX - 1, origY, origZ)) || - (isViableNode(origX, origY + 1, origZ) && isViableNode(origX, origY - 1, origZ)) || - (isViableNode(origX, origY, origZ + 1) && isViableNode(origX, origY, origZ - 1))) - { - isCorner = false; - } - - if(isCorner) - { - if(isViableNode(origX+1, origY, origZ)) - { - xmin = 0; - - while(isViableNode(origX+x+1, origY, origZ)) - { - x++; - } - - xmax = x; - } - else { - xmax = 0; - - while(isViableNode(origX+x-1, origY, origZ)) - { - x--; - } - - xmin = x; - } - - if(isViableNode(origX, origY+1, origZ)) - { - ymin = 0; - - while(isViableNode(origX, origY+y+1, origZ)) - { - y++; - } - - ymax = y; - } - else { - ymax = 0; - - while(isViableNode(origX, origY+y-1 ,origZ)) - { - y--; - } - - ymin = y; - } - - if(isViableNode(origX, origY, origZ+1)) - { - zmin = 0; - - while(isViableNode(origX, origY, origZ+z+1)) - { - z++; - } - - zmax = z; - } - else { - zmax = 0; - - while(isViableNode(origX, origY, origZ+z-1)) - { - z--; - } - - zmin = z; - } - - for(x = xmin; x <= xmax; x++) - { - for(y = ymin; y <= ymax; y++) - { - for(z = zmin; z <= zmax; z++) - { - if(x == xmin || x == xmax || y == ymin || y == ymax || z == zmin || z == zmax) - { - if(!isViableNode(origX+x, origY+y, origZ+z)) - { - rightBlocks = false; - break; - } - else if(isFrame(Coord4D.get(tile).translate(x, y, z), origX+xmin, origX+xmax, origY+ymin, origY+ymax, origZ+zmin, origZ+zmax) && !isValidFrame(origX+x, origY+y, origZ+z)) - { - rightFrame = false; - break; - } - else { - locations.add(Coord4D.get(tile).translate(x, y, z)); - } - } - else { - if(!isAir(origX+x, origY+y, origZ+z)) - { - isHollow = false; - break; - } - - volume++; - } - } - if(!isHollow || !rightBlocks || !rightFrame) - { - break; - } - } - if(!isHollow || !rightBlocks || !rightFrame) - { - break; - } - } - } - - volume += locations.size(); - - if(volume >= 27 && volume <= 5832 && locations.size() >= 26) - { - if(rightBlocks && rightFrame && isHollow && isCorner) - { - SynchronizedTankData structure = new SynchronizedTankData(); - structure.locations = locations; - structure.volLength = Math.abs(xmax-xmin)+1; - structure.volHeight = Math.abs(ymax-ymin)+1; - structure.volWidth = Math.abs(zmax-zmin)+1; - structure.volume = volume; - structure.renderLocation = Coord4D.get(tile).translate(0, 1, 0); - - for(Coord4D obj : structure.locations) - { - if(obj.getTileEntity(pointer.getWorldObj()) instanceof TileEntityDynamicValve) - { - 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); - } - } - - if(structure.locations.contains(Coord4D.get(pointer)) && isCorrectCorner(Coord4D.get(tile), origX+xmin, origY+ymin, origZ+zmin)) - { - structureFound = structure; - return; - } - } - } - - iteratedNodes.add((TileEntityDynamicTank)tile); - - for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) - { - TileEntity tileEntity = Coord4D.get(tile).getFromSide(side).getTileEntity(tile.getWorldObj()); - - if(tileEntity instanceof TileEntityDynamicTank) - { - if(!iteratedNodes.contains(tileEntity)) - { - loopThrough(tileEntity); - } - } - } - } - - public ForgeDirection getSide(Coord4D obj, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax) - { - if(obj.xCoord == xmin) - { - return ForgeDirection.WEST; - } - else if(obj.xCoord == xmax) - { - return ForgeDirection.EAST; - } - else if(obj.yCoord == ymin) - { - return ForgeDirection.DOWN; - } - else if(obj.yCoord == ymax) - { - return ForgeDirection.UP; - } - else if(obj.zCoord == zmin) - { - return ForgeDirection.NORTH; - } - else if(obj.zCoord == zmax) - { - return ForgeDirection.SOUTH; - } - - return ForgeDirection.UNKNOWN; - } - - /** - * Whether or not the block at the specified location is an air block. - * @param x - x coordinate - * @param y - y coordinate - * @param z - z coordinate - * @return - */ - private boolean isAir(int x, int y, int z) - { - return pointer.getWorldObj().isAirBlock(x, y, z); - } - - /** - * Whether or not the block at the specified location is a viable node for a dynamic tank. - * @param x - x coordinate - * @param y - y coordinate - * @param z - z coordinate - * @return - */ - private boolean isViableNode(int x, int y, int z) - { - if(pointer.getWorldObj().getTileEntity(x, y, z) instanceof TileEntityDynamicTank) - { - return true; - } - - return false; - } - - /** - * If the block at the specified location is on the minimum of all angles of this dynamic tank, and the one to use for the - * actual calculation. - * @param obj - location to check - * @param xmin - minimum x value - * @param ymin - minimum y value - * @param zmin - minimum z value - * @return - */ - private boolean isCorrectCorner(Coord4D obj, int xmin, int ymin, int zmin) - { - if(obj.xCoord == xmin && obj.yCoord == ymin && obj.zCoord == zmin) - { - return true; - } - - return false; - } - - /** - * Whether or not the block at the specified location is considered a frame on the dynamic tank. - * @param obj - location to check - * @param xmin - minimum x value - * @param xmax - maximum x value - * @param ymin - minimum y value - * @param ymax - maximum y value - * @param zmin - minimum z value - * @param zmax - maximum z value - * @return - */ - private boolean isFrame(Coord4D obj, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax) - { - if(obj.xCoord == xmin && obj.yCoord == ymin) - return true; - if(obj.xCoord == xmax && obj.yCoord == ymin) - return true; - if(obj.xCoord == xmin && obj.yCoord == ymax) - return true; - if(obj.xCoord == xmax && obj.yCoord == ymax) - return true; - - if(obj.xCoord == xmin && obj.zCoord == zmin) - return true; - if(obj.xCoord == xmax && obj.zCoord == zmin) - return true; - if(obj.xCoord == xmin && obj.zCoord == zmax) - return true; - if(obj.xCoord == xmax && obj.zCoord == zmax) - return true; - - if(obj.yCoord == ymin && obj.zCoord == zmin) - return true; - if(obj.yCoord == ymax && obj.zCoord == zmin) - return true; - if(obj.yCoord == ymin && obj.zCoord == zmax) - return true; - if(obj.yCoord == ymax && obj.zCoord == zmax) - return true; - - return false; - } - - /** - * Whether or not the block at the specified location serves as a frame for a dynamic tank. - * @param x - x coordinate - * @param y - y coordinate - * @param z - z coordinate - * @return - */ - private boolean isValidFrame(int x, int y, int z) + @Override + protected boolean isValidFrame(int x, int y, int z) { return pointer.getWorldObj().getBlock(x, y, z) == MekanismBlocks.BasicBlock && pointer.getWorldObj().getBlockMetadata(x, y, z) == 9; } - - /** - * Runs the protocol and updates all tanks that make a part of the dynamic tank. - */ - public void doUpdate() + + @Override + protected DynamicTankCache getNewCache() { - loopThrough(pointer); - - if(structureFound != null) + return new DynamicTankCache(); + } + + @Override + protected SynchronizedTankData getNewStructure() + { + return new SynchronizedTankData(); + } + + @Override + protected MultiblockManager getManager() + { + return Mekanism.tankManager; + } + + @Override + protected void mergeCaches(List rejectedItems, MultiblockCache cache, MultiblockCache merge) + { + if(((DynamicTankCache)cache).fluid == null) { - for(TileEntityDynamicTank tileEntity : iteratedNodes) - { - if(!structureFound.locations.contains(Coord4D.get(tileEntity))) - { - for(TileEntity tile : iteratedNodes) - { - ((TileEntityDynamicTank)tileEntity).structure = null; - } - - return; - } - } - - List idsFound = new ArrayList(); - int idToUse = -1; - - for(Coord4D obj : structureFound.locations) - { - TileEntityDynamicTank tileEntity = (TileEntityDynamicTank)obj.getTileEntity(pointer.getWorldObj()); - int id = Mekanism.tankManager.getInventoryId(tileEntity); - - if(id != -1) - { - idsFound.add(id); - } - } - - DynamicTankCache cache = new DynamicTankCache(); - List rejectedItems = new ArrayList(); - - if(!idsFound.isEmpty()) - { - for(int id : idsFound) - { - if(Mekanism.tankManager.inventories.get(id) != null) - { - if(cache == null) - { - cache = (DynamicTankCache)Mekanism.tankManager.pullInventory(pointer.getWorldObj(), id); - } - else { - DynamicTankCache merge = (DynamicTankCache)Mekanism.tankManager.pullInventory(pointer.getWorldObj(), id); - - if(cache.fluid == null) - { - cache.fluid = merge.fluid; - } - else if(merge.fluid != null && cache.fluid.isFluidEqual(merge.fluid)) - { - cache.fluid.amount += merge.fluid.amount; - } - - List rejects = StackUtils.getMergeRejects(cache.inventory, merge.inventory); - - if(!rejects.isEmpty()) - { - rejectedItems.addAll(rejects); - } - - StackUtils.merge(cache.inventory, merge.inventory); - } - - idToUse = id; - } - } - } - else { - idToUse = Mekanism.tankManager.getUniqueInventoryID(); - } - - //TODO someday: drop all items in rejectedItems - - cache.apply(structureFound); - - if(structureFound.fluidStored != null) - { - structureFound.fluidStored.amount = Math.min(structureFound.fluidStored.amount, structureFound.volume*FLUID_PER_TANK); - } - - structureFound.inventoryID = idToUse; - - for(Coord4D obj : structureFound.locations) - { - TileEntityDynamicTank tileEntity = (TileEntityDynamicTank)obj.getTileEntity(pointer.getWorldObj()); - - tileEntity.structure = structureFound; - } + ((DynamicTankCache)cache).fluid = ((DynamicTankCache)merge).fluid; } - else { - for(TileEntity tileEntity : iteratedNodes) + else if(((DynamicTankCache)merge).fluid != null && ((DynamicTankCache)cache).fluid.isFluidEqual(((DynamicTankCache)merge).fluid)) + { + ((DynamicTankCache)cache).fluid.amount += ((DynamicTankCache)merge).fluid.amount; + } + + List rejects = StackUtils.getMergeRejects(((DynamicTankCache)cache).inventory, ((DynamicTankCache)merge).inventory); + + if(!rejects.isEmpty()) + { + rejectedItems.addAll(rejects); + } + + StackUtils.merge(((DynamicTankCache)cache).inventory, ((DynamicTankCache)merge).inventory); + } + + @Override + protected void onFormed() + { + if(((SynchronizedTankData)structureFound).fluidStored != null) + { + ((SynchronizedTankData)structureFound).fluidStored.amount = Math.min(((SynchronizedTankData)structureFound).fluidStored.amount, structureFound.volume*FLUID_PER_TANK); + } + } + + @Override + protected void onStructureCreated(SynchronizedData 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.getWorldObj()) instanceof TileEntityDynamicValve) { - ((TileEntityDynamicTank)tileEntity).structure = null; + ValveData data = new ValveData(); + data.location = obj; + data.side = getSide(obj, origX+xmin, origX+xmax, origY+ymin, origY+ymax, origZ+zmin, origZ+zmax); + + ((SynchronizedTankData)structure).valves.add(data); } } } diff --git a/src/main/java/mekanism/common/multiblock/UpdateProtocol.java b/src/main/java/mekanism/common/multiblock/UpdateProtocol.java index c3996adab..3cc49854f 100644 --- a/src/main/java/mekanism/common/multiblock/UpdateProtocol.java +++ b/src/main/java/mekanism/common/multiblock/UpdateProtocol.java @@ -7,7 +7,6 @@ import java.util.Set; import mekanism.api.Coord4D; import mekanism.common.Mekanism; -import mekanism.common.MekanismBlocks; import mekanism.common.tile.TileEntityMultiblock; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; @@ -16,8 +15,6 @@ import net.minecraftforge.common.util.ForgeDirection; public abstract class UpdateProtocol { - public static final int FLUID_PER_TANK = 16000; - /** The multiblock nodes that have already been iterated over. */ public Set> iteratedNodes = new HashSet>(); @@ -344,10 +341,7 @@ public abstract class UpdateProtocol * @param z - z coordinate * @return */ - private boolean isValidFrame(int x, int y, int z) - { - return pointer.getWorldObj().getBlock(x, y, z) == MekanismBlocks.BasicBlock && pointer.getWorldObj().getBlockMetadata(x, y, z) == 9; - } + protected abstract boolean isValidFrame(int x, int y, int z); protected abstract MultiblockCache getNewCache(); @@ -355,7 +349,7 @@ public abstract class UpdateProtocol protected abstract MultiblockManager getManager(); - protected abstract void mergeCaches(MultiblockCache cache, MultiblockCache merge); + protected abstract void mergeCaches(List rejectedItems, MultiblockCache cache, MultiblockCache merge); protected void onFormed() {} @@ -411,7 +405,7 @@ public abstract class UpdateProtocol cache = (MultiblockCache)Mekanism.tankManager.pullInventory(pointer.getWorldObj(), id); } else { - mergeCaches(cache, (MultiblockCache)getManager().pullInventory(pointer.getWorldObj(), id)); + mergeCaches(rejectedItems, cache, (MultiblockCache)getManager().pullInventory(pointer.getWorldObj(), id)); } idToUse = id; diff --git a/src/main/java/mekanism/common/tile/TileEntityDynamicTank.java b/src/main/java/mekanism/common/tile/TileEntityDynamicTank.java index eba28ed03..6723f9d86 100644 --- a/src/main/java/mekanism/common/tile/TileEntityDynamicTank.java +++ b/src/main/java/mekanism/common/tile/TileEntityDynamicTank.java @@ -261,6 +261,12 @@ public class TileEntityDynamicTank extends TileEntityMultiblock getManager() { diff --git a/src/main/java/mekanism/common/tile/TileEntityMultiblock.java b/src/main/java/mekanism/common/tile/TileEntityMultiblock.java index b29525b44..34f39d8bb 100644 --- a/src/main/java/mekanism/common/tile/TileEntityMultiblock.java +++ b/src/main/java/mekanism/common/tile/TileEntityMultiblock.java @@ -11,6 +11,7 @@ import mekanism.common.content.tank.TankUpdateProtocol; import mekanism.common.multiblock.IMultiblock; import mekanism.common.multiblock.MultiblockManager; import mekanism.common.multiblock.SynchronizedData; +import mekanism.common.multiblock.UpdateProtocol; import mekanism.common.network.PacketTileEntity.TileEntityMessage; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -122,7 +123,7 @@ public abstract class TileEntityMultiblock extends TileEntityContainerBlock i { if(!worldObj.isRemote && (structure == null || !getSynchronizedData().didTick)) { - new TankUpdateProtocol(this).doUpdate(); + getProtocol().doUpdate(); if(structure != null) { @@ -149,6 +150,8 @@ public abstract class TileEntityMultiblock extends TileEntityContainerBlock i protected abstract T getNewStructure(); + protected abstract UpdateProtocol getProtocol(); + public abstract MultiblockManager getManager(); @Override