From 2bfcc50dd9822c54cabf4f8d34c8af6fc6c73884 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sat, 10 Nov 2012 23:47:40 -0600 Subject: [PATCH] Support world loading/unloading - allow viewing while world unloaded --- .../java/org/dynmap/bukkit/BukkitWorld.java | 95 +++++++++++++++---- .../java/org/dynmap/bukkit/DynmapPlugin.java | 25 +++-- .../org/dynmap/bukkit/NewMapChunkCache.java | 10 ++ 3 files changed, 106 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/dynmap/bukkit/BukkitWorld.java b/src/main/java/org/dynmap/bukkit/BukkitWorld.java index 8fb9ed6b..0791ee3e 100644 --- a/src/main/java/org/dynmap/bukkit/BukkitWorld.java +++ b/src/main/java/org/dynmap/bukkit/BukkitWorld.java @@ -17,13 +17,36 @@ public class BukkitWorld extends DynmapWorld { private World world; private World.Environment env; private boolean skylight; + private DynmapLocation spawnloc = new DynmapLocation(); public BukkitWorld(World w) { - super(w.getName(), w.getMaxHeight(), w.getSeaLevel()); + this(w.getName(), w.getMaxHeight(), w.getSeaLevel(), w.getEnvironment()); + setWorldLoaded(w); + new Permission("dynmap.world." + getName(), "Dynmap access for world " + getName(), PermissionDefault.OP); + } + public BukkitWorld(String name, int height, int sealevel, World.Environment env) { + super(name, height, sealevel); + world = null; + this.env = env; + skylight = (env == World.Environment.NORMAL); + new Permission("dynmap.world." + getName(), "Dynmap access for world " + getName(), PermissionDefault.OP); + } + /** + * Set world online + * @param w - loaded world + */ + public void setWorldLoaded(World w) { world = w; env = world.getEnvironment(); skylight = (env == World.Environment.NORMAL); - new Permission("dynmap.world." + getName(), "Dynmap access for world " + getName(), PermissionDefault.OP); + } + /** + * Set world unloaded + */ + @Override + public void setWorldUnloaded() { + getSpawnLocation(); /* Remember spawn location before unload */ + world = null; } /* Test if world is nether */ @Override @@ -33,26 +56,44 @@ public class BukkitWorld extends DynmapWorld { /* Get world spawn location */ @Override public DynmapLocation getSpawnLocation() { - DynmapLocation dloc = new DynmapLocation(); - Location sloc = world.getSpawnLocation(); - dloc.x = sloc.getBlockX(); dloc.y = sloc.getBlockY(); - dloc.z = sloc.getBlockZ(); dloc.world = normalizeWorldName(sloc.getWorld().getName()); - return dloc; + if(world != null) { + Location sloc = world.getSpawnLocation(); + spawnloc.x = sloc.getBlockX(); + spawnloc.y = sloc.getBlockY(); + spawnloc.z = sloc.getBlockZ(); + spawnloc.world = normalizeWorldName(sloc.getWorld().getName()); + } + return spawnloc; } /* Get world time */ @Override public long getTime() { - return world.getTime(); + if(world != null) { + return world.getTime(); + } + else { + return -1; + } } /* World is storming */ @Override public boolean hasStorm() { - return world.hasStorm(); + if(world != null) { + return world.hasStorm(); + } + else { + return false; + } } /* World is thundering */ @Override public boolean isThundering() { - return world.isThundering(); + if(world != null) { + return world.isThundering(); + } + else { + return false; + } } /* World is loaded */ @Override @@ -62,22 +103,37 @@ public class BukkitWorld extends DynmapWorld { /* Get light level of block */ @Override public int getLightLevel(int x, int y, int z) { - return world.getBlockAt(x, y, z).getLightLevel(); + if(world != null) { + return world.getBlockAt(x, y, z).getLightLevel(); + } + else { + return -1; + } } /* Get highest Y coord of given location */ @Override public int getHighestBlockYAt(int x, int z) { - return world.getHighestBlockYAt(x, z); + if(world != null) { + return world.getHighestBlockYAt(x, z); + } + else { + return -1; + } } /* Test if sky light level is requestable */ @Override public boolean canGetSkyLightLevel() { - return skylight; + return skylight && (world != null); } /* Return sky light level */ @Override public int getSkyLightLevel(int x, int y, int z) { - return world.getBlockAt(x, y, z).getLightFromSky(); + if(world != null) { + return world.getBlockAt(x, y, z).getLightFromSky(); + } + else { + return -1; + } } /** * Get world environment ID (lower case - normal, the_end, nether) @@ -91,9 +147,14 @@ public class BukkitWorld extends DynmapWorld { */ @Override public MapChunkCache getChunkCache(List chunks) { - NewMapChunkCache c = new NewMapChunkCache(); - c.setChunks(this, chunks); - return c; + if(isLoaded()) { + NewMapChunkCache c = new NewMapChunkCache(); + c.setChunks(this, chunks); + return c; + } + else { + return null; + } } public World getWorld() { diff --git a/src/main/java/org/dynmap/bukkit/DynmapPlugin.java b/src/main/java/org/dynmap/bukkit/DynmapPlugin.java index 02a28e8b..4fc5935e 100644 --- a/src/main/java/org/dynmap/bukkit/DynmapPlugin.java +++ b/src/main/java/org/dynmap/bukkit/DynmapPlugin.java @@ -128,6 +128,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { bw = new BukkitWorld(w); world_by_name.put(w.getName(), bw); } + else if(bw.isLoaded() == false) { + bw.setWorldLoaded(w); + } last_world = w; last_bworld = bw; @@ -257,7 +260,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { pm.registerEvents(new Listener() { @EventHandler(priority=EventPriority.MONITOR) public void onSpawnChange(SpawnChangeEvent evt) { - DynmapWorld w = getWorld(evt.getWorld()); + BukkitWorld w = getWorld(evt.getWorld()); core.listenerManager.processWorldEvent(EventType.WORLD_SPAWN_CHANGE, w); } }, DynmapPlugin.this); @@ -409,6 +412,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public MapChunkCache createMapChunkCache(DynmapWorld w, List chunks, boolean blockdata, boolean highesty, boolean biome, boolean rawbiome) { MapChunkCache c = w.getChunkCache(chunks); + if(c == null) { /* Can fail if not currently loaded */ + return null; + } if(w.visibility_limits != null) { for(MapChunkCache.VisibilityLimit limit: w.visibility_limits) { c.setVisibleRange(limit); @@ -445,8 +451,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public Boolean call() throws Exception { boolean exhausted; synchronized(loadlock) { - if(chunks_in_cur_tick > 0) + if(chunks_in_cur_tick > 0) { chunks_in_cur_tick -= cc.loadChunks(chunks_in_cur_tick); + } exhausted = (chunks_in_cur_tick == 0); } return exhausted; @@ -465,6 +472,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { try { Thread.sleep(25); } catch (InterruptedException ix) {} } } + /* If cancelled due to world unload return nothing */ + if(w.isLoaded() == false) + return null; return c; } @Override @@ -1342,17 +1352,18 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Listener worldTrigger = new Listener() { @EventHandler(priority=EventPriority.MONITOR) public void onWorldLoad(WorldLoadEvent event) { - core.updateConfigHashcode(); BukkitWorld w = getWorld(event.getWorld()); if(core.processWorldLoad(w)) /* Have core process load first - fire event listeners if good load after */ core.listenerManager.processWorldEvent(EventType.WORLD_LOAD, w); } @EventHandler(priority=EventPriority.MONITOR) public void onWorldUnload(WorldUnloadEvent event) { - core.updateConfigHashcode(); - DynmapWorld w = getWorld(event.getWorld()); - core.listenerManager.processWorldEvent(EventType.WORLD_UNLOAD, w); - removeWorld(event.getWorld()); + BukkitWorld w = getWorld(event.getWorld()); + if(w != null) { + core.listenerManager.processWorldEvent(EventType.WORLD_UNLOAD, w); + w.setWorldUnloaded(); + core.processWorldUnload(w); + } } @EventHandler(priority=EventPriority.MONITOR) public void onStructureGrow(StructureGrowEvent event) { diff --git a/src/main/java/org/dynmap/bukkit/NewMapChunkCache.java b/src/main/java/org/dynmap/bukkit/NewMapChunkCache.java index b92a7461..f9a491a1 100644 --- a/src/main/java/org/dynmap/bukkit/NewMapChunkCache.java +++ b/src/main/java/org/dynmap/bukkit/NewMapChunkCache.java @@ -720,6 +720,9 @@ public class NewMapChunkCache implements MapChunkCache { public void setChunks(BukkitWorld dw, List chunks) { this.dw = dw; this.w = dw.getWorld(); + if(this.w == null) { + this.chunks = new ArrayList(); + } nsect = dw.worldheight >> 4; this.chunks = chunks; /* Compute range */ @@ -762,6 +765,8 @@ public class NewMapChunkCache implements MapChunkCache { } public int loadChunks(int max_to_load) { + if(dw.isLoaded() == false) + return 0; long t0 = System.nanoTime(); CraftWorld cw = (CraftWorld)w; Object queue = null; @@ -926,6 +931,11 @@ public class NewMapChunkCache implements MapChunkCache { * Test if done loading */ public boolean isDoneLoading() { + if(dw.isLoaded() == false) { + isempty = true; + unloadChunks(); + return true; + } if(iterator != null) return !iterator.hasNext(); return false;