mirror of https://github.com/webbukkit/dynmap.git
287 lines
12 KiB
Java
287 lines
12 KiB
Java
package org.dynmap;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.InputStream;
|
|
import java.util.HashMap;
|
|
import java.util.Scanner;
|
|
|
|
import org.dynmap.common.BiomeMap;
|
|
import org.dynmap.debug.Debug;
|
|
|
|
public class ColorScheme {
|
|
private static final HashMap<String, ColorScheme> cache = new HashMap<String, ColorScheme>();
|
|
|
|
public String name;
|
|
/* Switch to arrays - faster than map */
|
|
public Color[][] colors; /* [blk-type][step] */
|
|
public 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, Color[][] biomecolors, Color[][] raincolors, Color[][] tempcolors) {
|
|
this.name = name;
|
|
this.colors = colors;
|
|
this.datacolors = datacolors;
|
|
this.biomecolors = biomecolors;
|
|
this.raincolors = raincolors;
|
|
this.tempcolors = tempcolors;
|
|
//TODO: see if we can fix this for IDs vs names...
|
|
// for(int i = 0; i < colors.length; i++) {
|
|
// int id = MapManager.mapman.getBlockAlias(i);
|
|
// if(id != i) {
|
|
// this.colors[i] = this.colors[id];
|
|
// this.datacolors[i] = this.datacolors[id];
|
|
// }
|
|
// }
|
|
}
|
|
|
|
private static File getColorSchemeDirectory(DynmapCore core) {
|
|
return new File(core.getDataFolder(), "colorschemes");
|
|
}
|
|
|
|
public static ColorScheme getScheme(DynmapCore core, String name) {
|
|
if (name == null)
|
|
name = "default";
|
|
ColorScheme scheme = cache.get(name);
|
|
if (scheme == null) {
|
|
scheme = loadScheme(core, name);
|
|
cache.put(name, scheme);
|
|
}
|
|
return scheme;
|
|
}
|
|
|
|
public static ColorScheme loadScheme(DynmapCore core, String name) {
|
|
File colorSchemeFile = new File(getColorSchemeDirectory(core), name + ".txt");
|
|
Color[][] colors = new Color[4096][];
|
|
Color[][][] datacolors = new Color[4096][][];
|
|
Color[][] biomecolors = new Color[BiomeMap.values().length][];
|
|
Color[][] raincolors = new Color[64][];
|
|
Color[][] tempcolors = new Color[64][];
|
|
|
|
/* Default the biome color */
|
|
for(int i = 0; i < biomecolors.length; i++) {
|
|
Color[] c = new Color[5];
|
|
int red = 0x80 | (0x40 * ((i >> 0) & 1)) | (0x20 * ((i >> 3) & 1)) | (0x10 * ((i >> 6) & 1));
|
|
int green = 0x80 | (0x40 * ((i >> 1) & 1)) | (0x20 * ((i >> 4) & 1)) | (0x10 * ((i >> 7) & 1));
|
|
int blue = 0x80 | (0x40 * ((i >> 2) & 1)) | (0x20 * ((i >> 5) & 1));
|
|
c[0] = new Color(red, green, blue);
|
|
c[3] = new Color(red*4/5, green*4/5, blue*4/5);
|
|
c[1] = new Color(red/2, green/2, blue/2);
|
|
c[2] = new Color(red*2/5, green*2/5, blue*2/5);
|
|
c[4] = new Color((c[1].getRed()+c[3].getRed())/2, (c[1].getGreen()+c[3].getGreen())/2, (c[1].getBlue()+c[3].getBlue())/2, (c[1].getAlpha()+c[3].getAlpha())/2);
|
|
|
|
biomecolors[i] = c;
|
|
}
|
|
|
|
InputStream stream;
|
|
try {
|
|
Debug.debug("Loading colors from '" + colorSchemeFile + "'...");
|
|
stream = new FileInputStream(colorSchemeFile);
|
|
|
|
Scanner scanner = new Scanner(stream);
|
|
while (scanner.hasNextLine()) {
|
|
String line = scanner.nextLine();
|
|
if (line.startsWith("#") || line.equals("")) {
|
|
continue;
|
|
}
|
|
/* Make parser less pedantic - tabs or spaces should be fine */
|
|
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) {
|
|
continue;
|
|
}
|
|
Integer id;
|
|
Integer dat = null;
|
|
boolean isbiome = false;
|
|
boolean istemp = false;
|
|
boolean israin = false;
|
|
int idx = split[0].indexOf(':');
|
|
if(idx > 0) { /* ID:data - data color */
|
|
id = new Integer(split[0].substring(0, idx));
|
|
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;
|
|
BiomeMap[] bm = BiomeMap.values();
|
|
for(int i = 0; i < bm.length; i++) {
|
|
if(bm[i].toString().equalsIgnoreCase(bio)) {
|
|
id = i;
|
|
break;
|
|
}
|
|
else if(bio.equalsIgnoreCase("BIOME_" + i)) {
|
|
id = i;
|
|
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 {
|
|
id = new Integer(split[0]);
|
|
}
|
|
if((!isbiome) && (id >= colors.length)) {
|
|
Color[][] newcolors = new Color[id+1][];
|
|
System.arraycopy(colors, 0, newcolors, 0, colors.length);
|
|
colors = newcolors;
|
|
Color[][][] newdatacolors = new Color[id+1][][];
|
|
System.arraycopy(datacolors, 0, newdatacolors, 0, datacolors.length);
|
|
datacolors = newdatacolors;
|
|
}
|
|
|
|
Color[] c = new Color[5];
|
|
|
|
/* store colors by raycast sequence number */
|
|
c[0] = new Color(Integer.parseInt(split[1]), Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4]));
|
|
c[3] = new Color(Integer.parseInt(split[5]), Integer.parseInt(split[6]), Integer.parseInt(split[7]), Integer.parseInt(split[8]));
|
|
c[1] = new Color(Integer.parseInt(split[9]), Integer.parseInt(split[10]), Integer.parseInt(split[11]), Integer.parseInt(split[12]));
|
|
c[2] = new Color(Integer.parseInt(split[13]), Integer.parseInt(split[14]), Integer.parseInt(split[15]), Integer.parseInt(split[16]));
|
|
/* Blended color - for 'smooth' option on flat map */
|
|
c[4] = new Color((c[1].getRed()+c[3].getRed())/2, (c[1].getGreen()+c[3].getGreen())/2, (c[1].getBlue()+c[3].getBlue())/2, (c[1].getAlpha()+c[3].getAlpha())/2);
|
|
|
|
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? */
|
|
if(dcolor == null) {
|
|
dcolor = new Color[16][]; /* Make 16 index long list */
|
|
datacolors[id] = dcolor;
|
|
}
|
|
if((dat >= 0) && (dat < 16)) { /* Add color to list */
|
|
dcolor[dat] = c;
|
|
}
|
|
if(dat == 0) { /* Index zero is base color too */
|
|
colors[id] = c;
|
|
}
|
|
}
|
|
else {
|
|
colors[id] = c;
|
|
}
|
|
}
|
|
scanner.close();
|
|
/* Last, push base color into any open slots in data colors list */
|
|
for(int k = 0; k < datacolors.length; k++) {
|
|
Color[][] dc = datacolors[k]; /* see if data colors too */
|
|
if(dc != null) {
|
|
Color[] c = colors[k];
|
|
for(int i = 0; i < 16; i++) {
|
|
if(dc[i] == null)
|
|
dc[i] = c;
|
|
}
|
|
}
|
|
}
|
|
/* And interpolate any missing rain and temperature colors */
|
|
interpolateColorTable(tempcolors);
|
|
interpolateColorTable(raincolors);
|
|
} catch (RuntimeException e) {
|
|
Log.severe("Could not load colors '" + name + "' ('" + colorSchemeFile + "').", e);
|
|
return null;
|
|
} catch (FileNotFoundException e) {
|
|
Log.severe("Could not load colors '" + name + "' ('" + colorSchemeFile + "'): File not found.", e);
|
|
}
|
|
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;
|
|
}
|
|
public void resizeColorArray(int idx) {
|
|
if(idx >= colors.length){
|
|
Color[][] newcolors = new Color[idx+1][];
|
|
System.arraycopy(colors, 0, newcolors, 0, colors.length);
|
|
colors = newcolors;
|
|
Color[][][] newdatacolors = new Color[idx+1][][];
|
|
System.arraycopy(datacolors, 0, newdatacolors, 0, datacolors.length);
|
|
datacolors = newdatacolors;
|
|
}
|
|
}
|
|
public static void reset() {
|
|
cache.clear();
|
|
}
|
|
}
|