Merge pull request #226 from mikeprimm/master

Add support for biome-data-based shading on surface map renderer
This commit is contained in:
mikeprimm 2011-06-20 14:11:42 -07:00
commit 427249b5a9
16 changed files with 514 additions and 27 deletions

View File

@ -227,3 +227,35 @@ Locked Chest
95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Trap Door Trap Door
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255 96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Biome Rainforest - Dark Green
[RAINFOREST] 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
Biome Swampland - Brown
[SWAMPLAND] 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Biome Seasonal Forest - Light Green
[SEASONAL_FOREST] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
Biome Forest - Light Gray
[FOREST] 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Biome Savanna - Dark Gray
[SAVANNA] 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
Biome Shrubland - Yellow
[SHRUBLAND] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
Biome Taiga - Cyan
[TAIGA] 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
Biome Desert - Orange
[DESERT] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
Biome Plains - Magenta
[PLAINS] 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
Biome Ice Desert - Blue
[ICE_DESERT] 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
Biome Tundra - White
[TUNDRA] 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Biome Hell - Pink
[HELL] 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
[RAINFALL-0.0] 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
[RAINFALL-1.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.5] 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
[TEMPERATURE-0.8] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
[TEMPERATURE-0.9] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
[TEMPERATURE-0.95] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
[TEMPERATURE-1.0] 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255

View File

@ -227,3 +227,35 @@ Locked Chest
95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Trap Door Trap Door
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255 96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Biome Rainforest - Dark Green
[RAINFOREST] 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
Biome Swampland - Brown
[SWAMPLAND] 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Biome Seasonal Forest - Light Green
[SEASONAL_FOREST] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
Biome Forest - Light Gray
[FOREST] 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Biome Savanna - Dark Gray
[SAVANNA] 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
Biome Shrubland - Yellow
[SHRUBLAND] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
Biome Taiga - Cyan
[TAIGA] 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
Biome Desert - Orange
[DESERT] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
Biome Plains - Magenta
[PLAINS] 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
Biome Ice Desert - Blue
[ICE_DESERT] 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
Biome Tundra - White
[TUNDRA] 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Biome Hell - Pink
[HELL] 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
[RAINFALL-0.0] 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
[RAINFALL-1.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.5] 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
[TEMPERATURE-0.8] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
[TEMPERATURE-0.9] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
[TEMPERATURE-0.95] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
[TEMPERATURE-1.0] 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255

View File

@ -227,4 +227,35 @@ Locked Chest
95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
Trap Door Trap Door
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255 96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Biome Rainforest - Dark Green
[RAINFOREST] 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
Biome Swampland - Brown
[SWAMPLAND] 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Biome Seasonal Forest - Light Green
[SEASONAL_FOREST] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
Biome Forest - Light Gray
[FOREST] 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Biome Savanna - Dark Gray
[SAVANNA] 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
Biome Shrubland - Yellow
[SHRUBLAND] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
Biome Taiga - Cyan
[TAIGA] 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
Biome Desert - Orange
[DESERT] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
Biome Plains - Magenta
[PLAINS] 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
Biome Ice Desert - Blue
[ICE_DESERT] 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
Biome Tundra - White
[TUNDRA] 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Biome Hell - Pink
[HELL] 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
[RAINFALL-0.0] 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
[RAINFALL-1.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.5] 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
[TEMPERATURE-0.8] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
[TEMPERATURE-0.9] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
[TEMPERATURE-0.95] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
[TEMPERATURE-1.0] 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255

View File

