mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-12-25 18:17:37 +01:00
Added unstable fullmap rendering. Also... messed up formatting by pressing ctrl+shift+f in eclipse, sigh
This commit is contained in:
parent
138aed8c33
commit
c8cf39a440
9
src/main/java/org/dynmap/DynmapChunk.java
Normal file
9
src/main/java/org/dynmap/DynmapChunk.java
Normal file
@ -0,0 +1,9 @@
|
||||
package org.dynmap;
|
||||
|
||||
public class DynmapChunk {
|
||||
public int x,y;
|
||||
public DynmapChunk(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
@ -34,6 +34,12 @@ public class DynmapPlayerListener extends PlayerListener {
|
||||
} else for (int i=2;i<split.length;i++)
|
||||
playerList.show(split[i]);
|
||||
event.setCancelled(true);
|
||||
} else if (split[1].equals("fullrender")) {
|
||||
Player player = event.getPlayer();
|
||||
mgr.renderFullWorld(player.getLocation());
|
||||
} else if (split[1].equals("fullrenderasync")) {
|
||||
Player player = event.getPlayer();
|
||||
mgr.renderFullWorldAsync(player.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ package org.dynmap;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.player.PlayerChatEvent;
|
||||
@ -45,20 +45,23 @@ public class MapManager extends Thread {
|
||||
/* time to pause between rendering tiles (ms) */
|
||||
public int renderWait = 500;
|
||||
|
||||
public void debug(String msg)
|
||||
{
|
||||
public boolean loadChunks = true;
|
||||
|
||||
public void debug(String msg) {
|
||||
debugger.debug(msg);
|
||||
}
|
||||
|
||||
private static File combinePaths(File parent, String path) { return combinePaths(parent, new File(path)); }
|
||||
private static File combinePaths(File parent, String path) {
|
||||
return combinePaths(parent, new File(path));
|
||||
}
|
||||
|
||||
private static File combinePaths(File parent, File path) {
|
||||
if (path.isAbsolute()) return path;
|
||||
if(path.isAbsolute())
|
||||
return path;
|
||||
return new File(parent, path.getPath());
|
||||
}
|
||||
|
||||
public MapManager(World world, Debugger debugger, ConfigurationNode configuration)
|
||||
{
|
||||
public MapManager(World world, Debugger debugger, ConfigurationNode configuration) {
|
||||
this.world = world;
|
||||
this.debugger = debugger;
|
||||
this.staleQueue = new StaleQueue();
|
||||
@ -67,6 +70,7 @@ public class MapManager extends Thread {
|
||||
tileDirectory = combinePaths(DynmapPlugin.dataRoot, configuration.getString("tilespath", "web/tiles"));
|
||||
webDirectory = combinePaths(DynmapPlugin.dataRoot, configuration.getString("webpath", "web"));
|
||||
renderWait = (int) (configuration.getDouble("renderinterval", 0.5) * 1000);
|
||||
loadChunks = configuration.getBoolean("loadchunks", true);
|
||||
|
||||
if(!tileDirectory.isDirectory())
|
||||
tileDirectory.mkdirs();
|
||||
@ -74,6 +78,107 @@ public class MapManager extends Thread {
|
||||
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) {
|
||||
debugger.debug("Full render starting...");
|
||||
for(MapType map : maps) {
|
||||
HashSet<MapTile> found = new HashSet<MapTile>();
|
||||
LinkedList<MapTile> renderQueue = new LinkedList<MapTile>();
|
||||
|
||||
for(MapTile tile : map.getTiles(l)) {
|
||||
if(!(found.contains(tile) || map.isRendered(tile))) {
|
||||
found.add(tile);
|
||||
renderQueue.add(tile);
|
||||
}
|
||||
}
|
||||
while(!renderQueue.isEmpty()) {
|
||||
MapTile tile = renderQueue.pollFirst();
|
||||
|
||||
loadRequiredChunks(tile);
|
||||
debugger.debug("renderQueue: " + renderQueue.size() + "/" + found.size());
|
||||
if(map.render(tile)) {
|
||||
found.remove(tile);
|
||||
staleQueue.onTileUpdated(tile);
|
||||
for(MapTile adjTile : map.getAdjecentTiles(tile)) {
|
||||
if(!(found.contains(adjTile) || map.isRendered(adjTile))) {
|
||||
found.add(adjTile);
|
||||
renderQueue.add(adjTile);
|
||||
}
|
||||
}
|
||||
}
|
||||
found.remove(tile);
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
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) {
|
||||
List<?> configuredMaps = (List<?>) configuration.getProperty("maps");
|
||||
ArrayList<MapType> mapTypes = new ArrayList<MapType>();
|
||||
@ -97,8 +202,7 @@ public class MapManager extends Thread {
|
||||
}
|
||||
|
||||
/* initialize and start map manager */
|
||||
public void startManager()
|
||||
{
|
||||
public void startManager() {
|
||||
synchronized(lock) {
|
||||
running = true;
|
||||
this.start();
|
||||
@ -112,8 +216,7 @@ public class MapManager extends Thread {
|
||||
}
|
||||
|
||||
/* stop map manager */
|
||||
public void stopManager()
|
||||
{
|
||||
public void stopManager() {
|
||||
synchronized(lock) {
|
||||
if(!running)
|
||||
return;
|
||||
@ -130,29 +233,22 @@ public class MapManager extends Thread {
|
||||
}
|
||||
|
||||
/* the worker/renderer thread */
|
||||
public void run()
|
||||
{
|
||||
public void run() {
|
||||
try {
|
||||
log.info("Map renderer has started.");
|
||||
|
||||
while(running) {
|
||||
MapTile t = staleQueue.popStaleTile();
|
||||
if(t != null) {
|
||||
MapType map = t.getMap();
|
||||
World world = map.getWorld();
|
||||
|
||||
Chunk[] requiredChunks = map.getRequiredChunks(t);
|
||||
debugger.debug("Loading " + requiredChunks.length + " chunks for tile " + t + "...");
|
||||
for (int i=0;i<requiredChunks.length;i++) {
|
||||
Chunk requiredChunk = requiredChunks[i];
|
||||
if (!world.isChunkLoaded(requiredChunk))
|
||||
world.loadChunk(requiredChunk);
|
||||
}
|
||||
loadRequiredChunks(t);
|
||||
|
||||
debugger.debug("Rendering tile " + t + "...");
|
||||
t.getMap().render(t);
|
||||
boolean isNonEmptyTile = t.getMap().render(t);
|
||||
staleQueue.onTileUpdated(t);
|
||||
|
||||
if(isNonEmptyTile)
|
||||
handleFullMapRender(t);
|
||||
|
||||
try {
|
||||
Thread.sleep(renderWait);
|
||||
} catch(InterruptedException e) {
|
||||
@ -168,6 +264,7 @@ public class MapManager extends Thread {
|
||||
log.info("Map renderer has stopped.");
|
||||
} catch(Exception ex) {
|
||||
debugger.error("Exception on rendering-thread: " + ex.toString());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,8 +282,7 @@ public class MapManager extends Thread {
|
||||
staleQueue.pushStaleTile(tile);
|
||||
}
|
||||
|
||||
public void addChatEvent(PlayerChatEvent event)
|
||||
{
|
||||
public void addChatEvent(PlayerChatEvent event) {
|
||||
chatQueue.pushChatMessage(event);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.dynmap;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.dynmap.debug.Debugger;
|
||||
@ -29,7 +28,7 @@ public abstract class MapType {
|
||||
|
||||
public abstract MapTile[] getTiles(Location l);
|
||||
public abstract MapTile[] getAdjecentTiles(MapTile tile);
|
||||
public abstract Chunk[] getRequiredChunks(MapTile tile);
|
||||
public abstract DynmapChunk[] getRequiredChunks(MapTile tile);
|
||||
public abstract boolean render(MapTile tile);
|
||||
public abstract boolean isRendered(MapTile tile);
|
||||
}
|
||||
|
@ -25,6 +25,10 @@ public class StaleQueue {
|
||||
tileUpdates = new LinkedList<TileUpdate>();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return staleTilesQueue.size();
|
||||
}
|
||||
|
||||
/* put a MapTile that needs to be regenerated on the list of stale tiles */
|
||||
public boolean pushStaleTile(MapTile m)
|
||||
{
|
||||
|
@ -68,13 +68,13 @@ public class BukkitPlayerDebugger implements Debugger {
|
||||
|
||||
public synchronized void error(String message) {
|
||||
sendToDebuggees(prepend + ChatColor.RED + message);
|
||||
if (isLogging) log.log(Level.SEVERE, prepend + message);
|
||||
log.log(Level.SEVERE, prepend + message);
|
||||
}
|
||||
|
||||
public synchronized void error(String message, Throwable thrown) {
|
||||
sendToDebuggees(prepend + ChatColor.RED + message);
|
||||
sendToDebuggees(thrown.toString());
|
||||
if (isLogging) log.log(Level.SEVERE, prepend + message);
|
||||
log.log(Level.SEVERE, prepend + message);
|
||||
}
|
||||
|
||||
protected class CommandListener extends PlayerListener {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.dynmap.debug;
|
||||
|
||||
public class NullDebugger implements Debugger {
|
||||
public static final NullDebugger instance = new NullDebugger();
|
||||
public void debug(String message) {
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.dynmap.DynmapChunk;
|
||||
import org.dynmap.MapManager;
|
||||
import org.dynmap.MapTile;
|
||||
import org.dynmap.MapType;
|
||||
@ -138,7 +137,7 @@ public class KzedMap extends MapType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk[] getRequiredChunks(MapTile tile) {
|
||||
public DynmapChunk[] getRequiredChunks(MapTile tile) {
|
||||
if (tile instanceof KzedMapTile) {
|
||||
KzedMapTile t = (KzedMapTile) tile;
|
||||
int x1 = t.mx - KzedMap.tileHeight / 2;
|
||||
@ -149,19 +148,18 @@ public class KzedMap extends MapType {
|
||||
|
||||
int x, z;
|
||||
|
||||
ArrayList<Chunk> chunks = new ArrayList<Chunk>();
|
||||
World world = getWorld();
|
||||
ArrayList<DynmapChunk> chunks = new ArrayList<DynmapChunk>();
|
||||
for (x = x1; x < x2; x += 16) {
|
||||
for (z = z1; z < z2; z += 16) {
|
||||
Chunk chunk = world.getChunkAt(x/16, z/16);
|
||||
DynmapChunk chunk = new DynmapChunk(x / 16, z / 16);
|
||||
chunks.add(chunk);
|
||||
}
|
||||
}
|
||||
Chunk[] result = new Chunk[chunks.size()];
|
||||
DynmapChunk[] result = new DynmapChunk[chunks.size()];
|
||||
chunks.toArray(result);
|
||||
return result;
|
||||
} else {
|
||||
return new Chunk[0];
|
||||
return new DynmapChunk[0];
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,8 +184,7 @@ public class KzedMap extends MapType {
|
||||
}
|
||||
|
||||
/* tile X for position x */
|
||||
static int tilex(int x)
|
||||
{
|
||||
static int tilex(int x) {
|
||||
if (x < 0)
|
||||
return x - (tileWidth + (x % tileWidth));
|
||||
else
|
||||
@ -195,8 +192,7 @@ public class KzedMap extends MapType {
|
||||
}
|
||||
|
||||
/* tile Y for position y */
|
||||
static int tiley(int y)
|
||||
{
|
||||
static int tiley(int y) {
|
||||
if (y < 0)
|
||||
return y - (tileHeight + (y % tileHeight));
|
||||
else
|
||||
@ -204,8 +200,7 @@ public class KzedMap extends MapType {
|
||||
}
|
||||
|
||||
/* zoomed-out tile X for tile position x */
|
||||
static int ztilex(int x)
|
||||
{
|
||||
static int ztilex(int x) {
|
||||
if (x < 0)
|
||||
return x + x % zTileWidth;
|
||||
else
|
||||
@ -213,8 +208,7 @@ public class KzedMap extends MapType {
|
||||
}
|
||||
|
||||
/* zoomed-out tile Y for tile position y */
|
||||
static int ztiley(int y)
|
||||
{
|
||||
static int ztiley(int y) {
|
||||
if (y < 0)
|
||||
return y + y % zTileHeight;
|
||||
//return y - (zTileHeight + (y % zTileHeight));
|
||||
|
Loading…
Reference in New Issue
Block a user