package org.dynmap; import org.dynmap.common.BiomeMap; import java.io.File; import java.io.InputStream; import java.util.HashMap; import java.util.Scanner; /** * Copied from dynmap. Modified to support loading colour schemes from the classpath. */ public class ColorScheme { private static final HashMap<String, ColorScheme> cache = new HashMap<>(); 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; } 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) { 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 { stream = ColorScheme.class.getResourceAsStream("/extracted/colorschemes/" + name + ".txt"); 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 + "'.", e); return null; } 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(); } }