@ -113,3 +113,35 @@
94 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0 94 159 127 80 255 102 0 0 0 255 0 0 255 204 0 0 0
95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255 95 125 91 38 255 100 72 30 255 62 45 19 255 50 36 15 255
96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255 96 111 91 54 255 88 72 43 255 55 45 27 255 44 36 21 255
Biome Rainforest - Dark Green
[RAINFOREST] 49 67 21 255 39 53 17 255 24 34 10 255 19 27 8 255
Biome Swampland - Brown
[SWAMPLAND] 75 44 24 255 60 35 19 255 37 22 12 255 30 18 10 255
Biome Seasonal Forest - Light Green
[SEASONAL_FOREST] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
Biome Forest - Light Gray
[FOREST] 138 145 145 255 110 115 115 255 69 72 72 255 55 57 57 255
Biome Savanna - Dark Gray
[SAVANNA] 58 58 58 255 47 47 47 255 29 29 29 255 23 23 23 255
Biome Shrubland - Yellow
[SHRUBLAND] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
Biome Taiga - Cyan
[TAIGA] 34 102 131 255 27 81 104 255 17 51 65 255 13 40 52 255
Biome Desert - Orange
[DESERT] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
Biome Plains - Magenta
[PLAINS] 166 66 175 255 133 53 140 255 83 33 87 255 66 26 69 255
Biome Ice Desert - Blue
[ICE_DESERT] 34 44 134 255 27 35 107 255 17 22 67 255 13 18 53 255
Biome Tundra - White
[TUNDRA] 222 222 222 255 177 177 177 255 111 111 111 255 88 88 88 255
Biome Hell - Pink
[HELL] 190 115 135 255 151 92 108 255 95 57 67 255 75 46 53 255
[RAINFALL-0.0] 120 120 120 255 96 96 96 255 60 60 60 255 48 48 48 255
[RAINFALL-1.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.0] 38 92 255 255 30 73 204 255 19 46 127 255 15 36 102 255
[TEMPERATURE-0.5] 91 121 185 255 73 96 147 255 46 61 92 255 36 48 73 255
[TEMPERATURE-0.8] 51 165 42 255 41 131 33 255 26 82 21 255 20 65 17 255
[TEMPERATURE-0.9] 170 158 24 255 135 126 19 255 85 79 12 255 67 62 10 255
[TEMPERATURE-0.95] 204 111 48 255 162 89 38 255 102 56 24 255 81 44 19 255
[TEMPERATURE-1.0] 143 39 36 255 114 31 28 255 71 20 18 255 57 16 14 255

View File

@ -178,7 +178,15 @@ templates:
# background: "#000000" # background: "#000000"
# # Sets the icon to 'images/block_custom.png' # # Sets the icon to 'images/block_custom.png'
# icon: custom # icon: custom
# # Biome-based mapping
# - class: org.dynmap.kzedmap.DefaultTileRenderer
# name: biome
# title: "Biome"
# prefix: b
# maximumheight: 127
# colorscheme: default
# # Biome-based coloring : biome=biome type, temperature=biome-temperature, rainfall=biome-rainfall
# biomecolored: biome
# - class: org.dynmap.kzedmap.HighlightTileRenderer # - class: org.dynmap.kzedmap.HighlightTileRenderer
# prefix: ht # prefix: ht
# maximumheight: 127 # maximumheight: 127

View File

