package com.dynious.biota.biosystem; import com.dynious.biota.Biota; import gnu.trove.map.TObjectFloatMap; import gnu.trove.map.hash.TObjectFloatHashMap; import gnu.trove.procedure.TObjectFloatProcedure; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import java.util.*; public class BioSystemHandler { private static WeakHashMap<World, BioSystemHandler> handlers = new WeakHashMap<World, BioSystemHandler>(); private Map<Chunk, BioSystem> bioSystemMap = new WeakHashMap<Chunk, BioSystem>(); public TObjectFloatMap<ChunkCoords> biomassChangeMap = new TObjectFloatHashMap<ChunkCoords>(); public TObjectFloatMap<ChunkCoords> nitrogenFixationChangeMap = new TObjectFloatHashMap<ChunkCoords>(); public List<BioSystem> stabilizeList = new ArrayList<BioSystem>(); public static void onChunkLoaded(World world, Chunk chunk, NBTTagCompound compound) { assert chunk != null; BioSystemHandler handler; if (!handlers.containsKey(world)) { handler = new BioSystemHandler(); handlers.put(world, handler); } else handler = handlers.get(world); BioSystem bioSystem; if (compound == null || compound.hasNoTags()) { if (handler.bioSystemMap.containsKey(chunk)) { //We already have this chunk loaded, but apparently it changed, we'll need to recheck it, but keep the nutrients for minimal loss BioSystem bioSystem1 = handler.bioSystemMap.remove(chunk); bioSystem = new BioSystem(chunk, bioSystem1.getPhosphorus(), bioSystem1.getPotassium(), bioSystem1.getNitrogen()); BioSystemInitThread.addBioSystem(bioSystem); } else { //Existing chunk, but new BioSystem! bioSystem = new BioSystem(chunk); BioSystemInitThread.addBioSystem(bioSystem); } } else { bioSystem = BioSystem.loadFromNBT(chunk, compound); } handler.bioSystemMap.put(chunk, bioSystem); } public static void onChunkLoaded(World world, Chunk chunk) { BioSystemHandler handler; if (!handlers.containsKey(world)) { handler = new BioSystemHandler(); handlers.put(world, handler); } else handler = handlers.get(world); if (!handler.bioSystemMap.containsKey(chunk)) handler.bioSystemMap.put(chunk, new BioSystem(chunk)); } public static void onChunkUnload(World world, Chunk chunk) { BioSystemHandler handler = handlers.get(world); if (handler != null) handler.bioSystemMap.remove(chunk); } public static BioSystemHandler get(World world) { return handlers.get(world); } public static BioSystem getBioSystem(World world, Chunk chunk) { BioSystemHandler handler = handlers.get(world); if (handler != null) return handler.getBioSystem(chunk); return null; } public BioSystem getBioSystem(Chunk chunk) { return bioSystemMap.get(chunk); } public Iterator<BioSystem> iterator() { return bioSystemMap.values().iterator(); } public void update() { biomassChangeMap.forEachEntry(BiomassProcedure.INSTANCE); biomassChangeMap.clear(); nitrogenFixationChangeMap.forEachEntry(NitrogenFixationProcedure.INSTANCE); nitrogenFixationChangeMap.clear(); if (!stabilizeList.isEmpty()) { List<BioSystem> copiedList = new ArrayList<BioSystem>(stabilizeList); stabilizeList.clear(); for (BioSystem bioSystem : copiedList) bioSystem.setStableBacteriaValuesNearChunk(); } Iterator<BioSystem> iterator = iterator(); while (iterator.hasNext()) { iterator.next().update(); } } public static class ChunkCoords { public World world; public int x, z; public ChunkCoords(World world, int x, int z) { this.world = world; this.x = x; this.z = z; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ChunkCoords that = (ChunkCoords) o; if (x != that.x) return false; if (z != that.z) return false; if (!world.equals(that.world)) return false; return true; } @Override public int hashCode() { int result = world.hashCode(); result = 31 * result + x; result = 31 * result + z; return result; } } private static class BiomassProcedure implements TObjectFloatProcedure<ChunkCoords> { public static final BiomassProcedure INSTANCE = new BiomassProcedure(); private BiomassProcedure() { } @Override public boolean execute(ChunkCoords coords, float amount) { Chunk chunk = coords.world.getChunkFromChunkCoords(coords.x, coords.z); BioSystem bioSystem = getBioSystem(coords.world, chunk); if (bioSystem != null) { bioSystem.addBiomass(amount); } else { Biota.logger.warn(String.format("Couldn't find BioSystem at: %d %d", coords.x, coords.z)); } return true; } } private static class NitrogenFixationProcedure implements TObjectFloatProcedure<ChunkCoords> { public static final NitrogenFixationProcedure INSTANCE = new NitrogenFixationProcedure(); private NitrogenFixationProcedure() { } @Override public boolean execute(ChunkCoords coords, float amount) { Chunk chunk = coords.world.getChunkFromChunkCoords(coords.x, coords.z); BioSystem bioSystem = getBioSystem(coords.world, chunk); if (bioSystem != null) { bioSystem.addNitrogenFixation(amount); } else { Biota.logger.warn(String.format("Couldn't find BioSystem at: %d %d", coords.x, coords.z)); } return true; } } }