mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-24 19:25:15 +01:00
Add support for throttling chunk load rate, spreading over ticks
This commit is contained in:
parent
8b35f4d3b7
commit
2bc9b410a6
@ -100,6 +100,9 @@ disable-webserver: false
|
|||||||
# Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load)
|
# Period between tile renders for fullrender, in seconds (non-zero to pace fullrenders, lessen CPU load)
|
||||||
timesliceinterval: 0.0
|
timesliceinterval: 0.0
|
||||||
|
|
||||||
|
# Maximum chunk loads per server tick (1/20th of a second) - reducing this below 90 will impact render performance, but also will reduce server thread load
|
||||||
|
maxchunkspertick: 200
|
||||||
|
|
||||||
# Interval the browser should poll for updates.
|
# Interval the browser should poll for updates.
|
||||||
updaterate: 2000
|
updaterate: 2000
|
||||||
|
|
||||||
|
@ -9,10 +9,10 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
@ -25,13 +25,18 @@ import org.dynmap.utils.NewMapChunkCache;
|
|||||||
public class MapManager {
|
public class MapManager {
|
||||||
public AsynchronousQueue<MapTile> tileQueue;
|
public AsynchronousQueue<MapTile> tileQueue;
|
||||||
|
|
||||||
|
private static final int DEFAULT_CHUNKS_PER_TICK = 200;
|
||||||
|
|
||||||
public List<DynmapWorld> worlds = new ArrayList<DynmapWorld>();
|
public List<DynmapWorld> worlds = new ArrayList<DynmapWorld>();
|
||||||
public Map<String, DynmapWorld> worldsLookup = new HashMap<String, DynmapWorld>();
|
public Map<String, DynmapWorld> worldsLookup = new HashMap<String, DynmapWorld>();
|
||||||
private BukkitScheduler scheduler;
|
private BukkitScheduler scheduler;
|
||||||
private DynmapPlugin plug_in;
|
private DynmapPlugin plug_in;
|
||||||
private long timeslice_int = 0; /* In milliseconds */
|
private long timeslice_int = 0; /* In milliseconds */
|
||||||
|
private int max_chunk_loads_per_tick = DEFAULT_CHUNKS_PER_TICK;
|
||||||
/* Which fullrenders are active */
|
/* Which fullrenders are active */
|
||||||
private HashMap<String, FullWorldRenderState> active_renders = new HashMap<String, FullWorldRenderState>();
|
private HashMap<String, FullWorldRenderState> active_renders = new HashMap<String, FullWorldRenderState>();
|
||||||
|
/* List of MapChunkCache requests to be processed */
|
||||||
|
private ConcurrentLinkedQueue<MapChunkCache> chunkloads = new ConcurrentLinkedQueue<MapChunkCache>();
|
||||||
/* Tile hash manager */
|
/* Tile hash manager */
|
||||||
public TileHashManager hashman;
|
public TileHashManager hashman;
|
||||||
/* lock for our data structures */
|
/* lock for our data structures */
|
||||||
@ -60,10 +65,22 @@ public class MapManager {
|
|||||||
public Collection<DynmapWorld> getWorlds() {
|
public Collection<DynmapWorld> getWorlds() {
|
||||||
return worlds;
|
return worlds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class OurThreadFactory implements ThreadFactory {
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
t.setName("Dynmap Render Thread");
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class DynmapScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
|
private class DynmapScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
|
||||||
DynmapScheduledThreadPoolExecutor() {
|
DynmapScheduledThreadPoolExecutor() {
|
||||||
super(POOL_SIZE);
|
super(POOL_SIZE);
|
||||||
|
this.setThreadFactory(new OurThreadFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void afterExecute(Runnable r, Throwable x) {
|
protected void afterExecute(Runnable r, Throwable x) {
|
||||||
@ -163,7 +180,7 @@ public class MapManager {
|
|||||||
}
|
}
|
||||||
World w = world.world;
|
World w = world.world;
|
||||||
/* Fetch chunk cache from server thread */
|
/* Fetch chunk cache from server thread */
|
||||||
DynmapChunk[] requiredChunks = tile.getMap().getRequiredChunks(tile);
|
List<DynmapChunk> requiredChunks = tile.getMap().getRequiredChunks(tile);
|
||||||
MapChunkCache cache = createMapChunkCache(world, requiredChunks);
|
MapChunkCache cache = createMapChunkCache(world, requiredChunks);
|
||||||
if(cache == null) {
|
if(cache == null) {
|
||||||
cleanup();
|
cleanup();
|
||||||
@ -222,6 +239,25 @@ public class MapManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ProcessChunkLoads implements Runnable {
|
||||||
|
public void run() {
|
||||||
|
int cnt = max_chunk_loads_per_tick;
|
||||||
|
|
||||||
|
while(cnt > 0) {
|
||||||
|
MapChunkCache c = chunkloads.peek();
|
||||||
|
if(c == null)
|
||||||
|
return;
|
||||||
|
cnt = cnt - c.loadChunks(cnt);
|
||||||
|
if(c.isDoneLoading()) {
|
||||||
|
chunkloads.poll();
|
||||||
|
synchronized(c) {
|
||||||
|
c.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MapManager(DynmapPlugin plugin, ConfigurationNode configuration) {
|
public MapManager(DynmapPlugin plugin, ConfigurationNode configuration) {
|
||||||
plug_in = plugin;
|
plug_in = plugin;
|
||||||
mapman = this;
|
mapman = this;
|
||||||
@ -235,7 +271,8 @@ public class MapManager {
|
|||||||
|
|
||||||
/* On dedicated thread, so default to no delays */
|
/* On dedicated thread, so default to no delays */
|
||||||
timeslice_int = (long)(configuration.getDouble("timesliceinterval", 0.0) * 1000);
|
timeslice_int = (long)(configuration.getDouble("timesliceinterval", 0.0) * 1000);
|
||||||
|
max_chunk_loads_per_tick = configuration.getInteger("maxchunkspertick", DEFAULT_CHUNKS_PER_TICK);
|
||||||
|
if(max_chunk_loads_per_tick < 5) max_chunk_loads_per_tick = 5;
|
||||||
scheduler = plugin.getServer().getScheduler();
|
scheduler = plugin.getServer().getScheduler();
|
||||||
|
|
||||||
hashman = new TileHashManager(DynmapPlugin.tilesDirectory, configuration.getBoolean("enabletilehash", true));
|
hashman = new TileHashManager(DynmapPlugin.tilesDirectory, configuration.getBoolean("enabletilehash", true));
|
||||||
@ -247,7 +284,7 @@ public class MapManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scheduler.scheduleSyncRepeatingTask(plugin, new CheckWorldTimes(), 5*20, 5*20); /* Check very 5 seconds */
|
scheduler.scheduleSyncRepeatingTask(plugin, new CheckWorldTimes(), 5*20, 5*20); /* Check very 5 seconds */
|
||||||
|
scheduler.scheduleSyncRepeatingTask(plugin, new ProcessChunkLoads(), 1, 1); /* Chunk loader task */
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderFullWorld(Location l, CommandSender sender) {
|
void renderFullWorld(Location l, CommandSender sender) {
|
||||||
@ -439,35 +476,32 @@ public class MapManager {
|
|||||||
/**
|
/**
|
||||||
* Render processor helper - used by code running on render threads to request chunk snapshot cache from server/sync thread
|
* Render processor helper - used by code running on render threads to request chunk snapshot cache from server/sync thread
|
||||||
*/
|
*/
|
||||||
public MapChunkCache createMapChunkCache(final DynmapWorld w, final DynmapChunk[] chunks) {
|
public MapChunkCache createMapChunkCache(final DynmapWorld w, final List<DynmapChunk> chunks) {
|
||||||
Callable<MapChunkCache> job = new Callable<MapChunkCache>() {
|
MapChunkCache c = null;
|
||||||
public MapChunkCache call() {
|
|
||||||
MapChunkCache c = null;
|
|
||||||
try {
|
|
||||||
if(!use_legacy)
|
|
||||||
c = new NewMapChunkCache();
|
|
||||||
} catch (NoClassDefFoundError ncdfe) {
|
|
||||||
use_legacy = true;
|
|
||||||
}
|
|
||||||
if(c == null)
|
|
||||||
c = new LegacyMapChunkCache();
|
|
||||||
if(w.visibility_limits != null) {
|
|
||||||
for(MapChunkCache.VisibilityLimit limit: w.visibility_limits) {
|
|
||||||
c.setVisibleRange(limit);
|
|
||||||
}
|
|
||||||
c.setHiddenFillStyle(w.hiddenchunkstyle);
|
|
||||||
}
|
|
||||||
c.loadChunks(w.world, chunks);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Future<MapChunkCache> rslt = scheduler.callSyncMethod(plug_in, job);
|
|
||||||
try {
|
try {
|
||||||
return rslt.get();
|
if(!use_legacy)
|
||||||
} catch (Exception x) {
|
c = new NewMapChunkCache();
|
||||||
Log.info("createMapChunk - " + x);
|
} catch (NoClassDefFoundError ncdfe) {
|
||||||
return null;
|
use_legacy = true;
|
||||||
}
|
}
|
||||||
|
if(c == null)
|
||||||
|
c = new LegacyMapChunkCache();
|
||||||
|
if(w.visibility_limits != null) {
|
||||||
|
for(MapChunkCache.VisibilityLimit limit: w.visibility_limits) {
|
||||||
|
c.setVisibleRange(limit);
|
||||||
|
}
|
||||||
|
c.setHiddenFillStyle(w.hiddenchunkstyle);
|
||||||
|
}
|
||||||
|
c.setChunks(w.world, chunks);
|
||||||
|
synchronized(c) {
|
||||||
|
chunkloads.add(c);
|
||||||
|
try {
|
||||||
|
c.wait();
|
||||||
|
} catch (InterruptedException ix) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Update map tile statistics
|
* Update map tile statistics
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.dynmap;
|
package org.dynmap;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.dynmap.utils.MapChunkCache;
|
import org.dynmap.utils.MapChunkCache;
|
||||||
@ -13,7 +14,7 @@ public abstract class MapType {
|
|||||||
|
|
||||||
public abstract MapTile[] getAdjecentTiles(MapTile tile);
|
public abstract MapTile[] getAdjecentTiles(MapTile tile);
|
||||||
|
|
||||||
public abstract DynmapChunk[] getRequiredChunks(MapTile tile);
|
public abstract List<DynmapChunk> getRequiredChunks(MapTile tile);
|
||||||
|
|
||||||
public abstract boolean render(MapChunkCache cache, MapTile tile, File outputFile);
|
public abstract boolean render(MapChunkCache cache, MapTile tile, File outputFile);
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import static org.dynmap.JSONUtils.a;
|
|||||||
import static org.dynmap.JSONUtils.s;
|
import static org.dynmap.JSONUtils.s;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
@ -101,18 +103,16 @@ public class FlatMap extends MapType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DynmapChunk[] getRequiredChunks(MapTile tile) {
|
public List<DynmapChunk> getRequiredChunks(MapTile tile) {
|
||||||
FlatMapTile t = (FlatMapTile) tile;
|
FlatMapTile t = (FlatMapTile) tile;
|
||||||
int chunksPerTile = t.size / 16;
|
int chunksPerTile = t.size / 16;
|
||||||
int sx = t.x * chunksPerTile;
|
int sx = t.x * chunksPerTile;
|
||||||
int sz = t.y * chunksPerTile;
|
int sz = t.y * chunksPerTile;
|
||||||
|
|
||||||
DynmapChunk[] result = new DynmapChunk[chunksPerTile * chunksPerTile];
|
ArrayList<DynmapChunk> result = new ArrayList<DynmapChunk>(chunksPerTile * chunksPerTile);
|
||||||
int index = 0;
|
|
||||||
for (int x = 0; x < chunksPerTile; x++)
|
for (int x = 0; x < chunksPerTile; x++)
|
||||||
for (int z = 0; z < chunksPerTile; z++) {
|
for (int z = 0; z < chunksPerTile; z++) {
|
||||||
result[index] = new DynmapChunk(sx + x, sz + z);
|
result.add(new DynmapChunk(sx + x, sz + z));
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ public class KzedMap extends MapType {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public DynmapChunk[] getRequiredChunks(MapTile tile) {
|
public List<DynmapChunk> getRequiredChunks(MapTile tile) {
|
||||||
if (tile instanceof KzedMapTile) {
|
if (tile instanceof KzedMapTile) {
|
||||||
KzedMapTile t = (KzedMapTile) tile;
|
KzedMapTile t = (KzedMapTile) tile;
|
||||||
|
|
||||||
@ -216,12 +216,9 @@ public class KzedMap extends MapType {
|
|||||||
chunks.add(chunk);
|
chunks.add(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return chunks;
|
||||||
DynmapChunk[] result = new DynmapChunk[chunks.size()];
|
|
||||||
chunks.toArray(result);
|
|
||||||
return result;
|
|
||||||
} else {
|
} else {
|
||||||
return new DynmapChunk[0];
|
return new ArrayList<DynmapChunk>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package org.dynmap.utils;
|
|||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.ListIterator;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
@ -20,7 +21,11 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
private static Method poppreservedchunk = null;
|
private static Method poppreservedchunk = null;
|
||||||
private static Field heightmap = null;
|
private static Field heightmap = null;
|
||||||
private static boolean initialized = false;
|
private static boolean initialized = false;
|
||||||
|
|
||||||
|
private World w;
|
||||||
|
private List<DynmapChunk> chunks;
|
||||||
|
private ListIterator<DynmapChunk> iterator;
|
||||||
|
|
||||||
private int x_min, x_max, z_min, z_max;
|
private int x_min, x_max, z_min, z_max;
|
||||||
private int x_dim;
|
private int x_dim;
|
||||||
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
|
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
|
||||||
@ -177,17 +182,15 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
public LegacyMapChunkCache() {
|
public LegacyMapChunkCache() {
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Create chunk cache container
|
* Set chunks to load, and world to load from
|
||||||
* @param w - world
|
|
||||||
* @param x_min - minimum chunk x coordinate
|
|
||||||
* @param z_min - minimum chunk z coordinate
|
|
||||||
* @param x_max - maximum chunk x coordinate
|
|
||||||
* @param z_max - maximum chunk z coordinate
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
public void loadChunks(World w, DynmapChunk[] chunks) {
|
public void setChunks(World w, List<DynmapChunk> chunks) {
|
||||||
|
this.w = w;
|
||||||
|
this.chunks = chunks;
|
||||||
|
|
||||||
/* Compute range */
|
/* Compute range */
|
||||||
if(chunks.length == 0) {
|
if(chunks.size() == 0) {
|
||||||
this.x_min = 0;
|
this.x_min = 0;
|
||||||
this.x_max = 0;
|
this.x_max = 0;
|
||||||
this.z_min = 0;
|
this.z_min = 0;
|
||||||
@ -195,17 +198,17 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
x_dim = 1;
|
x_dim = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
x_min = x_max = chunks[0].x;
|
x_min = x_max = chunks.get(0).x;
|
||||||
z_min = z_max = chunks[0].z;
|
z_min = z_max = chunks.get(0).z;
|
||||||
for(int i = 1; i < chunks.length; i++) {
|
for(DynmapChunk c : chunks) {
|
||||||
if(chunks[i].x > x_max)
|
if(c.x > x_max)
|
||||||
x_max = chunks[i].x;
|
x_max = c.x;
|
||||||
if(chunks[i].x < x_min)
|
if(c.x < x_min)
|
||||||
x_min = chunks[i].x;
|
x_min = c.x;
|
||||||
if(chunks[i].z > z_max)
|
if(c.z > z_max)
|
||||||
z_max = chunks[i].z;
|
z_max = c.z;
|
||||||
if(chunks[i].z < z_min)
|
if(c.z < z_min)
|
||||||
z_min = chunks[i].z;
|
z_min = c.z;
|
||||||
}
|
}
|
||||||
x_dim = x_max - x_min + 1;
|
x_dim = x_max - x_min + 1;
|
||||||
}
|
}
|
||||||
@ -238,9 +241,17 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
snaparray = new LegacyChunkSnapshot[x_dim * (z_max-z_min+1)];
|
snaparray = new LegacyChunkSnapshot[x_dim * (z_max-z_min+1)];
|
||||||
if(gethandle != null) {
|
}
|
||||||
// Load the required chunks.
|
|
||||||
for (DynmapChunk chunk : chunks) {
|
public int loadChunks(int max_to_load) {
|
||||||
|
int cnt = 0;
|
||||||
|
if(iterator == null)
|
||||||
|
iterator = chunks.listIterator();
|
||||||
|
|
||||||
|
// Load the required chunks.
|
||||||
|
while((cnt < max_to_load) && iterator.hasNext()) {
|
||||||
|
DynmapChunk chunk = iterator.next();
|
||||||
|
if(gethandle != null) {
|
||||||
boolean vis = true;
|
boolean vis = true;
|
||||||
if(visible_limits != null) {
|
if(visible_limits != null) {
|
||||||
vis = false;
|
vis = false;
|
||||||
@ -302,12 +313,25 @@ public class LegacyMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cnt++;
|
||||||
}
|
}
|
||||||
/* Fill missing chunks with empty dummy chunk */
|
/* If done, finish table */
|
||||||
for(int i = 0; i < snaparray.length; i++) {
|
if(iterator.hasNext() == false) {
|
||||||
if(snaparray[i] == null)
|
/* Fill missing chunks with empty dummy chunk */
|
||||||
snaparray[i] = EMPTY;
|
for(int i = 0; i < snaparray.length; i++) {
|
||||||
|
if(snaparray[i] == null)
|
||||||
|
snaparray[i] = EMPTY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test if done loading
|
||||||
|
*/
|
||||||
|
public boolean isDoneLoading() {
|
||||||
|
if(iterator != null)
|
||||||
|
return !iterator.hasNext();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Unload chunks
|
* Unload chunks
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.dynmap.utils;
|
package org.dynmap.utils;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import java.util.List;
|
||||||
import org.dynmap.DynmapChunk;
|
import org.dynmap.DynmapChunk;
|
||||||
|
|
||||||
public interface MapChunkCache {
|
public interface MapChunkCache {
|
||||||
@ -12,11 +13,19 @@ public interface MapChunkCache {
|
|||||||
public int x0, x1, z0, z1;
|
public int x0, x1, z0, z1;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Load chunks into cache
|
* Set chunks to load, and world to load from
|
||||||
* @param w - world
|
|
||||||
* @param chunks - chunks to be loaded
|
|
||||||
*/
|
*/
|
||||||
void loadChunks(World w, DynmapChunk[] chunks);
|
void setChunks(World w, List<DynmapChunk> chunks);
|
||||||
|
/**
|
||||||
|
* Load chunks into cache
|
||||||
|
* @param maxToLoad - maximum number to load at once
|
||||||
|
* @return number loaded
|
||||||
|
*/
|
||||||
|
int loadChunks(int maxToLoad);
|
||||||
|
/**
|
||||||
|
* Test if done loading
|
||||||
|
*/
|
||||||
|
boolean isDoneLoading();
|
||||||
/**
|
/**
|
||||||
* Unload chunks
|
* Unload chunks
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,7 @@ package org.dynmap.utils;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
@ -18,6 +19,9 @@ import org.dynmap.Log;
|
|||||||
public class NewMapChunkCache implements MapChunkCache {
|
public class NewMapChunkCache implements MapChunkCache {
|
||||||
private static Method poppreservedchunk = null;
|
private static Method poppreservedchunk = null;
|
||||||
|
|
||||||
|
private World w;
|
||||||
|
private List<DynmapChunk> chunks;
|
||||||
|
private ListIterator<DynmapChunk> iterator;
|
||||||
private int x_min, x_max, z_min, z_max;
|
private int x_min, x_max, z_min, z_max;
|
||||||
private int x_dim;
|
private int x_dim;
|
||||||
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
|
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
|
||||||
@ -189,16 +193,10 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
*/
|
*/
|
||||||
public NewMapChunkCache() {
|
public NewMapChunkCache() {
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Create chunk cache container
|
|
||||||
* @param w - world
|
|
||||||
* @param x_min - minimum chunk x coordinate
|
|
||||||
* @param z_min - minimum chunk z coordinate
|
|
||||||
* @param x_max - maximum chunk x coordinate
|
|
||||||
* @param z_max - maximum chunk z coordinate
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public void loadChunks(World w, DynmapChunk[] chunks) {
|
public void setChunks(World w, List<DynmapChunk> chunks) {
|
||||||
|
this.w = w;
|
||||||
|
this.chunks = chunks;
|
||||||
if(poppreservedchunk == null) {
|
if(poppreservedchunk == null) {
|
||||||
/* Get CraftWorld.popPreservedChunk(x,z) - reduces memory bloat from map traversals (optional) */
|
/* Get CraftWorld.popPreservedChunk(x,z) - reduces memory bloat from map traversals (optional) */
|
||||||
try {
|
try {
|
||||||
@ -209,7 +207,7 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Compute range */
|
/* Compute range */
|
||||||
if(chunks.length == 0) {
|
if(chunks.size() == 0) {
|
||||||
this.x_min = 0;
|
this.x_min = 0;
|
||||||
this.x_max = 0;
|
this.x_max = 0;
|
||||||
this.z_min = 0;
|
this.z_min = 0;
|
||||||
@ -217,24 +215,32 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
x_dim = 1;
|
x_dim = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
x_min = x_max = chunks[0].x;
|
x_min = x_max = chunks.get(0).x;
|
||||||
z_min = z_max = chunks[0].z;
|
z_min = z_max = chunks.get(0).z;
|
||||||
for(int i = 1; i < chunks.length; i++) {
|
for(DynmapChunk c : chunks) {
|
||||||
if(chunks[i].x > x_max)
|
if(c.x > x_max)
|
||||||
x_max = chunks[i].x;
|
x_max = c.x;
|
||||||
if(chunks[i].x < x_min)
|
if(c.x < x_min)
|
||||||
x_min = chunks[i].x;
|
x_min = c.x;
|
||||||
if(chunks[i].z > z_max)
|
if(c.z > z_max)
|
||||||
z_max = chunks[i].z;
|
z_max = c.z;
|
||||||
if(chunks[i].z < z_min)
|
if(c.z < z_min)
|
||||||
z_min = chunks[i].z;
|
z_min = c.z;
|
||||||
}
|
}
|
||||||
x_dim = x_max - x_min + 1;
|
x_dim = x_max - x_min + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snaparray = new ChunkSnapshot[x_dim * (z_max-z_min+1)];
|
snaparray = new ChunkSnapshot[x_dim * (z_max-z_min+1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int loadChunks(int max_to_load) {
|
||||||
|
int cnt = 0;
|
||||||
|
if(iterator == null)
|
||||||
|
iterator = chunks.listIterator();
|
||||||
|
|
||||||
// Load the required chunks.
|
// Load the required chunks.
|
||||||
for (DynmapChunk chunk : chunks) {
|
while((cnt < max_to_load) && iterator.hasNext()) {
|
||||||
|
DynmapChunk chunk = iterator.next();
|
||||||
boolean vis = true;
|
boolean vis = true;
|
||||||
if(visible_limits != null) {
|
if(visible_limits != null) {
|
||||||
vis = false;
|
vis = false;
|
||||||
@ -286,12 +292,24 @@ public class NewMapChunkCache implements MapChunkCache {
|
|||||||
Log.severe("Cannot pop preserved chunk - " + x.toString());
|
Log.severe("Cannot pop preserved chunk - " + x.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cnt++;
|
||||||
}
|
}
|
||||||
/* Fill missing chunks with empty dummy chunk */
|
if(iterator.hasNext() == false) { /* If we're done */
|
||||||
for(int i = 0; i < snaparray.length; i++) {
|
/* Fill missing chunks with empty dummy chunk */
|
||||||
if(snaparray[i] == null)
|
for(int i = 0; i < snaparray.length; i++) {
|
||||||
snaparray[i] = EMPTY;
|
if(snaparray[i] == null)
|
||||||
|
snaparray[i] = EMPTY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Test if done loading
|
||||||
|
*/
|
||||||
|
public boolean isDoneLoading() {
|
||||||
|
if(iterator != null)
|
||||||
|
return !iterator.hasNext();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Unload chunks
|
* Unload chunks
|
||||||
|
Loading…
Reference in New Issue
Block a user