@ -8,19 +8,26 @@ import java.util.HashMap;
import java.util.Scanner; import java.util.Scanner;
import org.dynmap.debug.Debug; import org.dynmap.debug.Debug;
import org.bukkit.block.Biome;
public class ColorScheme { public class ColorScheme {
private static final HashMap<String, ColorScheme> cache = new HashMap<String, ColorScheme>(); private static final HashMap<String, ColorScheme> cache = new HashMap<String, ColorScheme>();
public String name; public String name;
/* Switch to arrays - faster than map */ /* Switch to arrays - faster than map */
public Color[][] colors; /* [blk-type][step] */ public final Color[][] colors; /* [blk-type][step] */
public Color[][][] datacolors; /* [bkt-type][blk-dat][step] */ public final Color[][][] datacolors; /* [bkt-type][blk-dat][step] */
public final Color[][] biomecolors; /* [Biome.ordinal][step] */
public final Color[][] raincolors; /* [rain * 63][step] */
public final Color[][] tempcolors; /* [temp * 63][step] */
public ColorScheme(String name, Color[][] colors, Color[][][] datacolors) { public ColorScheme(String name, Color[][] colors, Color[][][] datacolors, Color[][] biomecolors, Color[][] raincolors, Color[][] tempcolors) {
this.name = name; this.name = name;
this.colors = colors; this.colors = colors;
this.datacolors = datacolors; this.datacolors = datacolors;
this.biomecolors = biomecolors;
this.raincolors = raincolors;
this.tempcolors = tempcolors;
} }
private static File getColorSchemeDirectory() { private static File getColorSchemeDirectory() {
@ -42,6 +49,10 @@ public class ColorScheme {
File colorSchemeFile = new File(getColorSchemeDirectory(), name + ".txt"); File colorSchemeFile = new File(getColorSchemeDirectory(), name + ".txt");
Color[][] colors = new Color[256][]; Color[][] colors = new Color[256][];
Color[][][] datacolors = new Color[256][][]; Color[][][] datacolors = new Color[256][][];
Color[][] biomecolors = new Color[Biome.values().length][];
Color[][] raincolors = new Color[64][];
Color[][] tempcolors = new Color[64][];
InputStream stream; InputStream stream;
try { try {
Debug.debug("Loading colors from '" + colorSchemeFile + "'..."); Debug.debug("Loading colors from '" + colorSchemeFile + "'...");
@ -54,18 +65,62 @@ public class ColorScheme {
if (line.startsWith("#") || line.equals("")) { if (line.startsWith("#") || line.equals("")) {
continue; continue;
} }
/* Make parser less pedantic - tabs or spaces should be fine */
String[] split = line.split("\t"); String[] split = line.split("[\t ]");
int cnt = 0;
for(String s: split) { if(s.length() > 0) cnt++; }
String[] nsplit = new String[cnt];
cnt = 0;
for(String s: split) { if(s.length() > 0) { nsplit[cnt] = s; cnt++; } }
split = nsplit;
if (split.length < 17) { if (split.length < 17) {
continue; continue;
} }
Integer id; Integer id;
Integer dat = null; Integer dat = null;
boolean isbiome = false;
boolean istemp = false;
boolean israin = false;
int idx = split[0].indexOf(':'); int idx = split[0].indexOf(':');
if(idx > 0) { /* ID:data - data color */ if(idx > 0) { /* ID:data - data color */
id = new Integer(split[0].substring(0, idx)); id = new Integer(split[0].substring(0, idx));
dat = new Integer(split[0].substring(idx+1)); dat = new Integer(split[0].substring(idx+1));
} }
else if(split[0].charAt(0) == '[') { /* Biome color data */
String bio = split[0].substring(1);
idx = bio.indexOf(']');
if(idx >= 0) bio = bio.substring(0, idx);
isbiome = true;
id = -1;
for(Biome b : Biome.values()) {
if(b.toString().equalsIgnoreCase(bio)) {
id = b.ordinal();
break;
}
}
if(id < 0) { /* Not biome - check for rain or temp */
if(bio.startsWith("RAINFALL-")) {
try {
double v = Double.parseDouble(bio.substring(9));
if((v >= 0) && (v <= 1.00)) {
id = (int)(v * 63.0);
israin = true;
}
} catch (NumberFormatException nfx) {
}
}
else if(bio.startsWith("TEMPERATURE-")) {
try {
double v = Double.parseDouble(bio.substring(12));
if((v >= 0) && (v <= 1.00)) {
id = (int)(v * 63.0);
istemp = true;
}
} catch (NumberFormatException nfx) {
}
}
}
}
else { else {
id = new Integer(split[0]); id = new Integer(split[0]);
} }
@ -79,7 +134,17 @@ public class ColorScheme {
/* Blended color - for 'smooth' option on flat map */ /* Blended color - for 'smooth' option on flat map */
c[4] = new Color((c[0].getRed()+c[2].getRed())/2, (c[0].getGreen()+c[2].getGreen())/2, (c[0].getBlue()+c[2].getBlue())/2, (c[0].getAlpha()+c[2].getAlpha())/2); c[4] = new Color((c[0].getRed()+c[2].getRed())/2, (c[0].getGreen()+c[2].getGreen())/2, (c[0].getBlue()+c[2].getBlue())/2, (c[0].getAlpha()+c[2].getAlpha())/2);
if(dat != null) { if(isbiome) {
if(istemp) {
tempcolors[id] = c;
}
else if(israin) {
raincolors[id] = c;
}
else if((id >= 0) && (id < biomecolors.length))
biomecolors[id] = c;
}
else if(dat != null) {
Color[][] dcolor = datacolors[id]; /* Existing list? */ Color[][] dcolor = datacolors[id]; /* Existing list? */
if(dcolor == null) { if(dcolor == null) {
dcolor = new Color[16][]; /* Make 16 index long list */ dcolor = new Color[16][]; /* Make 16 index long list */
@ -109,12 +174,65 @@ public class ColorScheme {
} }
} }
} }
/* And interpolate any missing rain and temperature colors */
interpolateColorTable(tempcolors);
interpolateColorTable(raincolors);
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.severe("Could not load colors '" + name + "' ('" + colorSchemeFile + "').", e); Log.severe("Could not load colors '" + name + "' ('" + colorSchemeFile + "').", e);
return null; return null;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
Log.severe("Could not load colors '" + name + "' ('" + colorSchemeFile + "'): File not found.", e); Log.severe("Could not load colors '" + name + "' ('" + colorSchemeFile + "'): File not found.", e);
} }
return new ColorScheme(name, colors, datacolors); return new ColorScheme(name, colors, datacolors, biomecolors, raincolors, tempcolors);
}
public static void interpolateColorTable(Color[][] c) {
int idx = -1;
for(int k = 0; k < c.length; k++) {
if(c[k] == null) { /* Missing? */
if((idx >= 0) && (k == (c.length-1))) { /* We're last - so fill forward from last color */
for(int kk = idx+1; kk <= k; kk++) {
c[kk] = c[idx];
}
}
/* Skip - will backfill when we find next color */
}
else if(idx == -1) { /* No previous color, just backfill this color */
for(int kk = 0; kk < k; kk++) {
c[kk] = c[k];
}
idx = k; /* This is now last defined color */
}
else { /* Else, interpolate between last idx and this one */
int cnt = c[k].length;
for(int kk = idx+1; kk < k; kk++) {
double interp = (double)(kk-idx)/(double)(k-idx);
Color[] cc = new Color[cnt];
for(int jj = 0; jj < cnt; jj++) {
cc[jj] = new Color(
(int)((1.0-interp)*c[idx][jj].getRed() + interp*c[k][jj].getRed()),
(int)((1.0-interp)*c[idx][jj].getGreen() + interp*c[k][jj].getGreen()),
(int)((1.0-interp)*c[idx][jj].getBlue() + interp*c[k][jj].getBlue()),
(int)((1.0-interp)*c[idx][jj].getAlpha() + interp*c[k][jj].getAlpha()));
}
c[kk] = cc;
}
idx = k;
}
}
}
public Color[] getRainColor(double rain) {
int idx = (int)(rain * 63.0);
if((idx >= 0) && (idx < raincolors.length))
return raincolors[idx];
else
return null;
}
public Color[] getTempColor(double temp) {
int idx = (int)(temp * 63.0);
if((idx >= 0) && (idx < tempcolors.length))
return tempcolors[idx];
else
return null;
} }
} }

View File

@ -180,8 +180,11 @@ public class MapManager {
} }
World w = world.world; World w = world.world;
/* Fetch chunk cache from server thread */ /* Fetch chunk cache from server thread */
List<DynmapChunk> requiredChunks = tile.getMap().getRequiredChunks(tile); MapType mt = tile.getMap();
MapChunkCache cache = createMapChunkCache(world, requiredChunks); List<DynmapChunk> requiredChunks = mt.getRequiredChunks(tile);
MapChunkCache cache = createMapChunkCache(world, requiredChunks, mt.isBlockTypeDataNeeded(),
mt.isHightestBlockYDataNeeded(), mt.isBiomeDataNeeded(),
mt.isRawBiomeDataNeeded());
if(cache == null) { if(cache == null) {
cleanup(); cleanup();
return; /* Cancelled/aborted */ return; /* Cancelled/aborted */
@ -476,7 +479,8 @@ public class MapManager {
/** /**
* Render processor helper - used by code running on render threads to request chunk snapshot cache from server/sync thread * Render processor helper - used by code running on render threads to request chunk snapshot cache from server/sync thread
*/ */
public MapChunkCache createMapChunkCache(final DynmapWorld w, final List<DynmapChunk> chunks) { public MapChunkCache createMapChunkCache(DynmapWorld w, List<DynmapChunk> chunks,
boolean blockdata, boolean highesty, boolean biome, boolean rawbiome) {
MapChunkCache c = null; MapChunkCache c = null;
try { try {
if(!use_legacy) if(!use_legacy)
@ -493,6 +497,9 @@ public class MapManager {
c.setHiddenFillStyle(w.hiddenchunkstyle); c.setHiddenFillStyle(w.hiddenchunkstyle);
} }
c.setChunks(w.world, chunks); c.setChunks(w.world, chunks);
if(c.setChunkDataTypes(blockdata, biome, highesty, rawbiome) == false)
Log.severe("CraftBukkit build does not support biome APIs");
synchronized(c) { synchronized(c) {
chunkloads.add(c); chunkloads.add(c);
try { try {

View File

@ -22,4 +22,10 @@ public abstract class MapType {
} }
public abstract String getName(); public abstract String getName();
public boolean isBiomeDataNeeded() { return false; }
public boolean isHightestBlockYDataNeeded() { return false; }
public boolean isRawBiomeDataNeeded() { return false; }
public boolean isBlockTypeDataNeeded() { return true; }
} }

View File

@ -117,6 +117,11 @@ public class FlatMap extends MapType {
return result; return result;
} }
@Override
public boolean isHightestBlockYDataNeeded() {
return true;
}
@Override @Override
public boolean render(MapChunkCache cache, MapTile tile, File outputFile) { public boolean render(MapChunkCache cache, MapTile tile, File outputFile) {
FlatMapTile t = (FlatMapTile) tile; FlatMapTile t = (FlatMapTile) tile;

View File

@ -11,6 +11,7 @@ import javax.imageio.ImageIO;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.dynmap.Client; import org.dynmap.Client;
import org.dynmap.Color; import org.dynmap.Color;
import org.dynmap.ColorScheme; import org.dynmap.ColorScheme;
@ -38,6 +39,10 @@ public class DefaultTileRenderer implements MapTileRenderer {
protected int lightscale[]; /* scale skylight level (light = lightscale[skylight] */ 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 night_and_day; /* If true, render both day (prefix+'-day') and night (prefix) tiles */
protected boolean transparency; /* Is transparency support active? */ protected boolean transparency; /* Is transparency support active? */
public enum BiomeColorOption {
NONE, BIOME, TEMPERATURE, RAINFALL
}
protected BiomeColorOption biomecolored = BiomeColorOption.NONE; /* Use biome for coloring */
@Override @Override
public String getName() { public String getName() {
return name; return name;
@ -81,6 +86,23 @@ public class DefaultTileRenderer implements MapTileRenderer {
colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme")); colorScheme = ColorScheme.getScheme((String)configuration.get("colorscheme"));
night_and_day = configuration.getBoolean("night-and-day", false); night_and_day = configuration.getBoolean("night-and-day", false);
transparency = configuration.getBoolean("transparency", true); /* Default on */ transparency = configuration.getBoolean("transparency", true); /* Default on */
String biomeopt = configuration.getString("biomecolored", "none");
if(biomeopt.equals("biome")) {
biomecolored = BiomeColorOption.BIOME;
}
else if(biomeopt.equals("temperature")) {
biomecolored = BiomeColorOption.TEMPERATURE;
}
else if(biomeopt.equals("rainfall")) {
biomecolored = BiomeColorOption.RAINFALL;
}
else {
biomecolored = BiomeColorOption.NONE;
}
}
public boolean isBiomeDataNeeded() { return biomecolored.equals(BiomeColorOption.BIOME); }
public boolean isRawBiomeDataNeeded() {
return biomecolored.equals(BiomeColorOption.RAINFALL) || biomecolored.equals(BiomeColorOption.TEMPERATURE);
} }
public boolean render(MapChunkCache cache, KzedMapTile tile, File outputFile) { public boolean render(MapChunkCache cache, KzedMapTile tile, File outputFile) {
@ -360,6 +382,9 @@ public class DefaultTileRenderer implements MapTileRenderer {
MapIterator mapiter) { MapIterator mapiter) {
int lightlevel = 15; int lightlevel = 15;
int lightlevel_day = 15; int lightlevel_day = 15;
Biome bio = null;
double rain = 0.0;
double temp = 0.0;
result.setTransparent(); result.setTransparent();
if(result_day != null) if(result_day != null)
result_day.setTransparent(); result_day.setTransparent();
@ -381,8 +406,21 @@ public class DefaultTileRenderer implements MapTileRenderer {
isnether = false; isnether = false;
} }
if(id != 0) { /* No update needed for air */ if(id != 0) { /* No update needed for air */
if(colorScheme.datacolors[id] != null) { /* If data colored */ switch(biomecolored) {
data = mapiter.getBlockData(); case NONE:
if(colorScheme.datacolors[id] != null) { /* If data colored */
data = mapiter.getBlockData();
}
break;
case BIOME:
bio = mapiter.getBiome();
break;
case RAINFALL:
rain = mapiter.getRawBiomeRainfall();
break;
case TEMPERATURE:
temp = mapiter.getRawBiomeTemperature();
break;
} }
if((shadowscale != null) && (mapiter.getY() < 127)) { if((shadowscale != null) && (mapiter.getY() < 127)) {
/* Find light level of previous chunk */ /* Find light level of previous chunk */
@ -441,11 +479,25 @@ public class DefaultTileRenderer implements MapTileRenderer {
result.setColor(highlightColor); result.setColor(highlightColor);
return; return;
} }
Color[] colors; Color[] colors = null;
if(data != 0) switch(biomecolored) {
colors = colorScheme.datacolors[id][data]; case NONE:
else if(data != 0)
colors = colorScheme.colors[id]; colors = colorScheme.datacolors[id][data];
else
colors = colorScheme.colors[id];
break;
case BIOME:
if(bio != null)
colors = colorScheme.biomecolors[bio.ordinal()];
break;
case RAINFALL:
colors = colorScheme.getRainColor(rain);
break;
case TEMPERATURE:
colors = colorScheme.getTempColor(temp);
break;
}
if (colors != null) { if (colors != null) {
Color c = colors[seq]; Color c = colors[seq];
if (c.getAlpha() > 0) { if (c.getAlpha() > 0) {

View File

@ -310,6 +310,22 @@ public class KzedMap extends MapType {
} }
} }
public boolean isBiomeDataNeeded() {
for(MapTileRenderer r : renderers) {
if(r.isBiomeDataNeeded())
return true;
}
return false;
}
public boolean isRawBiomeDataNeeded() {
for(MapTileRenderer r : renderers) {
if(r.isRawBiomeDataNeeded())
return true;
}
return false;
}
public String getName() { public String getName() {
return "KzedMap"; return "KzedMap";
} }

View File

@ -12,4 +12,7 @@ public interface MapTileRenderer {
boolean render(MapChunkCache cache, KzedMapTile tile, File outputFile); boolean render(MapChunkCache cache, KzedMapTile tile, File outputFile);
void buildClientConfiguration(JSONObject worldObject); void buildClientConfiguration(JSONObject worldObject);
boolean isBiomeDataNeeded();
boolean isRawBiomeDataNeeded();
} }

View File

@ -4,8 +4,11 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.ListIterator; import java.util.ListIterator;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import org.bukkit.ChunkSnapshot;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.dynmap.DynmapChunk; import org.dynmap.DynmapChunk;
import org.dynmap.Log; import org.dynmap.Log;
@ -68,6 +71,16 @@ public class LegacyMapChunkCache implements MapChunkCache {
public final int getBlockEmittedLight() { public final int getBlockEmittedLight() {
return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF); return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF);
} }
public Biome getBiome() {
return null;
}
public double getRawBiomeTemperature() {
return 0.0;
}
public double getRawBiomeRainfall() {
return 0.0;
}
public final void incrementX() { public final void incrementX() {
x++; x++;
if((x & 0xF) == 0) { /* Next chunk? */ if((x & 0xF) == 0) { /* Next chunk? */
@ -377,6 +390,16 @@ public class LegacyMapChunkCache implements MapChunkCache {
LegacyChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; LegacyChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBlockEmittedLight(x & 0xF, y, z & 0xF); return ss.getBlockEmittedLight(x & 0xF, y, z & 0xF);
} }
public Biome getBiome(int x, int z) {
return null;
}
public double getRawBiomeTemperature(int x, int z) {
return 0.0;
}
public double getRawBiomeRainfall(int x, int z) {
return 0.0;
}
/** /**
* Get cache iterator * Get cache iterator
*/ */
@ -412,4 +435,10 @@ public class LegacyMapChunkCache implements MapChunkCache {
visible_limits = new ArrayList<VisibilityLimit>(); visible_limits = new ArrayList<VisibilityLimit>();
visible_limits.add(limit); visible_limits.add(limit);
} }
@Override
public boolean setChunkDataTypes(boolean blockdata, boolean biome, boolean highestblocky, boolean rawbiome) {
if(biome || rawbiome) /* Legacy doesn't support these */
return false;
return true;
}
} }

View File

@ -1,5 +1,7 @@
package org.dynmap.utils; package org.dynmap.utils;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome;
import java.util.List; import java.util.List;
import org.dynmap.DynmapChunk; import org.dynmap.DynmapChunk;
@ -16,6 +18,15 @@ public interface MapChunkCache {
* Set chunks to load, and world to load from * Set chunks to load, and world to load from
*/ */
void setChunks(World w, List<DynmapChunk> chunks); void setChunks(World w, List<DynmapChunk> chunks);
/**
* Set chunk data type needed
* @param blockdata - need block type and data for chunk
* @param biome - need biome data
* @param highestblocky - need highest-block-y data
* @param rawbiome - need raw biome temp/rain data
* @return true if all data types can be retrieved, false if not
*/
boolean setChunkDataTypes(boolean blockdata, boolean biome, boolean highestblocky, boolean rawbiome);
/** /**
* Load chunks into cache * Load chunks into cache
* @param maxToLoad - maximum number to load at once * @param maxToLoad - maximum number to load at once
@ -50,6 +61,18 @@ public interface MapChunkCache {
* Get emitted light level * Get emitted light level
*/ */
int getBlockEmittedLight(int x, int y, int z); int getBlockEmittedLight(int x, int y, int z);
/**
* Get biome at coordinates
*/
public Biome getBiome(int x, int z);
/**
* Get raw temperature data (0.0-1.0)
*/
public double getRawBiomeTemperature(int x, int z);
/**
* Get raw rainfall data (0.0-1.0)
*/
public double getRawBiomeRainfall(int x, int z);
/** /**
* Get cache iterator * Get cache iterator
*/ */

View File

@ -1,5 +1,7 @@
package org.dynmap.utils; package org.dynmap.utils;
import org.bukkit.block.Biome;
/** /**
* Iterator for traversing map chunk cache (base is for non-snapshot) * Iterator for traversing map chunk cache (base is for non-snapshot)
*/ */
@ -38,6 +40,18 @@ public interface MapIterator {
* @return emitted light level * @return emitted light level
*/ */
int getBlockEmittedLight(); int getBlockEmittedLight();
/**
* Get biome at coordinates
*/
public Biome getBiome();
/**
* Get raw temperature data (0.0-1.0)
*/
public double getRawBiomeTemperature();
/**
* Get raw rainfall data (0.0-1.0)
*/
public double getRawBiomeRainfall();
/** /**
* Increment X of current position * Increment X of current position
*/ */

View File

@ -1,5 +1,6 @@
package org.dynmap.utils; package org.dynmap.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -17,13 +18,17 @@ import org.dynmap.Log;
* Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread * Container for managing chunks - dependent upon using chunk snapshots, since rendering is off server thread
*/ */
public class NewMapChunkCache implements MapChunkCache { public class NewMapChunkCache implements MapChunkCache {
private static boolean init = false;
private static Method poppreservedchunk = null; private static Method poppreservedchunk = null;
private static Method getsnapshot2 = null;
private static Method getemptysnapshot = null;
private World w; private World w;
private List<DynmapChunk> chunks; private List<DynmapChunk> chunks;
private ListIterator<DynmapChunk> iterator; private ListIterator<DynmapChunk> iterator;
private int x_min, x_max, z_min, z_max; private int x_min, x_max, z_min, z_max;
private int x_dim; private int x_dim;
private boolean biome, biomeraw, highesty, blockdata;
private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR; private HiddenChunkStyle hidestyle = HiddenChunkStyle.FILL_AIR;
private List<VisibilityLimit> visible_limits = null; private List<VisibilityLimit> visible_limits = null;
@ -64,6 +69,15 @@ public class NewMapChunkCache implements MapChunkCache {
public final int getBlockEmittedLight() { public final int getBlockEmittedLight() {
return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF); return snap.getBlockEmittedLight(x & 0xF, y, z & 0xF);
} }
public Biome getBiome() {
return snap.getBiome(x & 0xF, z & 0xF);
}
public double getRawBiomeTemperature() {
return snap.getRawBiomeTemperature(x & 0xf, z & 0xf);
}
public double getRawBiomeRainfall() {
return snap.getRawBiomeRainfall(x & 0xf, z & 0xf);
}
public final void incrementX() { public final void incrementX() {
x++; x++;
if((x & 0xF) == 0) { /* Next chunk? */ if((x & 0xF) == 0) { /* Next chunk? */
@ -126,9 +140,6 @@ public class NewMapChunkCache implements MapChunkCache {
public int getX() { return 0; } public int getX() { return 0; }
public int getZ() { return 0; } public int getZ() { return 0; }
public String getWorldName() { return ""; } public String getWorldName() { return ""; }
public Biome getBiome(int x, int z) { return null; }
public double getRawBiomeTemperature(int x, int z) { return 0.0; }
public double getRawBiomeRainfall(int x, int z) { return 0.0; }
public long getCaptureFullTime() { return 0; } public long getCaptureFullTime() { return 0; }
public final int getBlockTypeId(int x, int y, int z) { public final int getBlockTypeId(int x, int y, int z) {
@ -146,6 +157,15 @@ public class NewMapChunkCache implements MapChunkCache {
public final int getHighestBlockYAt(int x, int z) { public final int getHighestBlockYAt(int x, int z) {
return 0; return 0;
} }
public Biome getBiome(int x, int z) {
return null;
}
public double getRawBiomeTemperature(int x, int z) {
return 0.0;
}
public double getRawBiomeRainfall(int x, int z) {
return 0.0;
}
} }
/** /**
@ -187,11 +207,35 @@ public class NewMapChunkCache implements MapChunkCache {
private static final PlainChunk STONE = new PlainChunk(1); private static final PlainChunk STONE = new PlainChunk(1);
private static final PlainChunk OCEAN = new PlainChunk(9); private static final PlainChunk OCEAN = new PlainChunk(9);
/** /**
* Construct empty cache * Construct empty cache
*/ */
@SuppressWarnings({ "rawtypes", "unchecked" })
public NewMapChunkCache() { public NewMapChunkCache() {
if(!init) {
/* Get CraftWorld.popPreservedChunk(x,z) - reduces memory bloat from map traversals (optional) */
try {
Class c = Class.forName("org.bukkit.craftbukkit.CraftWorld");
poppreservedchunk = c.getDeclaredMethod("popPreservedChunk", new Class[] { int.class, int.class });
/* getEmptyChunkSnapshot(int x, int z, boolean includeBiome, boolean includeBiomeTempRain) */
getemptysnapshot = c.getDeclaredMethod("getEmptyChunkSnapshot", new Class[] { int.class, int.class,
boolean.class, boolean.class });
} catch (ClassNotFoundException cnfx) {
} catch (NoSuchMethodException nsmx) {
}
/* Get CraftChunk.getChunkSnapshot(boolean,boolean,boolean) */
try {
Class c = Class.forName("org.bukkit.craftbukkit.CraftChunk");
getsnapshot2 = c.getDeclaredMethod("getChunkSnapshot", new Class[] { boolean.class, boolean.class, boolean.class });
} catch (ClassNotFoundException cnfx) {
} catch (NoSuchMethodException nsmx) {
}
if(getsnapshot2 != null)
Log.info("Biome data support is enabled");
else
Log.info("Biome data support is disabled");
init = true;
}
} }
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
public void setChunks(World w, List<DynmapChunk> chunks) { public void setChunks(World w, List<DynmapChunk> chunks) {
@ -266,7 +310,19 @@ public class NewMapChunkCache implements MapChunkCache {
} }
else { else {
Chunk c = w.getChunkAt(chunk.x, chunk.z); Chunk c = w.getChunkAt(chunk.x, chunk.z);
ss = c.getChunkSnapshot(); if(getsnapshot2 != null) {
try {
if(blockdata || highesty)
ss = (ChunkSnapshot)getsnapshot2.invoke(c, highesty, biome, biomeraw);
else
ss = (ChunkSnapshot)getemptysnapshot.invoke(w, chunk.x, chunk.z, biome, biomeraw);
} catch (InvocationTargetException itx) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
else
ss = c.getChunkSnapshot();
} }
snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss; snaparray[(chunk.x-x_min) + (chunk.z - z_min)*x_dim] = ss;
} }
@ -355,6 +411,19 @@ public class NewMapChunkCache implements MapChunkCache {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim]; ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBlockEmittedLight(x & 0xF, y, z & 0xF); return ss.getBlockEmittedLight(x & 0xF, y, z & 0xF);
} }
public Biome getBiome(int x, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getBiome(x & 0xF, z & 0xF);
}
public double getRawBiomeTemperature(int x, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getRawBiomeTemperature(x & 0xF, z & 0xF);
}
public double getRawBiomeRainfall(int x, int z) {
ChunkSnapshot ss = snaparray[((x>>4) - x_min) + ((z>>4) - z_min) * x_dim];
return ss.getRawBiomeRainfall(x & 0xF, z & 0xF);
}
/** /**
* Get cache iterator * Get cache iterator
*/ */
@ -390,4 +459,14 @@ public class NewMapChunkCache implements MapChunkCache {
visible_limits = new ArrayList<VisibilityLimit>(); visible_limits = new ArrayList<VisibilityLimit>();
visible_limits.add(limit); visible_limits.add(limit);
} }
@Override
public boolean setChunkDataTypes(boolean blockdata, boolean biome, boolean highestblocky, boolean rawbiome) {
if((getsnapshot2 == null) && (biome || rawbiome))
return false;
this.biome = biome;
this.biomeraw = rawbiome;
this.highesty = highestblocky;
this.blockdata = blockdata;
return true;
}
} }