Support world loading/unloading - allow viewing while world unloaded

This commit is contained in:
Mike Primm 2012-11-10 23:47:40 -06:00
parent a20e55beab
commit 68f0c17f70
3 changed files with 106 additions and 24 deletions

View File

@ -17,13 +17,36 @@ public class BukkitWorld extends DynmapWorld {
private World world; private World world;
private World.Environment env; private World.Environment env;
private boolean skylight; private boolean skylight;
private DynmapLocation spawnloc = new DynmapLocation();
public BukkitWorld(World w) { 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; world = w;
env = world.getEnvironment(); env = world.getEnvironment();
skylight = (env == World.Environment.NORMAL); 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 */ /* Test if world is nether */
@Override @Override
@ -33,27 +56,45 @@ public class BukkitWorld extends DynmapWorld {
/* Get world spawn location */ /* Get world spawn location */
@Override @Override
public DynmapLocation getSpawnLocation() { public DynmapLocation getSpawnLocation() {
DynmapLocation dloc = new DynmapLocation(); if(world != null) {
Location sloc = world.getSpawnLocation(); Location sloc = world.getSpawnLocation();
dloc.x = sloc.getBlockX(); dloc.y = sloc.getBlockY(); spawnloc.x = sloc.getBlockX();
dloc.z = sloc.getBlockZ(); dloc.world = normalizeWorldName(sloc.getWorld().getName()); spawnloc.y = sloc.getBlockY();
return dloc; spawnloc.z = sloc.getBlockZ();
spawnloc.world = normalizeWorldName(sloc.getWorld().getName());
}
return spawnloc;
} }
/* Get world time */ /* Get world time */
@Override @Override
public long getTime() { public long getTime() {
if(world != null) {
return world.getTime(); return world.getTime();
} }
else {
return -1;
}
}
/* World is storming */ /* World is storming */
@Override @Override
public boolean hasStorm() { public boolean hasStorm() {
if(world != null) {
return world.hasStorm(); return world.hasStorm();
} }
else {
return false;
}
}
/* World is thundering */ /* World is thundering */
@Override @Override
public boolean isThundering() { public boolean isThundering() {
if(world != null) {
return world.isThundering(); return world.isThundering();
} }
else {
return false;
}
}
/* World is loaded */ /* World is loaded */
@Override @Override
public boolean isLoaded() { public boolean isLoaded() {
@ -62,23 +103,38 @@ public class BukkitWorld extends DynmapWorld {
/* Get light level of block */ /* Get light level of block */
@Override @Override
public int getLightLevel(int x, int y, int z) { public int getLightLevel(int x, int y, int z) {
if(world != null) {
return world.getBlockAt(x, y, z).getLightLevel(); return world.getBlockAt(x, y, z).getLightLevel();
} }
else {
return -1;
}
}
/* Get highest Y coord of given location */ /* Get highest Y coord of given location */
@Override @Override
public int getHighestBlockYAt(int x, int z) { public int getHighestBlockYAt(int x, int z) {
if(world != null) {
return world.getHighestBlockYAt(x, z); return world.getHighestBlockYAt(x, z);
} }
else {
return -1;
}
}
/* Test if sky light level is requestable */ /* Test if sky light level is requestable */
@Override @Override
public boolean canGetSkyLightLevel() { public boolean canGetSkyLightLevel() {
return skylight; return skylight && (world != null);
} }
/* Return sky light level */ /* Return sky light level */
@Override @Override
public int getSkyLightLevel(int x, int y, int z) { public int getSkyLightLevel(int x, int y, int z) {
if(world != null) {
return world.getBlockAt(x, y, z).getLightFromSky(); return world.getBlockAt(x, y, z).getLightFromSky();
} }
else {
return -1;
}
}
/** /**
* Get world environment ID (lower case - normal, the_end, nether) * Get world environment ID (lower case - normal, the_end, nether)
*/ */
@ -91,10 +147,15 @@ public class BukkitWorld extends DynmapWorld {
*/ */
@Override @Override
public MapChunkCache getChunkCache(List<DynmapChunk> chunks) { public MapChunkCache getChunkCache(List<DynmapChunk> chunks) {
if(isLoaded()) {
NewMapChunkCache c = new NewMapChunkCache(); NewMapChunkCache c = new NewMapChunkCache();
c.setChunks(this, chunks); c.setChunks(this, chunks);
return c; return c;
} }
else {
return null;
}
}
public World getWorld() { public World getWorld() {
return world; return world;

View File

@ -128,6 +128,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
bw = new BukkitWorld(w); bw = new BukkitWorld(w);
world_by_name.put(w.getName(), bw); world_by_name.put(w.getName(), bw);
} }
else if(bw.isLoaded() == false) {
bw.setWorldLoaded(w);
}
last_world = w; last_world = w;
last_bworld = bw; last_bworld = bw;
@ -257,7 +260,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
pm.registerEvents(new Listener() { pm.registerEvents(new Listener() {
@EventHandler(priority=EventPriority.MONITOR) @EventHandler(priority=EventPriority.MONITOR)
public void onSpawnChange(SpawnChangeEvent evt) { public void onSpawnChange(SpawnChangeEvent evt) {
DynmapWorld w = getWorld(evt.getWorld()); BukkitWorld w = getWorld(evt.getWorld());
core.listenerManager.processWorldEvent(EventType.WORLD_SPAWN_CHANGE, w); core.listenerManager.processWorldEvent(EventType.WORLD_SPAWN_CHANGE, w);
} }
}, DynmapPlugin.this); }, DynmapPlugin.this);
@ -409,6 +412,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public MapChunkCache createMapChunkCache(DynmapWorld w, List<DynmapChunk> chunks, public MapChunkCache createMapChunkCache(DynmapWorld w, List<DynmapChunk> chunks,
boolean blockdata, boolean highesty, boolean biome, boolean rawbiome) { boolean blockdata, boolean highesty, boolean biome, boolean rawbiome) {
MapChunkCache c = w.getChunkCache(chunks); MapChunkCache c = w.getChunkCache(chunks);
if(c == null) { /* Can fail if not currently loaded */
return null;
}
if(w.visibility_limits != null) { if(w.visibility_limits != null) {
for(MapChunkCache.VisibilityLimit limit: w.visibility_limits) { for(MapChunkCache.VisibilityLimit limit: w.visibility_limits) {
c.setVisibleRange(limit); c.setVisibleRange(limit);
@ -445,8 +451,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public Boolean call() throws Exception { public Boolean call() throws Exception {
boolean exhausted; boolean exhausted;
synchronized(loadlock) { synchronized(loadlock) {
if(chunks_in_cur_tick > 0) if(chunks_in_cur_tick > 0) {
chunks_in_cur_tick -= cc.loadChunks(chunks_in_cur_tick); chunks_in_cur_tick -= cc.loadChunks(chunks_in_cur_tick);
}
exhausted = (chunks_in_cur_tick == 0); exhausted = (chunks_in_cur_tick == 0);
} }
return exhausted; return exhausted;
@ -465,6 +472,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
try { Thread.sleep(25); } catch (InterruptedException ix) {} try { Thread.sleep(25); } catch (InterruptedException ix) {}
} }
} }
/* If cancelled due to world unload return nothing */
if(w.isLoaded() == false)
return null;
return c; return c;
} }
@Override @Override
@ -1342,17 +1352,18 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Listener worldTrigger = new Listener() { Listener worldTrigger = new Listener() {
@EventHandler(priority=EventPriority.MONITOR) @EventHandler(priority=EventPriority.MONITOR)
public void onWorldLoad(WorldLoadEvent event) { public void onWorldLoad(WorldLoadEvent event) {
core.updateConfigHashcode();
BukkitWorld w = getWorld(event.getWorld()); BukkitWorld w = getWorld(event.getWorld());
if(core.processWorldLoad(w)) /* Have core process load first - fire event listeners if good load after */ if(core.processWorldLoad(w)) /* Have core process load first - fire event listeners if good load after */
core.listenerManager.processWorldEvent(EventType.WORLD_LOAD, w); core.listenerManager.processWorldEvent(EventType.WORLD_LOAD, w);
} }
@EventHandler(priority=EventPriority.MONITOR) @EventHandler(priority=EventPriority.MONITOR)
public void onWorldUnload(WorldUnloadEvent event) { public void onWorldUnload(WorldUnloadEvent event) {
core.updateConfigHashcode(); BukkitWorld w = getWorld(event.getWorld());
DynmapWorld w = getWorld(event.getWorld()); if(w != null) {
core.listenerManager.processWorldEvent(EventType.WORLD_UNLOAD, w); core.listenerManager.processWorldEvent(EventType.WORLD_UNLOAD, w);
removeWorld(event.getWorld()); w.setWorldUnloaded();
core.processWorldUnload(w);
}
} }
@EventHandler(priority=EventPriority.MONITOR) @EventHandler(priority=EventPriority.MONITOR)
public void onStructureGrow(StructureGrowEvent event) { public void onStructureGrow(StructureGrowEvent event) {

View File

@ -720,6 +720,9 @@ public class NewMapChunkCache implements MapChunkCache {
public void setChunks(BukkitWorld dw, List<DynmapChunk> chunks) { public void setChunks(BukkitWorld dw, List<DynmapChunk> chunks) {
this.dw = dw; this.dw = dw;
this.w = dw.getWorld(); this.w = dw.getWorld();
if(this.w == null) {
this.chunks = new ArrayList<DynmapChunk>();
}
nsect = dw.worldheight >> 4; nsect = dw.worldheight >> 4;
this.chunks = chunks; this.chunks = chunks;
/* Compute range */ /* Compute range */
@ -762,6 +765,8 @@ public class NewMapChunkCache implements MapChunkCache {
} }
public int loadChunks(int max_to_load) { public int loadChunks(int max_to_load) {
if(dw.isLoaded() == false)
return 0;
long t0 = System.nanoTime(); long t0 = System.nanoTime();
CraftWorld cw = (CraftWorld)w; CraftWorld cw = (CraftWorld)w;
Object queue = null; Object queue = null;
@ -926,6 +931,11 @@ public class NewMapChunkCache implements MapChunkCache {
* Test if done loading * Test if done loading
*/ */
public boolean isDoneLoading() { public boolean isDoneLoading() {
if(dw.isLoaded() == false) {
isempty = true;
unloadChunks();
return true;
}
if(iterator != null) if(iterator != null)
return !iterator.hasNext(); return !iterator.hasNext();
return false; return false;