Made use of newly introduced unloadChunk in BukkitAPI + removal of unstable features.

This commit is contained in:
FrozenCow 2011-02-08 20:27:37 +01:00
parent b31bb14452
commit 89c8d564a4
3 changed files with 26 additions and 81 deletions

View File

@ -3,10 +3,6 @@
# How often a tile gets rendered (in seconds). # How often a tile gets rendered (in seconds).
renderinterval: 1 renderinterval: 1
# When enabled Dynmap will preload chunks before rendering a tile. This will avoid Dynmap rendering unloaded (=partially blue) tiles.
# This WILL impact memory and diskio.
loadChunks: false
# The path where the tile-files are placed. # The path where the tile-files are placed.
tilepath: web/tiles tilepath: web/tiles

View File

@ -54,9 +54,6 @@ public class DynmapPlayerListener extends PlayerListener {
} else if (split[1].equals("fullrender")) { } else if (split[1].equals("fullrender")) {
Player player = event.getPlayer(); Player player = event.getPlayer();
mgr.renderFullWorld(player.getLocation()); mgr.renderFullWorld(player.getLocation());
} else if (split[1].equals("fullrenderasync")) {
Player player = event.getPlayer();
mgr.renderFullWorldAsync(player.getLocation());
} }
} }
} }

View File

