From 0c9cfedb6eebc35cbcd334d03934fa7c7dc4ce78 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Mon, 15 Aug 2011 03:16:33 +0800 Subject: [PATCH] Handle tile invalidates better for bigger-than-one-block cases (chunks) --- src/main/java/org/dynmap/DynmapPlugin.java | 29 +++------ src/main/java/org/dynmap/MapManager.java | 15 +++++ src/main/java/org/dynmap/MapType.java | 2 + src/main/java/org/dynmap/flat/FlatMap.java | 29 +++++++++ src/main/java/org/dynmap/hdmap/HDMap.java | 5 ++ .../java/org/dynmap/hdmap/HDPerspective.java | 2 + .../org/dynmap/hdmap/IsoHDPerspective.java | 62 +++++++++++++++++++ src/main/java/org/dynmap/kzedmap/KzedMap.java | 32 ++++++++++ 8 files changed, 155 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index 87e59348..300d8a8e 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -412,14 +412,11 @@ public class DynmapPlugin extends JavaPlugin { return; mm.sscache.invalidateSnapshot(event.getBlock().getLocation()); Block b = event.getBlock(); - if(onpiston) - mm.touch(b.getLocation()); BlockFace dir = event.getDirection(); + if(onpiston) + mm.touchVolume(b.getLocation(), b.getRelative(dir, 2).getLocation()); for(int i = 0; i < 2; i++) { - b = b.getRelative(dir, 1); mm.sscache.invalidateSnapshot(b.getLocation()); - if(onpiston) - mm.touch(b.getLocation()); } } @Override @@ -428,14 +425,12 @@ public class DynmapPlugin extends JavaPlugin { return; mm.sscache.invalidateSnapshot(event.getBlock().getLocation()); Block b = event.getBlock(); - if(onpiston) - mm.touch(b.getLocation()); BlockFace dir = event.getDirection(); + if(onpiston) + mm.touchVolume(b.getLocation(), b.getRelative(dir, 1+event.getLength()).getLocation()); for(int i = 0; i < 1+event.getLength(); i++) { b = b.getRelative(dir, 1); mm.sscache.invalidateSnapshot(b.getLocation()); - if(onpiston) - mm.touch(b.getLocation()); } } }; @@ -492,19 +487,11 @@ public class DynmapPlugin extends JavaPlugin { if(generate_only) { if(!isNewChunk(event)) return; - /* Touch extreme corners */ - int x = event.getChunk().getX() * 16; - int z = event.getChunk().getZ() * 16; - mm.touch(new Location(event.getWorld(), x, 0, z)); - mm.touch(new Location(event.getWorld(), x+15, 127, z)); - mm.touch(new Location(event.getWorld(), x+15, 0, z+15)); - mm.touch(new Location(event.getWorld(), x, 127, z+15)); - } - else { - int x = event.getChunk().getX() * 16 + 8; - int z = event.getChunk().getZ() * 16 + 8; - mm.touch(new Location(event.getWorld(), x, 127, z)); } + /* Touch extreme corners */ + int x = event.getChunk().getX() << 4; + int z = event.getChunk().getZ() << 4; + mm.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+15, 127, z+15)); } private boolean isNewChunk(ChunkLoadEvent event) { return event.isNewChunk(); diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index d012762b..2bedb159 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -642,6 +642,21 @@ public class MapManager { return invalidates; } + public int touchVolume(Location l0, Location l1) { + DynmapWorld world = getWorld(l0.getWorld().getName()); + if (world == null) + return 0; + int invalidates = 0; + for (int i = 0; i < world.maps.size(); i++) { + MapTile[] tiles = world.maps.get(i).getTiles(l0, l1); + for (int j = 0; j < tiles.length; j++) { + invalidateTile(tiles[j]); + invalidates++; + } + } + return invalidates; + } + public void invalidateTile(MapTile tile) { Debug.debug("Invalidating tile " + tile.getFilename()); tileQueue.push(tile); diff --git a/src/main/java/org/dynmap/MapType.java b/src/main/java/org/dynmap/MapType.java index ba1d9642..fe9ddd95 100644 --- a/src/main/java/org/dynmap/MapType.java +++ b/src/main/java/org/dynmap/MapType.java @@ -19,6 +19,8 @@ public abstract class MapType { public abstract MapTile[] getTiles(Location l); + public abstract MapTile[] getTiles(Location l0, Location l1); + public abstract MapTile[] getAdjecentTiles(MapTile tile); public abstract List getRequiredChunks(MapTile tile); diff --git a/src/main/java/org/dynmap/flat/FlatMap.java b/src/main/java/org/dynmap/flat/FlatMap.java index 9788df71..136e87e9 100644 --- a/src/main/java/org/dynmap/flat/FlatMap.java +++ b/src/main/java/org/dynmap/flat/FlatMap.java @@ -95,6 +95,35 @@ public class FlatMap extends MapType { return new MapTile[] { new FlatMapTile(w, this, (int) Math.floor(l.getBlockX() / 128.0), (int) Math.floor(l.getBlockZ() / 128.0), 128) }; } + @Override + public MapTile[] getTiles(Location l0, Location l1) { + DynmapWorld w = MapManager.mapman.getWorld(l0.getWorld().getName()); + int xmin, xmax, zmin, zmax; + if(l0.getBlockX() < l1.getBlockX()) { + xmin = l0.getBlockX() >> 7; + xmax = l1.getBlockX() >> 7; + } + else { + xmin = l1.getBlockX() >> 7; + xmax = l0.getBlockX() >> 7; + } + if(l0.getBlockZ() < l1.getBlockZ()) { + zmin = l0.getBlockZ() >> 7; + zmax = l1.getBlockZ() >> 7; + } + else { + zmin = l1.getBlockZ() >> 7; + zmax = l0.getBlockZ() >> 7; + } + ArrayList rslt = new ArrayList(); + for(int i = xmin; i <= xmax; i++) { + for(int j = zmin; j < zmax; j++) { + rslt.add(new FlatMapTile(w, this, i, j, 128)); + } + } + return rslt.toArray(new MapTile[rslt.size()]); + } + @Override public MapTile[] getAdjecentTiles(MapTile tile) { FlatMapTile t = (FlatMapTile) tile; diff --git a/src/main/java/org/dynmap/hdmap/HDMap.java b/src/main/java/org/dynmap/hdmap/HDMap.java index 3a672990..1af608fb 100644 --- a/src/main/java/org/dynmap/hdmap/HDMap.java +++ b/src/main/java/org/dynmap/hdmap/HDMap.java @@ -106,6 +106,11 @@ public class HDMap extends MapType { return perspective.getTiles(loc); } + @Override + public MapTile[] getTiles(Location loc0, Location loc1) { + return perspective.getTiles(loc0, loc1); + } + @Override public MapTile[] getAdjecentTiles(MapTile tile) { return perspective.getAdjecentTiles(tile); diff --git a/src/main/java/org/dynmap/hdmap/HDPerspective.java b/src/main/java/org/dynmap/hdmap/HDPerspective.java index 6ef2ee5e..3dd74aed 100644 --- a/src/main/java/org/dynmap/hdmap/HDPerspective.java +++ b/src/main/java/org/dynmap/hdmap/HDPerspective.java @@ -13,6 +13,8 @@ public interface HDPerspective { String getName(); /* Get tiles invalidated by change at given location */ MapTile[] getTiles(Location loc); + /* Get tiles invalidated by change at given volume, defined by 2 opposite corner locations */ + MapTile[] getTiles(Location loc0, Location loc1); /* Get tiles adjacent to given tile */ MapTile[] getAdjecentTiles(MapTile tile); /* Get chunks needed for given tile */ diff --git a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java index f1d48ab9..837b14c1 100644 --- a/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java +++ b/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java @@ -726,6 +726,68 @@ public class IsoHDPerspective implements HDPerspective { return tiles.toArray(new MapTile[tiles.size()]); } + @Override + public MapTile[] getTiles(Location loc0, Location loc1) { + DynmapWorld world = MapManager.mapman.getWorld(loc0.getWorld().getName()); + HashSet tiles = new HashSet(); + Vector3D blocks[] = new Vector3D[] { new Vector3D(), new Vector3D() }; + /* Get ordered point - 0=minX,Y,Z, 1=maxX,Y,Z */ + if(loc0.getBlockX() < loc1.getBlockX()) { + blocks[0].x = loc0.getBlockX(); + blocks[1].x = loc1.getBlockX() + 1; + } + else { + blocks[0].x = loc1.getBlockX(); + blocks[1].x = loc0.getBlockX() + 1; + } + if(loc0.getBlockY() < loc1.getBlockY()) { + blocks[0].y = loc0.getBlockY(); + blocks[1].y = loc1.getBlockY() + 1; + } + else { + blocks[0].y = loc1.getBlockY(); + blocks[1].y = loc0.getBlockY() + 1; + } + if(loc0.getBlockZ() < loc1.getBlockZ()) { + blocks[0].z = loc0.getBlockZ(); + blocks[1].z = loc1.getBlockZ() + 1; + } + else { + blocks[0].z = loc1.getBlockZ(); + blocks[1].z = loc0.getBlockZ() + 1; + } + Vector3D corner = new Vector3D(); + Vector3D tcorner = new Vector3D(); + int mintilex = Integer.MAX_VALUE; + int maxtilex = Integer.MIN_VALUE; + int mintiley = Integer.MAX_VALUE; + int maxtiley = Integer.MIN_VALUE; + /* Loop through corners of the prism */ + for(int i = 0; i < 2; i++) { + corner.x = blocks[i].x; + for(int j = 0; j < 2; j++) { + corner.y = blocks[j].y; + for(int k = 0; k < 2; k++) { + corner.z = blocks[k].z; + world_to_map.transform(corner, tcorner); /* Get map coordinate of corner */ + int tx = (int)Math.floor(tcorner.x/tileWidth); + int ty = (int)Math.floor(tcorner.y/tileWidth); + if(mintilex > tx) mintilex = tx; + if(maxtilex < tx) maxtilex = tx; + if(mintiley > ty) mintiley = ty; + if(maxtiley < ty) maxtiley = ty; + } + } + } + /* Now, add the tiles for the ranges - not perfect, but it works (some extra tiles on corners possible) */ + for(int i = mintilex; i <= maxtilex; i++) { + for(int j = mintiley; j < maxtiley; j++) { + addTile(tiles, world, i, j); + } + } + return tiles.toArray(new MapTile[tiles.size()]); + } + @Override public MapTile[] getAdjecentTiles(MapTile tile) { HDMapTile t = (HDMapTile) tile; diff --git a/src/main/java/org/dynmap/kzedmap/KzedMap.java b/src/main/java/org/dynmap/kzedmap/KzedMap.java index 70169c64..b15c3afe 100644 --- a/src/main/java/org/dynmap/kzedmap/KzedMap.java +++ b/src/main/java/org/dynmap/kzedmap/KzedMap.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.logging.Logger; @@ -21,6 +22,7 @@ import org.dynmap.MapType; import org.dynmap.MapType.MapStep; import org.dynmap.utils.DynmapBufferedImage; import org.dynmap.utils.MapChunkCache; +import org.dynmap.utils.Vector3D; import org.json.simple.JSONObject; import java.awt.image.DataBufferInt; import java.awt.image.DataBuffer; @@ -109,6 +111,36 @@ public class KzedMap extends MapType { return result; } + @Override + public MapTile[] getTiles(Location loc0, Location loc1) { + DynmapWorld world = MapManager.mapman.getWorld(loc0.getWorld().getName()); + ArrayList tiles = new ArrayList(); + /* Transform both to tile coordinates */ + int dx = loc0.getBlockX() - anchorx; + int dy = loc0.getBlockY() - anchory; + int dz = loc0.getBlockZ() - anchorz; + int px0 = dx + dz; + int py0 = dx - dz - dy; + dx = loc0.getBlockX() - anchorx; + dy = loc0.getBlockY() - anchory; + dz = loc0.getBlockZ() - anchorz; + int px1 = dx + dz; + int py1 = dx - dz - dy; + /* Compute ranges */ + int mintx = (px1> 7; i <= maxtx >> 7; i++) { + for(int j = minty >> 7; j < maxty >> 7; j++) { + addTile(tiles, world, i << 7, j << 7); + } + } + return tiles.toArray(new MapTile[tiles.size()]); + } + @Override public MapTile[] getAdjecentTiles(MapTile tile) { if (tile instanceof KzedMapTile) {