Compare commits

..

10 Commits

67 changed files with 809 additions and 2770 deletions
+1 -7
View File
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.dynmap</groupId>
<artifactId>dynmap</artifactId>
<version>0.21</version>
<version>0.20.1</version>
<name>dynmap</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -29,12 +29,6 @@
<descriptors>
<descriptor>src/main/assembly/package.xml</descriptor>
</descriptors>
<!-- Hack for bug in maven-assembly: http://jira.codehaus.org/browse/MASSEMBLY-449 -->
<archiverConfig>
<fileMode>420</fileMode> <!-- 420(dec) = 644(oct) -->
<directoryMode>493</directoryMode> <!-- 493(dec) = 755(oct) -->
<defaultDirectoryMode>493</defaultDirectoryMode>
</archiverConfig>
</configuration>
<executions>
<execution>
+17 -25
View File
@@ -2,7 +2,6 @@ package org.dynmap;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.Material;
public class Armor {
@@ -11,34 +10,27 @@ public class Armor {
* We rely on getArmorContents() to return 4 armor pieces in the order
* of: boots, pants, chest, helmet
*/
private static final int armorPoints[] = {3, 6, 8, 3};
private static final double armorPoints[] = {1.5, 3.0, 4.0, 1.5};
public static final int getArmorPoints(Player player) {
int currentDurability = 0;
int baseDurability = 0;
int baseArmorPoints = 0;
ItemStack[] itm = new ItemStack[4];
PlayerInventory inv = player.getInventory();
itm[0] = inv.getBoots();
itm[1]= inv.getLeggings();
itm[2] = inv.getChestplate();
itm[3] = inv.getHelmet();
for(int i = 0; i < 4; i++) {
if(itm[i] == null) continue;
int dur = itm[i].getDurability();
int max = itm[i].getType().getMaxDurability();
if(max <= 0) continue;
if(i == 2)
max = max + 1; /* Always 1 too low for chestplate */
else
max = max - 3; /* Always 3 too high, versus how client calculates it */
baseDurability += max;
currentDurability += max - dur;
baseArmorPoints += armorPoints[i];
double baseArmorPoints = 0;
ItemStack inventory[] = player.getInventory().getArmorContents();
for(int i=0;i<inventory.length;i++) {
if(inventory[i] == null)
continue;
Material m = inventory[i].getType();
if(m == null)
continue;
final short maxDurability = m.getMaxDurability();
if(maxDurability < 0)
continue;
final short durability = inventory[i].getDurability();
baseDurability += maxDurability;
currentDurability += maxDurability - durability;
baseArmorPoints += armorPoints[i];
}
int ap = 0;
if(baseDurability > 0)
ap = ((baseArmorPoints - 1) * currentDurability) / baseDurability + 1;
return ap;
return (int)Math.round(2*baseArmorPoints*currentDurability/baseDurability);
}
}
+12 -14
View File
@@ -12,14 +12,10 @@ public class AsynchronousQueue<T> {
private Set<T> set = new HashSet<T>();
private Handler<T> handler;
private int dequeueTime;
private int accelDequeueTime;
private int accelDequeueThresh;
public AsynchronousQueue(Handler<T> handler, int dequeueTime, int accelDequeueThresh, int accelDequeueTime) {
public AsynchronousQueue(Handler<T> handler, int dequeueTime) {
this.handler = handler;
this.dequeueTime = dequeueTime;
this.accelDequeueTime = accelDequeueTime;
this.accelDequeueThresh = accelDequeueThresh;
}
public boolean push(T t) {
@@ -34,10 +30,15 @@ public class AsynchronousQueue<T> {
private T pop() {
synchronized (lock) {
T t = queue.pollFirst();
if(t != null)
set.remove(t);
return t;
try {
T t = queue.removeFirst();
if (!set.remove(t)) {
// This should never happen.
}
return t;
} catch (NoSuchElementException e) {
return null;
}
}
}
@@ -87,10 +88,7 @@ public class AsynchronousQueue<T> {
if (t != null) {
handler.handle(t);
}
if(set.size() >= accelDequeueThresh)
sleep(accelDequeueTime);
else
sleep(dequeueTime);
sleep(dequeueTime);
}
} catch (Exception ex) {
@@ -42,9 +42,7 @@ public class ClientUpdateComponent extends Component {
s(jp, "account", p.getName());
/* Don't leak player location for world not visible on maps, or if sendposition disbaled */
DynmapWorld pworld = MapManager.mapman.worldsLookup.get(p.getWorld().getName());
/* Fix typo on 'sendpositon' to 'sendposition', keep bad one in case someone used it */
if(configuration.getBoolean("sendposition", true) && configuration.getBoolean("sendpositon", true) &&
(pworld != null) && pworld.sendposition) {
if(configuration.getBoolean("sendpositon", true) && (pworld != null) && pworld.sendposition) {
s(jp, "world", p.getWorld().getName());
s(jp, "x", pl.getX());
s(jp, "y", pl.getY());
File diff suppressed because it is too large Load Diff
+7 -19
View File
@@ -6,6 +6,7 @@ import java.util.List;
import org.bukkit.World;
import org.bukkit.Location;
import org.dynmap.debug.Debug;
import org.dynmap.kzedmap.KzedMap;
import org.dynmap.utils.DynmapBufferedImage;
import org.dynmap.utils.FileLockManager;
import org.dynmap.utils.MapChunkCache;
@@ -31,7 +32,6 @@ public class DynmapWorld {
public ConfigurationNode configuration;
public List<Location> seedloc;
public List<MapChunkCache.VisibilityLimit> visibility_limits;
public List<MapChunkCache.VisibilityLimit> hidden_limits;
public AutoGenerateOption do_autogenerate;
public MapChunkCache.HiddenChunkStyle hiddenchunkstyle;
public int servertime;
@@ -104,21 +104,11 @@ public class DynmapWorld {
}
}
private static final String COORDSTART = "-0123456789";
private static class PNGFileFilter implements FilenameFilter {
String prefix;
String suffix;
public PNGFileFilter(String pre, MapType.ImageFormat fmt) {
if((pre != null) && (pre.length() > 0))
prefix = pre;
suffix = "." + fmt.getFileExt();
}
public PNGFileFilter(String pre) { prefix = pre; }
public boolean accept(File f, String n) {
if(n.endsWith(suffix)) {
if((prefix != null) && (!n.startsWith(prefix)))
return false;
if((prefix == null) && (COORDSTART.indexOf(n.charAt(0)) < 0))
return false;
if(n.endsWith(".png") && n.startsWith(prefix)) {
File fn = new File(f, n);
return fn.isFile();
}
@@ -156,7 +146,6 @@ public class DynmapWorld {
String zfnprefix;
int bigworldshift;
boolean isbigmap;
MapType.ImageFormat fmt;
}
public boolean freshenZoomOutFilesByLevel(int zoomlevel) {
@@ -263,7 +252,6 @@ public class DynmapWorld {
pd.zoomprefix = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz".substring(0, zoomlevel);
pd.bigworldshift = bigworldshift;
pd.isbigmap = mt.isBigWorldMap(this);
pd.fmt = mt.getImageFormat();
if(pd.isbigmap) {
if(zoomlevel > 0) {
pd.zoomprefix += "_";
@@ -294,15 +282,15 @@ public class DynmapWorld {
private String makeFilePath(PrefixData pd, int x, int y, boolean zoomed) {
if(pd.isbigmap)
return pd.baseprefix + "/" + (x >> pd.bigworldshift) + "_" + (y >> pd.bigworldshift) + "/" + (zoomed?pd.zfnprefix:pd.fnprefix) + x + "_" + y + "." + pd.fmt.getFileExt();
return pd.baseprefix + "/" + (x >> pd.bigworldshift) + "_" + (y >> pd.bigworldshift) + "/" + (zoomed?pd.zfnprefix:pd.fnprefix) + x + "_" + y + ".png";
else
return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + "." + pd.fmt.getFileExt();
return (zoomed?pd.zfnprefix:pd.fnprefix) + "_" + x + "_" + y + ".png";
}
private int processZoomDirectory(File dir, PrefixData pd) {
Debug.debug("processZoomDirectory(" + dir.getPath() + "," + pd.baseprefix + ")");
HashMap<String, ProcessTileRec> toprocess = new HashMap<String, ProcessTileRec>();
String[] files = dir.list(new PNGFileFilter(pd.fnprefix, pd.fmt));
String[] files = dir.list(new PNGFileFilter(pd.fnprefix));
if(files == null)
return 0;
for(String fn : files) {
@@ -446,7 +434,7 @@ public class DynmapWorld {
try {
if(!zf.getParentFile().exists())
zf.getParentFile().mkdirs();
FileLockManager.imageIOWrite(zIm, pd.fmt, zf);
FileLockManager.imageIOWrite(zIm, "png", zf);
Debug.debug("Saved zoom-out tile at " + zf.getPath());
} catch (IOException e) {
Debug.error("Failed to save zoom-out tile: " + zf.getName(), e);
+88 -215
View File
@@ -11,7 +11,6 @@ import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledFuture;
@@ -30,7 +29,6 @@ import org.dynmap.utils.LegacyMapChunkCache;
import org.dynmap.utils.MapChunkCache;
import org.dynmap.utils.NewMapChunkCache;
import org.dynmap.utils.SnapshotCache;
import org.dynmap.utils.TileFlags;
public class MapManager {
public AsynchronousQueue<MapTile> tileQueue;
@@ -43,8 +41,6 @@ public class MapManager {
private DynmapPlugin plug_in;
private long timeslice_int = 0; /* In milliseconds */
private int max_chunk_loads_per_tick = DEFAULT_CHUNKS_PER_TICK;
private int parallelrendercnt = 0;
private int progressinterval = 100;
private int zoomout_period = DEFAULT_ZOOMOUT_PERIOD; /* Zoom-out tile processing period, in seconds */
/* Which fullrenders are active */
@@ -99,7 +95,7 @@ public class MapManager {
private class DynmapScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
DynmapScheduledThreadPoolExecutor() {
super(POOL_SIZE + parallelrendercnt);
super(POOL_SIZE);
this.setThreadFactory(new OurThreadFactory());
/* Set shutdown policy to stop everything */
setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
@@ -155,10 +151,11 @@ public class MapManager {
Location loc;
int map_index = -1; /* Which map are we on */
MapType map;
TileFlags found = null;
TileFlags rendered = null;
HashSet<MapTile> found = null;
HashSet<MapTile> rendered = null;
LinkedList<MapTile> renderQueue = null;
MapTile tile0 = null;
MapTile tile = null;
int rendercnt = 0;
CommandSender sender;
long timeaccum;
@@ -169,20 +166,19 @@ public class MapManager {
int cxmin, cxmax, czmin, czmax;
String rendertype;
boolean cancelled;
String mapname;
/* Full world, all maps render */
FullWorldRenderState(DynmapWorld dworld, Location l, CommandSender sender, String mapname) {
this(dworld, l, sender, mapname, -1);
FullWorldRenderState(DynmapWorld dworld, Location l, CommandSender sender) {
this(dworld, l, sender, -1);
rendertype = "Full render";
}
/* Full world, all maps render, with optional render radius */
FullWorldRenderState(DynmapWorld dworld, Location l, CommandSender sender, String mapname, int radius) {
FullWorldRenderState(DynmapWorld dworld, Location l, CommandSender sender, int radius) {
world = dworld;
loc = l;
found = new TileFlags();
rendered = new TileFlags();
found = new HashSet<MapTile>();
rendered = new HashSet<MapTile>();
renderQueue = new LinkedList<MapTile>();
this.sender = sender;
if(radius < 0) {
@@ -197,7 +193,6 @@ public class MapManager {
czmax = (l.getBlockZ() + radius+15)>>4;
rendertype = "Radius render";
}
this.mapname = mapname;
}
/* Single tile render - used for incremental renders */
@@ -209,7 +204,7 @@ public class MapManager {
}
public String toString() {
return "world=" + world.world.getName() + ", map=" + map;
return "world=" + world.world.getName() + ", map=" + map + " tile=" + tile;
}
public void cleanup() {
@@ -221,8 +216,6 @@ public class MapManager {
}
public void run() {
long tstart = System.currentTimeMillis();
MapTile tile = null;
List<MapTile> tileset = null;
if(cancelled) {
cleanup();
@@ -247,17 +240,8 @@ public class MapManager {
/* Advance to next unrendered map */
while(map_index < world.maps.size()) {
map_index++; /* Move to next one */
if(map_index >= world.maps.size()) break;
/* If single map render, see if this is our target */
if(mapname != null) {
if(world.maps.get(map_index).getName().equals(mapname)) {
break;
}
}
else {
if(renderedmaps.contains(world.maps.get(map_index)) == false)
break;
}
if((map_index < world.maps.size()) && (renderedmaps.contains(world.maps.get(map_index)) == false))
break;
}
if(map_index >= world.maps.size()) { /* Last one done? */
sender.sendMessage(rendertype + " of '" + world.world.getName() + "' finished.");
@@ -269,8 +253,6 @@ public class MapManager {
/* Build active map list */
activemaps = "";
for(String n : activemaplist) {
if((mapname != null) && (!mapname.equals(n)))
continue;
if(activemaps.length() > 0)
activemaps += ",";
activemaps += n;
@@ -280,96 +262,28 @@ public class MapManager {
/* Now, prime the render queue */
for (MapTile mt : map.getTiles(loc)) {
if (!found.getFlag(mt.tileOrdinalX(), mt.tileOrdinalY())) {
found.setFlag(mt.tileOrdinalX(), mt.tileOrdinalY(), true);
if (!found.contains(mt)) {
found.add(mt);
renderQueue.add(mt);
}
}
if(world.seedloc != null) {
for(Location seed : world.seedloc) {
for (MapTile mt : map.getTiles(seed)) {
if (!found.getFlag(mt.tileOrdinalX(),mt.tileOrdinalY())) {
found.setFlag(mt.tileOrdinalX(),mt.tileOrdinalY(), true);
if (!found.contains(mt)) {
found.add(mt);
renderQueue.add(mt);
}
}
}
}
}
if(parallelrendercnt > 1) { /* Doing parallel renders? */
tileset = new ArrayList<MapTile>();
for(int i = 0; i < parallelrendercnt; i++) {
tile = renderQueue.pollFirst();
if(tile != null)
tileset.add(tile);
}
}
else {
tile = renderQueue.pollFirst();
}
tile = renderQueue.pollFirst();
}
else { /* Else, single tile render */
tile = tile0;
}
World w = world.world;
boolean notdone = true;
if(tileset != null) {
long save_timeaccum = timeaccum;
List<Future<Boolean>> rslt = new ArrayList<Future<Boolean>>();
final int cnt = tileset.size();
for(int i = 1; i < cnt; i++) { /* Do all but first on other threads */
final MapTile mt = tileset.get(i);
if((mapman != null) && (mapman.render_pool != null)) {
final long ts = tstart;
Future<Boolean> future = mapman.render_pool.submit(new Callable<Boolean>() {
public Boolean call() {
return processTile(mt, mt.world.world, ts, cnt);
}
});
rslt.add(future);
}
}
/* Now, do our render (first one) */
notdone = processTile(tileset.get(0), w, tstart, cnt);
/* Now, join with others */
for(int i = 0; i < rslt.size(); i++) {
try {
notdone = notdone && rslt.get(i).get();
} catch (ExecutionException xx) {
Log.severe(xx);
notdone = false;
} catch (InterruptedException ix) {
notdone = false;
}
}
timeaccum = save_timeaccum + System.currentTimeMillis() - tstart;
}
else {
notdone = processTile(tile, w, tstart, 1);
}
if(notdone) {
if(tile0 == null) { /* fullrender */
long tend = System.currentTimeMillis();
if(timeslice_int > (tend-tstart)) { /* We were fast enough */
scheduleDelayedJob(this, timeslice_int - (tend-tstart));
}
else { /* Schedule to run ASAP */
scheduleDelayedJob(this, 0);
}
}
else {
cleanup();
}
}
else {
cleanup();
}
}
private boolean processTile(MapTile tile, World w, long tstart, int parallelcnt) {
/* Get list of chunks required for tile */
List<DynmapChunk> requiredChunks = tile.getRequiredChunks();
/* If we are doing radius limit render, see if any are inside limits */
@@ -388,49 +302,55 @@ public class MapManager {
tile.isHightestBlockYDataNeeded(), tile.isBiomeDataNeeded(),
tile.isRawBiomeDataNeeded());
if(cache == null) {
return false; /* Cancelled/aborted */
cleanup();
return; /* Cancelled/aborted */
}
if(tile0 != null) { /* Single tile? */
if(cache.isEmpty() == false)
tile.render(cache, null);
tile.render(cache);
}
else {
/* Switch to not checking if rendered tile is blank - breaks us on skylands, where tiles can be nominally blank - just work off chunk cache empty */
/* Switch to not checking if rendered tile is blank - breaks us on skylands, where tiles can be nominally blank - just work off chunk cache empty */
if (cache.isEmpty() == false) {
tile.render(cache, mapname);
synchronized(lock) {
// found.setFlag(tile.tileOrdinalX(),tile.tileOrdinalY(),false);
rendered.setFlag(tile.tileOrdinalX(), tile.tileOrdinalY(), true);
for (MapTile adjTile : map.getAdjecentTiles(tile)) {
if (!found.getFlag(adjTile.tileOrdinalX(),adjTile.tileOrdinalY()) &&
!rendered.getFlag(adjTile.tileOrdinalX(),adjTile.tileOrdinalY())) {
found.setFlag(adjTile.tileOrdinalX(), adjTile.tileOrdinalY(), true);
renderQueue.add(adjTile);
}
tile.render(cache);
found.remove(tile);
rendered.add(tile);
for (MapTile adjTile : map.getAdjecentTiles(tile)) {
if (!found.contains(adjTile) && !rendered.contains(adjTile)) {
found.add(adjTile);
renderQueue.add(adjTile);
}
}
}
synchronized(lock) {
// found.setFlag(tile.tileOrdinalX(), tile.tileOrdinalY(), false);
if(!cache.isEmpty()) {
rendercnt++;
timeaccum += System.currentTimeMillis() - tstart;
if((rendercnt % progressinterval) == 0) {
double msecpertile = (double)timeaccum / (double)rendercnt / (double)activemaplist.size();
if(activemaplist.size() > 1)
sender.sendMessage(rendertype + " of maps [" + activemaps + "] of '" +
found.remove(tile);
if(!cache.isEmpty()) {
rendercnt++;
timeaccum += System.currentTimeMillis() - tstart;
if((rendercnt % 100) == 0) {
double msecpertile = (double)timeaccum / (double)rendercnt / (double)activemaplist.size();
if(activemaplist.size() > 1)
sender.sendMessage(rendertype + " of maps [" + activemaps + "] of '" +
w.getName() + "' in progress - " + rendercnt + " tiles rendered each (" + String.format("%.2f", msecpertile) + " msec/map-tile).");
else
sender.sendMessage(rendertype + " of map '" + activemaps + "' of '" +
else
sender.sendMessage(rendertype + " of map '" + activemaps + "' of '" +
w.getName() + "' in progress - " + rendercnt + " tiles rendered (" + String.format("%.2f", msecpertile) + " msec/tile).");
}
}
}
}
/* And unload what we loaded */
cache.unloadChunks();
return true;
if(tile0 == null) { /* fullrender */
long tend = System.currentTimeMillis();
if(timeslice_int > (tend-tstart)) { /* We were fast enough */
scheduleDelayedJob(this, timeslice_int - (tend-tstart));
}
else { /* Schedule to run ASAP */
scheduleDelayedJob(this, 0);
}
}
else {
cleanup();
}
}
public void cancelRender() {
@@ -487,20 +407,13 @@ public class MapManager {
hdmapman.loadHDPerspectives(plugin);
hdmapman.loadHDLightings(plugin);
sscache = new SnapshotCache(configuration.getInteger("snapshotcachesize", 500));
parallelrendercnt = configuration.getInteger("parallelrendercnt", 0);
progressinterval = configuration.getInteger("progressloginterval", 100);
if(progressinterval < 100) progressinterval = 100;
this.tileQueue = new AsynchronousQueue<MapTile>(
new Handler<MapTile>() {
@Override
public void handle(MapTile t) {
scheduleDelayedJob(new FullWorldRenderState(t), 0);
}
},
(int) (configuration.getDouble("renderinterval", 0.5) * 1000),
configuration.getInteger("renderacceleratethreshold", 30),
(int)(configuration.getDouble("renderaccelerateinterval", 0.2) * 1000));
this.tileQueue = new AsynchronousQueue<MapTile>(new Handler<MapTile>() {
@Override
public void handle(MapTile t) {
scheduleDelayedJob(new FullWorldRenderState(t), 0);
}
}, (int) (configuration.getDouble("renderinterval", 0.5) * 1000));
/* On dedicated thread, so default to no delays */
timeslice_int = (long)(configuration.getDouble("timesliceinterval", 0.0) * 1000);
@@ -521,7 +434,7 @@ public class MapManager {
}
}
void renderFullWorld(Location l, CommandSender sender, String mapname) {
void renderFullWorld(Location l, CommandSender sender) {
DynmapWorld world = getWorld(l.getWorld().getName());
if (world == null) {
sender.sendMessage("Could not render: world '" + l.getWorld().getName() + "' not defined in configuration.");
@@ -535,7 +448,7 @@ public class MapManager {
sender.sendMessage(rndr.rendertype + " of world '" + wname + "' already active.");
return;
}
rndr = new FullWorldRenderState(world,l,sender, mapname); /* Make new activation record */
rndr = new FullWorldRenderState(world,l,sender); /* Make new activation record */
active_renders.put(wname, rndr); /* Add to active table */
}
/* Schedule first tile to be worked */
@@ -544,7 +457,7 @@ public class MapManager {
sender.sendMessage("Full render starting on world '" + wname + "'...");
}
void renderWorldRadius(Location l, CommandSender sender, String mapname, int radius) {
void renderWorldRadius(Location l, CommandSender sender, int radius) {
DynmapWorld world = getWorld(l.getWorld().getName());
if (world == null) {
sender.sendMessage("Could not render: world '" + l.getWorld().getName() + "' not defined in configuration.");
@@ -558,7 +471,7 @@ public class MapManager {
sender.sendMessage(rndr.rendertype + " of world '" + wname + "' already active.");
return;
}
rndr = new FullWorldRenderState(world,l,sender, mapname, radius); /* Make new activation record */
rndr = new FullWorldRenderState(world,l,sender, radius); /* Make new activation record */
active_renders.put(wname, rndr); /* Add to active table */
}
/* Schedule first tile to be worked */
@@ -637,19 +550,6 @@ public class MapManager {
dynmapWorld.seedloc.add(new Location(w, (lim.x0+lim.x1)/2, 64, (lim.z0+lim.z1)/2));
}
}
/* Load hidden limits, if any are defined */
List<ConfigurationNode> hidelimits = worldConfiguration.getNodes("hiddenlimits");
if(hidelimits != null) {
dynmapWorld.hidden_limits = new ArrayList<MapChunkCache.VisibilityLimit>();
for(ConfigurationNode vis : hidelimits) {
MapChunkCache.VisibilityLimit lim = new MapChunkCache.VisibilityLimit();
lim.x0 = vis.getInteger("x0", 0);
lim.x1 = vis.getInteger("x1", 0);
lim.z0 = vis.getInteger("z0", 0);
lim.z1 = vis.getInteger("z1", 0);
dynmapWorld.hidden_limits.add(lim);
}
}
String autogen = worldConfiguration.getString("autogenerate-to-visibilitylimits", "none");
if(autogen.equals("permanent")) {
dynmapWorld.do_autogenerate = AutoGenerateOption.PERMANENT;
@@ -714,24 +614,9 @@ 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) {
if(tileQueue.push(tile))
Debug.debug("Invalidating tile " + tile.getFilename());
Debug.debug("Invalidating tile " + tile.getFilename());
tileQueue.push(tile);
}
public static void scheduleDelayedJob(Runnable job, long delay_in_msec) {
@@ -822,13 +707,6 @@ public class MapManager {
c.setHiddenFillStyle(w.hiddenchunkstyle);
c.setAutoGenerateVisbileRanges(w.do_autogenerate);
}
if(w.hidden_limits != null) {
for(MapChunkCache.VisibilityLimit limit: w.hidden_limits) {
c.setHiddenRange(limit);
}
c.setHiddenFillStyle(w.hiddenchunkstyle);
}
c.setChunks(w.world, chunks);
if(c.setChunkDataTypes(blockdata, biome, highesty, rawbiome) == false)
Log.severe("CraftBukkit build does not support biome APIs");
@@ -836,37 +714,33 @@ public class MapManager {
return c;
}
final MapChunkCache cc = c;
while(!cc.isDoneLoading()) {
synchronized(loadlock) {
long now = System.currentTimeMillis();
if(cur_tick != (now/50)) { /* New tick? */
chunks_in_cur_tick = max_chunk_loads_per_tick;
cur_tick = now/50;
}
}
Future<Boolean> f = scheduler.callSyncMethod(plug_in, new Callable<Boolean>() {
public Boolean call() throws Exception {
boolean exhausted;
synchronized(loadlock) {
if(chunks_in_cur_tick > 0)
chunks_in_cur_tick -= cc.loadChunks(chunks_in_cur_tick);
exhausted = (chunks_in_cur_tick == 0);
}
return exhausted;
synchronized(loadlock) {
final MapChunkCache cc = c;
long now = System.currentTimeMillis();
if(cur_tick != (now/50)) { /* New tick? */
chunks_in_cur_tick = max_chunk_loads_per_tick;
cur_tick = now/50;
}
while(!cc.isDoneLoading()) {
final int cntin = chunks_in_cur_tick;
Future<Integer> f = scheduler.callSyncMethod(plug_in, new Callable<Integer>() {
public Integer call() throws Exception {
return Integer.valueOf(cntin - cc.loadChunks(cntin));
}
});
try {
chunks_in_cur_tick = f.get();
} catch (Exception ix) {
Log.severe(ix);
return null;
}
if(chunks_in_cur_tick == 0) {
chunks_in_cur_tick = max_chunk_loads_per_tick;
try { Thread.sleep(50); } catch (InterruptedException ix) {}
}
});
boolean delay;
try {
delay = f.get();
} catch (Exception ix) {
Log.severe(ix);
return null;
}
if(delay)
try { Thread.sleep(50); } catch (InterruptedException ix) {}
}
}
return c;
}
@@ -914,7 +788,6 @@ public class MapManager {
sender.sendMessage(" TOTALS: processed=" + tot.loggedcnt + ", rendered=" + tot.renderedcnt +
", updated=" + tot.updatedcnt + ", transparent=" + tot.transparentcnt);
sender.sendMessage(" Cache hit rate: " + sscache.getHitRate() + "%");
sender.sendMessage(" Triggered update queue size: " + tileQueue.size());
}
/**
* Reset statistics
+1 -4
View File
@@ -10,7 +10,7 @@ import org.dynmap.utils.MapChunkCache;
public abstract class MapTile {
protected DynmapWorld world;
public abstract boolean render(MapChunkCache cache, String mapname);
public abstract boolean render(MapChunkCache cache);
public abstract List<DynmapChunk> getRequiredChunks();
public abstract MapTile[] getAdjecentTiles();
@@ -51,7 +51,4 @@ public abstract class MapTile {
public abstract boolean isRawBiomeDataNeeded();
public abstract boolean isBlockTypeDataNeeded();
public abstract int tileOrdinalX();
public abstract int tileOrdinalY();
}
+4 -28
View File
@@ -1,41 +1,20 @@
package org.dynmap;
import java.io.File;
import java.util.List;
import org.bukkit.Location;
import org.dynmap.utils.MapChunkCache;
import org.json.simple.JSONObject;
public abstract class MapType {
public enum ImageFormat {
FORMAT_PNG("png", "png", 0.0f),
FORMAT_JPG75("jpg-q75", "jpg", 0.75f),
FORMAT_JPG80("jpg-q80", "jpg", 0.80f),
FORMAT_JPG85("jpg-q85", "jpg", 0.85f),
FORMAT_JPG("jpg", "jpg", 0.85f),
FORMAT_JPG90("jpg-q90", "jpg", 0.90f),
FORMAT_JPG95("jpg-q95", "jpg", 0.95f),
FORMAT_JPG100("jpg-q100", "jpg", 1.00f);
String id;
String ext;
float qual;
ImageFormat(String id, String ext, float quality) {
this.id = id;
this.ext = ext;
this.qual = quality;
}
public String getID() { return id; }
public String getFileExt() { return ext; }
public float getQuality() { return qual; }
};
public abstract MapTile[] getTiles(Location l);
public abstract MapTile[] getTiles(Location l0, Location l1);
public abstract MapTile[] getAdjecentTiles(MapTile tile);
public abstract List<DynmapChunk> getRequiredChunks(MapTile tile);
public abstract boolean render(MapChunkCache cache, MapTile tile, File outputFile);
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld w) {
}
@@ -62,9 +41,6 @@ public abstract class MapType {
public abstract boolean isBigWorldMap(DynmapWorld w);
/* Return number of zoom levels needed by this map (before extra levels from extrazoomout) */
public int getMapZoomOutLevels() { return 0; }
public ImageFormat getImageFormat() { return ImageFormat.FORMAT_PNG; }
/**
* Step sequence for creating zoomed file: first index is top-left, second top-right, third bottom-left, forth bottom-right
* Values correspond to tile X,Y (0), X+step,Y (1), X,Y+step (2), X+step,Y+step (3)
-139
View File
@@ -1,139 +0,0 @@
package org.dynmap;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Type;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.dynmap.MapType.ImageFormat;
import org.dynmap.debug.Debug;
import org.dynmap.utils.DynmapBufferedImage;
import org.dynmap.utils.FileLockManager;
/**
* Listen for player logins, and process player faces by fetching skins *
*/
public class PlayerFaces {
private DynmapPlugin plugin;
private File facesdir;
private File faces8x8dir;
private File faces16x16dir;
private File faces32x32dir;
private class LoadPlayerImages implements Runnable {
public String playername;
public LoadPlayerImages(String playername) {
this.playername = playername;
}
public void run() {
BufferedImage img = null;
try {
URL url = new URL("http://s3.amazonaws.com/MinecraftSkins/" + playername + ".png");
img = ImageIO.read(url); /* Load skin for player */
} catch (IOException iox) {
Debug.debug("Error loading skin for '" + playername + "' - " + iox);
}
if(img == null) {
try {
InputStream in = getClass().getResourceAsStream("/char.png");
img = ImageIO.read(in); /* Load generic skin for player */
in.close();
} catch (IOException iox) {
Debug.debug("Error loading default skin for '" + playername + "' - " + iox);
}
}
if(img == null) { /* No image to process? Quit */
return;
}
int[] faceaccessory = new int[64]; /* 8x8 of face accessory */
/* Get buffered image for face at 8x8 */
DynmapBufferedImage face8x8 = DynmapBufferedImage.allocateBufferedImage(8, 8);
int[] bgcolor = new int[1];
img.getRGB(0, 0, 1, 1, bgcolor, 0, 1); /* Get BG color (for accessory face) */
img.getRGB(8, 8, 8, 8, face8x8.argb_buf, 0, 8); /* Read face from image */
img.getRGB(40, 8, 8, 8, faceaccessory, 0, 8); /* Read face accessory from image */
/* Apply accessory to face: first element is transparency color so only ones not matching it */
for(int i = 0; i < 64; i++) {
if(faceaccessory[i] != bgcolor[0])
face8x8.argb_buf[i] = faceaccessory[i];
else if(face8x8.argb_buf[i] == bgcolor[0])
face8x8.argb_buf[i] = 0;
}
/* Write 8x8 file */
File img_8x8 = new File(faces8x8dir, playername + ".png");
FileLockManager.getWriteLock(img_8x8);
try {
FileLockManager.imageIOWrite(face8x8.buf_img, ImageFormat.FORMAT_PNG, img_8x8);
} catch (IOException iox) {
Log.severe("Cannot write player icon " + img_8x8.getPath());
}
FileLockManager.releaseWriteLock(img_8x8);
/* Make 16x16 version */
DynmapBufferedImage face16x16 = DynmapBufferedImage.allocateBufferedImage(16, 16);
for(int i = 0; i < 16; i++) {
for(int j = 0; j < 16; j++) {
face16x16.argb_buf[i*16+j] = face8x8.argb_buf[(i/2)*8 + (j/2)];
}
}
/* Write 16x16 file */
File img_16x16 = new File(faces16x16dir, playername + ".png");
FileLockManager.getWriteLock(img_16x16);
try {
FileLockManager.imageIOWrite(face16x16.buf_img, ImageFormat.FORMAT_PNG, img_16x16);
} catch (IOException iox) {
Log.severe("Cannot write player icon " + img_16x16.getPath());
}
FileLockManager.releaseWriteLock(img_16x16);
DynmapBufferedImage.freeBufferedImage(face16x16);
/* Make 32x32 version */
DynmapBufferedImage face32x32 = DynmapBufferedImage.allocateBufferedImage(32, 32);
for(int i = 0; i < 32; i++) {
for(int j = 0; j < 32; j++) {
face32x32.argb_buf[i*32+j] = face8x8.argb_buf[(i/4)*8 + (j/4)];
}
}
/* Write 32x32 file */
File img_32x32 = new File(faces32x32dir, playername + ".png");
FileLockManager.getWriteLock(img_32x32);
try {
FileLockManager.imageIOWrite(face32x32.buf_img, ImageFormat.FORMAT_PNG, img_32x32);
} catch (IOException iox) {
Log.severe("Cannot write player icon " + img_32x32.getPath());
}
FileLockManager.releaseWriteLock(img_32x32);
DynmapBufferedImage.freeBufferedImage(face32x32);
DynmapBufferedImage.freeBufferedImage(face8x8);
/* TODO: signal update for player icon to client */
}
}
private class LoginListener extends PlayerListener {
@Override
public void onPlayerLogin(PlayerLoginEvent event) {
MapManager.scheduleDelayedJob(new LoadPlayerImages(event.getPlayer().getName()), 0);
}
}
public PlayerFaces(DynmapPlugin plugin) {
this.plugin = plugin;
plugin.registerEvent(Type.PLAYER_LOGIN, new LoginListener());
facesdir = new File(plugin.tilesDirectory, "faces");
facesdir.mkdirs(); /* Make sure directory exists */
faces8x8dir = new File(facesdir, "8x8");
faces8x8dir.mkdirs();
faces16x16dir = new File(facesdir, "16x16");
faces16x16dir.mkdirs();
faces32x32dir = new File(facesdir, "32x32");
faces32x32dir.mkdirs();
}
}
@@ -32,10 +32,11 @@ public class SimpleWebChatComponent extends Component {
if (configuration.getBoolean("allowchat", false)) {
PlayerChatListener playerListener = new PlayerChatListener();
plugin.registerEvent(org.bukkit.event.Event.Type.PLAYER_CHAT, playerListener);
plugin.registerEvent(org.bukkit.event.Event.Type.PLAYER_LOGIN, playerListener);
plugin.registerEvent(org.bukkit.event.Event.Type.PLAYER_JOIN, playerListener);
plugin.registerEvent(org.bukkit.event.Event.Type.PLAYER_QUIT, playerListener);
PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvent(org.bukkit.event.Event.Type.PLAYER_CHAT, playerListener, org.bukkit.event.Event.Priority.Monitor, plugin);
pm.registerEvent(org.bukkit.event.Event.Type.PLAYER_LOGIN, playerListener, org.bukkit.event.Event.Priority.Monitor, plugin);
pm.registerEvent(org.bukkit.event.Event.Type.PLAYER_JOIN, playerListener, org.bukkit.event.Event.Priority.Monitor, plugin);
pm.registerEvent(org.bukkit.event.Event.Type.PLAYER_QUIT, playerListener, org.bukkit.event.Event.Priority.Monitor, plugin);
}
}
+9 -53
View File
@@ -9,6 +9,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.World.Environment;
@@ -21,7 +23,9 @@ import org.dynmap.MapManager;
import org.dynmap.TileHashManager;
import org.dynmap.MapTile;
import org.dynmap.MapType;
import org.dynmap.MapType.MapStep;
import org.dynmap.debug.Debug;
import org.dynmap.kzedmap.KzedMap;
import org.dynmap.utils.DynmapBufferedImage;
import org.dynmap.utils.FileLockManager;
import org.dynmap.utils.MapChunkCache;
@@ -91,35 +95,6 @@ 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<MapTile> rslt = new ArrayList<MapTile>();
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;
@@ -149,6 +124,7 @@ public class FlatMap extends MapType {
return result;
}
@Override
public boolean render(MapChunkCache cache, MapTile tile, File outputFile) {
FlatMapTile t = (FlatMapTile) tile;
World w = t.getWorld();
@@ -308,7 +284,7 @@ public class FlatMap extends MapType {
if(!outputFile.getParentFile().exists())
outputFile.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(im.buf_img, ImageFormat.FORMAT_PNG, outputFile);
FileLockManager.imageIOWrite(im.buf_img, "png", outputFile);
} catch (IOException e) {
Debug.error("Failed to save image: " + outputFile.getPath(), e);
} catch (java.lang.NullPointerException e) {
@@ -339,7 +315,7 @@ public class FlatMap extends MapType {
if(!dayfile.getParentFile().exists())
dayfile.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(im_day.buf_img, ImageFormat.FORMAT_PNG, dayfile);
FileLockManager.imageIOWrite(im_day.buf_img, "png", dayfile);
} catch (IOException e) {
Debug.error("Failed to save image: " + dayfile.getPath(), e);
} catch (java.lang.NullPointerException e) {
@@ -443,7 +419,7 @@ public class FlatMap extends MapType {
public String getPrefix() {
return prefix;
}
/* Get maps rendered concurrently with this map in this world */
public List<MapType> getMapsSharingRender(DynmapWorld w) {
return Collections.singletonList((MapType)this);
@@ -520,7 +496,7 @@ public class FlatMap extends MapType {
}
@Override
public boolean render(MapChunkCache cache, String mapname) {
public boolean render(MapChunkCache cache) {
return map.render(cache, this, MapManager.mapman.getTileFile(this));
}
@@ -534,22 +510,6 @@ public class FlatMap extends MapType {
return map.getAdjecentTiles(this);
}
@Override
public int hashCode() {
return x ^ y ^ size ^ map.getName().hashCode();
}
@Override
public boolean equals(Object x) {
if(x instanceof FlatMapTile) {
return equals((FlatMapTile)x);
}
return false;
}
public boolean equals(FlatMapTile o) {
return (o.x == x) && (o.y == y) && (o.map == map);
}
@Override
public String getKey() {
return world.world.getName() + "." + map.getPrefix();
@@ -559,9 +519,6 @@ public class FlatMap extends MapType {
public boolean isBiomeDataNeeded() { return false; }
public boolean isRawBiomeDataNeeded() { return false; }
public boolean isBlockTypeDataNeeded() { return true; }
public int tileOrdinalX() { return x; }
public int tileOrdinalY() { return y; }
}
@Override
@@ -581,7 +538,6 @@ public class FlatMap extends MapType {
s(o, "mapzoomin", c.getInteger("mapzoomin", 3));
s(o, "mapzoomout", world.getExtraZoomOutLevels());
s(o, "compassview", "S"); /* Always from south */
s(o, "image-format", ImageFormat.FORMAT_PNG.getFileExt());
a(worldObject, "maps", o);
}
}
+9 -27
View File
@@ -19,7 +19,6 @@ import org.dynmap.utils.MapChunkCache;
import org.json.simple.JSONObject;
public class HDMap extends MapType {
private String name;
private String prefix;
private HDPerspective perspective;
@@ -27,11 +26,6 @@ public class HDMap extends MapType {
private HDLighting lighting;
private ConfigurationNode configuration;
private int mapzoomout;
private MapType.ImageFormat imgformat;
public static final String IMGFORMAT_PNG = "png";
public static final String IMGFORMAT_JPG = "jpg";
public HDMap(ConfigurationNode configuration) {
name = configuration.getString("name", null);
@@ -89,19 +83,7 @@ public class HDMap extends MapType {
mapzoomout++;
scale = scale / 2.0;
}
String fmt = configuration.getString("image-format", "png");
/* Only allow png or jpg */
for(ImageFormat f : ImageFormat.values()) {
if(fmt.equals(f.getID())) {
imgformat = f;
break;
}
}
if(imgformat == null) {
Log.severe("HDMap '"+name+"' set invalid image-format: " + fmt);
imgformat = ImageFormat.FORMAT_PNG;
}
}
}
public HDShader getShader() { return shader; }
public HDPerspective getPerspective() { return perspective; }
@@ -112,11 +94,6 @@ 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);
@@ -127,6 +104,14 @@ public class HDMap extends MapType {
return perspective.getRequiredChunks(tile);
}
@Override
public boolean render(MapChunkCache cache, MapTile tile, File bogus) {
if(tile instanceof HDMapTile)
return perspective.render(cache, (HDMapTile)tile);
else
return false;
}
@Override
public List<String> baseZoomFilePrefixes() {
ArrayList<String> s = new ArrayList<String>();
@@ -196,8 +181,6 @@ public class HDMap extends MapType {
return lst;
}
@Override
public ImageFormat getImageFormat() { return imgformat; }
@Override
public void buildClientConfiguration(JSONObject worldObject, DynmapWorld world) {
@@ -214,7 +197,6 @@ public class HDMap extends MapType {
s(o, "bigmap", true);
s(o, "mapzoomout", (world.getExtraZoomOutLevels()+mapzoomout));
s(o, "mapzoomin", c.getInteger("mapzoomin", 2));
s(o, "image-format", imgformat.getFileExt());
perspective.addClientConfiguration(o);
shader.addClientConfiguration(o);
lighting.addClientConfiguration(o);
@@ -119,7 +119,7 @@ public class HDMapManager {
/**
* Initialize shader states for all shaders for given tile
*/
public HDShaderState[] getShaderStateForTile(HDMapTile tile, MapChunkCache cache, MapIterator mapiter, String mapname) {
public HDShaderState[] getShaderStateForTile(HDMapTile tile, MapChunkCache cache, MapIterator mapiter) {
DynmapWorld w = MapManager.mapman.worldsLookup.get(tile.getWorld().getName());
if(w == null) return new HDShaderState[0];
ArrayList<HDShaderState> shaders = new ArrayList<HDShaderState>();
@@ -127,9 +127,6 @@ public class HDMapManager {
if(map instanceof HDMap) {
HDMap hdmap = (HDMap)map;
if(hdmap.getPerspective() == tile.perspective) {
/* If limited to one map, and this isn't it, skip */
if((mapname != null) && (!hdmap.getName().equals(mapname)))
continue;
shaders.add(hdmap.getShader().getStateInstance(hdmap, cache, mapiter));
}
}
+11 -16
View File
@@ -3,7 +3,6 @@ package org.dynmap.hdmap;
import org.dynmap.DynmapChunk;
import org.dynmap.DynmapWorld;
import org.dynmap.MapManager;
import org.dynmap.MapType;
import java.util.List;
import org.dynmap.MapTile;
@@ -22,25 +21,25 @@ public class HDMapTile extends MapTile {
@Override
public String getFilename() {
return getFilename("hdmap", MapType.ImageFormat.FORMAT_PNG);
return getFilename("hdmap");
}
public String getFilename(String prefix, MapType.ImageFormat format) {
return prefix + "/" + (tx >> 5) + '_' + (ty >> 5) + '/' + tx + "_" + ty + "." + format.getFileExt();
public String getFilename(String prefix) {
return prefix + "/" + (tx >> 5) + '_' + (ty >> 5) + '/' + tx + "_" + ty + ".png";
}
@Override
public String getDayFilename() {
return getDayFilename("hdmap", MapType.ImageFormat.FORMAT_PNG);
return getDayFilename("hdmap");
}
public String getDayFilename(String prefix, MapType.ImageFormat format) {
return prefix + "_day/" + (tx >> 5) + '_' + (ty >> 5) + '/' + tx + "_" + ty + "." + format.getFileExt();
public String getDayFilename(String prefix) {
return prefix + "_day/" + (tx >> 5) + '_' + (ty >> 5) + '/' + tx + "_" + ty + ".png";
}
@Override
public int hashCode() {
return tx ^ ty ^ perspective.getName().hashCode() ^ getWorld().getName().hashCode();
return perspective.getName().hashCode() ^ getWorld().hashCode();
}
@Override
@@ -48,11 +47,11 @@ public class HDMapTile extends MapTile {
if (obj instanceof HDMapTile) {
return equals((HDMapTile) obj);
}
return false;
return super.equals(obj);
}
public boolean equals(HDMapTile o) {
return o.tx == tx && o.ty == ty && (perspective == o.perspective) && (o.getWorld() == getWorld());
return o.tx == tx && o.ty == ty && o.getWorld().equals(getWorld()) && (perspective.equals(o.perspective));
}
public String getKey() {
@@ -76,8 +75,8 @@ public class HDMapTile extends MapTile {
@Override
public boolean isBlockTypeDataNeeded() { return MapManager.mapman.hdmapman.isBlockTypeDataNeeded(this); }
public boolean render(MapChunkCache cache, String mapname) {
return perspective.render(cache, this, mapname);
public boolean render(MapChunkCache cache) {
return perspective.render(cache, this);
}
public List<DynmapChunk> getRequiredChunks() {
@@ -87,8 +86,4 @@ public class HDMapTile extends MapTile {
public MapTile[] getAdjecentTiles() {
return perspective.getAdjecentTiles(this);
}
public int tileOrdinalX() { return tx; }
public int tileOrdinalY() { return ty; }
}
@@ -13,14 +13,12 @@ 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 */
List<DynmapChunk> getRequiredChunks(MapTile tile);
/* Render given tile */
boolean render(MapChunkCache cache, HDMapTile tile, String mapname);
boolean render(MapChunkCache cache, HDMapTile tile);
public boolean isBiomeDataNeeded();
public boolean isHightestBlockYDataNeeded();
@@ -21,7 +21,6 @@ import org.dynmap.DynmapChunk;
import org.dynmap.Log;
import org.dynmap.MapManager;
import org.dynmap.MapTile;
import org.dynmap.MapType;
import org.dynmap.TileHashManager;
import org.dynmap.debug.Debug;
import org.dynmap.utils.MapIterator.BlockStep;
@@ -726,68 +725,6 @@ 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<MapTile> tiles = new HashSet<MapTile>();
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;
@@ -950,11 +887,11 @@ public class IsoHDPerspective implements HDPerspective {
}
@Override
public boolean render(MapChunkCache cache, HDMapTile tile, String mapname) {
public boolean render(MapChunkCache cache, HDMapTile tile) {
Color rslt = new Color();
MapIterator mapiter = cache.getIterator(0, 0, 0);
/* Build shader state object for each shader */
HDShaderState[] shaderstate = MapManager.mapman.hdmapman.getShaderStateForTile(tile, cache, mapiter, mapname);
HDShaderState[] shaderstate = MapManager.mapman.hdmapman.getShaderStateForTile(tile, cache, mapiter);
int numshaders = shaderstate.length;
if(numshaders == 0)
return false;
@@ -1030,8 +967,7 @@ public class IsoHDPerspective implements HDPerspective {
String prefix = shaderstate[i].getMap().getPrefix();
if(rendered[i]) {
renderone = true;
MapType.ImageFormat fmt = shaderstate[i].getMap().getImageFormat();
String fname = tile.getFilename(prefix, fmt);
String fname = tile.getFilename(prefix);
File f = new File(tile.getDynmapWorld().worldtilepath, fname);
FileLockManager.getWriteLock(f);
try {
@@ -1041,7 +977,7 @@ public class IsoHDPerspective implements HDPerspective {
if(!f.getParentFile().exists())
f.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(im[i].buf_img, fmt, f);
FileLockManager.imageIOWrite(im[i].buf_img, "png", f);
} catch (IOException e) {
Debug.error("Failed to save image: " + f.getPath(), e);
} catch (java.lang.NullPointerException e) {
@@ -1062,7 +998,7 @@ public class IsoHDPerspective implements HDPerspective {
MapManager.mapman.updateStatistics(tile, prefix, true, tile_update, !rendered[i]);
/* Handle day image, if needed */
if(dayim[i] != null) {
fname = tile.getDayFilename(prefix, fmt);
fname = tile.getDayFilename(prefix);
f = new File(tile.getDynmapWorld().worldtilepath, fname);
FileLockManager.getWriteLock(f);
prefix = prefix+"_day";
@@ -1074,7 +1010,7 @@ public class IsoHDPerspective implements HDPerspective {
if(!f.getParentFile().exists())
f.getParentFile().mkdirs();
try {
FileLockManager.imageIOWrite(dayim[i].buf_img, fmt, f);
FileLockManager.imageIOWrite(dayim[i].buf_img, "png", f);
} catch (IOException e) {
Debug.error("Failed to save image: " + f.getPath(), e);
} catch (java.lang.NullPointerException e) {
+33 -110
View File
@@ -54,7 +54,6 @@ public class TexturePack {
private static final String CUSTOMWATERSTILL_PNG = "custom_water_still.png";
private static final String CUSTOMWATERFLOWING_PNG = "custom_water_flowing.png";
private static final String STANDARDTP = "standard";
/* Color modifier codes (x1000 for value in mapping code) */
private static final int COLORMOD_NONE = 0;
private static final int COLORMOD_GRASSTONED = 1;
@@ -72,8 +71,6 @@ public class TexturePack {
/* Special tile index values */
private static final int BLOCKINDEX_BLANK = -1;
private static final int BLOCKINDEX_GRASSMASK = 38;
private static final int BLOCKINDEX_PISTONSIDE = 108;
private static final int BLOCKINDEX_REDSTONE_NSEW_TONE = 164;
private static final int BLOCKINDEX_REDSTONE_EW_TONE = 165;
private static final int BLOCKINDEX_REDSTONE_NSEW = 180;
@@ -82,9 +79,7 @@ public class TexturePack {
private static final int BLOCKINDEX_MOVINGWATER = 258;
private static final int BLOCKINDEX_STATIONARYLAVA = 259;
private static final int BLOCKINDEX_MOVINGLAVA = 260;
private static final int BLOCKINDEX_PISTONEXTSIDE = 261;
private static final int BLOCKINDEX_PISTONSIDE_EXT = 262;
private static final int MAX_BLOCKINDEX = 262;
private static final int MAX_BLOCKINDEX = 260;
private static final int BLOCKTABLELEN = MAX_BLOCKINDEX+1;
private static class LoadedImage {
@@ -195,57 +190,36 @@ public class TexturePack {
/* Try to open zip */
zf = new ZipFile(f);
/* Find and load terrain.png */
InputStream is;
ZipEntry ze = zf.getEntry(TERRAIN_PNG); /* Try to find terrain.png */
if(ze == null) {
/* Check for terrain.png under standard texture pack*/
File ff = new File(texturedir, STANDARDTP + "/" + TERRAIN_PNG);
is = new FileInputStream(ff);
}
else {
is = zf.getInputStream(ze); /* Get input stream for terrain.png */
throw new FileNotFoundException();
}
InputStream is = zf.getInputStream(ze); /* Get input stream for terrain.png */
loadTerrainPNG(is);
is.close();
/* Try to find and load misc/grasscolor.png */
ze = zf.getEntry(GRASSCOLOR_PNG);
if(ze == null) { /* Fall back to standard file */
/* Check for misc/grasscolor.png under standard texture pack*/
File ff = new File(texturedir, STANDARDTP + "/" + GRASSCOLOR_PNG);
is = new FileInputStream(ff);
}
else {
is = zf.getInputStream(ze);
}
loadBiomeShadingImage(is, IMG_GRASSCOLOR);
is.close();
if(ze == null)
throw new FileNotFoundException();
is = zf.getInputStream(ze);
loadBiomeShadingImage(is, IMG_GRASSCOLOR);
is.close();
/* Try to find and load misc/foliagecolor.png */
ze = zf.getEntry(FOLIAGECOLOR_PNG);
if(ze == null) {
/* Check for misc/foliagecolor.png under standard texture pack*/
File ff = new File(texturedir, STANDARDTP + "/" + FOLIAGECOLOR_PNG);
is = new FileInputStream(ff);
}
else {
is = zf.getInputStream(ze);
}
loadBiomeShadingImage(is, IMG_FOLIAGECOLOR);
is.close();
if(ze == null)
throw new FileNotFoundException();
is = zf.getInputStream(ze);
loadBiomeShadingImage(is, IMG_FOLIAGECOLOR);
is.close();
/* Try to find and load misc/water.png */
ze = zf.getEntry(WATER_PNG);
if(ze == null) {
File ff = new File(texturedir, STANDARDTP + "/" + WATER_PNG);
is = new FileInputStream(ff);
}
else {
is = zf.getInputStream(ze);
}
loadImage(is, IMG_WATER);
if(ze == null)
throw new FileNotFoundException();
is = zf.getInputStream(ze);
loadImage(is, IMG_WATER);
patchTextureWithImage(IMG_WATER, BLOCKINDEX_STATIONARYWATER);
patchTextureWithImage(IMG_WATER, BLOCKINDEX_MOVINGWATER);
is.close();
is.close();
/* Optional files - process if they exist */
ze = zf.getEntry(CUSTOMLAVAFLOWING_PNG);
if(ze != null) {
@@ -284,33 +258,21 @@ public class TexturePack {
try {
/* Open and load terrain.png */
f = new File(texturedir, tpname + "/" + TERRAIN_PNG);
if(!f.canRead()) {
f = new File(texturedir, STANDARDTP + "/" + TERRAIN_PNG);
}
fis = new FileInputStream(f);
loadTerrainPNG(fis);
fis.close();
/* Check for misc/grasscolor.png */
f = new File(texturedir, tpname + "/" + GRASSCOLOR_PNG);
if(!f.canRead()) {
f = new File(texturedir, STANDARDTP + "/" + GRASSCOLOR_PNG);
}
fis = new FileInputStream(f);
loadBiomeShadingImage(fis, IMG_GRASSCOLOR);
fis.close();
/* Check for misc/foliagecolor.png */
f = new File(texturedir, tpname + "/" + FOLIAGECOLOR_PNG);
if(!f.canRead()) {
f = new File(texturedir, STANDARDTP + "/" + FOLIAGECOLOR_PNG);
}
fis = new FileInputStream(f);
loadBiomeShadingImage(fis, IMG_FOLIAGECOLOR);
fis.close();
/* Check for misc/water.png */
f = new File(texturedir, tpname + "/" + WATER_PNG);
if(!f.canRead()) {
f = new File(texturedir, STANDARDTP + "/" + WATER_PNG);
}
fis = new FileInputStream(f);
loadImage(fis, IMG_WATER);
patchTextureWithImage(IMG_WATER, BLOCKINDEX_STATIONARYWATER);
@@ -367,9 +329,8 @@ public class TexturePack {
/* Load terrain.png */
private void loadTerrainPNG(InputStream is) throws IOException {
int i, j;
int i;
/* Load image */
ImageIO.setUseCache(false);
BufferedImage img = ImageIO.read(is);
if(img == null) { throw new FileNotFoundException(); }
terrain_width = img.getWidth();
@@ -403,34 +364,12 @@ public class TexturePack {
terrain_argb[BLOCKINDEX_REDSTONE_EW][i] = tc.getARGB();
}
}
/* Build extended piston side texture - take top 1/4 of piston side, use to make piston extension */
terrain_argb[BLOCKINDEX_PISTONEXTSIDE] = new int[native_scale*native_scale];
System.arraycopy(terrain_argb[BLOCKINDEX_PISTONSIDE], 0, terrain_argb[BLOCKINDEX_PISTONEXTSIDE], 0,
native_scale * native_scale / 4);
for(i = 0; i < native_scale/4; i++) {
for(j = 0; j < (3*native_scale/4); j++) {
terrain_argb[BLOCKINDEX_PISTONEXTSIDE][native_scale*(native_scale/4 + j) + (3*native_scale/8 + i)] =
terrain_argb[BLOCKINDEX_PISTONSIDE][native_scale*i + j];
}
}
/* Build piston side while extended (cut off top 1/4, replace with rotated top for extension */
terrain_argb[BLOCKINDEX_PISTONSIDE_EXT] = new int[native_scale*native_scale];
System.arraycopy(terrain_argb[BLOCKINDEX_PISTONSIDE], native_scale*native_scale/4,
terrain_argb[BLOCKINDEX_PISTONSIDE_EXT], native_scale*native_scale/4,
3 * native_scale * native_scale / 4); /* Copy bottom 3/4 */
for(i = 0; i < native_scale/4; i++) {
for(j = 3*native_scale/4; j < native_scale; j++) {
terrain_argb[BLOCKINDEX_PISTONSIDE_EXT][native_scale*(j - 3*native_scale/4) + (3*native_scale/8 + i)] =
terrain_argb[BLOCKINDEX_PISTONSIDE][native_scale*i + j];
}
}
img.flush();
}
/* Load image into image array */
private void loadImage(InputStream is, int idx) throws IOException {
/* Load image */
ImageIO.setUseCache(false);
BufferedImage img = ImageIO.read(is);
if(img == null) { throw new FileNotFoundException(); }
imgs[idx] = new LoadedImage();
@@ -512,8 +451,6 @@ public class TexturePack {
tp.terrain_argb[idx] = new int[tp.native_scale*tp.native_scale];
scaleTerrainPNGSubImage(native_scale, tp.native_scale, terrain_argb[idx], tp.terrain_argb[idx]);
}
/* Special case - some textures are used as masks - need pure alpha (00 or FF) */
makeAlphaPure(tp.terrain_argb[BLOCKINDEX_GRASSMASK]); /* Grass side mask */
}
private static void scaleTerrainPNGSubImage(int srcscale, int destscale, int[] src_argb, int[] dest_argb) {
int nativeres = srcscale;
@@ -562,18 +499,15 @@ public class TexturePack {
if(wy == 0) continue;
/* Accumulate */
c.setARGB(src_argb[(ind_y+yy)*nativeres + ind_x + xx]);
int a = c.getAlpha();
accum_red += c.getRed() * a * wx * wy;
accum_green += c.getGreen() * a* wx * wy;
accum_blue += c.getBlue() * a * wx * wy;
accum_alpha += a * wx * wy;
accum_red += c.getRed() * wx * wy;
accum_green += c.getGreen() * wx * wy;
accum_blue += c.getBlue() * wx * wy;
accum_alpha += c.getAlpha() * wx * wy;
}
}
int newalpha = accum_alpha / (nativeres*nativeres);
if(newalpha == 0) newalpha = 1;
/* Generate weighted compnents into color */
c.setRGBA(accum_red / (nativeres*nativeres*newalpha), accum_green / (nativeres*nativeres*newalpha),
accum_blue / (nativeres*nativeres*newalpha), accum_alpha / (nativeres*nativeres));
c.setRGBA(accum_red / (nativeres*nativeres), accum_green / (nativeres*nativeres),
accum_blue / (nativeres*nativeres), accum_alpha / (nativeres*nativeres));
dest_argb[(y*res) + x] = c.getARGB();
}
}
@@ -614,11 +548,10 @@ public class TexturePack {
for(int yy = 0; yy < 2; yy++) {
int wy = (yy==0)?wgt_y:(res-wgt_y);
if(wy == 0) continue;
int a = c.getAlpha();
accum_red[(ind_y+yy)*res + (ind_x+xx)] += c.getRed() * a * wx * wy;
accum_green[(ind_y+yy)*res + (ind_x+xx)] += c.getGreen() * a * wx * wy;
accum_blue[(ind_y+yy)*res + (ind_x+xx)] += c.getBlue() * a * wx * wy;
accum_alpha[(ind_y+yy)*res + (ind_x+xx)] += a * wx * wy;
accum_red[(ind_y+yy)*res + (ind_x+xx)] += c.getRed() * wx * wy;
accum_green[(ind_y+yy)*res + (ind_x+xx)] += c.getGreen() * wx * wy;
accum_blue[(ind_y+yy)*res + (ind_x+xx)] += c.getBlue() * wx * wy;
accum_alpha[(ind_y+yy)*res + (ind_x+xx)] += c.getAlpha() * wx * wy;
}
}
}
@@ -627,10 +560,8 @@ public class TexturePack {
for(int y = 0; y < res; y++) {
for(int x = 0; x < res; x++) {
int off = (y*res) + x;
int aa = accum_alpha[off] / (nativeres*nativeres);
if(aa == 0) aa = 1;
c.setRGBA(accum_red[off]/(aa*nativeres*nativeres), accum_green[off]/(aa*nativeres*nativeres),
accum_blue[off]/(aa*nativeres*nativeres), accum_alpha[off] / (nativeres*nativeres));
c.setRGBA(accum_red[off]/(nativeres*nativeres), accum_green[off]/(nativeres*nativeres),
accum_blue[off]/(nativeres*nativeres), accum_alpha[off]/(nativeres*nativeres));
dest_argb[y*res + x] = c.getARGB();
}
}
@@ -644,7 +575,6 @@ public class TexturePack {
}
}
BufferedImage img = DynmapBufferedImage.createBufferedImage(outbuf, terrain_width, terrain_height);
ImageIO.setUseCache(false);
ImageIO.write(img, "png", f);
}
@@ -917,9 +847,9 @@ public class TexturePack {
textid = 68;
}
else { /* Else, check the grass color overlay */
int ovclr = terrain_argb[BLOCKINDEX_GRASSMASK][v*native_scale+u];
int ovclr = terrain_argb[38][v*native_scale+u];
if((ovclr & 0xFF000000) != 0) { /* Hit? */
texture = terrain_argb[BLOCKINDEX_GRASSMASK]; /* Use it */
texture = terrain_argb[38]; /* Use it */
textop = COLORMOD_GRASSTONED; /* Force grass toning */
}
}
@@ -962,11 +892,4 @@ public class TexturePack {
if(t > w) t = w;
return argb[width*h + t];
}
private static final void makeAlphaPure(int[] argb) {
for(int i = 0; i < argb.length; i++) {
if((argb[i] & 0xFF000000) != 0)
argb[i] |= 0xFF000000;
}
}
}
@@ -258,7 +258,8 @@ public class HeroChatHandler {
}
else {
/* Set up to hear when HeroChat is enabled */
plugin.registerEvent(Event.Type.PLUGIN_ENABLE, new OurPluginListener());
server.getPluginManager().registerEvent(Event.Type.PLUGIN_ENABLE,
new OurPluginListener(), Event.Priority.Normal, plugin);
}
}
@@ -276,7 +277,8 @@ public class HeroChatHandler {
return;
}
/* Register event handler */
plugin.registerEvent(Event.Type.CUSTOM_EVENT, new OurEventListener());
plugin.getServer().getPluginManager().registerEvent(Event.Type.CUSTOM_EVENT,
new OurEventListener(), Event.Priority.Monitor, plugin);
Log.verboseinfo("HeroChat integration active");
}
/**
@@ -43,9 +43,10 @@ public class HeroWebChatComponent extends Component {
// Also make HeroChat announce joins and quits.
PlayerChatListener playerListener = new PlayerChatListener();
plugin.registerEvent(org.bukkit.event.Event.Type.PLAYER_LOGIN, playerListener);
plugin.registerEvent(org.bukkit.event.Event.Type.PLAYER_JOIN, playerListener);
plugin.registerEvent(org.bukkit.event.Event.Type.PLAYER_QUIT, playerListener);
PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvent(org.bukkit.event.Event.Type.PLAYER_LOGIN, playerListener, org.bukkit.event.Event.Priority.Monitor, plugin);
pm.registerEvent(org.bukkit.event.Event.Type.PLAYER_JOIN, playerListener, org.bukkit.event.Event.Priority.Monitor, plugin);
pm.registerEvent(org.bukkit.event.Event.Type.PLAYER_QUIT, playerListener, org.bukkit.event.Event.Priority.Monitor, plugin);
}
protected class PlayerChatListener extends PlayerListener {

Some files were not shown because too many files have changed in this diff Show More