mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 02:03:59 +00:00
Map Command Overhaul in 1.17
- Features biomes using random color (based on vanilla derivative) if a color isn't provided in the biome class - Allows a map to be opened for packs that don't have a world open (`/iris std map overworld`)
This commit is contained in:
parent
147d5902ed
commit
1f2871f649
@ -5,7 +5,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group 'com.volmit.iris'
|
group 'com.volmit.iris'
|
||||||
version '1.5-TOTALLY-UNSTABLE'
|
version '1.5-UNSTABLE-MAP'
|
||||||
def apiVersion = '1.17'
|
def apiVersion = '1.17'
|
||||||
def name = 'Iris'
|
def name = 'Iris'
|
||||||
def main = 'com.volmit.iris.Iris'
|
def main = 'com.volmit.iris.Iris'
|
||||||
|
@ -78,6 +78,10 @@ public class IrisComplex implements DataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IrisComplex(Engine engine) {
|
public IrisComplex(Engine engine) {
|
||||||
|
this(engine, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisComplex(Engine engine, boolean simple) {
|
||||||
int cacheSize = IrisSettings.get().getCache().getStreamingCacheSize();
|
int cacheSize = IrisSettings.get().getCache().getStreamingCacheSize();
|
||||||
this.rng = new RNG(engine.getWorld().getSeed());
|
this.rng = new RNG(engine.getWorld().getSeed());
|
||||||
this.data = engine.getData();
|
this.data = engine.getData();
|
||||||
|
@ -2,15 +2,24 @@ package com.volmit.iris.manager.command.studio;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.IrisSettings;
|
import com.volmit.iris.IrisSettings;
|
||||||
import com.volmit.iris.manager.gui.IrisVision;
|
import com.volmit.iris.generator.IrisComplex;
|
||||||
import com.volmit.iris.scaffold.IrisWorlds;
|
import com.volmit.iris.manager.IrisDataManager;
|
||||||
|
import com.volmit.iris.map.MapVision;
|
||||||
|
import com.volmit.iris.object.IrisDimension;
|
||||||
import com.volmit.iris.scaffold.engine.IrisAccess;
|
import com.volmit.iris.scaffold.engine.IrisAccess;
|
||||||
|
import com.volmit.iris.util.FakeEngine;
|
||||||
|
import com.volmit.iris.util.FakeWorld;
|
||||||
import com.volmit.iris.util.KList;
|
import com.volmit.iris.util.KList;
|
||||||
import com.volmit.iris.util.MortarCommand;
|
import com.volmit.iris.util.MortarCommand;
|
||||||
import com.volmit.iris.util.MortarSender;
|
import com.volmit.iris.util.MortarSender;
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
public class CommandIrisStudioMap extends MortarCommand {
|
import java.io.File;
|
||||||
public CommandIrisStudioMap() {
|
|
||||||
|
public class CommandIrisStudioMap extends MortarCommand
|
||||||
|
{
|
||||||
|
public CommandIrisStudioMap()
|
||||||
|
{
|
||||||
super("map", "render");
|
super("map", "render");
|
||||||
setDescription("Render a map (gui outside of mc)");
|
setDescription("Render a map (gui outside of mc)");
|
||||||
requiresPermission(Iris.perm.studio);
|
requiresPermission(Iris.perm.studio);
|
||||||
@ -23,33 +32,79 @@ public class CommandIrisStudioMap extends MortarCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(MortarSender sender, String[] args) {
|
public boolean handle(MortarSender sender, String[] args)
|
||||||
if (!IrisSettings.get().isStudio()) {
|
{
|
||||||
|
if(!IrisSettings.get().isStudio())
|
||||||
|
{
|
||||||
sender.sendMessage("To use Iris Studio, please enable studio in Iris/settings.json");
|
sender.sendMessage("To use Iris Studio, please enable studio in Iris/settings.json");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrisSettings.get().isUseServerLaunchedGuis()) {
|
if(!IrisSettings.get().isUseServerLaunchedGuis())
|
||||||
|
{
|
||||||
sender.sendMessage("To use Iris Guis, please enable serverLaunchedGuis in Iris/settings.json");
|
sender.sendMessage("To use Iris Guis, please enable serverLaunchedGuis in Iris/settings.json");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IrisComplex complex;
|
||||||
|
|
||||||
try {
|
if (args.length > 0) {
|
||||||
|
String type = "";
|
||||||
|
long seed = 1337;
|
||||||
|
for(String i : args)
|
||||||
|
{
|
||||||
|
if (i.contains("=")) {
|
||||||
|
type = i.startsWith("type=") ? i.split("\\Q=\\E")[1] : type;
|
||||||
|
seed = i.startsWith("seed=") ? Long.valueOf(i.split("\\Q=\\E")[1]) : seed;
|
||||||
|
} else {
|
||||||
|
if (type.equals("")) {
|
||||||
|
type = i;
|
||||||
|
} else if (seed == 1337) {
|
||||||
|
seed = Long.valueOf(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.equals("")) {
|
||||||
|
sender.sendMessage("Open this in a studio world or do /iris studio map [pack]");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisDimension dim = IrisDataManager.loadAnyDimension(type);
|
||||||
|
|
||||||
|
if (dim == null) {
|
||||||
|
sender.sendMessage("Can't find dimension: " + type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dim.getEnvironment() == null) {
|
||||||
|
dim.setEnvironment(World.Environment.NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Setup the fake world and engine objects so we can get an IrisComplex for the terrain they will
|
||||||
|
//generate without actually generating any of it
|
||||||
|
sender.sendMessage("Preparing map...");
|
||||||
|
FakeWorld world = new FakeWorld(dim.getName(), 0, 256, seed, new File(dim.getName()), dim.getEnvironment());
|
||||||
|
FakeEngine engine = new FakeEngine(dim, world);
|
||||||
|
complex = new IrisComplex(engine, true);
|
||||||
|
sender.sendMessage("Opening Map!");
|
||||||
|
} else if (Iris.proj.isProjectOpen()) {
|
||||||
IrisAccess g = Iris.proj.getActiveProject().getActiveProvider();
|
IrisAccess g = Iris.proj.getActiveProject().getActiveProvider();
|
||||||
IrisVision.launch(g, 0);
|
complex = g.getCompound().getDefaultEngine().getFramework().getComplex();
|
||||||
sender.sendMessage("Opening Map!");
|
sender.sendMessage("Opening map for existing studio world!");
|
||||||
} catch (Throwable e) {
|
} else {
|
||||||
IrisAccess g = IrisWorlds.access(sender.player().getWorld());
|
sender.sendMessage("Open this in a studio world or do /iris studio map [pack]");
|
||||||
IrisVision.launch(g, 0);
|
return true;
|
||||||
sender.sendMessage("Opening Map!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapVision map = new MapVision(complex);
|
||||||
|
map.open();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getArgsUsage() {
|
protected String getArgsUsage()
|
||||||
return "";
|
{
|
||||||
|
return "[pack] [seed=1337]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
67
src/main/java/com/volmit/iris/map/BiomeMap.java
Normal file
67
src/main/java/com/volmit/iris/map/BiomeMap.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package com.volmit.iris.map;
|
||||||
|
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.google.common.collect.HashBiMap;
|
||||||
|
import com.volmit.iris.object.IrisBiome;
|
||||||
|
import com.volmit.iris.object.IrisDimension;
|
||||||
|
import com.volmit.iris.object.IrisRegion;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class BiomeMap {
|
||||||
|
|
||||||
|
private BiMap<IrisBiome, Integer> biomeMap;
|
||||||
|
private BiMap<IrisRegion, Integer> regionMap;
|
||||||
|
private IrisDimension dimension;
|
||||||
|
|
||||||
|
private Set<Integer> activeBiomes = new HashSet<>();
|
||||||
|
private Set<Integer> activeRegions = new HashSet<>();
|
||||||
|
|
||||||
|
public BiomeMap(IrisDimension dimension) {
|
||||||
|
this.dimension = dimension;
|
||||||
|
|
||||||
|
List<IrisBiome> biomes = dimension.getAllAnyBiomes();
|
||||||
|
List<IrisRegion> regions = dimension.getAllAnyRegions();
|
||||||
|
|
||||||
|
biomeMap = HashBiMap.create(biomes.size());
|
||||||
|
regionMap = HashBiMap.create(regions.size());
|
||||||
|
|
||||||
|
int nextID = 0;
|
||||||
|
|
||||||
|
for (IrisBiome biome : biomes) {
|
||||||
|
biomeMap.putIfAbsent(biome, nextID);
|
||||||
|
activeBiomes.add(nextID);
|
||||||
|
nextID++;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextID = 0;
|
||||||
|
|
||||||
|
for (IrisRegion region : regions) {
|
||||||
|
regionMap.putIfAbsent(region, nextID);
|
||||||
|
activeRegions.add(nextID);
|
||||||
|
nextID++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisDimension getDimension() {
|
||||||
|
return dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisBiome getBiome(int id) {
|
||||||
|
return biomeMap.inverse().get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBiomeId(IrisBiome biome) {
|
||||||
|
return biomeMap.get(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisRegion getRegion(int id) {
|
||||||
|
return regionMap.inverse().get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRegionId(IrisRegion region) {
|
||||||
|
return regionMap.get(region);
|
||||||
|
}
|
||||||
|
}
|
586
src/main/java/com/volmit/iris/map/MapVision.java
Normal file
586
src/main/java/com/volmit/iris/map/MapVision.java
Normal file
@ -0,0 +1,586 @@
|
|||||||
|
package com.volmit.iris.map;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.generator.IrisComplex;
|
||||||
|
import com.volmit.iris.util.J;
|
||||||
|
import com.volmit.iris.util.KMap;
|
||||||
|
import com.volmit.iris.util.KSet;
|
||||||
|
import com.volmit.iris.util.PrecisionStopwatch;
|
||||||
|
import com.volmit.iris.util.RandomColor;
|
||||||
|
import com.volmit.iris.util.RollingSequence;
|
||||||
|
import io.netty.util.internal.ConcurrentSet;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.awt.event.ComponentListener;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.KeyListener;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseMotionListener;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class MapVision extends JPanel {
|
||||||
|
|
||||||
|
private int threadId = 0;
|
||||||
|
|
||||||
|
private static final int TILE_SIZE = 128; //Tile size in pixels
|
||||||
|
private static final int TILE_REALITY = 512; //How many blocks a tile is
|
||||||
|
private static final int TILE_SIZE_R = 7; //The number of bits to shift to get the pixel side
|
||||||
|
private static final int TILE_REALITY_R = 9; //The number of bits to shift to get the real size
|
||||||
|
|
||||||
|
private static final int DEF_WIDTH = 1440;
|
||||||
|
private static final int DEF_HEIGHT = 820;
|
||||||
|
|
||||||
|
|
||||||
|
private IrisComplex complex;
|
||||||
|
private RenderType currentType = RenderType.BIOME_LAND;
|
||||||
|
|
||||||
|
private int mouseX; //The current mouse coords
|
||||||
|
private int mouseY;
|
||||||
|
private double draggedOffsetX; //The amount the mouse has dragged the map
|
||||||
|
private double draggedOffsetY;
|
||||||
|
private int centerTileX; //The center tile in the screen
|
||||||
|
private int centerTileY;
|
||||||
|
private int offsetX; //Offset to draw tiles to
|
||||||
|
private int offsetY;
|
||||||
|
private int lastTileWidth;
|
||||||
|
|
||||||
|
private boolean dirty = true; //Whether to repaint textures
|
||||||
|
private double scale = 1;
|
||||||
|
private boolean realname = false;
|
||||||
|
|
||||||
|
private KMap<Integer, Tile> tiles = new KMap<>();
|
||||||
|
|
||||||
|
private Set<Tile> visibleTiles = new ConcurrentSet<>(); //Tiles that are visible on screen
|
||||||
|
private Set<Tile> halfDirtyTiles = new ConcurrentSet<>(); //Tiles that should be drawn next draw
|
||||||
|
|
||||||
|
private short[][] spiral; //See #generateSpiral
|
||||||
|
|
||||||
|
private final Color overlay = new Color(80, 80, 80);
|
||||||
|
private final Font overlayFont = new Font("Arial", Font.BOLD, 16);
|
||||||
|
|
||||||
|
private RollingSequence roll = new RollingSequence(50);
|
||||||
|
|
||||||
|
private boolean debug = false;
|
||||||
|
private int[] debugBorder = new int[] {-5, -3, 6, 4};
|
||||||
|
|
||||||
|
private boolean recalculating;
|
||||||
|
|
||||||
|
// IrisComplex is the main class I need for a biome map. You can make one from an Engine object,
|
||||||
|
// which does need a FakeWorld object in it for the seed
|
||||||
|
public MapVision(IrisComplex worldComplex)
|
||||||
|
{
|
||||||
|
this.complex = worldComplex;
|
||||||
|
this.setBackground(Color.BLACK);
|
||||||
|
this.setVisible(true);
|
||||||
|
roll.put(1);
|
||||||
|
generateSpiral(64);
|
||||||
|
|
||||||
|
addMouseWheelListener((mouseWheelEvent) -> {
|
||||||
|
double oldScale = this.scale;
|
||||||
|
this.scale = Math.min(4, Math.max(scale + scale * mouseWheelEvent.getWheelRotation() * 0.2, 1));
|
||||||
|
double wx = getWidth();
|
||||||
|
double hy = getHeight();
|
||||||
|
double xScale = (mouseX - wx) / wx * 0.5;
|
||||||
|
double yScale = (mouseY - hy) / hy * 0.5;
|
||||||
|
|
||||||
|
if (mouseWheelEvent.getWheelRotation() > 0) { //Only on zoom in, adjust the position to zoom into
|
||||||
|
this.draggedOffsetX += xScale * (wx / 2) * (oldScale - scale);
|
||||||
|
this.draggedOffsetY += yScale * (hy / 2) * (oldScale - scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
dirty = true;
|
||||||
|
repaint();
|
||||||
|
softRecalculate();
|
||||||
|
});
|
||||||
|
addMouseMotionListener(new MouseMotionListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(MouseEvent e)
|
||||||
|
{
|
||||||
|
Point cp = e.getPoint();
|
||||||
|
mouseX = cp.x;
|
||||||
|
mouseY = cp.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDragged(MouseEvent e)
|
||||||
|
{
|
||||||
|
Point cp = e.getPoint();
|
||||||
|
draggedOffsetX -= (mouseX - cp.x) / scale;
|
||||||
|
draggedOffsetY -= (mouseY - cp.y) / scale;
|
||||||
|
mouseX = cp.x;
|
||||||
|
mouseY = cp.y;
|
||||||
|
softRecalculate();
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
recalculate(); //Setup
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open this GUI
|
||||||
|
*/
|
||||||
|
public void open() {
|
||||||
|
JFrame frame = new JFrame("Iris Map (" + complex.getData().getDataFolder().getName() + ")");
|
||||||
|
frame.add(this);
|
||||||
|
frame.setSize(DEF_WIDTH, DEF_HEIGHT);
|
||||||
|
frame.setBackground(Color.BLACK);
|
||||||
|
frame.addComponentListener(new ComponentListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentResized(ComponentEvent e) {
|
||||||
|
dirty = true;
|
||||||
|
softRecalculate();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentMoved(ComponentEvent e) {
|
||||||
|
dirty = true;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentShown(ComponentEvent e) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentHidden(ComponentEvent e) { }
|
||||||
|
});
|
||||||
|
frame.addKeyListener(new KeyListener() {
|
||||||
|
@Override
|
||||||
|
public void keyTyped(KeyEvent e) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
|
||||||
|
realname = true;
|
||||||
|
else if (e.getKeyCode() == KeyEvent.VK_ALT) debug = !debug;
|
||||||
|
else if (e.getKeyCode() == KeyEvent.VK_R) {
|
||||||
|
dirty = true;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyReleased(KeyEvent e) {
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
|
||||||
|
realname = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
|
||||||
|
|
||||||
|
if(file != null) {
|
||||||
|
try {
|
||||||
|
frame.setIconImage(ImageIO.read(file));
|
||||||
|
} catch(IOException ignored) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.setVisible(true);
|
||||||
|
frame.requestFocus();
|
||||||
|
frame.toFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics gx) {
|
||||||
|
//super.paint(gx);
|
||||||
|
PrecisionStopwatch stopwatch = PrecisionStopwatch.start();
|
||||||
|
|
||||||
|
int windowOffsetX = getWidth() / 2;
|
||||||
|
int windowOffsetY = getHeight() / 2;
|
||||||
|
|
||||||
|
offsetX = (int) Math.round(draggedOffsetX * scale) + windowOffsetX;
|
||||||
|
offsetY = (int) Math.round(draggedOffsetY * scale) + windowOffsetY;
|
||||||
|
|
||||||
|
//If we should do a full repaint of the entire frame. Only done when the zoom level changes, etc
|
||||||
|
if (dirty) {
|
||||||
|
super.paint(gx); //Clear the frame first
|
||||||
|
for (Iterator<Tile> iterator = visibleTiles.iterator(); iterator.hasNext();) {
|
||||||
|
Tile tile = iterator.next();
|
||||||
|
drawTile(gx, tile);
|
||||||
|
}
|
||||||
|
dirty = false;
|
||||||
|
} else {
|
||||||
|
//Loop through all the tiles that haven't been drawn last draw and draw them
|
||||||
|
//This saves us having to do a FULL redraw when only 1 new tile has been added
|
||||||
|
for (Iterator<Tile> iterator = halfDirtyTiles.iterator(); iterator.hasNext();) {
|
||||||
|
Tile tile = iterator.next();
|
||||||
|
drawTile(gx, tile);
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gx.setColor(overlay);
|
||||||
|
gx.fillRect(getWidth() - 400, 4, 396, 27);
|
||||||
|
gx.setColor(Color.WHITE);
|
||||||
|
//int x = (int) (((int) ((mouseX - windowOffsetX)) << 2) + (draggedOffsetX * scale));
|
||||||
|
//int y = (int) (((int) ((mouseY - windowOffsetY)) << 2) + (draggedOffsetY * scale));
|
||||||
|
int x = (int) (((int) ((mouseX - windowOffsetX))) + (-draggedOffsetX * scale)) << 2;
|
||||||
|
int y = (int) (((int) ((mouseY - windowOffsetY))) + (-draggedOffsetY * scale)) << 2;
|
||||||
|
String text = " [" + x+ ", " + y + "]";
|
||||||
|
if (realname)
|
||||||
|
text = complex.getLandBiomeStream().get(x, y).getLoadKey().toUpperCase() + text;
|
||||||
|
else
|
||||||
|
text = complex.getLandBiomeStream().get(x, y).getName().toUpperCase() + text;
|
||||||
|
gx.setFont(overlayFont);
|
||||||
|
gx.drawString(text, getWidth() - 400 + 6, 23);
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
gx.setColor(Color.RED);
|
||||||
|
int xx = (int) Math.round((debugBorder[0] << TILE_SIZE_R) / scale + offsetX);
|
||||||
|
int yy = (int) Math.round((debugBorder[1] << TILE_SIZE_R) / scale + offsetY);
|
||||||
|
int xx2 = (int) Math.round((debugBorder[2] << TILE_SIZE_R) / scale + offsetX);
|
||||||
|
int yy2 = (int) Math.round((debugBorder[3] << TILE_SIZE_R) / scale + offsetY);
|
||||||
|
gx.drawRect(xx, yy, xx2, yy2);
|
||||||
|
gx.drawRect(xx-1, yy-1, xx2+1, yy2+1);
|
||||||
|
gx.drawRect(xx-2, yy-2, xx2+2, yy2+2);
|
||||||
|
|
||||||
|
|
||||||
|
gx.setColor(overlay);
|
||||||
|
gx.fillRect(10, 10, 220, 200);
|
||||||
|
gx.setColor(Color.WHITE);
|
||||||
|
gx.drawString("Center [" + centerTileX + ", " + centerTileY + "]", 20, 25);
|
||||||
|
gx.drawString((60 / (Math.max(roll.getAverage(), 1))) + " fps", 20, 45);
|
||||||
|
gx.drawString("Width = " + lastTileWidth, 20, 65);
|
||||||
|
gx.drawString("Dirty = " + dirty, 20, 85);
|
||||||
|
gx.drawString("Scale = " + scale, 20, 105);
|
||||||
|
gx.drawString("Tiles (Visible)" + visibleTiles.size(), 20, 125);
|
||||||
|
gx.drawString("Tiles (Total) " + tiles.size(), 20, 145);
|
||||||
|
|
||||||
|
x = (int) (((int) ((mouseX - windowOffsetX))) + (-draggedOffsetX * scale)) >> TILE_SIZE_R;
|
||||||
|
y = (int) (((int) ((mouseY - windowOffsetY))) + (-draggedOffsetY * scale)) >> TILE_SIZE_R;
|
||||||
|
Tile t = getTile((short)x, (short)y);
|
||||||
|
boolean b1 = t != null;
|
||||||
|
boolean b2 = b1 && visibleTiles.contains(t);
|
||||||
|
gx.drawString("Cursor Tile [" + x + ", " + y + "]", 20, 165);
|
||||||
|
gx.drawString("Tile Details [" + String.valueOf(b1).toUpperCase() + ", " + String.valueOf(b2).toUpperCase() + "]", 20, 185);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
stopwatch.end();
|
||||||
|
roll.put(stopwatch.getMillis());
|
||||||
|
|
||||||
|
/*J.a(() ->
|
||||||
|
{
|
||||||
|
J.sleep(1000 / targetFPS);
|
||||||
|
repaint();
|
||||||
|
});*/
|
||||||
|
J.a(sleepTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawTile(Graphics gx, Tile tile) {
|
||||||
|
if (gx == null) return;
|
||||||
|
|
||||||
|
int x = (int) Math.round((tile.getX() << TILE_SIZE_R) / scale + offsetX);
|
||||||
|
int y = (int) Math.round((tile.getY() << TILE_SIZE_R) / scale + offsetY);
|
||||||
|
//int x = (int) ((tile.getX() * TILE_SIZE) / scale + offsetX);
|
||||||
|
//int y = (int) ((tile.getY() * TILE_SIZE) / scale + offsetY);
|
||||||
|
|
||||||
|
int size = (int) (TILE_SIZE / scale);
|
||||||
|
int off = (int) (TILE_SIZE % scale);
|
||||||
|
gx.drawImage(tile.getImage(), x, y, size, size, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Runnable sleepTask = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
double t = Math.max(Math.min(roll.getAverage(), 1000), 30);
|
||||||
|
J.sleep((long) t);
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we should do a full recalculation of what tiles should be visible
|
||||||
|
*/
|
||||||
|
public void softRecalculate() {
|
||||||
|
short x = (short) (((-draggedOffsetX * scale)) / TILE_SIZE * scale);
|
||||||
|
short y = (short) (((-draggedOffsetY * scale)) / TILE_SIZE * scale);
|
||||||
|
int xTiles = (((int)(getWidth() * scale) >> TILE_SIZE_R)) / 2 + 1;
|
||||||
|
|
||||||
|
if (centerTileX != x || centerTileY != y || xTiles != lastTileWidth) {
|
||||||
|
recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
centerTileX = x;
|
||||||
|
centerTileY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recalculate what tiles should be visible on screen, as well as queue
|
||||||
|
* new tiles to be created
|
||||||
|
*/
|
||||||
|
public void recalculate() {
|
||||||
|
PrecisionStopwatch stopwatch = PrecisionStopwatch.start();
|
||||||
|
|
||||||
|
//Clears out the queue of existing tiles to do because we are redoing them anyway
|
||||||
|
//If we don't do this, the queue gets so clogged that it literally takes up the
|
||||||
|
//entire CPU with thread locking/unlocking
|
||||||
|
executorService.getQueue().clear();
|
||||||
|
|
||||||
|
int W = getWidth();
|
||||||
|
int H = getHeight();
|
||||||
|
|
||||||
|
if (W == 0|| H == 0) { //The window hasn't fully opened yet; assume defaults
|
||||||
|
W = DEF_WIDTH;
|
||||||
|
H = DEF_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
short centerTileX = (short) (((-draggedOffsetX * scale)) / TILE_SIZE * scale);
|
||||||
|
short centerTileY = (short) (((-draggedOffsetY * scale)) / TILE_SIZE * scale);
|
||||||
|
|
||||||
|
//Iris.info("Center is " + centerTileX + ", " + centerTileY);
|
||||||
|
//Iris.info("Width is " + W + ", " + H);
|
||||||
|
|
||||||
|
int woh = Math.max(W, H);
|
||||||
|
int newSize = ((int)(woh * scale) >> TILE_SIZE_R) + 1;
|
||||||
|
int checkSizeX = (((int)(W * scale) >> TILE_SIZE_R)) / 2;
|
||||||
|
int checkSizeY = (((int)(H * scale) >> TILE_SIZE_R)) / 2;
|
||||||
|
lastTileWidth = checkSizeX;
|
||||||
|
generateSpiral(newSize);
|
||||||
|
|
||||||
|
Set<Integer> checked = new HashSet<>();
|
||||||
|
Set<Integer> clone = new HashSet(visibleTiles.stream().map((t) ->
|
||||||
|
getTileId(t.getX(), t.getY()))
|
||||||
|
.collect(Collectors.toSet())); //Clone the visible tiles
|
||||||
|
|
||||||
|
if (debug) { //These are the 4 corners of the red line that shows the visibility check region for tiles
|
||||||
|
debugBorder[0] = -checkSizeX + centerTileX;
|
||||||
|
debugBorder[1] = -checkSizeY + centerTileY;
|
||||||
|
debugBorder[2] = checkSizeX + 1 + centerTileX;
|
||||||
|
debugBorder[3] = checkSizeY + 1 + centerTileY;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (short[] coords : spiral) { //Start from the center of the spiral and work outwards to find new tiles to queue
|
||||||
|
short x = (short)(coords[0] + centerTileX);
|
||||||
|
short y = (short)(coords[1] + centerTileY);
|
||||||
|
|
||||||
|
//When it goes offscreen, don't queue the tile by continuing
|
||||||
|
if (Math.abs(coords[0]) > checkSizeX + 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (Math.abs(coords[1]) > checkSizeY + 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = getTileId(x, y);
|
||||||
|
|
||||||
|
//If the tile is not already made
|
||||||
|
if (!tiles.containsKey(id)) {
|
||||||
|
short[] c = getTileCoords(id);
|
||||||
|
queue(c[0], c[1]); //Queue for creation
|
||||||
|
} else {
|
||||||
|
checked.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clone.removeAll(checked); //Remove the tiles that we know are onscreen
|
||||||
|
|
||||||
|
for (int id : clone) { //Loop through the invisible tiles and mark them for removal from memory
|
||||||
|
short[] c = getTileCoords(id);
|
||||||
|
queueForRemoval(getTile(c[0], c[1]));
|
||||||
|
//visibleTiles.remove(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
stopwatch.end();
|
||||||
|
roll.put(stopwatch.getMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue a tile for creation
|
||||||
|
* @param tileX X tile coord
|
||||||
|
* @param tileY Y tile coord
|
||||||
|
*/
|
||||||
|
public void queue(short tileX, short tileY) {
|
||||||
|
//If the tile still exists but just isn't visible
|
||||||
|
if (tiles.containsKey(getTileId(tileX, tileY))) {
|
||||||
|
Tile tile = getTile(tileX, tileY);
|
||||||
|
if (visibleTiles.contains(tile)) return;
|
||||||
|
|
||||||
|
visibleTiles.add(tile);
|
||||||
|
halfDirtyTiles.add(tile); //Re-render it without doing a full repaint
|
||||||
|
//dirty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//I turned all lambda around here into objects just to see if they would
|
||||||
|
//show up in timings instead of "$lambda". But they didn't. So it's not
|
||||||
|
//not my code DIRECTLY. I believe the thing timings show is just to do
|
||||||
|
//with threads stopping and starting/halting in the thread pool. Don't
|
||||||
|
//know why or how to fix it, though
|
||||||
|
|
||||||
|
/*executorService.execute(() -> {
|
||||||
|
Tile tile = new Tile(tileX, tileY);
|
||||||
|
tile.render(complex, currentType);
|
||||||
|
tiles.put(getTileId(tileX, tileY), tile);
|
||||||
|
visibleTiles.add(tile);
|
||||||
|
dirty = true;
|
||||||
|
});*/
|
||||||
|
executorService.execute(queueTask(tileX, tileY));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Runnable queueTask(short tileX, short tileY) {
|
||||||
|
return new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Tile tile = new Tile(tileX, tileY);
|
||||||
|
tile.render(complex, currentType);
|
||||||
|
tiles.put(getTileId(tileX, tileY), tile);
|
||||||
|
visibleTiles.add(tile);
|
||||||
|
//dirty = true; //Disabled marking as dirty so a redraw of the entire map isn't needed
|
||||||
|
halfDirtyTiles.add(tile);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pend a tile for removal from the screen
|
||||||
|
* @param tile The tile to remove
|
||||||
|
*/
|
||||||
|
public void queueForRemoval(Tile tile) {
|
||||||
|
//TODO Change from using the async task system as it may be putting strain on the server from being called so often
|
||||||
|
J.a(() -> visibleTiles.remove(tile), 20); //Remove visibility in a bit
|
||||||
|
|
||||||
|
J.a(() -> { //Remove it completely from memory after 5 seconds if it's still not visible
|
||||||
|
if (!visibleTiles.contains(tile)) {
|
||||||
|
tiles.remove(getTileId(tile.getX(), tile.getY()));
|
||||||
|
}
|
||||||
|
}, 20 * 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a tile based on the X and Z coords of the tile
|
||||||
|
* @param tileX X Coord
|
||||||
|
* @param tileY Y Coord
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Tile getTile(short tileX, short tileY) {
|
||||||
|
return tiles.get(getTileId(tileX, tileY));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an integer that represents a tile's location
|
||||||
|
* @param tileX X Coord
|
||||||
|
* @param tileY Y Coord
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getTileId(short tileX, short tileY) {
|
||||||
|
return tileX | tileY << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an integer representing a tiles location back into 2 shorts
|
||||||
|
* @param id The tile integer
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public short[] getTileCoords(int id) {
|
||||||
|
return new short[] {(short) (id & 0x0000FFFF), (short) (id >> 16)};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a 2D array of relative tile locations. This is so we know what order
|
||||||
|
* to search for new tiles in a nice, spiral way
|
||||||
|
* @param size Size of the array
|
||||||
|
*/
|
||||||
|
public void generateSpiral(int size) {
|
||||||
|
if (size % 2 == 0) size++;
|
||||||
|
short[][] newSpiral = new short[size * size][2];
|
||||||
|
|
||||||
|
int x = 0; // current position; x
|
||||||
|
int y = 0; // current position; y
|
||||||
|
int d = 0; // current direction; 0=RIGHT, 1=DOWN, 2=LEFT, 3=UP
|
||||||
|
int s = 1; // chain size
|
||||||
|
int c = 0; // count
|
||||||
|
|
||||||
|
// starting point
|
||||||
|
x = ((int)(size/2.0))-1;
|
||||||
|
y = ((int)(size/2.0))-1;
|
||||||
|
int offset = (size / 2) - 1;
|
||||||
|
|
||||||
|
for (int k=1; k<=(size-1); k++)
|
||||||
|
{
|
||||||
|
for (int j=0; j<(k<(size-1)?2:3); j++)
|
||||||
|
{
|
||||||
|
for (int i=0; i<s; i++)
|
||||||
|
{
|
||||||
|
short[] coords = {(short) (x - offset), (short) (y - offset)};
|
||||||
|
newSpiral[c] = coords;
|
||||||
|
c++;
|
||||||
|
//Iris.info("Spiral " + coords[0] + ", " + coords[1]); //Testing
|
||||||
|
|
||||||
|
switch (d)
|
||||||
|
{
|
||||||
|
case 0: y = y + 1; break;
|
||||||
|
case 1: x = x + 1; break;
|
||||||
|
case 2: y = y - 1; break;
|
||||||
|
case 3: x = x - 1; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d = (d+1)%4;
|
||||||
|
}
|
||||||
|
s = s + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
spiral = newSpiral;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*private final ExecutorService executorService = Executors.newFixedThreadPool(8, r -> {
|
||||||
|
threadId++;
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setName("Iris Map Renderer " + threadId);
|
||||||
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
t.setUncaughtExceptionHandler((et, e) ->
|
||||||
|
{
|
||||||
|
Iris.info("Exception encountered in " + et.getName());
|
||||||
|
e.printStackTrace();
|
||||||
|
});
|
||||||
|
|
||||||
|
return t;
|
||||||
|
});*/
|
||||||
|
|
||||||
|
private ThreadFactory factory = new ThreadFactory() {
|
||||||
|
@Override
|
||||||
|
public Thread newThread(@NotNull Runnable r) {
|
||||||
|
threadId++;
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setName("Iris Map Renderer " + threadId);
|
||||||
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.setUncaughtExceptionHandler((et, e) ->
|
||||||
|
{
|
||||||
|
Iris.info("Exception encountered in " + et.getName());
|
||||||
|
e.printStackTrace();
|
||||||
|
});
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Our thread pool that draws the tiles for us
|
||||||
|
private final ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(8, factory);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
5
src/main/java/com/volmit/iris/map/RenderType.java
Normal file
5
src/main/java/com/volmit/iris/map/RenderType.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package com.volmit.iris.map;
|
||||||
|
|
||||||
|
public enum RenderType {
|
||||||
|
BIOME_LAND, REGION, CAVE_LAND
|
||||||
|
}
|
87
src/main/java/com/volmit/iris/map/Tile.java
Normal file
87
src/main/java/com/volmit/iris/map/Tile.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package com.volmit.iris.map;
|
||||||
|
|
||||||
|
import com.volmit.iris.generator.IrisComplex;
|
||||||
|
import com.volmit.iris.object.IrisBiome;
|
||||||
|
import com.volmit.iris.object.IrisRegion;
|
||||||
|
import com.volmit.iris.scaffold.stream.ProceduralStream;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
public class Tile {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private short x;
|
||||||
|
@Getter
|
||||||
|
private short y;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private BufferedImage image;
|
||||||
|
|
||||||
|
private Set<Integer> biomes;
|
||||||
|
private Set<Integer> regions;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private boolean dirty;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private boolean rendering;
|
||||||
|
|
||||||
|
public Tile(short x, short y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasBiome(int biome) {
|
||||||
|
return biomes.contains(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasRegion(int region) {
|
||||||
|
return regions.contains(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the tile
|
||||||
|
* @param complex The world complex
|
||||||
|
* @param type The type of render
|
||||||
|
* @return True when rendered
|
||||||
|
*/
|
||||||
|
public boolean render(IrisComplex complex, RenderType type) {
|
||||||
|
BufferedImage newImage = new BufferedImage(128, 128, BufferedImage.TYPE_INT_RGB);
|
||||||
|
|
||||||
|
ProceduralStream stream;
|
||||||
|
BiFunction<Integer, Integer, Integer> getColor;
|
||||||
|
if (type == RenderType.BIOME_LAND) {
|
||||||
|
stream = complex.getLandBiomeStream();
|
||||||
|
getColor = (x, z) -> ((ProceduralStream<IrisBiome>)stream).get(x, z).getColor().getAsRGB();
|
||||||
|
} else if (type == RenderType.REGION) {
|
||||||
|
stream = complex.getRegionStream();
|
||||||
|
getColor = (x, z) -> ((ProceduralStream<IrisRegion>)stream).get(x, z).getColor().getColor().getRGB();
|
||||||
|
} else {
|
||||||
|
stream = complex.getCaveBiomeStream();
|
||||||
|
getColor = (x, z) -> ((ProceduralStream<IrisBiome>)stream).get(x, z).getColor().getAsRGB();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
for (int j = 0; j < 128; j++) {
|
||||||
|
newImage.setRGB(i, j, getColor.apply(translate(x, i), translate(y, j)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image = newImage;
|
||||||
|
rendering = false;
|
||||||
|
dirty = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int translate(int section, int pixel) {
|
||||||
|
return (section << 9) | (pixel << 2) | 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package com.volmit.iris.object;
|
package com.volmit.iris.object;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.generator.IrisComplex;
|
import com.volmit.iris.generator.IrisComplex;
|
||||||
import com.volmit.iris.generator.noise.CNG;
|
import com.volmit.iris.generator.noise.CNG;
|
||||||
import com.volmit.iris.manager.IrisDataManager;
|
import com.volmit.iris.manager.IrisDataManager;
|
||||||
@ -583,4 +584,26 @@ public class IrisBiome extends IrisRegistrant implements IRare {
|
|||||||
|
|
||||||
return getLayers().get(0).get(rng, x, 0, z, idm);
|
return getLayers().get(0).get(rng, x, 0, z, idm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IrisColor getColor() {
|
||||||
|
if (this.color == null) {
|
||||||
|
RandomColor randomColor = new RandomColor(getName().hashCode());
|
||||||
|
if (this.getVanillaDerivative() == null) {
|
||||||
|
this.color = new IrisColor();
|
||||||
|
this.color.setRed(255).setGreen(255).setBlue(255);
|
||||||
|
Iris.warn("No vanilla biome found for " + getName());
|
||||||
|
}
|
||||||
|
RandomColor.Color col = VanillaBiomeMap.getColorType(this.getVanillaDerivative());
|
||||||
|
RandomColor.Luminosity lum = VanillaBiomeMap.getColorLuminosity(this.getVanillaDerivative());
|
||||||
|
RandomColor.SaturationType sat = VanillaBiomeMap.getColorSaturatiom(this.getVanillaDerivative());
|
||||||
|
int newColorI = randomColor.randomColor(col, col == RandomColor.Color.MONOCHROME ? RandomColor.SaturationType.MONOCHROME : sat, lum);
|
||||||
|
|
||||||
|
|
||||||
|
Color newColor = new Color(newColorI);
|
||||||
|
this.color = new IrisColor();
|
||||||
|
this.color.setRed(newColor.getRed()).setBlue(newColor.getBlue()).setGreen(newColor.getGreen());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,4 +86,17 @@ public class IrisColor {
|
|||||||
|
|
||||||
return new Color(a << 24 | r << 16 | g << 8 | b);
|
return new Color(a << 24 | r << 16 | g << 8 | b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getAsRGB() {
|
||||||
|
if (hex != null) {
|
||||||
|
try {
|
||||||
|
if (hex.startsWith("#")) hex = hex.substring(1);
|
||||||
|
return Integer.parseInt(hex, 16);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return red << 16 | green << 8 | blue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
139
src/main/java/com/volmit/iris/util/FakeEngine.java
Normal file
139
src/main/java/com/volmit/iris/util/FakeEngine.java
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package com.volmit.iris.util;
|
||||||
|
|
||||||
|
import com.volmit.iris.manager.IrisDataManager;
|
||||||
|
import com.volmit.iris.object.IrisBiome;
|
||||||
|
import com.volmit.iris.object.IrisDimension;
|
||||||
|
import com.volmit.iris.scaffold.engine.Engine;
|
||||||
|
import com.volmit.iris.scaffold.engine.EngineCompound;
|
||||||
|
import com.volmit.iris.scaffold.engine.EngineEffects;
|
||||||
|
import com.volmit.iris.scaffold.engine.EngineFramework;
|
||||||
|
import com.volmit.iris.scaffold.engine.EngineMetrics;
|
||||||
|
import com.volmit.iris.scaffold.engine.EngineTarget;
|
||||||
|
import com.volmit.iris.scaffold.engine.EngineWorldManager;
|
||||||
|
import com.volmit.iris.scaffold.hunk.Hunk;
|
||||||
|
import com.volmit.iris.util.FakeWorld;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
|
||||||
|
|
||||||
|
public class FakeEngine implements Engine {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private IrisDimension dimension;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private World world;
|
||||||
|
|
||||||
|
public FakeEngine(IrisDimension dimension, FakeWorld world) {
|
||||||
|
this.dimension = dimension;
|
||||||
|
this.world = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IrisDataManager getData() {
|
||||||
|
return dimension.getLoader().copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EngineWorldManager getWorldManager() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParallelism(int parallelism) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getParallelism() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EngineTarget getTarget() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EngineFramework getFramework() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMinHeight(int min) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recycle() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIndex() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double modifyX(double x) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double modifyZ(double z) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generate(int x, int z, Hunk<BlockData> blocks, Hunk<Biome> biomes) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EngineMetrics getMetrics() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EngineEffects getEffects() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EngineCompound getCompound() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IrisBiome getFocus() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fail(String error, Throwable e) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFailed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCacheID() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hotload() { }
|
||||||
|
}
|
506
src/main/java/com/volmit/iris/util/RandomColor.java
Normal file
506
src/main/java/com/volmit/iris/util/RandomColor.java
Normal file
@ -0,0 +1,506 @@
|
|||||||
|
package com.volmit.iris.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Credit to https://github.com/lzyzsd/AndroidRandomColor
|
||||||
|
*/
|
||||||
|
public class RandomColor {
|
||||||
|
|
||||||
|
public static int hueOffset = 0;
|
||||||
|
|
||||||
|
public static class ColorInfo {
|
||||||
|
Range hueRange;
|
||||||
|
Range saturationRange;
|
||||||
|
Range brightnessRange;
|
||||||
|
List<Range> lowerBounds;
|
||||||
|
|
||||||
|
public ColorInfo(Range hueRange, Range saturationRange, Range brightnessRange, List<Range> lowerBounds) {
|
||||||
|
this.hueRange = hueRange;
|
||||||
|
this.saturationRange = saturationRange;
|
||||||
|
this.brightnessRange = brightnessRange;
|
||||||
|
this.lowerBounds = lowerBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Range getHueRange() {
|
||||||
|
return hueRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHueRange(Range hueRange) {
|
||||||
|
this.hueRange = hueRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Range getSaturationRange() {
|
||||||
|
return saturationRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaturationRange(Range saturationRange) {
|
||||||
|
this.saturationRange = saturationRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Range getBrightnessRange() {
|
||||||
|
return brightnessRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBrightnessRange(Range brightnessRange) {
|
||||||
|
this.brightnessRange = brightnessRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Range> getLowerBounds() {
|
||||||
|
return lowerBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLowerBounds(List<Range> lowerBounds) {
|
||||||
|
this.lowerBounds = lowerBounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Range {
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
|
||||||
|
public Range(int start, int end) {
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contain(int value) {
|
||||||
|
return value >= start && value <= end;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "start: " + start + " end: " + end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Random random;
|
||||||
|
|
||||||
|
public static enum SaturationType {
|
||||||
|
RANDOM, MONOCHROME, HIGH, LOW, MEDIUM
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum Luminosity {
|
||||||
|
BRIGHT, LIGHT, DARK, RANDOM
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Options {
|
||||||
|
int hue;
|
||||||
|
SaturationType saturationType;
|
||||||
|
Luminosity luminosity;
|
||||||
|
|
||||||
|
public int getHue() {
|
||||||
|
return hue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHue(int hue) {
|
||||||
|
this.hue = hue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaturationType getSaturationType() {
|
||||||
|
return saturationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaturationType(SaturationType saturationType) {
|
||||||
|
this.saturationType = saturationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Luminosity getLuminosity() {
|
||||||
|
return luminosity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLuminosity(Luminosity luminosity) {
|
||||||
|
this.luminosity = luminosity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashMap<String, ColorInfo> colors = new HashMap<>();
|
||||||
|
|
||||||
|
public RandomColor() {
|
||||||
|
loadColorBounds();
|
||||||
|
random = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RandomColor(long seed){
|
||||||
|
loadColorBounds();
|
||||||
|
random = new Random();
|
||||||
|
random.setSeed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getColor(int hue, int saturation, int brightness) {
|
||||||
|
return java.awt.Color.getHSBColor((float)(hue + hueOffset % 360) / 360, (float)saturation / 100, (float)brightness / 100).getRGB();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int randomColor() {
|
||||||
|
return randomColor(0, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int randomColor(int value, SaturationType saturationType, Luminosity luminosity) {
|
||||||
|
int hue = value;
|
||||||
|
hue = pickHue(hue);
|
||||||
|
int saturation = pickSaturation(hue, saturationType, luminosity);
|
||||||
|
int brightness = pickBrightness(hue, saturation, luminosity);
|
||||||
|
|
||||||
|
return getColor(hue, saturation, brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int randomColor(Color color, SaturationType saturationType, Luminosity luminosity) {
|
||||||
|
int hue = pickHue(color.name());
|
||||||
|
int saturation = pickSaturation(hue, saturationType, luminosity);
|
||||||
|
int brightness = pickBrightness(hue, saturation, luminosity);
|
||||||
|
|
||||||
|
return getColor(hue, saturation, brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] randomColor(int count) {
|
||||||
|
if (count <= 0) {
|
||||||
|
throw new IllegalArgumentException("count must be greater than 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] colors = new int[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
colors[i] = randomColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int randomColor(Color color) {
|
||||||
|
int hue = pickHue(color.name());
|
||||||
|
int saturation = pickSaturation(color, null, null);
|
||||||
|
int brightness = pickBrightness(color, saturation, null);
|
||||||
|
|
||||||
|
int colorValue = getColor(hue, saturation, brightness);
|
||||||
|
return colorValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] random(Color color, int count) {
|
||||||
|
if (count <= 0) {
|
||||||
|
throw new IllegalArgumentException("count must be greater than 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] colors = new int[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
colors[i] = randomColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pickHue(int hue) {
|
||||||
|
Range hueRange = getHueRange(hue);
|
||||||
|
return doPickHue(hueRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int doPickHue(Range hueRange) {
|
||||||
|
int hue = randomWithin(hueRange);
|
||||||
|
|
||||||
|
// Instead of storing red as two seperate ranges,
|
||||||
|
// we group them, using negative numbers
|
||||||
|
if (hue < 0) {
|
||||||
|
hue = 360 + hue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pickHue(String name) {
|
||||||
|
Range hueRange = getHueRange(name);
|
||||||
|
return doPickHue(hueRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Range getHueRange(int number) {
|
||||||
|
if (number < 360 && number > 0) {
|
||||||
|
return new Range(number, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Range(0, 360);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Range getHueRange(String name) {
|
||||||
|
if (colors.containsKey(name)) {
|
||||||
|
return colors.get(name).getHueRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Range(0, 360);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pickSaturation(int hue, SaturationType saturationType, Luminosity luminosity) {
|
||||||
|
return pickSaturation(getColorInfo(hue), saturationType, luminosity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pickSaturation(Color color, SaturationType saturationType, Luminosity luminosity) {
|
||||||
|
ColorInfo colorInfo = colors.get(color.name());
|
||||||
|
return pickSaturation(colorInfo, saturationType, luminosity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pickSaturation(ColorInfo colorInfo, SaturationType saturationType, Luminosity luminosity) {
|
||||||
|
if (saturationType != null) {
|
||||||
|
switch (saturationType) {
|
||||||
|
case RANDOM:
|
||||||
|
return randomWithin(new Range(0, 100));
|
||||||
|
case MONOCHROME:
|
||||||
|
return 0;
|
||||||
|
case HIGH:
|
||||||
|
return randomWithin(new Range(75, 100));
|
||||||
|
case MEDIUM:
|
||||||
|
return randomWithin(new Range(55, 75));
|
||||||
|
case LOW:
|
||||||
|
return randomWithin(new Range(35, 55));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorInfo == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Range saturationRange = colorInfo.getSaturationRange();
|
||||||
|
|
||||||
|
int min = saturationRange.start;
|
||||||
|
int max = saturationRange.end;
|
||||||
|
|
||||||
|
if (luminosity != null) {
|
||||||
|
switch (luminosity) {
|
||||||
|
case LIGHT:
|
||||||
|
min = 55;
|
||||||
|
break;
|
||||||
|
case BRIGHT:
|
||||||
|
min = max - 10;
|
||||||
|
break;
|
||||||
|
case DARK:
|
||||||
|
max = 55;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomWithin(new Range(min, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pickBrightness(int hue, int saturation, Luminosity luminosity) {
|
||||||
|
ColorInfo colorInfo = getColorInfo(hue);
|
||||||
|
|
||||||
|
return pickBrightness(colorInfo, saturation, luminosity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pickBrightness(Color color, int saturation, Luminosity luminosity) {
|
||||||
|
ColorInfo colorInfo = colors.get(color.name());
|
||||||
|
|
||||||
|
return pickBrightness(colorInfo, saturation, luminosity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pickBrightness(ColorInfo colorInfo, int saturation, Luminosity luminosity) {
|
||||||
|
int min = getMinimumBrightness(colorInfo, saturation),
|
||||||
|
max = 100;
|
||||||
|
|
||||||
|
if (luminosity != null) {
|
||||||
|
switch (luminosity) {
|
||||||
|
|
||||||
|
case DARK:
|
||||||
|
max = min + 20;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LIGHT:
|
||||||
|
min = (max + min) / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RANDOM:
|
||||||
|
min = 0;
|
||||||
|
max = 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomWithin(new Range(min, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMinimumBrightness(ColorInfo colorInfo, int saturation) {
|
||||||
|
if (colorInfo == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Range> lowerBounds = colorInfo.getLowerBounds();
|
||||||
|
for (int i = 0; i < lowerBounds.size() - 1; i++) {
|
||||||
|
|
||||||
|
int s1 = lowerBounds.get(i).start,
|
||||||
|
v1 = lowerBounds.get(i).end;
|
||||||
|
|
||||||
|
if (i == lowerBounds.size() - 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int s2 = lowerBounds.get(i + 1).start,
|
||||||
|
v2 = lowerBounds.get(i + 1).end;
|
||||||
|
|
||||||
|
if (saturation >= s1 && saturation <= s2) {
|
||||||
|
|
||||||
|
float m = (v2 - v1)/(float) (s2 - s1),
|
||||||
|
b = v1 - m*s1;
|
||||||
|
|
||||||
|
return (int) (m*saturation + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ColorInfo getColorInfo(int hue) {
|
||||||
|
// Maps red colors to make picking hue easier
|
||||||
|
if (hue >= 334 && hue <= 360) {
|
||||||
|
hue-= 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String key : colors.keySet()) {
|
||||||
|
ColorInfo colorInfo = colors.get(key);
|
||||||
|
if (colorInfo.getHueRange() != null && colorInfo.getHueRange().contain(hue)) {
|
||||||
|
return colorInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int randomWithin (Range range) {
|
||||||
|
return (int) Math.floor(range.start + random.nextDouble()*(range.end + 1 - range.start));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void defineColor(String name, Range hueRange, List<Range> lowerBounds) {
|
||||||
|
int sMin = lowerBounds.get(0).start;
|
||||||
|
int sMax = lowerBounds.get(lowerBounds.size() - 1).start;
|
||||||
|
int bMin = lowerBounds.get(lowerBounds.size() - 1).end;
|
||||||
|
int bMax = lowerBounds.get(0).end;
|
||||||
|
|
||||||
|
colors.put(name, new ColorInfo(hueRange, new Range(sMin, sMax), new Range(bMin, bMax), lowerBounds));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadColorBounds() {
|
||||||
|
List<Range> lowerBounds1 = new ArrayList<>();
|
||||||
|
lowerBounds1.add(new Range(0, 0));
|
||||||
|
lowerBounds1.add(new Range(100, 0));
|
||||||
|
defineColor(
|
||||||
|
Color.MONOCHROME.name(),
|
||||||
|
new Range(0, 0),
|
||||||
|
lowerBounds1
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Range> lowerBounds2 = new ArrayList<>();
|
||||||
|
lowerBounds2.add(new Range(20, 100));
|
||||||
|
lowerBounds2.add(new Range(30, 92));
|
||||||
|
lowerBounds2.add(new Range(40, 89));
|
||||||
|
lowerBounds2.add(new Range(50, 85));
|
||||||
|
lowerBounds2.add(new Range(60, 78));
|
||||||
|
lowerBounds2.add(new Range(70, 70));
|
||||||
|
lowerBounds2.add(new Range(80, 60));
|
||||||
|
lowerBounds2.add(new Range(90, 55));
|
||||||
|
lowerBounds2.add(new Range(100, 50));
|
||||||
|
defineColor(
|
||||||
|
Color.RED.name(),
|
||||||
|
new Range(-26, 18),
|
||||||
|
lowerBounds2
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Range> lowerBounds3 = new ArrayList<Range>();
|
||||||
|
lowerBounds3.add(new Range(20, 100));
|
||||||
|
lowerBounds3.add(new Range(30, 93));
|
||||||
|
lowerBounds3.add(new Range(40, 88));
|
||||||
|
lowerBounds3.add(new Range(50, 86));
|
||||||
|
lowerBounds3.add(new Range(60, 85));
|
||||||
|
lowerBounds3.add(new Range(70, 70));
|
||||||
|
lowerBounds3.add(new Range(100, 70));
|
||||||
|
defineColor(
|
||||||
|
Color.ORANGE.name(),
|
||||||
|
new Range(19, 46),
|
||||||
|
lowerBounds3
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Range> lowerBounds4 = new ArrayList<>();
|
||||||
|
lowerBounds4.add(new Range(25, 100));
|
||||||
|
lowerBounds4.add(new Range(40, 94));
|
||||||
|
lowerBounds4.add(new Range(50, 89));
|
||||||
|
lowerBounds4.add(new Range(60, 86));
|
||||||
|
lowerBounds4.add(new Range(70, 84));
|
||||||
|
lowerBounds4.add(new Range(80, 82));
|
||||||
|
lowerBounds4.add(new Range(90, 80));
|
||||||
|
lowerBounds4.add(new Range(100, 75));
|
||||||
|
|
||||||
|
defineColor(
|
||||||
|
Color.YELLOW.name(),
|
||||||
|
new Range(47, 62),
|
||||||
|
lowerBounds4
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Range> lowerBounds5 = new ArrayList<>();
|
||||||
|
lowerBounds5.add(new Range(30, 100));
|
||||||
|
lowerBounds5.add(new Range(40, 90));
|
||||||
|
lowerBounds5.add(new Range(50, 85));
|
||||||
|
lowerBounds5.add(new Range(60, 81));
|
||||||
|
lowerBounds5.add(new Range(70, 74));
|
||||||
|
lowerBounds5.add(new Range(80, 64));
|
||||||
|
lowerBounds5.add(new Range(90, 50));
|
||||||
|
lowerBounds5.add(new Range(100, 40));
|
||||||
|
|
||||||
|
defineColor(
|
||||||
|
Color.GREEN.name(),
|
||||||
|
new Range(63,178),
|
||||||
|
lowerBounds5
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Range> lowerBounds6 = new ArrayList<>();
|
||||||
|
lowerBounds6.add(new Range(20, 100));
|
||||||
|
lowerBounds6.add(new Range(30, 86));
|
||||||
|
lowerBounds6.add(new Range(40, 80));
|
||||||
|
lowerBounds6.add(new Range(50, 74));
|
||||||
|
lowerBounds6.add(new Range(60, 60));
|
||||||
|
lowerBounds6.add(new Range(70, 52));
|
||||||
|
lowerBounds6.add(new Range(80, 44));
|
||||||
|
lowerBounds6.add(new Range(90, 39));
|
||||||
|
lowerBounds6.add(new Range(100, 35));
|
||||||
|
|
||||||
|
defineColor(
|
||||||
|
Color.BLUE.name(),
|
||||||
|
new Range(179, 257),
|
||||||
|
lowerBounds6
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Range> lowerBounds7 = new ArrayList<>();
|
||||||
|
lowerBounds7.add(new Range(20, 100));
|
||||||
|
lowerBounds7.add(new Range(30, 87));
|
||||||
|
lowerBounds7.add(new Range(40, 79));
|
||||||
|
lowerBounds7.add(new Range(50, 70));
|
||||||
|
lowerBounds7.add(new Range(60, 65));
|
||||||
|
lowerBounds7.add(new Range(70, 59));
|
||||||
|
lowerBounds7.add(new Range(80, 52));
|
||||||
|
lowerBounds7.add(new Range(90, 45));
|
||||||
|
lowerBounds7.add(new Range(100, 42));
|
||||||
|
|
||||||
|
defineColor(
|
||||||
|
Color.PURPLE.name(),
|
||||||
|
new Range(258, 282),
|
||||||
|
lowerBounds7
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Range> lowerBounds8 = new ArrayList<>();
|
||||||
|
lowerBounds8.add(new Range(20, 100));
|
||||||
|
lowerBounds8.add(new Range(30, 90));
|
||||||
|
lowerBounds8.add(new Range(40, 86));
|
||||||
|
lowerBounds8.add(new Range(60, 84));
|
||||||
|
lowerBounds8.add(new Range(80, 80));
|
||||||
|
lowerBounds8.add(new Range(90, 75));
|
||||||
|
lowerBounds8.add(new Range(100, 73));
|
||||||
|
|
||||||
|
defineColor(
|
||||||
|
Color.PINK.name(),
|
||||||
|
new Range(283, 334),
|
||||||
|
lowerBounds8
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum Color {
|
||||||
|
MONOCHROME, RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE, PINK
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
128
src/main/java/com/volmit/iris/util/VanillaBiomeMap.java
Normal file
128
src/main/java/com/volmit/iris/util/VanillaBiomeMap.java
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package com.volmit.iris.util;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutableTriple;
|
||||||
|
import org.apache.commons.lang3.tuple.Triple;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import com.volmit.iris.util.RandomColor.*;
|
||||||
|
|
||||||
|
public class VanillaBiomeMap {
|
||||||
|
|
||||||
|
private static KMap<Biome, Integer> BIOME_HEX = new KMap<>();
|
||||||
|
private static KMap<Biome, Color> BIOME_COLOR = new KMap<>();
|
||||||
|
private static KMap<Biome, Luminosity> BIOME_LUMINOSITY = new KMap<>();
|
||||||
|
private static KMap<Biome, SaturationType> BIOME_SATURATION = new KMap<>();
|
||||||
|
private static KMap<Biome, Short> BIOME_IDs = new KMap<>();
|
||||||
|
|
||||||
|
private static void add(Biome biome, int color, short id, Color randomColor, Luminosity luminosity, SaturationType saturation) {
|
||||||
|
BIOME_HEX.put(biome, color);
|
||||||
|
BIOME_COLOR.put(biome, randomColor);
|
||||||
|
if (luminosity != null) BIOME_LUMINOSITY.put(biome, luminosity);
|
||||||
|
if (saturation != null) BIOME_SATURATION.put(biome, saturation);
|
||||||
|
BIOME_IDs.put(biome, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void add(Biome biome, int color, short id, Color randomColor, Luminosity luminosity) {
|
||||||
|
add(biome, color, id, randomColor, luminosity, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getColor(Biome biome) {
|
||||||
|
return BIOME_HEX.get(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color getColorType(Biome biome) {
|
||||||
|
return BIOME_COLOR.get(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Luminosity getColorLuminosity(Biome biome) {
|
||||||
|
return BIOME_LUMINOSITY.get(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SaturationType getColorSaturatiom(Biome biome) {
|
||||||
|
return BIOME_SATURATION.get(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static short getId(Biome biome) {
|
||||||
|
return BIOME_IDs.get(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
add(Biome.OCEAN, 0x000070, (short) 0, Color.BLUE, Luminosity.BRIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.PLAINS, 0x8DB360, (short) 1, Color.GREEN, Luminosity.LIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.DESERT, 0xFA9418, (short) 2, Color.YELLOW, Luminosity.LIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.MOUNTAINS, 0x606060, (short) 3, Color.MONOCHROME, Luminosity.BRIGHT, null);
|
||||||
|
add(Biome.FOREST, 0x056621, (short) 4, Color.GREEN, Luminosity.BRIGHT);
|
||||||
|
add(Biome.TAIGA, 0x0B6659, (short) 5, Color.GREEN, Luminosity.BRIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.SWAMP, 0x07F9B2, (short) 6, Color.ORANGE, Luminosity.DARK, SaturationType.MEDIUM);
|
||||||
|
add(Biome.RIVER, 0x0000FF, (short) 7, Color.BLUE, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.NETHER_WASTES, 0xBF3B3B, (short) 8, Color.RED, Luminosity.LIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.THE_END, 0x8080FF, (short) 9, Color.PURPLE, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.FROZEN_OCEAN, 0x7070D6, (short) 10, Color.BLUE, Luminosity.BRIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.FROZEN_RIVER, 0xA0A0FF, (short) 11, Color.BLUE, Luminosity.BRIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.SNOWY_TUNDRA, 0xFFFFFF, (short) 12, Color.MONOCHROME, Luminosity.LIGHT);
|
||||||
|
add(Biome.SNOWY_MOUNTAINS, 0xA0A0A0, (short) 13, Color.MONOCHROME, Luminosity.LIGHT);
|
||||||
|
add(Biome.MUSHROOM_FIELDS, 0xFF00FF, (short) 14, Color.PURPLE, Luminosity.BRIGHT);
|
||||||
|
add(Biome.MUSHROOM_FIELD_SHORE, 0xA000FF, (short) 15, Color.PURPLE, Luminosity.BRIGHT);
|
||||||
|
add(Biome.BEACH, 0xFADE55, (short) 16, Color.YELLOW, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.DESERT_HILLS, 0xD25F12, (short) 17, Color.YELLOW, Luminosity.LIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.WOODED_HILLS, 0x22551C, (short) 18, Color.GREEN, Luminosity.LIGHT);
|
||||||
|
add(Biome.TAIGA_HILLS, 0x163933, (short) 19, Color.GREEN, Luminosity.BRIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.MOUNTAIN_EDGE, 0x72789A, (short) 20, Color.MONOCHROME, Luminosity.BRIGHT);
|
||||||
|
add(Biome.JUNGLE, 0x537B09, (short) 21, Color.GREEN, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.JUNGLE_HILLS, 0x2C4205, (short) 22, Color.GREEN, Luminosity.DARK, SaturationType.HIGH);
|
||||||
|
add(Biome.JUNGLE_EDGE, 0x628B17, (short) 23, Color.GREEN, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.DEEP_OCEAN, 0x000030, (short) 24, Color.BLUE, Luminosity.DARK);
|
||||||
|
add(Biome.STONE_SHORE, 0xA2A284, (short) 25, Color.GREEN, Luminosity.DARK);
|
||||||
|
add(Biome.SNOWY_BEACH, 0xFAF0C0, (short) 26, Color.YELLOW, Luminosity.LIGHT);
|
||||||
|
add(Biome.BIRCH_FOREST, 0x307444, (short) 27, Color.GREEN, Luminosity.LIGHT);
|
||||||
|
add(Biome.BIRCH_FOREST_HILLS, 0x1F5F32, (short) 28, Color.GREEN, Luminosity.LIGHT);
|
||||||
|
add(Biome.DARK_FOREST, 0x40511A, (short) 29, Color.GREEN, Luminosity.DARK);
|
||||||
|
add(Biome.SNOWY_TAIGA, 0x31554A, (short) 30, Color.BLUE, Luminosity.LIGHT);
|
||||||
|
add(Biome.SNOWY_TAIGA_HILLS, 0x243F36, (short) 31, Color.BLUE, Luminosity.LIGHT);
|
||||||
|
add(Biome.GIANT_TREE_TAIGA, 0x596651, (short) 32, Color.ORANGE, Luminosity.LIGHT);
|
||||||
|
add(Biome.GIANT_TREE_TAIGA_HILLS, 0x454F3E, (short) 33, Color.ORANGE, Luminosity.LIGHT);
|
||||||
|
add(Biome.WOODED_MOUNTAINS, 0x507050, (short) 34, Color.MONOCHROME, Luminosity.BRIGHT);
|
||||||
|
add(Biome.SAVANNA, 0xBDB25F, (short) 35, Color.GREEN, Luminosity.LIGHT);
|
||||||
|
add(Biome.SAVANNA_PLATEAU, 0xA79D64, (short) 36, Color.GREEN, Luminosity.LIGHT);
|
||||||
|
add(Biome.BADLANDS, 0xD94515, (short) 37, Color.ORANGE, Luminosity.BRIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.WOODED_BADLANDS_PLATEAU, 0xB09765, (short) 38, Color.ORANGE, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.BADLANDS_PLATEAU, 0xCA8C65, (short) 39, Color.ORANGE, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.END_MIDLANDS, 0x8080FF, (short) 41, Color.YELLOW, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.END_HIGHLANDS, 0x8080FF, (short) 42, Color.PURPLE, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.END_BARRENS, 0x8080FF, (short) 43, Color.PURPLE, Luminosity.LIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.WARM_OCEAN, 0x0000AC, (short) 44, Color.BLUE, Luminosity.BRIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.LUKEWARM_OCEAN, 0x000090, (short) 45, Color.BLUE, Luminosity.BRIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.COLD_OCEAN, 0x202070, (short) 46, Color.BLUE, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.DEEP_WARM_OCEAN, 0x000050, (short) 47, Color.BLUE, Luminosity.DARK, SaturationType.LOW);
|
||||||
|
add(Biome.DEEP_LUKEWARM_OCEAN, 0x000040, (short) 48, Color.BLUE, Luminosity.DARK, SaturationType.MEDIUM);
|
||||||
|
add(Biome.DEEP_COLD_OCEAN, 0x202038, (short) 49, Color.BLUE, Luminosity.DARK, SaturationType.HIGH);
|
||||||
|
add(Biome.DEEP_FROZEN_OCEAN, 0x404090, (short) 50, Color.BLUE, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.THE_VOID, 0x000000, (short) 127, Color.MONOCHROME, Luminosity.DARK);
|
||||||
|
add(Biome.SUNFLOWER_PLAINS, 0xB5DB88, (short) 129, Color.GREEN, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.DESERT_LAKES, 0xFFBC40, (short) 130, Color.BLUE, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.GRAVELLY_MOUNTAINS, 0x888888, (short) 131, Color.MONOCHROME, Luminosity.LIGHT);
|
||||||
|
add(Biome.FLOWER_FOREST, 0x2D8E49, (short) 132, Color.RED, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.TAIGA_MOUNTAINS, 0x338E81, (short) 133, Color.GREEN, Luminosity.DARK, SaturationType.MEDIUM);
|
||||||
|
add(Biome.SWAMP_HILLS, 0x2FFFDA, (short) 134, Color.ORANGE, Luminosity.DARK, SaturationType.MEDIUM);
|
||||||
|
add(Biome.ICE_SPIKES, 0xB4DCDC, (short) 140, Color.BLUE, Luminosity.LIGHT, SaturationType.LOW);
|
||||||
|
add(Biome.MODIFIED_JUNGLE, 0x7BA331, (short) 149, Color.GREEN, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.MODIFIED_JUNGLE_EDGE, 0x8AB33F, (short) 151, Color.GREEN, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.TALL_BIRCH_FOREST, 0x589C6C, (short) 155, Color.GREEN, Luminosity.LIGHT);
|
||||||
|
add(Biome.TALL_BIRCH_HILLS, 0x47875A, (short) 156, Color.GREEN, Luminosity.LIGHT);
|
||||||
|
add(Biome.DARK_FOREST_HILLS, 0x687942, (short) 157, Color.GREEN, Luminosity.DARK);
|
||||||
|
add(Biome.SNOWY_TAIGA_MOUNTAINS, 0x597D72, (short) 158, Color.BLUE, Luminosity.LIGHT);
|
||||||
|
add(Biome.GIANT_SPRUCE_TAIGA, 0x818E79, (short) 160, Color.ORANGE, Luminosity.DARK, SaturationType.HIGH);
|
||||||
|
add(Biome.GIANT_SPRUCE_TAIGA_HILLS, 0x6D7766, (short) 161, Color.ORANGE, Luminosity.DARK, SaturationType.HIGH);
|
||||||
|
add(Biome.GRAVELLY_MOUNTAINS, 0x789878, (short) 162, Color.MONOCHROME, Luminosity.LIGHT);
|
||||||
|
add(Biome.SHATTERED_SAVANNA, 0xE5DA87, (short) 163, Color.ORANGE, Luminosity.LIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.SHATTERED_SAVANNA_PLATEAU, 0xCFC58C, (short) 164, Color.ORANGE, Luminosity.LIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.ERODED_BADLANDS, 0xFF6D3D, (short) 165, Color.ORANGE, Luminosity.LIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.MODIFIED_WOODED_BADLANDS_PLATEAU, 0xD8BF8D, (short) 166, Color.ORANGE, Luminosity.BRIGHT);
|
||||||
|
add(Biome.MODIFIED_BADLANDS_PLATEAU, 0xF2B48D, (short) 167, Color.ORANGE, Luminosity.BRIGHT);
|
||||||
|
add(Biome.BAMBOO_JUNGLE, 0x768E14, (short) 168, Color.GREEN, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.BAMBOO_JUNGLE_HILLS, 0x3B470A, (short) 169, Color.GREEN, Luminosity.BRIGHT, SaturationType.HIGH);
|
||||||
|
add(Biome.SOUL_SAND_VALLEY, 0x5E3830, (short) 170, Color.BLUE, Luminosity.BRIGHT, SaturationType.MEDIUM);
|
||||||
|
add(Biome.CRIMSON_FOREST, 0xDD0808, (short) 171, Color.RED, Luminosity.DARK, SaturationType.HIGH);
|
||||||
|
add(Biome.WARPED_FOREST, 0x49907B, (short) 172, Color.BLUE, Luminosity.BRIGHT);
|
||||||
|
add(Biome.BASALT_DELTAS, 0x403636, (short) 173, Color.MONOCHROME, Luminosity.DARK);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user