dynmap/DynmapCore/src/main/java/org/dynmap/ColorScheme.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();
}
}