blob: 0f152acc31e921b30aeb0e997584c90e6177fd44 [file] [log] [blame] [raw]
package mekanism.common.multiblock;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import mekanism.api.Coord4D;
import mekanism.common.Mekanism;
import mekanism.common.tank.DynamicTankCache;
import mekanism.common.tile.TileEntityDynamicTank;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraft.world.WorldSavedData;
import net.minecraftforge.common.util.Constants.NBT;
public class MultiblockManager
{
private static Set<MultiblockManager> managers = new HashSet<MultiblockManager>();
public static boolean loaded;
public DataHandler dataHandler;
public String name;
/** A map containing references to all dynamic tank inventory caches. */
public Map<Integer, DynamicTankCache> inventories = new HashMap<Integer, DynamicTankCache>();
public MultiblockManager(String s)
{
name = s;
managers.add(this);
}
public void createOrLoad(World world)
{
if(dataHandler == null)
{
dataHandler = (DataHandler)world.perWorldStorage.loadData(DataHandler.class, name);
if(dataHandler == null)
{
dataHandler = new DataHandler(name);
dataHandler.setManager(this);
world.perWorldStorage.setData(name, dataHandler);
}
else {
dataHandler.setManager(this);
dataHandler.syncManager();
}
}
}
/**
* Grabs an inventory from the world's caches, and removes all the world's references to it.
* @param world - world the cache is stored in
* @param id - inventory ID to pull
* @return correct Dynamic Tank inventory cache
*/
public DynamicTankCache pullInventory(World world, int id)
{
if(!loaded)
{
load(world);
}
DynamicTankCache toReturn = inventories.get(id);
inventories.remove(id);
dataHandler.markDirty();
return toReturn;
}
/**
* Updates a dynamic tank cache with the defined inventory ID with the parameterized values.
* @param inventoryID - inventory ID of the dynamic tank
* @param cache - cache of the dynamic tank
* @param tileEntity - dynamic tank TileEntity
*/
public void updateCache(TileEntityDynamicTank tileEntity)
{
if(!loaded)
{
load(tileEntity.getWorldObj());
}
if(!inventories.containsKey(tileEntity.structure.inventoryID))
{
DynamicTankCache cache = new DynamicTankCache();
cache.sync(tileEntity.structure);
cache.locations.add(Coord4D.get(tileEntity));
inventories.put(tileEntity.structure.inventoryID, cache);
return;
}
inventories.get(tileEntity.structure.inventoryID).sync(tileEntity.structure);
inventories.get(tileEntity.structure.inventoryID).locations.add(Coord4D.get(tileEntity));
dataHandler.markDirty();
}
/**
* Grabs a unique inventory ID for a dynamic tank.
* @return unique inventory ID
*/
public int getUniqueInventoryID()
{
int id = 0;
while(true)
{
for(Integer i : inventories.keySet())
{
if(id == i)
{
id++;
continue;
}
}
return id;
}
}
public static void tick(World world)
{
if(!loaded)
{
load(world);
}
for(MultiblockManager manager : managers)
{
ArrayList<Integer> idsToKill = new ArrayList<Integer>();
HashMap<Integer, HashSet<Coord4D>> tilesToKill = new HashMap<Integer, HashSet<Coord4D>>();
for(Map.Entry<Integer, DynamicTankCache> entry : manager.inventories.entrySet())
{
int inventoryID = entry.getKey();
for(Coord4D obj : entry.getValue().locations)
{
if(obj.dimensionId == world.provider.dimensionId && obj.exists(world))
{
TileEntity tileEntity = obj.getTileEntity(world);
if(!(tileEntity instanceof TileEntityDynamicTank) || (getStructureId(((TileEntityDynamicTank)tileEntity)) != -1 && getStructureId(((TileEntityDynamicTank)tileEntity)) != inventoryID))
{
if(!tilesToKill.containsKey(inventoryID))
{
tilesToKill.put(inventoryID, new HashSet<Coord4D>());
}
tilesToKill.get(inventoryID).add(obj);
}
}
}
if(entry.getValue().locations.isEmpty())
{
idsToKill.add(inventoryID);
}
}
for(Map.Entry<Integer, HashSet<Coord4D>> entry : tilesToKill.entrySet())
{
for(Coord4D obj : entry.getValue())
{
manager.inventories.get(entry.getKey()).locations.remove(obj);
manager.dataHandler.markDirty();
}
}
for(int inventoryID : idsToKill)
{
manager.inventories.remove(inventoryID);
manager.dataHandler.markDirty();
}
}
}
public static int getStructureId(TileEntityDynamicTank tile)
{
return tile.structure != null ? tile.structure.inventoryID : -1;
}
public int getInventoryId(TileEntityDynamicTank tile)
{
Coord4D coord = Coord4D.get(tile);
for(Map.Entry<Integer, DynamicTankCache> entry : inventories.entrySet())
{
if(entry.getValue().locations.contains(coord))
{
return entry.getKey();
}
}
return -1;
}
public static void load(World world)
{
loaded = true;
for(MultiblockManager manager : managers)
{
manager.createOrLoad(world);
}
}
public static void reset()
{
for(MultiblockManager manager : managers)
{
manager.inventories.clear();
manager.dataHandler = null;
}
loaded = false;
}
public static class DataHandler extends WorldSavedData
{
public MultiblockManager manager;
public Map<Integer, DynamicTankCache> loadedInventories;
public DataHandler(String tagName)
{
super(tagName);
}
public void setManager(MultiblockManager m)
{
manager = m;
}
public void syncManager()
{
if(loadedInventories != null)
{
manager.inventories = loadedInventories;
}
}
@Override
public void readFromNBT(NBTTagCompound nbtTags)
{
NBTTagList list = nbtTags.getTagList("invList", NBT.TAG_COMPOUND);
loadedInventories = new HashMap<Integer, DynamicTankCache>();
for(int i = 0; i < list.tagCount(); i++)
{
NBTTagCompound compound = list.getCompoundTagAt(i);
DynamicTankCache cache = new DynamicTankCache();
cache.load(compound);
NBTTagList coordsList = compound.getTagList("coordsList", NBT.TAG_COMPOUND);
for(int j = 0; j < coordsList.tagCount(); j++)
{
cache.locations.add(Coord4D.read(coordsList.getCompoundTagAt(j)));
}
loadedInventories.put(compound.getInteger("id"), cache);
}
}
@Override
public void writeToNBT(NBTTagCompound nbtTags)
{
NBTTagList list = new NBTTagList();
for(Map.Entry<Integer, DynamicTankCache> entry : manager.inventories.entrySet())
{
NBTTagCompound compound = new NBTTagCompound();
compound.setInteger("id", entry.getKey());
entry.getValue().save(compound);
NBTTagList coordsList = new NBTTagList();
for(Coord4D coord : entry.getValue().locations)
{
coordsList.appendTag(coord.write(new NBTTagCompound()));
}
compound.setTag("coordsList", coordsList);
list.appendTag(compound);
}
nbtTags.setTag("invList", list);
}
}
}