Biome coloring

This commit is contained in:
Jesse Boyd 2017-04-29 22:47:34 +10:00
parent fb779a8daa
commit 96f9452608
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
13 changed files with 1151 additions and 399 deletions

View File

@ -626,6 +626,7 @@ public class FaweCache {
*/
public static boolean hasNBT(int id) {
switch (id) {
case 218:
case 54:
case 130:
case 142:

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.util.CachedTextureUtil;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.RandomTextureUtil;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
@ -42,6 +43,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
private final char[] floor;
private final char[] main;
private char[] overlay;
private TextureUtil textureUtil;
private boolean randomVariation = true;
private boolean modifiedMain = false;
@ -63,11 +66,30 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
Arrays.fill(floor, grass);
}
public TextureUtil getTextureUtil() {
if (textureUtil == null) {
textureUtil = Fawe.get().getTextureUtil();
}
if (randomVariation) {
return new RandomTextureUtil(textureUtil);
} else {
return new CachedTextureUtil(textureUtil);
}
}
public void setTextureRandomVariation(boolean randomVariation) {
this.randomVariation = randomVariation;
}
public void setTextureUtil(TextureUtil textureUtil) {
this.textureUtil = textureUtil;
}
public void setHeight(BufferedImage img) {
int index = 0;
for (int z = 0; z < getLength(); z++) {
for (int x = 0; x < getWidth(); x++, index++){
heights[index] = (byte) img.getRGB(x, z);
heights[index] = (byte) (img.getRGB(x, z) >> 8);
}
}
}
@ -238,43 +260,100 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
}
}
public void setColor(BufferedImage img) {
try {
RandomTextureUtil textureUtil = new RandomTextureUtil(Fawe.get().getTextureUtil());
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
int index = 0;
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int color = img.getRGB(x, y);
BaseBlock block = textureUtil.getNearestBlock(color);
if (block == null) {
continue;
public void setBlockAndBiomeColor(BufferedImage img) {
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
TextureUtil textureUtil = getTextureUtil();
int index = 0;
int widthIndex = img.getWidth() - 1;
int heightIndex = img.getHeight() - 1;
int maxIndex = biomes.length - 1;
for (int y = 0; y < img.getHeight(); y++) {
boolean yBiome = y > 0 && y < heightIndex;
for (int x = 0; x < img.getWidth(); x++) {
int color = img.getRGB(x, y);
BaseBlock block = textureUtil.getNearestBlock(color);
TextureUtil.BiomeColor biome = textureUtil.getNearestBiome(color);
int blockColor = textureUtil.getColor(block);
if (textureUtil.colorDistance(biome.grass, color) < textureUtil.colorDistance(blockColor, color)) {
byte biomeByte = (byte) biome.id;
biomes[index] = biomeByte;
if (yBiome && x > 0 && x < widthIndex) {
setBiomeIfZero(index+ 1, biomeByte);
setBiomeIfZero(index- 1, biomeByte);
setBiomeIfZero(index+ getWidth(), biomeByte);
setBiomeIfZero(index+ getWidth() + 1, biomeByte);
setBiomeIfZero(index+ getWidth() - 1, biomeByte);
setBiomeIfZero(index- getWidth(), biomeByte);
setBiomeIfZero(index- getWidth() + 1, biomeByte);
setBiomeIfZero(index- getWidth() - 1, biomeByte);
}
} else {
char combined = (char) block.getCombined();
main[index] = combined;
floor[index++] = combined;
floor[index] = combined;
}
index++;
}
}
}
private void setBiomeIfZero(int index, byte value) {
if (biomes[index] == 0) {
biomes[index] = value;
}
}
public void setBiomeColor(BufferedImage img) {
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
TextureUtil textureUtil = getTextureUtil();
int index = 0;
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int color = img.getRGB(x, y);
TextureUtil.BiomeColor biome = textureUtil.getNearestBiome(color);
if (biome != null) {
biomes[index] = (byte) biome.id;
}
index++;
}
}
}
public void setColor(BufferedImage img) {
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
TextureUtil textureUtil = getTextureUtil();
int index = 0;
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int color = img.getRGB(x, y);
BaseBlock block = textureUtil.getNearestBlock(color);
if (block != null) {
char combined = (char) block.getCombined();
main[index] = combined;
floor[index] = combined;
}
index++;
}
} catch (Throwable e) {
e.printStackTrace();
}
}
public void setColorWithGlass(BufferedImage img) {
CachedTextureUtil textureUtil = new CachedTextureUtil(Fawe.get().getTextureUtil());
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
TextureUtil textureUtil = getTextureUtil();
int index = 0;
for (int y = 0; y < img.getHeight(); y++) {
for (int x = 0; x < img.getWidth(); x++) {
int color = img.getRGB(x, y);
char[] layer = textureUtil.getNearestLayer(color);
if (layer == null) {
continue;
if (layer != null) {
floor[index] = layer[0];
main[index] = layer[1];
}
floor[index] = layer[0];
main[index++] = layer[1];
index++;
}
}
}
@ -565,6 +644,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
globalIndex = z * getWidth() + csx;
for (int x = csx; x <= cex; x++, index++, globalIndex++) {
indexes[index] = globalIndex;
chunk.biomes[index] = biomes[globalIndex];
int height = heights[globalIndex] & 0xFF;
heightMap[index] = height;
maxY = Math.max(maxY, height);

View File

@ -73,7 +73,7 @@ public class LayerBrush implements Brush {
public boolean apply(Vector pos) throws WorldEditException {
int depth = visitor.getDepth();
BaseBlock currentPattern = layers[depth];
return editSession.setBlock(pos, currentPattern);
return editSession.setBlockFast(pos, currentPattern);
}
}, layers.length - 1, editSession);
for (Vector pos : visited) {

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.brush.heightmap;
import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
@ -91,7 +92,7 @@ public class ScalableHeightMap implements com.boydti.fawe.object.brush.heightmap
}
public static ScalableHeightMap fromPNG(InputStream stream) throws IOException {
BufferedImage heightFile = ImageIO.read(stream);
BufferedImage heightFile = MainUtil.toRGB(ImageIO.read(stream));
int width = heightFile.getWidth();
int length = heightFile.getHeight();
Raster data = heightFile.getData();

View File

@ -1,9 +1,12 @@
package com.boydti.fawe.regions.general.plot;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.CleanTextureUtil;
import com.boydti.fawe.util.FilteredTextureUtil;
import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.TaskManager;
import com.intellectualcrafters.plot.PS;
@ -26,6 +29,7 @@ import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
@ -43,6 +47,7 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Set;
import javax.imageio.ImageIO;
@CommandDeclaration(
@ -67,332 +72,433 @@ public class CreateFromImage extends Command {
List<String> argList = StringMan.split(StringMan.join(args, " "), ' ');
checkTrue(argList.size() >= 1, C.COMMAND_SYNTAX, getUsage());
PlotAreaManager manager = PS.get().getPlotAreaManager();
if (manager instanceof SinglePlotAreaManager) {
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
FawePlayer<Object> fp = FawePlayer.wrap(player.getName());
HeightMapMCAGenerator generator = player.getMeta("HMGenerator");
Plot plot = player.getMeta("HMGeneratorPlot");
if (generator == null) {
final Vector2D dimensions;
final BufferedImage image;
if (argList.get(0).toLowerCase().startsWith("http")) {
try {
URL url = new URL(argList.get(0));
if (!url.getHost().equals("i.imgur.com")) {
player.sendMessage("Images can only be loaded from i.imgur.com");
return;
}
player.sendMessage(BBC.getPrefix() + "Loading image... (1)");
image = ImageIO.read(url);
} catch (IOException e) {
player.sendMessage(e.getMessage());
if (manager instanceof SinglePlotAreaManager) TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
FawePlayer<Object> fp = FawePlayer.wrap(player.getName());
HeightMapMCAGenerator generator = player.getMeta("HMGenerator");
Plot plot = player.getMeta("HMGeneratorPlot");
if (generator == null) {
final Vector2D dimensions;
final BufferedImage image;
if (argList.get(0).toLowerCase().startsWith("http")) {
try {
URL url = new URL(argList.get(0));
if (!url.getHost().equals("i.imgur.com")) {
player.sendMessage("Images can only be loaded from i.imgur.com");
return;
}
dimensions = null;
} else {
image = null;
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, getUsage());
return;
}
dimensions = new Vector2D(Integer.parseInt(argList.get(0)), Integer.parseInt(argList.get(1)));
player.sendMessage(BBC.getPrefix() + "Loading image... (1)");
image = com.boydti.fawe.util.MainUtil.toRGB(ImageIO.read(url));
} catch (IOException e) {
player.sendMessage(e.getMessage());
return;
}
fp.runAction(new Runnable() {
@Override
public void run() {
SinglePlotAreaManager sManager = (SinglePlotAreaManager) manager;
SinglePlotArea area = sManager.getArea();
Plot plot = TaskManager.IMP.sync(new com.boydti.fawe.object.RunnableVal<Plot>() {
@Override
public void run(Plot o) {
int currentPlots = Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(area.worldname);
int diff = player.getAllowedPlots() - currentPlots;
if (diff < 1) {
MainUtil.sendMessage(player, C.CANT_CLAIM_MORE_PLOTS_NUM, -diff + "");
return;
}
if (area.getMeta("lastPlot") == null) {
area.setMeta("lastPlot", new PlotId(0, 0));
}
PlotId lastId = (PlotId) area.getMeta("lastPlot");
while (true) {
lastId = Auto.getNextPlotId(lastId, 1);
if (area.canClaim(player, lastId, lastId)) {
break;
}
}
area.setMeta("lastPlot", lastId);
this.value = area.getPlot(lastId);
this.value.setOwner(player.getUUID());
}
});
fp.sendMessage(BBC.getPrefix() + "Initializing components... (2)");
fp.sendMessage(BBC.getPrefix() + "/2 cfi setbiome");
fp.sendMessage(BBC.getPrefix() + "/2 cfi setoverlay");
fp.sendMessage(BBC.getPrefix() + "/2 cfi setmain");
fp.sendMessage(BBC.getPrefix() + "/2 cfi setfloor");
fp.sendMessage(BBC.getPrefix() + "/2 cfi setcolumn");
fp.sendMessage(BBC.getPrefix() + "/2 cfi addcaves");
fp.sendMessage(BBC.getPrefix() + "/2 cfi addore[s]");
fp.sendMessage(BBC.getPrefix() + "/2 cfi addschems");
fp.sendMessage(BBC.getPrefix() + "/2 cfi setheight");
fp.sendMessage(BBC.getPrefix() + "/2 cfi setcolor");
fp.sendMessage(BBC.getPrefix() + "/2 cfi done");
fp.sendMessage(BBC.getPrefix() + "/2 cfi cancel");
File folder = new File(PS.imp().getWorldContainer(), plot.getWorldName() + File.separator + "region");
HeightMapMCAGenerator generator;
if (image != null) {
generator = new HeightMapMCAGenerator(image, folder);
} else {
generator = new HeightMapMCAGenerator(dimensions.getBlockX(), dimensions.getBlockZ(), folder);
}
player.setMeta("HMGenerator", generator);
player.setMeta("HMGeneratorPlot", plot);
}
}, true, false);
return;
dimensions = null;
} else {
image = null;
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, getUsage());
return;
}
dimensions = new Vector2D(Integer.parseInt(argList.get(0)), Integer.parseInt(argList.get(1)));
}
fp.runAction(new Runnable() {
@Override
public void run() {
if (generator == null) {
C.COMMAND_SYNTAX.send(player, getUsage());
return;
}
if (argList.size() == 1) {
if (StringMan.isEqualIgnoreCaseToAny(argList.get(0), "setbiome", "setoverlay", "setmain", "setfloor", "setcolumn", "setcolor", "setglasscolor")) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <image or mask> <value> [white-only]");
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <value>");
return;
} else if (!StringMan.isEqualIgnoreCaseToAny(argList.get(0), "done", "cancel", "addcaves", "addore", "addores", "addschems", "setheight")) {
C.COMMAND_SYNTAX.send(player, "/2 cfi <setbiome|setoverlay|setmain|setfloor|setcolumn|done|cancel|addcaves|addore[s]|addschems|setheight|setcolor|setglasscolor>");
return;
SinglePlotAreaManager sManager = (SinglePlotAreaManager) manager;
SinglePlotArea area = sManager.getArea();
Plot plot = TaskManager.IMP.sync(new RunnableVal<Plot>() {
@Override
public void run(Plot o) {
int currentPlots = Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(area.worldname);
int diff = player.getAllowedPlots() - currentPlots;
if (diff < 1) {
MainUtil.sendMessage(player, C.CANT_CLAIM_MORE_PLOTS_NUM, -diff + "");
return;
}
if (area.getMeta("lastPlot") == null) {
area.setMeta("lastPlot", new PlotId(0, 0));
}
PlotId lastId = (PlotId) area.getMeta("lastPlot");
while (true) {
lastId = Auto.getNextPlotId(lastId, 1);
if (area.canClaim(player, lastId, lastId)) {
break;
}
}
area.setMeta("lastPlot", lastId);
this.value = area.getPlot(lastId);
this.value.setOwner(player.getUUID());
}
});
// setGlassColor|setBiomeColor|setBlockAndBiomeColor|setColorPaletteComplexity|setColorPaletteRandomization|setColorPaletteBlocks|done|cancel|>");
fp.sendMessage(BBC.getPrefix() + "Initializing components... (2)");
fp.sendMessage(BBC.getPrefix() + "/2 cfi biome [url|mask] <biome> [white=false]");
fp.sendMessage(BBC.getPrefix() + "/2 cfi overlay [url|mask] <pattern> [white=false]");
fp.sendMessage(BBC.getPrefix() + "/2 cfi main [url|mask] <pattern> [white=false]");
fp.sendMessage(BBC.getPrefix() + "/2 cfi floor [url|mask] <pattern> [white=false]");
fp.sendMessage(BBC.getPrefix() + "/2 cfi column [url|mask] <pattern> [white=false]");
fp.sendMessage(BBC.getPrefix() + "/2 cfi caves");
fp.sendMessage(BBC.getPrefix() + "/2 cfi ore[s]");
fp.sendMessage(BBC.getPrefix() + "/2 cfi schem <mask> <schem> <rarity> <rotate>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi height <image-url|height>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi color <image-url>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi glass <image-url>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi biomeColor <image-url>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi blockBiomeColor <image-url>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi paletteComplexity <min=0> <max=100>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi paletteRandomization <true|false>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi paletteBlocks <block-list>");
fp.sendMessage(BBC.getPrefix() + "/2 cfi done");
fp.sendMessage(BBC.getPrefix() + "/2 cfi cancel");
File folder = new File(PS.imp().getWorldContainer(), plot.getWorldName() + File.separator + "region");
HeightMapMCAGenerator generator;
if (image != null) {
generator = new HeightMapMCAGenerator(image, folder);
} else {
generator = new HeightMapMCAGenerator(dimensions.getBlockX(), dimensions.getBlockZ(), folder);
}
ParserContext context = new ParserContext();
context.setActor(fp.getPlayer());
context.setWorld(fp.getWorld());
context.setSession(fp.getSession());
context.setExtent(generator);
Request.request().setExtent(generator);
try {
switch (argList.get(0).toLowerCase()) {
case "addschems": {
if (argList.size() != 5) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <mask> <file|folder|url> <rarity> <rotate>");
return;
}
World world = fp.getWorld();
WorldData wd = world.getWorldData();
Mask mask = we.getMaskFactory().parseFromInput(argList.get(1), context);
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(fp.getPlayer(), wd, argList.get(2), true);
if (clipboards == null) {
return;
}
int rarity = Integer.parseInt(argList.get(3));
boolean rotate = Boolean.parseBoolean(argList.get(4));
generator.addSchems(mask, wd, clipboards, rarity, rotate);
player.sendMessage(BBC.getPrefix() + "Added schems, what's next?");
return;
}
case "setcolor": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <url>");
return;
}
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setColor(image);
player.sendMessage("Set color, what's next?");
return;
}
case "setglasscolor": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <url>");
return;
}
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setColorWithGlass(image);
player.sendMessage("Set glass color, what's next?");
return;
}
case "setheight": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <height>");
return;
}
if (argList.get(1).startsWith("http")) {
player.sendMessage("Loading image (3)...");
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setHeight(image);
} else {
generator.setHeights(Integer.parseInt(args[1]));
}
player.sendMessage("Set height, what's next?");
return;
}
case "addores":
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <mask>");
return;
}
generator.addDefaultOres(we.getMaskFactory().parseFromInput(argList.get(1), context));
player.sendMessage(BBC.getPrefix() + "Added ores, what's next?");
return;
case "addore": {
if (argList.size() != 8) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <mask> <pattern> <size> <frequency> <rarity> <min-Y> <max-Y>");
return;
}
// mask pattern size freq rarity miny maxy
Mask mask = we.getMaskFactory().parseFromInput(argList.get(1), context);
Pattern pattern = we.getPatternFactory().parseFromInput(argList.get(2), context);
int size = Integer.parseInt(argList.get(3));
int frequency = Integer.parseInt(argList.get(4));
int rarity = Integer.parseInt(argList.get(5));
int min = Integer.parseInt(argList.get(6));
int max = Integer.parseInt(argList.get(7));
generator.addOre(mask, pattern, size, frequency, rarity, min, max);
player.sendMessage(BBC.getPrefix() + "Added ore, what's next?");
return;
}
case "addcaves": {
generator.addCaves();
player.sendMessage(BBC.getPrefix() + "Added caves, what's next?");
return;
}
case "setbiome": {
int id;
if (argList.size() == 2) {
id = getBiome(argList.get(1), fp).getId();
generator.setBiome(id);
} else {
id = getBiome(argList.get(2), fp).getId();
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setBiome(img, (byte) id, whiteOnly);
} else {
generator.setBiome(we.getMaskFactory().parseFromInput(argList.get(1), context), (byte) id);
}
}
player.sendMessage(BBC.getPrefix() + "Set biome, what's next?");
return;
}
case "setoverlay": {
Pattern id;
if (argList.size() == 2) {
id = we.getPatternFactory().parseFromInput(argList.get(1), context);
generator.setOverlay(id);
} else {
id = we.getPatternFactory().parseFromInput(argList.get(2), context);
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setOverlay(img, id, whiteOnly);
} else {
generator.setOverlay(we.getMaskFactory().parseFromInput(argList.get(1), context), id);
}
}
player.sendMessage(BBC.getPrefix() + "Set overlay, what's next?");
return;
}
case "setmain": {
Pattern id;
if (argList.size() == 2) {
id = we.getPatternFactory().parseFromInput(argList.get(1), context);
generator.setMain(id);
} else {
id = we.getPatternFactory().parseFromInput(argList.get(2), context);
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setMain(img, id, whiteOnly);
} else {
generator.setMain(we.getMaskFactory().parseFromInput(argList.get(1), context), id);
}
}
player.sendMessage(BBC.getPrefix() + "Set main, what's next?");
return;
}
case "setfloor": {
Pattern id;
if (argList.size() == 2) {
id = we.getPatternFactory().parseFromInput(argList.get(1), context);
generator.setFloor(id);
} else {
id = we.getPatternFactory().parseFromInput(argList.get(2), context);
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setFloor(img, id, whiteOnly);
} else {
generator.setFloor(we.getMaskFactory().parseFromInput(argList.get(1), context), id);
}
}
player.sendMessage(BBC.getPrefix() + "Set floor, what's next?");
return;
}
case "setcolumn": {
Pattern id;
if (argList.size() == 2) {
id = we.getPatternFactory().parseFromInput(argList.get(1), context);
generator.setColumn(id);
} else {
id = we.getPatternFactory().parseFromInput(argList.get(2), context);
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setColumn(img, id, whiteOnly);
} else {
generator.setColumn(we.getMaskFactory().parseFromInput(argList.get(1), context), id);
}
}
player.sendMessage(BBC.getPrefix() + "Set columns, what's next?");
return;
}
case "done":
player.deleteMeta("HMGenerator");
player.deleteMeta("HMGeneratorPlot");
player.sendMessage("Generating... (4)");
try {
generator.generate();
} catch (IOException e) {
e.printStackTrace();
player.sendMessage(e.getMessage() + " (see console)");
return;
}
player.sendMessage("Done!");
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
plot.teleportPlayer(player);
}
});
return;
case "cancel":
player.deleteMeta("HMGenerator");
player.deleteMeta("HMGeneratorPlot");
player.sendMessage(BBC.getPrefix() + "Cancelled!");
return;
default:
C.COMMAND_SYNTAX.send(player, getUsage());
}
} catch (IOException e) {
player.sendMessage("Invalid url: " + e.getMessage());
} catch (InputParseException e) {
player.sendMessage("Invalid mask " + e.getMessage());
} catch (Throwable e) {
player.sendMessage("Error " + e.getMessage());
} finally {
Request.reset();
}
player.setMeta("HMGenerator", generator);
player.setMeta("HMGeneratorPlot", plot);
}
}, true, false);
return;
}
});
} else {
fp.runAction(new Runnable() {
@Override
public void run() {
if (generator == null) {
C.COMMAND_SYNTAX.send(player, getUsage());
return;
}
ParserContext context = new ParserContext();
context.setActor(fp.getPlayer());
context.setWorld(fp.getWorld());
context.setSession(fp.getSession());
context.setExtent(generator);
Request.request().setExtent(generator);
try {
switch (argList.get(0).toLowerCase()) {
case "schem":
case "schems":
case "addschems": {
if (argList.size() != 5) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <mask> <file|folder|url> <rarity> <rotate>");
return;
}
World world = fp.getWorld();
WorldData wd = world.getWorldData();
Mask mask = we.getMaskFactory().parseFromInput(argList.get(1), context);
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(fp.getPlayer(), wd, argList.get(2), true);
if (clipboards == null) {
return;
}
int rarity = Integer.parseInt(argList.get(3));
boolean rotate = Boolean.parseBoolean(argList.get(4));
generator.addSchems(mask, wd, clipboards, rarity, rotate);
player.sendMessage(BBC.getPrefix() + "Added schems, what's next?");
return;
}
case "palettecomplexity":
case "colorpalettecomplexity":
case "setcolorpalettecomplexity": {
// roughness
// blocks
if (argList.size() != 3) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <min-percent> <max-percent>");
return;
}
int min = Integer.parseInt(argList.get(1));
int max = Integer.parseInt(argList.get(2));
generator.setTextureUtil(new CleanTextureUtil(Fawe.get().getTextureUtil(), min, max));
player.sendMessage("Set color palette complexity, what's next?");
return;
}
case "paletterandomization":
case "colorpaletterandomization":
case "setcolorpaletterandomization": {
// roughness
// blocks
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <true|false>");
return;
}
generator.setTextureRandomVariation(Boolean.parseBoolean(argList.get(1)));
player.sendMessage("Set color palette randomization, what's next?");
return;
}
case "paletteblocks":
case "colorpaletterblocks":
case "setcolorpaletteblocks": {
// roughness
// blocks
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <pattern>");
return;
}
context.setPreferringWildcard(true);
Set<BaseBlock> blocks = we.getBlockFactory().parseFromListInput(argList.get(1), context);
generator.setTextureUtil(new FilteredTextureUtil(Fawe.get().getTextureUtil(), blocks));
player.sendMessage("Set color palette blocks, what's next?");
return;
}
case "color":
case "setcolor": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <url>");
return;
}
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setColor(image);
player.sendMessage("Set color, what's next?");
return;
}
case "biomecolor":
case "setbiomecolor": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <url>");
return;
}
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setBiomeColor(image);
player.sendMessage("Set color, what's next?");
return;
}
case "blockbiomecolor":
case "setblockandbiomecolor": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <url>");
return;
}
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setBlockAndBiomeColor(image);
player.sendMessage("Set color, what's next?");
return;
}
case "glass":
case "glasscolor":
case "setglasscolor": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <url>");
return;
}
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setColorWithGlass(image);
player.sendMessage("Set glass color, what's next?");
return;
}
case "height":
case "setheight": {
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <image-url|height>");
return;
}
if (argList.get(1).startsWith("http")) {
player.sendMessage("Loading image (3)...");
BufferedImage image = getImgurImage(argList.get(1), fp);
generator.setHeight(image);
} else {
generator.setHeights(Integer.parseInt(args[1]));
}
player.sendMessage("Set height, what's next?");
return;
}
case "ores":
case "addores":
if (argList.size() != 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <mask>");
return;
}
generator.addDefaultOres(we.getMaskFactory().parseFromInput(argList.get(1), context));
player.sendMessage(BBC.getPrefix() + "Added ores, what's next?");
return;
case "ore":
case "addore": {
if (argList.size() != 8) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <mask> <pattern> <size> <frequency> <rarity> <min-Y> <max-Y>");
return;
}
// mask pattern size freq rarity miny maxy
Mask mask = we.getMaskFactory().parseFromInput(argList.get(1), context);
Pattern pattern = we.getPatternFactory().parseFromInput(argList.get(2), context);
int size = Integer.parseInt(argList.get(3));
int frequency = Integer.parseInt(argList.get(4));
int rarity = Integer.parseInt(argList.get(5));
int min = Integer.parseInt(argList.get(6));
int max = Integer.parseInt(argList.get(7));
generator.addOre(mask, pattern, size, frequency, rarity, min, max);
player.sendMessage(BBC.getPrefix() + "Added ore, what's next?");
return;
}
case "cave":
case "caves":
case "addcaves": {
generator.addCaves();
player.sendMessage(BBC.getPrefix() + "Added caves, what's next?");
return;
}
case "biome":
case "setbiome": {
int id;
if (argList.size() < 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " [url|mask] <biome-id> [whiteonly]");
return;
}
if (argList.size() == 2) {
id = getBiome(argList.get(1), fp).getId();
generator.setBiome(id);
} else {
id = getBiome(argList.get(2), fp).getId();
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setBiome(img, (byte) id, whiteOnly);
} else {
generator.setBiome(we.getMaskFactory().parseFromInput(argList.get(1), context), (byte) id);
}
}
player.sendMessage(BBC.getPrefix() + "Set biome, what's next?");
return;
}
case "overlay":
case "setoverlay": {
Pattern id;
if (argList.size() < 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " [url|mask] <pattern> [whiteonly]");
return;
}
if (argList.size() == 2) {
id = we.getPatternFactory().parseFromInput(argList.get(1), context);
generator.setOverlay(id);
} else {
id = we.getPatternFactory().parseFromInput(argList.get(2), context);
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setOverlay(img, id, whiteOnly);
} else {
generator.setOverlay(we.getMaskFactory().parseFromInput(argList.get(1), context), id);
}
}
player.sendMessage(BBC.getPrefix() + "Set overlay, what's next?");
return;
}
case "main":
case "setmain": {
Pattern id;
if (argList.size() < 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " [url|mask] <pattern> [whiteonly]");
return;
}
if (argList.size() == 2) {
id = we.getPatternFactory().parseFromInput(argList.get(1), context);
generator.setMain(id);
} else {
id = we.getPatternFactory().parseFromInput(argList.get(2), context);
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setMain(img, id, whiteOnly);
} else {
generator.setMain(we.getMaskFactory().parseFromInput(argList.get(1), context), id);
}
}
player.sendMessage(BBC.getPrefix() + "Set main, what's next?");
return;
}
case "floor":
case "setfloor": {
Pattern id;
if (argList.size() < 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " [url|mask] <pattern> [whiteonly]");
return;
}
if (argList.size() == 2) {
id = we.getPatternFactory().parseFromInput(argList.get(1), context);
generator.setFloor(id);
} else {
id = we.getPatternFactory().parseFromInput(argList.get(2), context);
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setFloor(img, id, whiteOnly);
} else {
generator.setFloor(we.getMaskFactory().parseFromInput(argList.get(1), context), id);
}
}
player.sendMessage(BBC.getPrefix() + "Set floor, what's next?");
return;
}
case "column":
case "setcolumn": {
Pattern id;
if (argList.size() < 2) {
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " [url|mask] <pattern> [whiteonly]");
return;
}
if (argList.size() == 2) {
id = we.getPatternFactory().parseFromInput(argList.get(1), context);
generator.setColumn(id);
} else {
id = we.getPatternFactory().parseFromInput(argList.get(2), context);
BufferedImage img = getImgurImage(argList.get(1), fp);
if (img != null) {
boolean whiteOnly = argList.size() == 4 && Boolean.parseBoolean(argList.get(3));
generator.setColumn(img, id, whiteOnly);
} else {
generator.setColumn(we.getMaskFactory().parseFromInput(argList.get(1), context), id);
}
}
player.sendMessage(BBC.getPrefix() + "Set columns, what's next?");
return;
}
case "create":
case "done":
player.deleteMeta("HMGenerator");
player.deleteMeta("HMGeneratorPlot");
player.sendMessage("Generating... (4)");
try {
generator.generate();
} catch (IOException e) {
e.printStackTrace();
player.sendMessage(e.getMessage() + " (see console)");
return;
}
player.sendMessage("Done!");
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
plot.teleportPlayer(player);
}
});
return;
case "exit":
case "cancel":
player.deleteMeta("HMGenerator");
player.deleteMeta("HMGeneratorPlot");
player.sendMessage(BBC.getPrefix() + "Cancelled!");
return;
default:
C.COMMAND_SYNTAX.send(player, "/2 cfi <setBiome|setOverlay|setMain|setFloor|setColumn|addCaves|addOre[s]|addSchems|setHeight|setColor|setGlassColor|setBiomeColor|setBlockAndBiomeColor|setColorPaletteComplexity|setColorPaletteRandomization|setColorPaletteBlocks|done|cancel|>");
return;
}
} catch (IOException e) {
player.sendMessage("Invalid url: " + e.getMessage());
} catch (InputParseException e) {
player.sendMessage("Invalid mask " + e.getMessage());
} catch (Throwable e) {
player.sendMessage("Error " + e.getMessage());
} finally {
Request.reset();
}
}
}, true, false);
}
});
else {
player.sendMessage("Must have the `worlds` component enabled in the PlotSquared config.yml");
}
}
@ -411,7 +517,7 @@ public class CreateFromImage extends Command {
throw new IOException("Only i.imgur.com links are allowed!");
}
fp.sendMessage(BBC.getPrefix() + "Downloading image... (3)");
return ImageIO.read(url);
return com.boydti.fawe.util.MainUtil.toRGB(ImageIO.read(url));
}
return null;
}

