diff --git a/src/main/java/org/dynmap/Color.java b/src/main/java/org/dynmap/Color.java new file mode 100644 index 00000000..4c7fe0ae --- /dev/null +++ b/src/main/java/org/dynmap/Color.java @@ -0,0 +1,46 @@ +package org.dynmap; + +/** + * Simple replacement for java.awt.Color for dynmap - it's not an invariant, so we don't make millions + * of them during rendering + */ +public class Color { + /* RGBA value */ + private int val; + + public static final int TRANSPARENT = 0; + + public Color(int red, int green, int blue, int alpha) { + setRGBA(red, green, blue, alpha); + } + public Color(int red, int green, int blue) { + setRGBA(red, green, blue, 0xFF); + } + public Color() { + setTransparent(); + } + public final int getRed() { + return (val >> 24) & 0xFF; + } + public final int getGreen() { + return (val >> 16) & 0xFF; + } + public final int getBlue() { + return (val >> 8) & 0xFF; + } + public final int getAlpha() { + return (val & 0xFF); + } + public final boolean isTransparent() { + return (val == TRANSPARENT); + } + public final void setTransparent() { + val = TRANSPARENT; + } + public final void setColor(Color c) { + val = c.val; + } + public final void setRGBA(int red, int green, int blue, int alpha) { + val = ((red & 0xFF) << 24) | ((green & 0xFF) << 16) | ((blue & 0xFF) << 8) | (alpha & 0xFF); + } +} diff --git a/src/main/java/org/dynmap/ColorScheme.java b/src/main/java/org/dynmap/ColorScheme.java index 99894b82..bd59b34d 100644 --- a/src/main/java/org/dynmap/ColorScheme.java +++ b/src/main/java/org/dynmap/ColorScheme.java @@ -1,6 +1,6 @@ package org.dynmap; -import java.awt.Color; +import org.dynmap.Color; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; diff --git a/src/main/java/org/dynmap/flat/FlatMap.java b/src/main/java/org/dynmap/flat/FlatMap.java index 32d6d90c..b9e2abd3 100644 --- a/src/main/java/org/dynmap/flat/FlatMap.java +++ b/src/main/java/org/dynmap/flat/FlatMap.java @@ -1,6 +1,6 @@ package org.dynmap.flat; -import java.awt.Color; +import org.dynmap.Color; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.File; diff --git a/src/main/java/org/dynmap/kzedmap/CaveTileRenderer.java b/src/main/java/org/dynmap/kzedmap/CaveTileRenderer.java index 7a5ee9d4..3c1f557f 100644 --- a/src/main/java/org/dynmap/kzedmap/CaveTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/CaveTileRenderer.java @@ -1,6 +1,6 @@ package org.dynmap.kzedmap; -import java.awt.Color; +import org.dynmap.Color; import java.util.Map; import org.bukkit.World; @@ -12,12 +12,12 @@ public class CaveTileRenderer extends DefaultTileRenderer { } @Override - protected Color scan(World world, int x, int y, int z, int seq, boolean isnether) { + protected void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result) { boolean air = true; - + result.setTransparent(); for (;;) { if (y < 0) - return translucent; + return; int id = world.getBlockTypeIdAt(x, y, z); if(isnether) { /* Make ceiling into air in nether */ @@ -93,7 +93,8 @@ public class CaveTileRenderer extends DefaultTileRenderer { cg = cg * mult / 256; cb = cb * mult / 256; - return new Color(cr, cg, cb); + result.setRGBA(cr, cg, cb, 255); + return; } } } diff --git a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java index 6fa68dbc..8e034835 100644 --- a/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/DefaultTileRenderer.java @@ -1,6 +1,6 @@ package org.dynmap.kzedmap; -import java.awt.Color; +import org.dynmap.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; @@ -66,24 +66,28 @@ public class DefaultTileRenderer implements MapTileRenderer { int x, y; + Color c1 = new Color(); + Color c2 = new Color(); + int[] rgb = new int[3]; /* draw the map */ for (y = 0; y < KzedMap.tileHeight;) { jx = ix; jz = iz; for (x = KzedMap.tileWidth - 1; x >= 0; x -= 2) { - Color c1 = scan(world, jx, iy, jz, 0, isnether); - Color c2 = scan(world, jx, iy, jz, 2, isnether); - isempty = isempty && c1 == translucent && c2 == translucent; - r.setPixel(x, y, new int[] { - c1.getRed(), - c1.getGreen(), - c1.getBlue() }); - r.setPixel(x - 1, y, new int[] { - c2.getRed(), - c2.getGreen(), - c2.getBlue() }); - + scan(world, jx, iy, jz, 0, isnether, c1); + scan(world, jx, iy, jz, 2, isnether, c2); + if(c1.isTransparent() == false) { + rgb[0] = c1.getRed(); rgb[1] = c1.getGreen(); rgb[2] = c1.getBlue(); + r.setPixel(x, y, rgb); + isempty = false; + } + if(c2.isTransparent() == false) { + rgb[0] = c2.getRed(); rgb[1] = c2.getGreen(); rgb[2] = c2.getBlue(); + r.setPixel(x - 1, y, rgb); + isempty = false; + } + jx++; jz++; @@ -95,19 +99,21 @@ public class DefaultTileRenderer implements MapTileRenderer { jz = iz - 1; for (x = KzedMap.tileWidth - 1; x >= 0; x -= 2) { - Color c1 = scan(world, jx, iy, jz, 2, isnether); + scan(world, jx, iy, jz, 2, isnether, c1); jx++; jz++; - Color c2 = scan(world, jx, iy, jz, 0, isnether); - isempty = isempty && c1 == translucent && c2 == translucent; - r.setPixel(x, y, new int[] { - c1.getRed(), - c1.getGreen(), - c1.getBlue() }); - r.setPixel(x - 1, y, new int[] { - c2.getRed(), - c2.getGreen(), - c2.getBlue() }); + scan(world, jx, iy, jz, 0, isnether, c2); + if(c1.isTransparent() == false) { + rgb[0] = c1.getRed(); rgb[1] = c1.getGreen(); rgb[2] = c1.getBlue(); + r.setPixel(x, y, rgb); + isempty = false; + } + if(c2.isTransparent() == false) { + rgb[0] = c2.getRed(); rgb[1] = c2.getGreen(); rgb[2] = c2.getBlue(); + + r.setPixel(x - 1, y, rgb); + isempty = false; + } } y++; @@ -205,20 +211,20 @@ public class DefaultTileRenderer implements MapTileRenderer { } - protected Color scan(World world, int x, int y, int z, int seq, boolean isnether) { - Color result = translucent; + protected void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result) { + result.setTransparent(); for (;;) { if (y < 0) { - return result; + return; } int id = world.getBlockTypeIdAt(x, y, z); byte data = 0; if(isnether) { /* Make bedrock ceiling into air in nether */ if(id != 0) { /* Remember first color we see, in case we wind up solid */ - if(result == translucent) + if(result.isTransparent()) if(colorScheme.colors[id] != null) - result = colorScheme.colors[id][seq]; + result.setColor(colorScheme.colors[id][seq]); id = 0; } else @@ -246,7 +252,8 @@ public class DefaultTileRenderer implements MapTileRenderer { if (id != 0) { if (highlightBlocks.contains(id)) { - return highlightColor; + result.setColor(highlightColor); + return; } Color[] colors; if(data != 0) @@ -259,11 +266,12 @@ public class DefaultTileRenderer implements MapTileRenderer { /* we found something that isn't transparent! */ if (c.getAlpha() == 255) { /* it's opaque - the ray ends here */ - return c; + result.setColor(c); + return; } /* this block is transparent, so recurse */ - Color bg = scan(world, x, y, z, seq, isnether); + scan(world, x, y, z, seq, isnether, result); int cr = c.getRed(); int cg = c.getGreen(); @@ -273,8 +281,8 @@ public class DefaultTileRenderer implements MapTileRenderer { cg *= ca; cb *= ca; int na = 255 - ca; - - return new Color((bg.getRed() * na + cr) >> 8, (bg.getGreen() * na + cg) >> 8, (bg.getBlue() * na + cb) >> 8); + result.setRGBA((result.getRed() * na + cr) >> 8, (result.getGreen() * na + cg) >> 8, (result.getBlue() * na + cb) >> 8, 255); + return; } } } diff --git a/src/main/java/org/dynmap/kzedmap/HighlightTileRenderer.java b/src/main/java/org/dynmap/kzedmap/HighlightTileRenderer.java index c0541289..f30c73f6 100644 --- a/src/main/java/org/dynmap/kzedmap/HighlightTileRenderer.java +++ b/src/main/java/org/dynmap/kzedmap/HighlightTileRenderer.java @@ -1,6 +1,6 @@ package org.dynmap.kzedmap; -import java.awt.Color; +import org.dynmap.Color; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -23,8 +23,8 @@ public class HighlightTileRenderer extends DefaultTileRenderer { } @Override - protected Color scan(World world, int x, int y, int z, int seq, boolean isnether) { - Color result = translucent; + protected void scan(World world, int x, int y, int z, int seq, boolean isnether, final Color result) { + result.setTransparent(); int top_nether_id = 0; for (;;) { if (y < 0) { @@ -35,9 +35,9 @@ public class HighlightTileRenderer extends DefaultTileRenderer { if(isnether) { /* Make bedrock ceiling into air in nether */ if(id != 0) { /* Remember first color we see, in case we wind up solid */ - if(result == translucent) + if(result.isTransparent()) if(colorScheme.colors[id] != null) - result = colorScheme.colors[id][seq]; + result.setColor(colorScheme.colors[id][seq]); id = 0; } else @@ -75,7 +75,8 @@ public class HighlightTileRenderer extends DefaultTileRenderer { Color c = colors[seq]; if (highlightBlocks.contains(id)) { - return c; + result.setColor(c); + return; } if (c.getAlpha() > 0) { @@ -88,26 +89,22 @@ public class HighlightTileRenderer extends DefaultTileRenderer { // No need to blend if result is opaque. if (result.getAlpha() < 255) { - Color bg = c; - c = result; - - int cr = c.getRed(); - int cg = c.getGreen(); - int cb = c.getBlue(); - int ca = c.getAlpha(); + int cr = result.getRed(); + int cg = result.getGreen(); + int cb = result.getBlue(); + int ca = result.getAlpha(); cr *= ca; cg *= ca; cb *= ca; int na = 255 - ca; - result = new Color((bg.getRed() * na + cr) >> 8, (bg.getGreen() * na + cg) >> 8, (bg.getBlue() * na + cb) >> 8, - Math.min(255, bg.getAlpha()+c.getAlpha()) // Not really correct, but gets the job done without recursion while still looking ok. + result.setRGBA((c.getRed() * na + cr) >> 8, (c.getGreen() * na + cg) >> 8, (c.getBlue() * na + cb) >> 8, + Math.min(255, c.getAlpha()+ca) // Not really correct, but gets the job done without recursion while still looking ok. ); } } } } } - return result; } }