diff --git a/src/main/java/org/dynmap/flat/FlatMap.java b/src/main/java/org/dynmap/flat/FlatMap.java index 1d641307..e3b44ae5 100644 --- a/src/main/java/org/dynmap/flat/FlatMap.java +++ b/src/main/java/org/dynmap/flat/FlatMap.java @@ -38,7 +38,8 @@ public class FlatMap extends MapType { private int ambientlight = 15;; private int shadowscale[] = null; private boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */ - + protected boolean transparency; + public FlatMap(ConfigurationNode configuration) { this.configuration = configuration; prefix = (String) configuration.get("prefix"); @@ -69,6 +70,7 @@ public class FlatMap extends MapType { ambientlight = Integer.parseInt(String.valueOf(o)); } night_and_day = configuration.getBoolean("night-and-day", false); + transparency = configuration.getBoolean("transparency", false); /* Default off */ } @Override @@ -115,8 +117,8 @@ public class FlatMap extends MapType { boolean rendered = false; Color rslt = new Color(); - int[] pixel = new int[3]; - int[] pixel_day = new int[3]; + int[] pixel = new int[4]; + int[] pixel_day = null; KzedBufferedImage im = KzedMap.allocateBufferedImage(t.size, t.size); int[] argb_buf = im.argb_buf; KzedBufferedImage im_day = null; @@ -124,6 +126,7 @@ public class FlatMap extends MapType { if(night_and_day) { im_day = KzedMap.allocateBufferedImage(t.size, t.size); argb_buf_day = im_day.argb_buf; + pixel_day = new int[4]; } MapChunkCache.MapIterator mapiter = cache.getIterator(t.x * t.size, 127, t.y * t.size); for (int x = 0; x < t.size; x++) { @@ -178,20 +181,27 @@ public class FlatMap extends MapType { pixel[0] = c.getRed(); pixel[1] = c.getGreen(); pixel[2] = c.getBlue(); - + pixel[3] = c.getAlpha(); + + /* If transparency needed, process it */ + if(transparency && (pixel[3] < 255)) { + process_transparent(pixel, pixel_day, mapiter); + } /* If ambient light less than 15, do scaling */ - if((shadowscale != null) && (ambientlight < 15)) { + else if((shadowscale != null) && (ambientlight < 15)) { if(mapiter.y < 127) mapiter.incrementY(); if(night_and_day) { /* Use unscaled color for day (no shadows from above) */ pixel_day[0] = pixel[0]; pixel_day[1] = pixel[1]; pixel_day[2] = pixel[2]; + pixel_day[3] = 255; } int light = Math.max(ambientlight, mapiter.getBlockEmittedLight()); pixel[0] = (pixel[0] * shadowscale[light]) >> 8; pixel[1] = (pixel[1] * shadowscale[light]) >> 8; pixel[2] = (pixel[2] * shadowscale[light]) >> 8; + pixel[3] = 255; } else { /* Only do height keying if we're not messing with ambient light */ boolean below = mapiter.y < 64; @@ -215,22 +225,25 @@ public class FlatMap extends MapType { pixel[0] -= pixel[0] * scale; pixel[1] -= pixel[1] * scale; pixel[2] -= pixel[2] * scale; + pixel[3] = 255; } else { pixel[0] += (255-pixel[0]) * scale; pixel[1] += (255-pixel[1]) * scale; pixel[2] += (255-pixel[2]) * scale; + pixel[3] = 255; } if(night_and_day) { pixel_day[0] = pixel[0]; pixel_day[1] = pixel[1]; pixel_day[2] = pixel[2]; + pixel_day[3] = 255; } } - rslt.setRGBA(pixel[0], pixel[1], pixel[2], 255); + rslt.setRGBA(pixel[0], pixel[1], pixel[2], pixel[3]); argb_buf[(t.size-y-1) + (x*t.size)] = rslt.getARGB(); if(night_and_day) { - rslt.setRGBA(pixel_day[0], pixel_day[1], pixel_day[2], 255); + rslt.setRGBA(pixel_day[0], pixel_day[1], pixel_day[2], pixel[3]); argb_buf_day[(t.size-y-1) + (x*t.size)] = rslt.getARGB(); } rendered = true; @@ -291,7 +304,76 @@ public class FlatMap extends MapType { return rendered; } - + private void process_transparent(int[] pixel, int[] pixel_day, MapChunkCache.MapIterator mapiter) { + int r = pixel[0], g = pixel[1], b = pixel[2], a = pixel[3]; + int r_day = 0, g_day = 0, b_day = 0, a_day = 0; + if(pixel_day != null) { + r_day = pixel[0]; g_day = pixel[1]; b_day = pixel[2]; a_day = pixel[3]; + } + /* Handle lighting on cube */ + if((shadowscale != null) && (ambientlight < 15)) { + boolean did_inc = false; + if(mapiter.y < 127) { + mapiter.incrementY(); + did_inc = true; + } + if(night_and_day) { /* Use unscaled color for day (no shadows from above) */ + r_day = r; g_day = g; b_day = b; a_day = a; + } + int light = Math.max(ambientlight, mapiter.getBlockEmittedLight()); + r = (r * shadowscale[light]) >> 8; + g = (g * shadowscale[light]) >> 8; + b = (b * shadowscale[light]) >> 8; + if(did_inc) + mapiter.decrementY(); + } + if(a < 255) { /* If not opaque */ + pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0; + if(pixel_day != null) + pixel_day[0] = pixel_day[1] = pixel_day[2] = pixel_day[3] = 0; + mapiter.decrementY(); + if(mapiter.y >= 0) { + int blockType = mapiter.getBlockTypeID(); + int data = 0; + Color[] colors = colorScheme.colors[blockType]; + if(colorScheme.datacolors[blockType] != null) { + data = mapiter.getBlockData(); + colors = colorScheme.datacolors[blockType][data]; + } + if (colors != null) { + Color c = colors[0]; + if (c != null) { + pixel[0] = c.getRed(); + pixel[1] = c.getGreen(); + pixel[2] = c.getBlue(); + pixel[3] = c.getAlpha(); + /* Recurse to resolve color here */ + process_transparent(pixel, pixel_day, mapiter); + } + } + } + } + /* Blend colors from behind block and block, based on alpha */ + r *= a; + g *= a; + b *= a; + int na = 255 - a; + pixel[0] = (pixel[0] * na + r) >> 8; + pixel[1] = (pixel[1] * na + g) >> 8; + pixel[2] = (pixel[2] * na + b) >> 8; + pixel[3] = 255; + if(pixel_day != null) { + r_day *= a_day; + g_day *= a_day; + b_day *= a_day; + na = 255 - a_day; + pixel_day[0] = (pixel_day[0] * na + r_day) >> 8; + pixel_day[1] = (pixel_day[1] * na + g_day) >> 8; + pixel_day[2] = (pixel_day[2] * na + b_day) >> 8; + pixel_day[3] = 255; + } + } + public String getName() { return prefix; } diff --git a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java index a7f6dbfd..1180b8a8 100644 --- a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java @@ -36,6 +36,7 @@ public class DefaultTileRenderer implements MapTileRenderer { protected int shadowscale[]; /* index=skylight level, value = 256 * scaling value */ protected int lightscale[]; /* scale skylight level (light = lightscale[skylight] */ protected boolean night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */ + protected boolean transparency; /* Is transparency support active? */ @Override public String getName() { return name; @@ -78,6 +79,7 @@ public class DefaultTileRenderer implements MapTileRenderer { } colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme")); night_and_day = configuration.getBoolean("night-and-day", false); + transparency = configuration.getBoolean("transparency", true); /* Default on */ } public boolean render(MapChunkCache cache, KzedMapTile tile, File outputFile) { @@ -438,10 +440,10 @@ public class DefaultTileRenderer implements MapTileRenderer { if (colors != null) { Color c = colors[seq]; if (c.getAlpha() > 0) { - /* we found something that isn't transparent! */ - if (c.getAlpha() == 255) { + /* we found something that isn't transparent, or not doing transparency */ + if ((!transparency) || (c.getAlpha() == 255)) { /* it's opaque - the ray ends here */ - result.setColor(c); + result.setARGB(c.getARGB() | 0xFF000000); if(lightlevel < 15) { /* Not full light? */ shadowColor(result, lightlevel); } diff --git a/src/main/java/org/dynmap/utils/FileLockManager.java b/src/main/java/org/dynmap/utils/FileLockManager.java index e6f5b7a4..c60efcf5 100644 --- a/src/main/java/org/dynmap/utils/FileLockManager.java +++ b/src/main/java/org/dynmap/utils/FileLockManager.java @@ -72,7 +72,7 @@ public class FileLockManager { } else { /* Write lock in place */ try { - lock.wait(); + lock.wait(); } catch (InterruptedException ix) { Log.severe("getReadLock(" + fn + ") interrupted"); } diff --git a/src/main/java/org/dynmap/web/handlers/FileHandler.java b/src/main/java/org/dynmap/web/handlers/FileHandler.java index 439f78e2..9ee75128 100644 --- a/src/main/java/org/dynmap/web/handlers/FileHandler.java +++ b/src/main/java/org/dynmap/web/handlers/FileHandler.java @@ -113,15 +113,17 @@ public abstract class FileHandler implements HttpHandler { out.write(readBuffer, 0, readBytes); } } catch (IOException e) { - fileInput.close(); throw e; } finally { freeReadBuffer(readBuffer); + if(fileInput != null) { + closeFileInput(path, fileInput); + fileInput = null; + } } - closeFileInput(path, fileInput); } catch (Exception e) { if (fileInput != null) { - try { fileInput.close(); } catch (IOException ex) { } + try { closeFileInput(path, fileInput); fileInput = null; } catch (IOException ex) { } } throw e; } diff --git a/src/main/java/org/dynmap/web/handlers/FilesystemHandler.java b/src/main/java/org/dynmap/web/handlers/FilesystemHandler.java index de4e0091..50a82e25 100644 --- a/src/main/java/org/dynmap/web/handlers/FilesystemHandler.java +++ b/src/main/java/org/dynmap/web/handlers/FilesystemHandler.java @@ -28,6 +28,7 @@ public class FilesystemHandler extends FileHandler { try { result = new FileInputStream(file); } catch (FileNotFoundException e) { + FileLockManager.releaseReadLock(file); return null; } response.fields.put(HttpField.ContentLength, Long.toString(file.length()));