package buildcraft.robotics.map; import java.io.File; import java.util.Date; import com.google.common.collect.HashBiMap; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.ChunkProviderServer; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.relauncher.Side; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; import buildcraft.core.lib.utils.Utils; public class MapManager implements Runnable { private static final int UPDATE_DELAY = 60000; private final HashBiMap<World, MapWorld> worldMap = HashBiMap.create(); private final File location; private boolean stop = false; private long lastSaveTime; public MapManager(File location) { this.location = location; } public void stop() { stop = true; saveAllWorlds(); } public MapWorld getWorld(World world) { if (world == null || world.isRemote) { return null; } if (!worldMap.containsKey(world)) { synchronized (worldMap) { worldMap.put(world, new MapWorld(world, location)); } } return worldMap.get(world); } private boolean doUpdate(MapWorld world, Chunk chunk) { int x = chunk.xPosition; int z = chunk.zPosition; long updateTime = (new Date()).getTime() - UPDATE_DELAY; return world.getUpdateTime(x, z) < updateTime || !world.hasChunk(x, z); } private void updateChunk(World rworld, Chunk chunk, boolean force) { MapWorld world = getWorld(rworld); if (world != null && (force || doUpdate(world, chunk))) { world.updateChunk(chunk); } } private void updateChunkDelayed(World rworld, Chunk chunk, boolean force, byte time) { MapWorld world = getWorld(rworld); if (world != null && (force || doUpdate(world, chunk))) { world.updateChunkDelayed(chunk, time); } } @SubscribeEvent public void tickDelayedWorlds(TickEvent.WorldTickEvent event) { if (event.phase == TickEvent.Phase.END && event.side == Side.SERVER) { MapWorld w = worldMap.get(event.world); if (w != null) { w.tick(); } } } @SubscribeEvent public void worldUnloaded(WorldEvent.Unload event) { if (worldMap.containsKey(event.world)) { worldMap.get(event.world).save(); synchronized (worldMap) { worldMap.remove(event.world); } } } @SubscribeEvent public void chunkLoaded(ChunkEvent.Load event) { updateChunkDelayed(event.world, event.getChunk(), false, (byte) (40 + Utils.RANDOM.nextInt(20))); } @SubscribeEvent public void chunkUnloaded(ChunkEvent.Unload event) { updateChunk(event.world, event.getChunk(), false); } @SubscribeEvent public void blockPlaced(BlockEvent.PlaceEvent placeEvent) { Chunk chunk = placeEvent.world.getChunkFromBlockCoords(placeEvent.x, placeEvent.z); MapWorld world = getWorld(placeEvent.world); if (world != null && doUpdate(world, chunk)) { int hv = placeEvent.world.getHeightValue(placeEvent.x, placeEvent.z); if (placeEvent.y >= (hv - 3)) { world.updateChunk(chunk); } } } @SubscribeEvent public void blockBroken(BlockEvent.BreakEvent placeEvent) { Chunk chunk = placeEvent.world.getChunkFromBlockCoords(placeEvent.x, placeEvent.z); MapWorld world = getWorld(placeEvent.world); if (world != null && doUpdate(world, chunk)) { int hv = placeEvent.world.getHeightValue(placeEvent.x, placeEvent.z); if (placeEvent.y >= (hv - 3)) { world.updateChunk(chunk); } } } public void saveAllWorlds() { synchronized (worldMap) { for (MapWorld world : worldMap.values()) { world.save(); } } } @Override public void run() { lastSaveTime = (new Date()).getTime(); while (!stop) { long now = (new Date()).getTime(); if (now - lastSaveTime > 120000) { saveAllWorlds(); lastSaveTime = now; } try { Thread.sleep(4000); } catch (Exception e) { } } } public void initialize() { for (WorldServer ws : DimensionManager.getWorlds()) { MapWorld mw = getWorld(ws); IChunkProvider provider = ws.getChunkProvider(); if (provider instanceof ChunkProviderServer) { for (Object o : ((ChunkProviderServer) provider).func_152380_a()) { if (o != null && o instanceof Chunk) { Chunk c = (Chunk) o; if (!mw.hasChunk(c.xPosition, c.zPosition)) { mw.updateChunkDelayed(c, (byte) (40 + Utils.RANDOM.nextInt(20))); } } } } } } }