diff --git a/src/main/java/com/volmit/iris/map/MapVision.java b/src/main/java/com/volmit/iris/map/MapVision.java index 8b49f8afe..17b18b8ed 100644 --- a/src/main/java/com/volmit/iris/map/MapVision.java +++ b/src/main/java/com/volmit/iris/map/MapVision.java @@ -4,42 +4,36 @@ 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.FocusEvent; +import java.awt.event.FocusListener; 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.Arrays; import java.util.Collection; 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 { @@ -101,15 +95,15 @@ public class MapVision extends JPanel { 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; + double wx = getWidth() / 2; + double hy = getHeight() / 2; + double xScale = (mouseX - wx) / wx; + double yScale = (mouseY - hy) / hy; - 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); - } + /*if (mouseWheelEvent.getWheelRotation() > 0) { //Only on zoom in, adjust the position to zoom into + this.draggedOffsetX += xScale * (wx) * (oldScale - scale); + this.draggedOffsetY += yScale * (hy) * (oldScale - scale); + }*/ dirty = true; repaint(); @@ -165,7 +159,7 @@ public class MapVision extends JPanel { } @Override - public void componentShown(ComponentEvent e) { } + public void componentShown(ComponentEvent e) { } @Override public void componentHidden(ComponentEvent e) { } @@ -202,6 +196,18 @@ public class MapVision extends JPanel { frame.setVisible(true); frame.requestFocus(); frame.toFront(); + frame.addFocusListener(new FocusListener() { + + @Override + public void focusGained(FocusEvent e) { + dirty = true; + } + + @Override + public void focusLost(FocusEvent e) { + + } + }); } @Override @@ -238,8 +244,8 @@ public class MapVision extends JPanel { 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; + int x = (int) (((int) ((mouseX - windowOffsetX))) - (draggedOffsetX)) << 2; + int y = (int) (((int) ((mouseY - windowOffsetY))) - (draggedOffsetY)) << 2; String text = " [" + x+ ", " + y + "]"; if (realname) text = complex.getLandBiomeStream().get(x, y).getLoadKey().toUpperCase() + text; @@ -294,14 +300,12 @@ public class MapVision extends JPanel { 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 x = (int) Math.floor((tile.getX() << TILE_SIZE_R) / scale + offsetX); + int y = (int) Math.floor((tile.getY() << TILE_SIZE_R) / scale + offsetY); int size = (int) (TILE_SIZE / scale); - int off = (int) (TILE_SIZE % scale); - gx.drawImage(tile.getImage(), x, y, size, size, null); + int off = (int) Math.round((TILE_SIZE % scale)); + gx.drawImage(tile.getImage(), x, y, size + off, size + off,null); } private Runnable sleepTask = new Runnable() { @@ -362,16 +366,13 @@ public class MapVision extends JPanel { lastTileWidth = checkSizeX; generateSpiral(newSize); - Set checked = new HashSet<>(); - Set clone = new HashSet(visibleTiles.stream().map((t) -> - getTileId(t.getX(), t.getY())) - .collect(Collectors.toSet())); //Clone the visible tiles + Set toRemove = new HashSet(visibleTiles); //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; + debugBorder[0] = -checkSizeX + centerTileX - 1; + debugBorder[1] = -checkSizeY + centerTileY - 1; + debugBorder[2] = checkSizeX + centerTileX; + debugBorder[3] = checkSizeY + centerTileY; } for (short[] coords : spiral) { //Start from the center of the spiral and work outwards to find new tiles to queue @@ -379,10 +380,10 @@ public class MapVision extends JPanel { short y = (short)(coords[1] + centerTileY); //When it goes offscreen, don't queue the tile by continuing - if (Math.abs(coords[0]) > checkSizeX + 1) { + if (x > checkSizeX + centerTileX || x < -checkSizeX + centerTileX - 1) { continue; } - if (Math.abs(coords[1]) > checkSizeY + 1) { + if (y > checkSizeY + centerTileY || y < -checkSizeY + centerTileY - 1) { continue; } @@ -393,13 +394,16 @@ public class MapVision extends JPanel { short[] c = getTileCoords(id); queue(c[0], c[1]); //Queue for creation } else { - checked.add(id); + Tile t = tiles.get(id); + toRemove.remove(t); //Make sure this tile isn't removed + + if (!visibleTiles.contains(t)) { + visibleTiles.add(t); //Make sure it's visible again if it isn't + } } } - clone.removeAll(checked); //Remove the tiles that we know are onscreen - - queueForRemoval(clone); + queueForRemoval(toRemove); //Queue all tiles not on screen for removal stopwatch.end(); roll.put(stopwatch.getMillis()); @@ -457,11 +461,9 @@ public class MapVision extends JPanel { /** * Pend tiles for removal from the screen */ - public void queueForRemoval(Collection ids) { + public void queueForRemoval(Collection tile) { J.a(() -> { - for (int id : ids) { - Tile t = tiles.get(id); - + for (Tile t : tile) { if (t != null) { visibleTiles.remove(t); } @@ -471,10 +473,9 @@ public class MapVision extends JPanel { //TODO Change from using the async task system as it may be putting strain on the server from being called so often J.a(() -> { //Remove it completely from memory after 5 seconds if it's still not visible - for (int id : ids) { - Tile t = tiles.get(id); + for (Tile t : tile) { if (t != null && !visibleTiles.contains(t)) { - tiles.remove(id); + tiles.remove(t); } } @@ -499,7 +500,7 @@ public class MapVision extends JPanel { * @return */ public int getTileId(short tileX, short tileY) { - return tileX + tileY << 16; + return (tileX << 16) | (tileY & 0xFFFF); } /** @@ -508,7 +509,7 @@ public class MapVision extends JPanel { * @return */ public short[] getTileCoords(int id) { - return new short[] {(short) (id & 0x0000FFFF), (short) (id >> 16)}; + return new short[] {(short)(id >> 16), (short) id}; } /** @@ -578,7 +579,7 @@ public class MapVision extends JPanel { threadId++; Thread t = new Thread(r); t.setName("Iris Map Renderer " + threadId); - t.setPriority(Thread.MIN_PRIORITY); + t.setPriority(4); t.setDaemon(true); t.setUncaughtExceptionHandler((et, e) -> { @@ -591,7 +592,7 @@ public class MapVision extends JPanel { }; //Our thread pool that draws the tiles for us - private final ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(8, factory); + private final ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(3, factory); } diff --git a/src/main/java/com/volmit/iris/map/RenderType.java b/src/main/java/com/volmit/iris/map/RenderType.java index 991d8dd43..3193eb49f 100644 --- a/src/main/java/com/volmit/iris/map/RenderType.java +++ b/src/main/java/com/volmit/iris/map/RenderType.java @@ -1,5 +1,5 @@ package com.volmit.iris.map; public enum RenderType { - BIOME_LAND, REGION, CAVE_LAND + BIOME_LAND, REGION, CAVE_LAND, HEIGHT } diff --git a/src/main/java/com/volmit/iris/map/Tile.java b/src/main/java/com/volmit/iris/map/Tile.java index 43506bca4..428c08d2a 100644 --- a/src/main/java/com/volmit/iris/map/Tile.java +++ b/src/main/java/com/volmit/iris/map/Tile.java @@ -7,6 +7,7 @@ import com.volmit.iris.scaffold.stream.ProceduralStream; import lombok.Getter; import lombok.Setter; +import java.awt.Color; import java.awt.image.BufferedImage; import java.util.Set; import java.util.function.BiFunction; @@ -55,17 +56,15 @@ public class Tile { public boolean render(IrisComplex complex, RenderType type) { BufferedImage newImage = new BufferedImage(128, 128, BufferedImage.TYPE_INT_RGB); - ProceduralStream stream; BiFunction getColor; if (type == RenderType.BIOME_LAND) { - stream = complex.getLandBiomeStream(); - getColor = (x, z) -> ((ProceduralStream)stream).get(x, z).getColor().getAsRGB(); + getColor = (x, z) -> complex.getLandBiomeStream().get(x, z).getColor().getRGB(); } else if (type == RenderType.REGION) { - stream = complex.getRegionStream(); - getColor = (x, z) -> ((ProceduralStream)stream).get(x, z).getColor().getColor().getRGB(); + getColor = (x, z) -> complex.getRegionStream().get(x, z).getColor(complex).getRGB(); + } else if (type == RenderType.HEIGHT) { + getColor = (x, z) -> Color.getHSBColor(complex.getHeightStream().get(x, z).floatValue(), 100, 100).getRGB(); } else { - stream = complex.getCaveBiomeStream(); - getColor = (x, z) -> ((ProceduralStream)stream).get(x, z).getColor().getAsRGB(); + getColor = (x, z) -> complex.getCaveBiomeStream().get(x, z).getColor().getRGB(); } for (int i = 0; i < 128; i++) { diff --git a/src/main/java/com/volmit/iris/object/IrisBiome.java b/src/main/java/com/volmit/iris/object/IrisBiome.java index 8e79ca688..b36266f2b 100644 --- a/src/main/java/com/volmit/iris/object/IrisBiome.java +++ b/src/main/java/com/volmit/iris/object/IrisBiome.java @@ -92,7 +92,7 @@ public class IrisBiome extends IrisRegistrant implements IRare { @DontObfuscate @Desc("A color for visualizing this biome with a color. I.e. #F13AF5. This will show up on the map.") - private IrisColor color = null; + private String color = null; @Required @DontObfuscate @@ -187,7 +187,7 @@ public class IrisBiome extends IrisRegistrant implements IRare { private final transient AtomicCache> genCacheMin = new AtomicCache<>(); private final transient AtomicCache> surfaceObjectsCache = new AtomicCache<>(false); private final transient AtomicCache> carveObjectsCache = new AtomicCache<>(false); - private final transient AtomicCache cacheColor = new AtomicCache<>(true); + private final transient AtomicCache cacheColor = new AtomicCache<>(); private final transient AtomicCache childrenCell = new AtomicCache<>(); private final transient AtomicCache biomeGenerator = new AtomicCache<>(); private final transient AtomicCache maxHeight = new AtomicCache<>(); @@ -585,25 +585,28 @@ public class IrisBiome extends IrisRegistrant implements IRare { 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()); + public Color getColor() { + return this.cacheColor.aquire(() -> { + if (this.color == null) { + RandomColor randomColor = new RandomColor(getName().hashCode()); + if (this.getVanillaDerivative() == null) { + Iris.warn("No vanilla biome found for " + getName()); + return new Color(randomColor.randomColor()); + } + 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); + + return new Color(newColorI); } - 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; + try { + return Color.decode(this.color); + } catch (NumberFormatException e) { + Iris.warn("Could not parse color \"" + this.color + "\" for biome " + getName()); + return new Color(new RandomColor(getName().hashCode()).randomColor()); + } + }); } } diff --git a/src/main/java/com/volmit/iris/object/IrisColor.java b/src/main/java/com/volmit/iris/object/IrisColor.java index 9d648371d..8774bd713 100644 --- a/src/main/java/com/volmit/iris/object/IrisColor.java +++ b/src/main/java/com/volmit/iris/object/IrisColor.java @@ -11,6 +11,7 @@ import lombok.experimental.Accessors; import java.awt.*; +@Deprecated(forRemoval = true) @Accessors(chain = true) @NoArgsConstructor @Desc("Represents a color") diff --git a/src/main/java/com/volmit/iris/object/IrisRegion.java b/src/main/java/com/volmit/iris/object/IrisRegion.java index f7ebc8b81..29e435176 100644 --- a/src/main/java/com/volmit/iris/object/IrisRegion.java +++ b/src/main/java/com/volmit/iris/object/IrisRegion.java @@ -1,5 +1,6 @@ package com.volmit.iris.object; +import com.volmit.iris.Iris; import com.volmit.iris.generator.noise.CNG; import com.volmit.iris.manager.IrisDataManager; import com.volmit.iris.scaffold.cache.AtomicCache; @@ -11,6 +12,9 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; +import java.awt.Color; +import java.util.Random; + @Accessors(chain = true) @NoArgsConstructor @AllArgsConstructor @@ -217,7 +221,7 @@ public class IrisRegion extends IrisRegistrant implements IRare { @DontObfuscate @Desc("A color for visualizing this region with a color. I.e. #F13AF5. This will show up on the map.") - private IrisColor color = null; + private String color = null; private final transient AtomicCache> surfaceObjectsCache = new AtomicCache<>(); private final transient AtomicCache> carveObjectsCache = new AtomicCache<>(); @@ -233,6 +237,7 @@ public class IrisRegion extends IrisRegistrant implements IRare { private final transient AtomicCache lakeGen = new AtomicCache<>(); private final transient AtomicCache riverGen = new AtomicCache<>(); private final transient AtomicCache riverChanceGen = new AtomicCache<>(); + private final transient AtomicCache cacheColor = new AtomicCache<>(); public String getName() { return name; @@ -518,4 +523,45 @@ public class IrisRegion extends IrisRegistrant implements IRare { return b.v(); } + + public Color getColor(DataProvider dataProvider) { + + return this.cacheColor.aquire(() -> { + if (this.color == null) { + Random rand = new Random(getName().hashCode() + getAllBiomeIds().hashCode()); + RandomColor randomColor = new RandomColor(rand); + + KList biomes = getRealLandBiomes(dataProvider); + + while (biomes.size() > 0) { + int index = rand.nextInt(biomes.size()); + IrisBiome biome = biomes.get(index); + + if (biome.getVanillaDerivative() != null) { + RandomColor.Color col = VanillaBiomeMap.getColorType(biome.getVanillaDerivative()); + RandomColor.Luminosity lum = VanillaBiomeMap.getColorLuminosity(biome.getVanillaDerivative()); + RandomColor.SaturationType sat = VanillaBiomeMap.getColorSaturatiom(biome.getVanillaDerivative()); + int newColorI = randomColor.randomColor(col, col == RandomColor.Color.MONOCHROME ? RandomColor.SaturationType.MONOCHROME : sat, lum); + return new Color(newColorI); + } + + biomes.remove(index); + } + + Iris.warn("Couldn't find a suitable color for region " + getName()); + return new Color(new RandomColor(rand).randomColor()); + } + + try { + return Color.decode(this.color); + } catch (NumberFormatException e) { + Iris.warn("Could not parse color \"" + this.color + "\" for region " + getName()); + return Color.WHITE; + } + }); + } + + public void pickRandomColor(DataProvider data) { + + } } diff --git a/src/main/java/com/volmit/iris/scaffold/engine/Engine.java b/src/main/java/com/volmit/iris/scaffold/engine/Engine.java index ea2fc678a..e0dbc0803 100644 --- a/src/main/java/com/volmit/iris/scaffold/engine/Engine.java +++ b/src/main/java/com/volmit/iris/scaffold/engine/Engine.java @@ -91,10 +91,10 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro IrisBiome biome = getSurfaceBiome((int) x, (int) z); int height = getHeight((int) x, (int) z); double heightFactor = M.lerpInverse(0, getHeight(), height); - IrisColor irc = region.getColor(); - IrisColor ibc = biome.getColor(); - Color rc = irc != null ? irc.getColor() : Color.GREEN.darker(); - Color bc = ibc != null ? ibc.getColor() : biome.isAquatic() ? Color.BLUE : Color.YELLOW; + Color irc = region.getColor(this.getFramework().getComplex()); + Color ibc = biome.getColor(); + Color rc = irc != null ? irc : Color.GREEN.darker(); + Color bc = ibc != null ? ibc : biome.isAquatic() ? Color.BLUE : Color.YELLOW; Color f = IrisColor.blend(rc, bc, bc, Color.getHSBColor(0, 0, (float) heightFactor)); return f; diff --git a/src/main/java/com/volmit/iris/util/RandomColor.java b/src/main/java/com/volmit/iris/util/RandomColor.java index 23e11ffa9..be0ec0b78 100644 --- a/src/main/java/com/volmit/iris/util/RandomColor.java +++ b/src/main/java/com/volmit/iris/util/RandomColor.java @@ -130,6 +130,11 @@ public class RandomColor { random.setSeed(seed); } + public RandomColor(Random random) { + loadColorBounds(); + this.random = random; + } + 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(); }