View File

@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class CachedTextureUtil extends DelegateTextureUtil {
private final TextureUtil parent;
private Int2ObjectOpenHashMap<Integer> colorBlockMap;
private Int2ObjectOpenHashMap<Integer> colorBiomeMap;
private Int2ObjectOpenHashMap<char[]> colorLayerMap;
public CachedTextureUtil(TextureUtil parent) {
@ -14,6 +15,7 @@ public class CachedTextureUtil extends DelegateTextureUtil {
this.parent = parent;
this.colorBlockMap = new Int2ObjectOpenHashMap<>();
this.colorLayerMap = new Int2ObjectOpenHashMap<>();
this.colorBiomeMap = new Int2ObjectOpenHashMap<>();
}
@Override
@ -29,6 +31,19 @@ public class CachedTextureUtil extends DelegateTextureUtil {
return closest;
}
@Override
public BiomeColor getNearestBiome(int color) {
Integer value = colorBiomeMap.get(color);
if (value != null) {
return getBiome(value);
}
BiomeColor result = parent.getNearestBiome(color);
if (result != null) {
colorBiomeMap.put((int) color, (Integer) result.id);
}
return result;
}
@Override
public BaseBlock getNearestBlock(int color) {
Integer value = colorBlockMap.get(color);

View File

@ -0,0 +1,30 @@
package com.boydti.fawe.util;
import java.util.Arrays;
public class CleanTextureUtil extends TextureUtil {
public CleanTextureUtil(TextureUtil parent, int minPercent, int maxPercent) {
super(parent.getFolder());
int minIndex = (parent.distances.length * minPercent) / 100;
int maxIndex = (parent.distances.length * maxPercent) / 100;
long min = parent.distances[minIndex];
long max = parent.distances[maxIndex];
int num = maxIndex - minIndex + 1;
this.blockColors = parent.blockColors;
this.blockDistance = parent.blockDistance;
this.distances = Arrays.copyOfRange(parent.blockDistance, minIndex, maxIndex + 1);
this.validColors = new int[distances.length];
this.validBlockIds = new char[distances.length];
for (int i = 0, j = 0; i < parent.validBlockIds.length; i++) {
char combined = parent.validBlockIds[i];
long distance = parent.blockDistance[combined];
if (distance >= min && distance <= max) {
int color = parent.validColors[i];
this.validColors[j] = color;
this.validBlockIds[j++] = combined;
}
}
this.calculateLayerArrays();
}
}

View File

@ -0,0 +1,32 @@
package com.boydti.fawe.util;
import com.boydti.fawe.FaweCache;
import com.sk89q.worldedit.blocks.BaseBlock;
import java.util.Set;
public class FilteredTextureUtil extends TextureUtil {
public FilteredTextureUtil(TextureUtil parent, Set<BaseBlock> blocks) {
super(parent.getFolder());
this.blockColors = parent.blockColors;
this.blockDistance = parent.blockDistance;
this.distances = parent.distances;
this.validColors = new int[distances.length];
this.validBlockIds = new char[distances.length];
int num = 0;
for (int i = 0; i < parent.validBlockIds.length; i++) {
BaseBlock block = FaweCache.CACHE_BLOCK[parent.validBlockIds[i]];
if (blocks.contains(block) || blocks.contains(new BaseBlock(block.getId(), -1))) num++;
}
this.validBlockIds = new char[num];
this.validColors = new int[num];
num = 0;
for (int i = 0; i < parent.validBlockIds.length; i++) {
BaseBlock block = FaweCache.CACHE_BLOCK[parent.validBlockIds[i]];
if (blocks.contains(block) || blocks.contains(new BaseBlock(block.getId(), -1))) {
validBlockIds[num] = parent.validBlockIds[i];
validColors[num++] = parent.validColors[i];
}
}
this.calculateLayerArrays();
}
}

View File

@ -24,6 +24,8 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.util.Location;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
@ -549,6 +551,15 @@ public class MainUtil {
return destFile;
}
public static BufferedImage toRGB(BufferedImage src) {
if (src == null) return src;
BufferedImage img = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_BGR);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(src, 0, 0, null);
g2d.dispose();
return img;
}
public static File copyFile(File jar, String resource, File output) {
try {
if (output == null) {

View File

@ -85,6 +85,10 @@ public class MathMan {
return check > max ? max : (check < min ? min : check);
}
public static float clamp(float check, float min, float max) {
return check > max ? max : (check < min ? min : check);
}
static {
for(int i = 0; i < 65536; ++i) {
ANGLES[i] = (float)Math.sin((double)i * 3.141592653589793D * 2.0D / 65536.0D);

View File

@ -1,16 +1,22 @@
package com.boydti.fawe.util;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.PseudoRandom;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class RandomTextureUtil extends CachedTextureUtil {
private final int grassColor;
public RandomTextureUtil(TextureUtil parent) {
super(parent);
this.grassColor = parent.getColor(FaweCache.getBlock(BlockID.GRASS, 0));
}
private Int2ObjectOpenHashMap<Integer> offsets = new Int2ObjectOpenHashMap<>();
private Int2ObjectOpenHashMap<Integer> biomeOffsets = new Int2ObjectOpenHashMap<>();
protected int addRandomColor(int c1, int c2) {
int red1 = (c1 >> 16) & 0xFF;
@ -25,13 +31,32 @@ public class RandomTextureUtil extends CachedTextureUtil {
return (red << 16) + (green << 8) + (blue << 0) + (255 << 24);
}
private int random(int i) {
if (i < 0) {
return -PseudoRandom.random.nextInt(-i);
return -PseudoRandom.random.nextInt((-i));
} else {
return PseudoRandom.random.nextInt(i);
}
// return i;
}
@Override
public BiomeColor getNearestBiome(int color) {
int offsetColor = biomeOffsets.getOrDefault(color, 0);
if (offsetColor != 0) {
offsetColor = addRandomColor(color, offsetColor);
} else {
offsetColor = color;
}
BiomeColor res = super.getNearestBiome(offsetColor);
int newColor = res.grass;
{
byte dr = (byte) (((color >> 16) & 0xFF) - ((newColor >> 16) & 0xFF));
byte dg = (byte) (((color >> 8) & 0xFF) - ((newColor >> 8) & 0xFF));
byte db = (byte) (((color >> 0) & 0xFF) - ((newColor >> 0) & 0xFF));
biomeOffsets.put(color, (Integer) ((dr << 16) + (dg << 8) + (db << 0)));
}
return res;
}
@Override

View File

@ -4,10 +4,10 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
@ -18,8 +18,10 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@ -33,13 +35,285 @@ import org.json.simple.parser.ParseException;
public class TextureUtil {
private final File folder;
private static final int[] FACTORS = new int[766];
static {
for (int i = 1; i < FACTORS.length; i++) {
FACTORS[i] = 65535 / i;
}
}
protected int[] blockColors = new int[Character.MAX_VALUE + 1];
protected long[] blockDistance = new long[Character.MAX_VALUE + 1];
protected long[] distances;
protected int[] validColors;
protected char[] validBlockIds;
protected int[] validLayerColors;
protected char[][] validLayerBlocks;
/**
* https://github.com/erich666/Mineways/blob/master/Win/biomes.cpp
*/
private BiomeColor[] validBiomes;
private BiomeColor[] biomes = new BiomeColor[] {
// ID Name Temperature, rainfall, grass, foliage colors
// - note: the colors here are just placeholders, they are computed in the program
new BiomeColor( 0, "Ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F ), // default values of temp and rain
new BiomeColor( 1, "Plains", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 2, "Desert", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 3, "Extreme Hills", 0.2f, 0.3f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 4, "Forest", 0.7f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 5, "Taiga", 0.25f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 6, "Swampland", 0.8f, 0.9f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 7, "River", 0.5f, 0.5f, 0x92BD59, 0x77AB2F ), // default values of temp and rain
new BiomeColor( 8, "Nether", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 9, "End", 0.5f, 0.5f, 0x92BD59, 0x77AB2F ), // default values of temp and rain
new BiomeColor( 10, "Frozen Ocean", 0.0f, 0.5f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 11, "Frozen River", 0.0f, 0.5f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 12, "Ice Plains", 0.0f, 0.5f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 13, "Ice Mountains", 0.0f, 0.5f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 14, "Mushroom Island", 0.9f, 1.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 15, "Mushroom Island Shore", 0.9f, 1.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 16, "Beach", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 17, "Desert Hills", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 18, "Forest Hills", 0.7f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 19, "Taiga Hills", 0.25f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 20, "Extreme Hills Edge", 0.2f, 0.3f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 21, "Jungle", 0.95f, 0.9f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 22, "Jungle Hills", 0.95f, 0.9f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 23, "Jungle Edge", 0.95f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 24, "Deep Ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 25, "Stone Beach", 0.2f, 0.3f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 26, "Cold Beach", 0.05f, 0.3f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 27, "Birch Forest", 0.6f, 0.6f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 28, "Birch Forest Hills", 0.6f, 0.6f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 29, "Roofed Forest", 0.7f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 30, "Cold Taiga", -0.5f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 31, "Cold Taiga Hills", -0.5f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 32, "Mega Taiga", 0.3f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 33, "Mega Taiga Hills", 0.3f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 34, "Extreme Hills+", 0.2f, 0.3f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 35, "Savanna", 1.2f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 36, "Savanna Plateau", 1.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 37, "Mesa", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 38, "Mesa Plateau F", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 39, "Mesa Plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 40, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 41, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 42, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 43, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 44, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 45, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 46, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 47, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 48, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 49, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 50, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 51, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 52, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 53, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 54, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 55, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 56, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 57, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 58, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 59, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 60, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 61, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 62, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 63, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 64, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 65, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 66, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 67, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 68, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 69, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 70, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 71, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 72, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 73, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 74, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 75, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 76, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 77, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 78, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 79, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 80, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 81, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 82, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 83, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 84, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 85, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 86, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 87, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 88, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 89, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 90, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 91, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 92, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 93, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 94, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 95, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 96, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 97, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 98, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor( 99, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(100, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(101, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(102, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(103, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(104, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(105, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(106, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(107, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(108, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(109, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(110, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(111, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(112, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(113, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(114, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(115, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(116, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(117, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(118, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(119, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(120, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(121, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(122, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(123, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(124, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(125, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(126, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(127, "The Void", 0.5f, 0.5f, 0x92BD59, 0x77AB2F ), // default values of temp and rain; also, no height differences
new BiomeColor(128, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(129, "Sunflower Plains", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(130, "Desert M", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor(131, "Extreme Hills M", 0.2f, 0.3f, 0x92BD59, 0x77AB2F ),
new BiomeColor(132, "Flower Forest", 0.7f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor(133, "Taiga M", 0.25f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor(134, "Swampland M", 0.8f, 0.9f, 0x92BD59, 0x77AB2F ),
new BiomeColor(135, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(136, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(137, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(138, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(139, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(140, "Ice Plains Spikes", 0.0f, 0.5f, 0x92BD59, 0x77AB2F ),
new BiomeColor(141, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(142, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(143, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(144, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(145, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(146, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(147, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(148, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(149, "Jungle M", 0.95f, 0.9f, 0x92BD59, 0x77AB2F ),
new BiomeColor(150, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(151, "JungleEdge M", 0.95f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor(152, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(153, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(154, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(155, "Birch Forest M", 0.6f, 0.6f, 0x92BD59, 0x77AB2F ),
new BiomeColor(156, "Birch Forest Hills M", 0.6f, 0.6f, 0x92BD59, 0x77AB2F ),
new BiomeColor(157, "Roofed Forest M", 0.7f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor(158, "Cold Taiga M", -0.5f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(159, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(160, "Mega Spruce Taiga", 0.25f, 0.8f, 0x92BD59, 0x77AB2F ), // special exception, temperature not 0.3
new BiomeColor(161, "Mega Spruce Taiga Hills", 0.25f, 0.8f, 0x92BD59, 0x77AB2F ),
new BiomeColor(162, "Extreme Hills+ M", 0.2f, 0.3f, 0x92BD59, 0x77AB2F ),
new BiomeColor(163, "Savanna M", 1.1f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor(164, "Savanna Plateau M", 1.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor(165, "Mesa (Bryce)", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor(166, "Mesa Plateau F M", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor(167, "Mesa Plateau M", 2.0f, 0.0f, 0x92BD59, 0x77AB2F ),
new BiomeColor(168, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(169, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(170, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(171, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(172, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(173, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(174, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(175, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(176, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(177, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(178, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(179, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(180, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(181, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(182, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(183, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(184, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(185, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(186, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(187, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(188, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(189, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(190, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(191, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(192, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(193, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(194, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(195, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(196, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(197, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(198, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(199, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(200, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(201, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(202, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(203, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(204, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(205, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(206, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(207, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(208, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(209, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(210, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(211, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(212, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(213, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(214, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(215, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(216, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(217, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(218, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(219, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(220, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(221, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(222, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(223, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(224, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(225, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(226, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(227, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(228, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(229, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(230, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(231, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(232, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(233, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(234, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(235, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(236, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(237, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(238, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(239, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(240, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(241, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(242, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(243, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(244, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(245, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(246, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(247, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(248, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(249, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(250, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(251, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(252, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(253, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(254, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
new BiomeColor(255, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F ),
};
public TextureUtil() {
this(MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.TEXTURES));
}
@ -106,55 +380,45 @@ public class TextureUtil {
return blockColors[block.getCombined()];
}
public BiomeColor getBiome(int biome) {
return biomes[biome];
}
public BiomeColor getNearestBiome(int color) {
int grass = blockColors[2 << 4];
if (grass == 0) {
return null;
}
BiomeColor closest = null;
long min = Long.MAX_VALUE;
int red = (color >> 16) & 0xFF;
int green = (color >> 8) & 0xFF;
int blue = (color >> 0) & 0xFF;
for (int i = 0; i < validBiomes.length; i++) {
BiomeColor biome = validBiomes[i];
long distance = colorDistance(red, green, blue, biome.grass);
if (distance < min) {
min = distance;
closest = biome;
}
}
return closest;
}
public File getFolder() {
return folder;
}
/**
* Assumes the top layer is a transparent color and the bottom is opaque
*/
protected int combineTransparency(int top, int bottom) {
int alpha1 = (top >> 24) & 0xFF;
int alpha2 = 255 - alpha1;
int red1 = (top >> 16) & 0xFF;
int green1 = (top >> 8) & 0xFF;
int blue1 = (top >> 0) & 0xFF;
int red2 = (bottom >> 16) & 0xFF;
int green2 = (bottom >> 8) & 0xFF;
int blue2 = (bottom >> 0) & 0xFF;
int red = ((red1 * alpha1) + (red2 * alpha2)) / 255;
int green = ((green1 * alpha1) + (green2 * alpha2)) / 255;
int blue = ((blue1 * alpha1) + (blue2 * alpha2)) / 255;
return (red << 16) + (green << 8) + (blue << 0) + (255 << 24);
}
private void calculateLayerArrays() {
Int2ObjectOpenHashMap<char[]> colorLayerMap = new Int2ObjectOpenHashMap<>();
for (int i = 0; i < validBlockIds.length; i++) {
int color = validColors[i];
int combined = validBlockIds[i];
if (hasAlpha(color)) {
for (int j = 0; j < validBlockIds.length; j++) {
int colorOther = validColors[j];
if (!hasAlpha(colorOther)) {
int combinedOther = validBlockIds[j];
int combinedColor = combineTransparency(color, colorOther);
colorLayerMap.put(combinedColor, new char[] {(char) combined, (char) combinedOther});
}
}
}
}
this.validLayerColors = new int[colorLayerMap.size()];
this.validLayerBlocks = new char[colorLayerMap.size()][];
int index = 0;
for (Int2ObjectMap.Entry<char[]> entry : colorLayerMap.int2ObjectEntrySet()) {
validLayerColors[index] = entry.getIntKey();
validLayerBlocks[index++] = entry.getValue();
}
public long colorDistance(int c1, int c2) {
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
return colorDistance(red1, green1, blue1, c2);
}
public void loadModTextures() throws IOException, ParseException {
Int2ObjectOpenHashMap<Integer> colorMap = new Int2ObjectOpenHashMap<>();
Int2ObjectOpenHashMap<Long> distanceMap = new Int2ObjectOpenHashMap<>();
if (folder.exists()) {
// Get all the jar files
for (File file : folder.listFiles(new FilenameFilter() {
@ -237,6 +501,9 @@ public class TextureUtil {
if (id.startsWith(modId)) {
BaseBlock block = bundled.findByState(id);
BundledBlockData.BlockEntry state = bundled.findById(block.getId());
if (FaweCache.hasNBT(block.getId())) {
continue;
}
// Ignore non blocks
if (!state.material.isFullCube() && !state.material.isRenderedAsNormalBlock()) {
switch (block.getId()) {
@ -248,6 +515,7 @@ public class TextureUtil {
}
} else if (!state.material.isFullCube() || !state.material.isRenderedAsNormalBlock()) {
switch (block.getId()) {
case 165:
case 52:
continue;
}
@ -262,8 +530,14 @@ public class TextureUtil {
}
if (texture != null) {
int combined = block.getCombined();
if (id.startsWith("log_") || id.startsWith("log2_")) {
combined += 12;
switch (block.getId()) {
case 17:
case 162:
combined += 12;
break;
case 43:
combined += 8;
break;
}
idMap.put(combined, texture);
}
@ -277,11 +551,58 @@ public class TextureUtil {
try (InputStream is = zipFile.getInputStream(textureEntry)) {
BufferedImage image = ImageIO.read(is);
int color = getColor(image);
long distance = getDistance(image, color);
distanceMap.put((int) combined, (Long) distance);
colorMap.put((int) combined, (Integer) color);
}
}
}
}
{
Integer grass = colorMap.remove(FaweCache.getCombined(BlockID.GRASS, 0));
if (grass != null) {
blockColors[FaweCache.getCombined(BlockID.GRASS, 0)] = grass;
// assets\minecraft\textures\colormap
ZipEntry grassEntry = zipFile.getEntry("assets/minecraft/textures/colormap/grass.png");
if (grassEntry != null) {
try (InputStream is = zipFile.getInputStream(grassEntry)) {
BufferedImage image = ImageIO.read(is);
for (int i = 0; i < biomes.length; i++) {
BiomeColor biome = biomes[i];
float adjTemp = MathMan.clamp(biome.temperature, 0.0f, 1.0f);
float adjRainfall = MathMan.clamp(biome.rainfall, 0.0f, 1.0f) * adjTemp;
int x = (int) (255 - adjTemp * 255);
int z = (int) (255 - adjRainfall * 255);
int color = image.getRGB(x, z);
biome.grass = color;
}
}
// swampland: perlin - avoid
biomes[6].grass = 0;
biomes[134].grass = 0;
// roofed forest: averaged w/ 0x28340A
biomes[29].grass = multiply(biomes[29].grass, 0x28340A + (255 << 24));
biomes[157].grass = multiply(biomes[157].grass, 0x28340A + (255 << 24));
// mesa : 0x90814D
biomes[37].grass = 0x90814D + (255 << 24);
biomes[38].grass = 0x90814D + (255 << 24);
biomes[39].grass = 0x90814D + (255 << 24);
biomes[165].grass = 0x90814D + (255 << 24);
biomes[166].grass = 0x90814D + (255 << 24);
biomes[167].grass = 0x90814D + (255 << 24);
List<BiomeColor> valid = new ArrayList<>();
for (int i = 0; i < biomes.length; i++) {
BiomeColor biome = biomes[i];
biome.grass = multiply(biome.grass, grass);
if (biome.grass != 0 && !biome.name.equalsIgnoreCase("Unknown Biome")) {
valid.add(biome);
}
}
this.validBiomes = valid.toArray(new BiomeColor[valid.size()]);
}
}
}
// Close the file
zipFile.close();
}
@ -298,9 +619,77 @@ public class TextureUtil {
validColors[index] = color;
index++;
}
ArrayList<Long> distances = new ArrayList<>(distanceMap.values());
Collections.sort(distances);
this.distances = new long[distances.size()];
for (int i = 0; i < this.distances.length; i++) {
this.distances[i] = distances.get(i);
}
for (Int2ObjectMap.Entry<Long> entry : distanceMap.int2ObjectEntrySet()) {
blockDistance[entry.getIntKey()] = entry.getValue();
}
calculateLayerArrays();
}
protected int multiply(int c1, int c2) {
int alpha1 = (c1 >> 24) & 0xFF;
int alpha2 = (c2 >> 24) & 0xFF;
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
int blue2 = (c2 >> 0) & 0xFF;
int red = ((red1 * red2)) / 255;
int green = ((green1 * green2)) / 256;
int blue = ((blue1 * blue2)) / 256;
int alpha = ((alpha1 * alpha2)) / 256;
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
}
/**
* Assumes the top layer is a transparent color and the bottom is opaque
*/
protected int combineTransparency(int top, int bottom) {
int alpha1 = (top >> 24) & 0xFF;
int alpha2 = 255 - alpha1;
int red1 = (top >> 16) & 0xFF;
int green1 = (top >> 8) & 0xFF;
int blue1 = (top >> 0) & 0xFF;
int red2 = (bottom >> 16) & 0xFF;
int green2 = (bottom >> 8) & 0xFF;
int blue2 = (bottom >> 0) & 0xFF;
int red = ((red1 * alpha1) + (red2 * alpha2)) / 255;
int green = ((green1 * alpha1) + (green2 * alpha2)) / 255;
int blue = ((blue1 * alpha1) + (blue2 * alpha2)) / 255;
return (red << 16) + (green << 8) + (blue << 0) + (255 << 24);
}
protected void calculateLayerArrays() {
Int2ObjectOpenHashMap<char[]> colorLayerMap = new Int2ObjectOpenHashMap<>();
for (int i = 0; i < validBlockIds.length; i++) {
int color = validColors[i];
int combined = validBlockIds[i];
if (hasAlpha(color)) {
for (int j = 0; j < validBlockIds.length; j++) {
int colorOther = validColors[j];
if (!hasAlpha(colorOther)) {
int combinedOther = validBlockIds[j];
int combinedColor = combineTransparency(color, colorOther);
colorLayerMap.put(combinedColor, new char[] {(char) combined, (char) combinedOther});
}
}
}
}
this.validLayerColors = new int[colorLayerMap.size()];
this.validLayerBlocks = new char[colorLayerMap.size()][];
int index = 0;
for (Int2ObjectMap.Entry<char[]> entry : colorLayerMap.int2ObjectEntrySet()) {
validLayerColors[index] = entry.getIntKey();
validLayerBlocks[index++] = entry.getValue();
}
}
protected BaseBlock getNearestBlock(BaseBlock block, boolean darker) {
int color = getColor(block);
if (color == 0) {
@ -370,6 +759,9 @@ public class TextureUtil {
}
Set<String> names = new HashSet<>();
String all = (String) textures.get("all");
if (all == null) {
all = (String) textures.get("top");
}
if (all != null) {
String textureName = getFileName(all);
// Add the model
@ -380,6 +772,9 @@ public class TextureUtil {
name = name.replaceAll("big_oak", "oak");
names.add(name);
}
if (!textures.containsKey("all")) {
names.add(name.replaceAll("_top", ""));
}
String[] split = name.split("_");
switch (split[0]) {
case "glass":
@ -390,8 +785,13 @@ public class TextureUtil {
break;
case "leaves":
names.add(name.replaceAll("leaves_", "leaves2_"));
break;
case "mushroom":
names.add(name.replaceAll("mushroom_block_skin_", "mushroom_block_"));
break;
case "half":
names.add(name.replaceAll("half_", "double_stone_"));
break;
default:
continue;
}
@ -414,13 +814,6 @@ public class TextureUtil {
return alpha != 255;
}
protected long colorDistance(int c1, int c2) {
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
return colorDistance(red1, green1, blue1, c2);
}
protected long colorDistance(int red1, int green1, int blue1, int c2) {
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
@ -429,7 +822,22 @@ public class TextureUtil {
int r = red1 - red2;
int g = green1 - green2;
int b = blue1 - blue2;
return (((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8);
int hd = hueDistance(red1, green1, blue1, red2, green2, blue2);
return (((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8) + (hd);
}
protected static int hueDistance(int red1, int green1, int blue1, int red2, int green2, int blue2) {
int total1 = (red1 + green1 + blue1);
int total2 = (red2 + green2 + blue2);
if (total1 == 0 || total2 == 0) {
return 0;
}
int factor1 = FACTORS[total1];
int factor2 = FACTORS[total2];
long r = (512 * (red1 * factor1 - red2 * factor2)) >> 10;
long g = (green1 * factor1 - green2 * factor2);
long b = (767 * (blue1 * factor1 - blue2 * factor2)) >> 10;
return (int) ((r * r + g * g + b * b) >> 25);
}
protected int getColor(BufferedImage image) {
@ -449,7 +857,46 @@ public class TextureUtil {
}
}
int a = width * height;
Color color = new Color((int) (totalRed / a), (int) (totalGreen / a), (int) (totalBlue / a), (int) (totalAlpha / a));
return color.getRGB();
int red = (int) (totalRed / a);
int green = (int) (totalGreen / a);
int blue = (int) (totalBlue / a);
int alpha = (int) (totalAlpha / a);
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
}
public long getDistance(BufferedImage image, int c1) {
long totalDistSqr = 0;
int width = image.getWidth();
int height = image.getHeight();
int area = width * height;
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int c2 = image.getRGB(x, y);
long distance = colorDistance(red1, green1, blue1, c2);
totalDistSqr += distance * distance;
}
}
return totalDistSqr / area;
}
public static class BiomeColor {
public int id;
public String name;
public float temperature;
public float rainfall;
public int grass;
public int foliage;
public BiomeColor(int id, String name, float temperature, float rainfall, int grass, int foliage) {
this.id = id;
this.name = name;
this.temperature = temperature;
this.rainfall = rainfall;
this.grass = grass;
this.foliage = foliage;
}
}
}

View File

@ -160,8 +160,8 @@ public class BundledBlockData {
idMap.putIfAbsent(id, entry);
localIdMap.putIfAbsent(id, entry);
legacyMap[entry.legacyId] = entry;
stateMap.putIfAbsent(id, FaweCache.getBlock(entry.legacyId, 0));
stateMap.putIfAbsent(entry.id, FaweCache.getBlock(entry.legacyId, 0));
stateMap.put(entry.id, FaweCache.getBlock(entry.legacyId, 0));
stateMap.put(id, FaweCache.getBlock(entry.legacyId, 0));
if (entry.states == null) {
return true;
}
@ -171,8 +171,8 @@ public class BundledBlockData {
if (key.equals("true")) {
key = stateEntry.getKey();
}
stateMap.putIfAbsent(id + ":" + key, FaweCache.getBlock(entry.legacyId, valueEntry.getValue().data));
stateMap.putIfAbsent(entry.id + ":" + key, FaweCache.getBlock(entry.legacyId, valueEntry.getValue().data));
stateMap.put(entry.id + ":" + key, FaweCache.getBlock(entry.legacyId, valueEntry.getValue().data));
stateMap.put(id + ":" + key, FaweCache.getBlock(entry.legacyId, valueEntry.getValue().data));
stateMap.putIfAbsent(modId + ":" + key, FaweCache.getBlock(entry.legacyId, valueEntry.getValue().data));
stateMap.putIfAbsent(key, FaweCache.getBlock(entry.legacyId, valueEntry.getValue().data));
}