Added prefab classes for UpdateProtocol and ThreadMultiblockSparkle, still yet to get the Dynamic Tank to extend them
This commit is contained in:
parent
8cae029ed7
commit
7e6be317af
8 changed files with 475 additions and 17 deletions
|
@ -491,9 +491,9 @@ public class ClientProxy extends CommonProxy
|
|||
}
|
||||
|
||||
@Override
|
||||
public void doTankAnimation(TileEntityMultiblock<?> tileEntity)
|
||||
public void doAnimation(TileEntityMultiblock<?> tileEntity)
|
||||
{
|
||||
new ThreadTankSparkle(tileEntity).start();
|
||||
new ThreadMultiblockSparkle(tileEntity).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.Set;
|
|||
|
||||
import mekanism.api.Coord4D;
|
||||
import mekanism.api.MekanismConfig.general;
|
||||
import mekanism.common.multiblock.MultiblockManager;
|
||||
import mekanism.common.tile.TileEntityMultiblock;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -14,7 +15,7 @@ import cpw.mods.fml.relauncher.Side;
|
|||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class ThreadTankSparkle extends Thread
|
||||
public class ThreadMultiblockSparkle extends Thread
|
||||
{
|
||||
public TileEntityMultiblock<?> pointer;
|
||||
|
||||
|
@ -22,7 +23,7 @@ public class ThreadTankSparkle extends Thread
|
|||
|
||||
public Set<TileEntity> iteratedNodes = new HashSet<TileEntity>();
|
||||
|
||||
public ThreadTankSparkle(TileEntityMultiblock<?> tileEntity)
|
||||
public ThreadMultiblockSparkle(TileEntityMultiblock<?> tileEntity)
|
||||
{
|
||||
pointer = tileEntity;
|
||||
}
|
||||
|
@ -83,7 +84,7 @@ public class ThreadTankSparkle extends Thread
|
|||
{
|
||||
TileEntity tile = Coord4D.get(tileEntity).getFromSide(side).getTileEntity(pointer.getWorldObj());
|
||||
|
||||
if(tile instanceof TileEntityMultiblock && tile.getClass() == pointer.getClass() && !iteratedNodes.contains(tile))
|
||||
if(MultiblockManager.areEqual(tile, pointer) && !iteratedNodes.contains(tile))
|
||||
{
|
||||
loop((TileEntityMultiblock<?>)tile);
|
||||
}
|
|
@ -311,9 +311,9 @@ public class CommonProxy
|
|||
}
|
||||
|
||||
/**
|
||||
* Does the Dynamic Tank creation animation, starting from the rendering block.
|
||||
* Does the multiblock creation animation, starting from the rendering block.
|
||||
*/
|
||||
public void doTankAnimation(TileEntityMultiblock<?> tileEntity) {}
|
||||
public void doAnimation(TileEntityMultiblock<?> tileEntity) {}
|
||||
|
||||
/**
|
||||
* Get the actual interface for a GUI. Client-only.
|
||||
|
|
|
@ -363,7 +363,7 @@ public class TankUpdateProtocol
|
|||
/**
|
||||
* Runs the protocol and updates all tanks that make a part of the dynamic tank.
|
||||
*/
|
||||
public void updateTanks()
|
||||
public void doUpdate()
|
||||
{
|
||||
loopThrough(pointer);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import mekanism.api.Coord4D;
|
||||
import mekanism.common.tile.TileEntityDynamicTank;
|
||||
import mekanism.common.tile.TileEntityMultiblock;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
@ -155,7 +155,7 @@ public class MultiblockManager<T>
|
|||
{
|
||||
TileEntity tileEntity = obj.getTileEntity(world);
|
||||
|
||||
if(!(tileEntity instanceof TileEntityDynamicTank) || (getStructureId(((TileEntityDynamicTank)tileEntity)) != -1 && getStructureId(((TileEntityDynamicTank)tileEntity)) != inventoryID))
|
||||
if(!(tileEntity instanceof TileEntityMultiblock) || ((TileEntityMultiblock)tileEntity).getManager() != manager || (getStructureId(((TileEntityMultiblock<?>)tileEntity)) != -1 && getStructureId(((TileEntityMultiblock)tileEntity)) != inventoryID))
|
||||
{
|
||||
if(!tilesToKill.containsKey(inventoryID))
|
||||
{
|
||||
|
@ -190,12 +190,22 @@ public class MultiblockManager<T>
|
|||
}
|
||||
}
|
||||
|
||||
public static int getStructureId(TileEntityDynamicTank tile)
|
||||
public static int getStructureId(TileEntityMultiblock<?> tile)
|
||||
{
|
||||
return tile.structure != null ? tile.structure.inventoryID : -1;
|
||||
return tile.structure != null ? tile.getSynchronizedData().inventoryID : -1;
|
||||
}
|
||||
|
||||
public int getInventoryId(TileEntityDynamicTank tile)
|
||||
public static boolean areEqual(TileEntity tile1, TileEntity tile2)
|
||||
{
|
||||
if(!(tile1 instanceof TileEntityMultiblock) || !(tile2 instanceof TileEntityMultiblock))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((TileEntityMultiblock)tile1).getManager() == ((TileEntityMultiblock)tile2).getManager();
|
||||
}
|
||||
|
||||
public int getInventoryId(TileEntityMultiblock<T> tile)
|
||||
{
|
||||
Coord4D coord = Coord4D.get(tile);
|
||||
|
||||
|
|
447
src/main/java/mekanism/common/multiblock/UpdateProtocol.java
Normal file
447
src/main/java/mekanism/common/multiblock/UpdateProtocol.java
Normal file
|
@ -0,0 +1,447 @@
|
|||
package mekanism.common.multiblock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
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;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
public abstract class UpdateProtocol<T>
|
||||
{
|
||||
public static final int FLUID_PER_TANK = 16000;
|
||||
|
||||
/** The multiblock nodes that have already been iterated over. */
|
||||
public Set<TileEntityMultiblock<T>> iteratedNodes = new HashSet<TileEntityMultiblock<T>>();
|
||||
|
||||
/** The structures found, all connected by some nodes to the pointer. */
|
||||
public SynchronizedData<T> structureFound = null;
|
||||
|
||||
/** The original block the calculation is getting run from. */
|
||||
public TileEntityMultiblock<T> pointer;
|
||||
|
||||
public UpdateProtocol(TileEntityMultiblock<T> tileEntity)
|
||||
{
|
||||
pointer = tileEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively loops through each node connected to the given TileEntity.
|
||||
* @param tile - the TileEntity to loop over
|
||||
*/
|
||||
public void loopThrough(TileEntityMultiblock<T> 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<Coord4D> locations = new HashSet<Coord4D>();
|
||||
|
||||
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)
|
||||
{
|
||||
SynchronizedData<T> structure = getNewStructure();
|
||||
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);
|
||||
|
||||
onStructureCreated(structure, origX, origY, origZ, xmin, xmax, ymin, ymax, zmin, zmax);
|
||||
|
||||
if(structure.locations.contains(Coord4D.get(pointer)) && isCorrectCorner(Coord4D.get(tile), origX+xmin, origY+ymin, origZ+zmin))
|
||||
{
|
||||
structureFound = structure;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iteratedNodes.add(tile);
|
||||
|
||||
for(ForgeDirection side : ForgeDirection.VALID_DIRECTIONS)
|
||||
{
|
||||
TileEntity tileEntity = Coord4D.get(tile).getFromSide(side).getTileEntity(tile.getWorldObj());
|
||||
|
||||
if(MultiblockManager.areEqual(tileEntity, pointer))
|
||||
{
|
||||
if(!iteratedNodes.contains(tileEntity))
|
||||
{
|
||||
loopThrough((TileEntityMultiblock<T>)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)
|
||||
{
|
||||
TileEntity tile = pointer.getWorldObj().getTileEntity(x, y, z);
|
||||
|
||||
if(MultiblockManager.areEqual(tile, pointer))
|
||||
{
|
||||
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)
|
||||
{
|
||||
return pointer.getWorldObj().getBlock(x, y, z) == MekanismBlocks.BasicBlock && pointer.getWorldObj().getBlockMetadata(x, y, z) == 9;
|
||||
}
|
||||
|
||||
protected abstract MultiblockCache<T> getNewCache();
|
||||
|
||||
protected abstract SynchronizedData<T> getNewStructure();
|
||||
|
||||
protected abstract MultiblockManager<T> getManager();
|
||||
|
||||
protected abstract void mergeCaches(MultiblockCache<T> cache, MultiblockCache<T> merge);
|
||||
|
||||
protected void onFormed() {}
|
||||
|
||||
protected void onStructureCreated(SynchronizedData<T> structure, int origX, int origY, int origZ, int xmin, int xmax, int ymin, int ymax, int zmin, int zmax) {}
|
||||
|
||||
/**
|
||||
* Runs the protocol and updates all tanks that make a part of the dynamic tank.
|
||||
*/
|
||||
public void doUpdate()
|
||||
{
|
||||
loopThrough(pointer);
|
||||
|
||||
if(structureFound != null)
|
||||
{
|
||||
for(TileEntityMultiblock<T> tileEntity : iteratedNodes)
|
||||
{
|
||||
if(!structureFound.locations.contains(Coord4D.get(tileEntity)))
|
||||
{
|
||||
for(TileEntity tile : iteratedNodes)
|
||||
{
|
||||
((TileEntityMultiblock<T>)tileEntity).structure = null;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> idsFound = new ArrayList<Integer>();
|
||||
int idToUse = -1;
|
||||
|
||||
for(Coord4D obj : structureFound.locations)
|
||||
{
|
||||
TileEntityMultiblock<T> tileEntity = (TileEntityMultiblock<T>)obj.getTileEntity(pointer.getWorldObj());
|
||||
int id = getManager().getInventoryId(tileEntity);
|
||||
|
||||
if(id != -1)
|
||||
{
|
||||
idsFound.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
MultiblockCache<T> cache = getNewCache();
|
||||
List<ItemStack> rejectedItems = new ArrayList<ItemStack>();
|
||||
|
||||
if(!idsFound.isEmpty())
|
||||
{
|
||||
for(int id : idsFound)
|
||||
{
|
||||
if(Mekanism.tankManager.inventories.get(id) != null)
|
||||
{
|
||||
if(cache == null)
|
||||
{
|
||||
cache = (MultiblockCache<T>)Mekanism.tankManager.pullInventory(pointer.getWorldObj(), id);
|
||||
}
|
||||
else {
|
||||
mergeCaches(cache, (MultiblockCache<T>)getManager().pullInventory(pointer.getWorldObj(), id));
|
||||
}
|
||||
|
||||
idToUse = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
idToUse = Mekanism.tankManager.getUniqueInventoryID();
|
||||
}
|
||||
|
||||
//TODO someday: drop all items in rejectedItems
|
||||
|
||||
cache.apply((T)structureFound);
|
||||
|
||||
onFormed();
|
||||
|
||||
structureFound.inventoryID = idToUse;
|
||||
|
||||
for(Coord4D obj : structureFound.locations)
|
||||
{
|
||||
TileEntityMultiblock<T> tileEntity = (TileEntityMultiblock<T>)obj.getTileEntity(pointer.getWorldObj());
|
||||
|
||||
tileEntity.structure = (T)structureFound;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(TileEntity tileEntity : iteratedNodes)
|
||||
{
|
||||
((TileEntityMultiblock<T>)tileEntity).structure = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -256,7 +256,7 @@ public class TileEntityDynamicTank extends TileEntityMultiblock<SynchronizedTank
|
|||
}
|
||||
|
||||
@Override
|
||||
public SynchronizedTankData getNewStructure()
|
||||
protected SynchronizedTankData getNewStructure()
|
||||
{
|
||||
return new SynchronizedTankData();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public abstract class TileEntityMultiblock<T> extends TileEntityContainerBlock i
|
|||
{
|
||||
if(!prevStructure)
|
||||
{
|
||||
Mekanism.proxy.doTankAnimation(this);
|
||||
Mekanism.proxy.doAnimation(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ public abstract class TileEntityMultiblock<T> extends TileEntityContainerBlock i
|
|||
{
|
||||
if(!worldObj.isRemote && (structure == null || !getSynchronizedData().didTick))
|
||||
{
|
||||
new TankUpdateProtocol(this).updateTanks();
|
||||
new TankUpdateProtocol(this).doUpdate();
|
||||
|
||||
if(structure != null)
|
||||
{
|
||||
|
@ -149,7 +149,7 @@ public abstract class TileEntityMultiblock<T> extends TileEntityContainerBlock i
|
|||
|
||||
protected abstract T getNewStructure();
|
||||
|
||||
protected abstract MultiblockManager<T> getManager();
|
||||
public abstract MultiblockManager<T> getManager();
|
||||
|
||||
@Override
|
||||
public ArrayList getNetworkedData(ArrayList data)
|
||||
|
|
Loading…
Reference in a new issue