@ -78,27 +78,16 @@ public class MapManager extends Thread {
maps = loadMapTypes(configuration); maps = loadMapTypes(configuration);
} }
void renderFullWorldAsync(Location l) {
fullmapTiles.clear();
fullmapTilesRendered.clear();
debugger.debug("Full render starting...");
for (MapType map : maps) {
for (MapTile tile : map.getTiles(l)) {
fullmapTiles.add(tile);
invalidateTile(tile);
}
}
debugger.debug("Full render finished.");
}
void renderFullWorld(Location l) { void renderFullWorld(Location l) {
debugger.debug("Full render starting..."); debugger.debug("Full render starting...");
for (MapType map : maps) { for (MapType map : maps) {
HashSet<MapTile> found = new HashSet<MapTile>(); HashSet<MapTile> found = new HashSet<MapTile>();
HashSet<MapTile> rendered = new HashSet<MapTile>();
LinkedList<MapTile> renderQueue = new LinkedList<MapTile>(); LinkedList<MapTile> renderQueue = new LinkedList<MapTile>();
LinkedList<DynmapChunk> loadedChunks = new LinkedList<DynmapChunk>();
for (MapTile tile : map.getTiles(l)) { for (MapTile tile : map.getTiles(l)) {
if (!(found.contains(tile) || map.isRendered(tile))) { if (!found.contains(tile)) {
found.add(tile); found.add(tile);
renderQueue.add(tile); renderQueue.add(tile);
} }
@ -106,13 +95,29 @@ public class MapManager extends Thread {
while (!renderQueue.isEmpty()) { while (!renderQueue.isEmpty()) {
MapTile tile = renderQueue.pollFirst(); MapTile tile = renderQueue.pollFirst();
loadRequiredChunks(tile); DynmapChunk[] requiredChunks = tile.getMap().getRequiredChunks(tile);
// Unload old chunks.
while (loadedChunks.size() >= Math.max(0, 200 - requiredChunks.length)) {
DynmapChunk c = loadedChunks.pollFirst();
world.unloadChunk(c.x, c.y, false, true);
}
// Load the required chunks.
for (DynmapChunk chunk : requiredChunks) {
boolean wasLoaded = world.isChunkLoaded(chunk.x, chunk.y);
world.loadChunk(chunk.x, chunk.y, false);
if (!wasLoaded)
loadedChunks.add(chunk);
}
debugger.debug("renderQueue: " + renderQueue.size() + "/" + found.size()); debugger.debug("renderQueue: " + renderQueue.size() + "/" + found.size());
if (map.render(tile)) { if (map.render(tile)) {
found.remove(tile); found.remove(tile);
rendered.add(tile);
updateQueue.pushUpdate(new Client.Tile(tile.getName())); updateQueue.pushUpdate(new Client.Tile(tile.getName()));
for (MapTile adjTile : map.getAdjecentTiles(tile)) { for (MapTile adjTile : map.getAdjecentTiles(tile)) {
if (!(found.contains(adjTile) || map.isRendered(adjTile))) { if (!(found.contains(adjTile) || rendered.contains(adjTile))) {
found.add(adjTile); found.add(adjTile);
renderQueue.add(adjTile); renderQueue.add(adjTile);
} }
@ -121,64 +126,16 @@ public class MapManager extends Thread {
found.remove(tile); found.remove(tile);
System.gc(); System.gc();
} }
// Unload remaining chunks to clean-up.
while (!loadedChunks.isEmpty()) {
DynmapChunk c = loadedChunks.pollFirst();
world.unloadChunk(c.x, c.y, false, true);
}
} }
debugger.debug("Full render finished."); debugger.debug("Full render finished.");
} }
public HashSet<MapTile> fullmapTiles = new HashSet<MapTile>();
public boolean fullmapRenderStarting = false;
public HashSet<MapTile> fullmapTilesRendered = new HashSet<MapTile>();
void handleFullMapRender(MapTile tile) {
if (!fullmapTiles.contains(tile)) {
debugger.debug("Non fullmap-render tile: " + tile);
return;
}
fullmapTilesRendered.add(tile);
MapType map = tile.getMap();
MapTile[] adjecenttiles = map.getAdjecentTiles(tile);
for (int i = 0; i < adjecenttiles.length; i++) {
MapTile adjecentTile = adjecenttiles[i];
if (!fullmapTiles.contains(adjecentTile)) {
fullmapTiles.add(adjecentTile);
staleQueue.pushStaleTile(adjecentTile);
}
}
debugger.debug("Queue size: " + staleQueue.size() + "+" + fullmapTilesRendered.size() + "/" + fullmapTiles.size());
}
private boolean hasEnoughMemory() {
return Runtime.getRuntime().freeMemory() >= 100 * 1024 * 1024;
}
private void waitForMemory() {
if (!hasEnoughMemory()) {
debugger.debug("Waiting for memory...");
// Wait until there is at least 50mb of free memory.
do {
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (!hasEnoughMemory());
debugger.debug(Runtime.getRuntime().freeMemory() / (1024 * 1024) + "MB of memory free, will continue...");
}
}
private void loadRequiredChunks(MapTile tile) {
if (!loadChunks)
return;
waitForMemory();
// Actually load the chunks.
for (DynmapChunk chunk : tile.getMap().getRequiredChunks(tile)) {
if (!world.isChunkLoaded(chunk.x, chunk.y))
world.loadChunk(chunk.x, chunk.y);
}
}
private MapType[] loadMapTypes(ConfigurationNode configuration) { private MapType[] loadMapTypes(ConfigurationNode configuration) {
List<?> configuredMaps = (List<?>) configuration.getProperty("maps"); List<?> configuredMaps = (List<?>) configuration.getProperty("maps");
ArrayList<MapType> mapTypes = new ArrayList<MapType>(); ArrayList<MapType> mapTypes = new ArrayList<MapType>();
@ -240,15 +197,10 @@ public class MapManager extends Thread {
while (running) { while (running) {
MapTile t = staleQueue.popStaleTile(); MapTile t = staleQueue.popStaleTile();
if (t != null) { if (t != null) {
loadRequiredChunks(t);
debugger.debug("Rendering tile " + t + "..."); debugger.debug("Rendering tile " + t + "...");
boolean isNonEmptyTile = t.getMap().render(t); boolean isNonEmptyTile = t.getMap().render(t);
updateQueue.pushUpdate(new Client.Tile(t.getName())); updateQueue.pushUpdate(new Client.Tile(t.getName()));
if (isNonEmptyTile)
handleFullMapRender(t);
try { try {
Thread.sleep(renderWait); Thread.sleep(renderWait);
} catch (InterruptedException e) { } catch (InterruptedException e) {