package codechicken.lib.world; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraft.client.Minecraft; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.EmptyChunk; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.ChunkWatchEvent.UnWatch; import net.minecraftforge.event.world.ChunkWatchEvent.Watch; import net.minecraftforge.event.world.WorldEvent; import java.util.ArrayList; import java.util.HashMap; public class WorldExtensionManager { public static class WorldExtensionEventHandler { @SubscribeEvent public void onChunkDataLoad(ChunkDataEvent.Load event) { if(!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); createChunkExtension(event.world, event.getChunk()); for(WorldExtension extension : worldMap.get(event.world)) extension.loadChunkData(event.getChunk(), event.getData()); } @SubscribeEvent public void onChunkDataSave(ChunkDataEvent.Save event) { for(WorldExtension extension : worldMap.get(event.world)) extension.saveChunkData(event.getChunk(), event.getData()); if(!event.getChunk().isChunkLoaded) removeChunk(event.world, event.getChunk()); } @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { if(!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); createChunkExtension(event.world, event.getChunk()); for(WorldExtension extension : worldMap.get(event.world)) extension.loadChunk(event.getChunk()); } @SubscribeEvent public void onChunkUnLoad(ChunkEvent.Unload event) { if(event.getChunk() instanceof EmptyChunk) return; for(WorldExtension extension : worldMap.get(event.world)) extension.unloadChunk(event.getChunk()); if(event.world.isRemote) removeChunk(event.world, event.getChunk()); } @SubscribeEvent public void onWorldSave(WorldEvent.Save event) { if(worldMap.containsKey(event.world)) for(WorldExtension extension : worldMap.get(event.world)) extension.save(); } @SubscribeEvent public void onWorldLoad(WorldEvent.Load event) { if(!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); } @SubscribeEvent public void onWorldUnLoad(WorldEvent.Unload event) { if(worldMap.containsKey(event.world))//because force closing unloads a world twice for(WorldExtension extension : worldMap.remove(event.world)) extension.unload(); } @SubscribeEvent public void onChunkWatch(Watch event) { Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); for(WorldExtension extension : worldMap.get(event.player.worldObj)) extension.watchChunk(chunk, event.player); } @SubscribeEvent @SideOnly(Side.CLIENT) public void onChunkUnWatch(UnWatch event) { Chunk chunk = event.player.worldObj.getChunkFromChunkCoords(event.chunk.chunkXPos, event.chunk.chunkZPos); for(WorldExtension extension : worldMap.get(event.player.worldObj)) extension.unwatchChunk(chunk, event.player); } @SubscribeEvent @SideOnly(Side.CLIENT) public void clientTick(TickEvent.ClientTickEvent event) { World world = Minecraft.getMinecraft().theWorld; if (worldMap.containsKey(world)) if (event.phase == TickEvent.Phase.START) preTick(world); else postTick(world); } @SubscribeEvent public void serverTick(TickEvent.WorldTickEvent event) { if(!worldMap.containsKey(event.world)) WorldExtensionManager.onWorldLoad(event.world); if(event.phase == TickEvent.Phase.START) preTick(event.world); else postTick(event.world); } } private static boolean initialised; private static ArrayList<WorldExtensionInstantiator> extensionIntialisers = new ArrayList<WorldExtensionInstantiator>(); public static void registerWorldExtension(WorldExtensionInstantiator init) { if(!initialised) init(); init.instantiatorID = extensionIntialisers.size(); extensionIntialisers.add(init); } private static void init() { initialised = true; MinecraftForge.EVENT_BUS.register(new WorldExtensionEventHandler()); FMLCommonHandler.instance().bus().register(new WorldExtensionEventHandler()); } private static HashMap<World, WorldExtension[]> worldMap = new HashMap<World, WorldExtension[]>(); private static void onWorldLoad(World world) { WorldExtension[] extensions = new WorldExtension[extensionIntialisers.size()]; for(int i = 0; i < extensions.length; i++) extensions[i] = extensionIntialisers.get(i).createWorldExtension(world); worldMap.put(world, extensions); for(WorldExtension extension : extensions) extension.load(); } private static void createChunkExtension(World world, Chunk chunk) { WorldExtension[] extensions = worldMap.get(world); for(int i = 0; i < extensionIntialisers.size(); i++) if(!extensions[i].containsChunk(chunk)) extensions[i].addChunk(extensionIntialisers.get(i).createChunkExtension(chunk, extensions[i])); } private static void removeChunk(World world, Chunk chunk) { for(WorldExtension extension : worldMap.get(world)) extension.remChunk(chunk); } private static void preTick(World world) { for(WorldExtension extension : worldMap.get(world)) extension.preTick(); } private static void postTick(World world) { for(WorldExtension extension : worldMap.get(world)) extension.postTick(); } public static WorldExtension getWorldExtension(World world, int instantiatorID) { return worldMap.get(world)[instantiatorID]; } }