From 753b69726ab326a21d9ab54876661ac01e8471c2 Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Thu, 15 Jul 2021 07:58:20 -0400 Subject: [PATCH] Mapping overload --- .../volmit/iris/manager/gui/IrisRenderer.java | 22 +- .../volmit/iris/manager/gui/IrisVision.java | 381 +++++++++++++++--- .../java/com/volmit/iris/map/MapVision.java | 5 +- .../scaffold/hunk/io/HunkRegionSlice.java | 2 +- .../iris/scaffold/parallel/MultiBurst.java | 1 - 5 files changed, 341 insertions(+), 70 deletions(-) diff --git a/src/main/java/com/volmit/iris/manager/gui/IrisRenderer.java b/src/main/java/com/volmit/iris/manager/gui/IrisRenderer.java index 085b443b3..3afd5ce86 100644 --- a/src/main/java/com/volmit/iris/manager/gui/IrisRenderer.java +++ b/src/main/java/com/volmit/iris/manager/gui/IrisRenderer.java @@ -18,22 +18,36 @@ package com.volmit.iris.manager.gui; +import com.volmit.iris.map.RenderType; import com.volmit.iris.scaffold.engine.Engine; import com.volmit.iris.util.IrisInterpolation; import org.bukkit.Material; +import java.awt.*; import java.awt.image.BufferedImage; +import java.util.function.BiFunction; @SuppressWarnings("ClassCanBeRecord") public class IrisRenderer { - private final Renderer renderer; + private final Engine renderer; - public IrisRenderer(Renderer renderer) { + public IrisRenderer(Engine renderer) { this.renderer = renderer; } - public BufferedImage render(double sx, double sz, double size, int resolution) { + public BufferedImage render(double sx, double sz, double size, int resolution, RenderType currentType) { BufferedImage image = new BufferedImage(resolution, resolution, BufferedImage.TYPE_INT_RGB); + BiFunction colorFunction = (d, dx) -> Color.black.getRGB(); + + switch (currentType) { + case BIOME, DECORATOR_LOAD, OBJECT_LOAD, LAYER_LOAD -> colorFunction = (x, z) -> renderer.getFramework().getComplex().getTrueBiomeStream().get(x, z).getColor(renderer, currentType).getRGB(); + case BIOME_LAND -> colorFunction = (x, z) -> renderer.getFramework().getComplex().getLandBiomeStream().get(x, z).getColor(renderer, currentType).getRGB(); + case BIOME_SEA -> colorFunction = (x, z) -> renderer.getFramework().getComplex().getSeaBiomeStream().get(x, z).getColor(renderer, currentType).getRGB(); + case REGION -> colorFunction = (x, z) -> renderer.getFramework().getComplex().getRegionStream().get(x, z).getColor(renderer.getFramework().getComplex(), currentType).getRGB(); + case CAVE_LAND -> colorFunction = (x, z) -> renderer.getFramework().getComplex().getCaveBiomeStream().get(x, z).getColor(renderer, currentType).getRGB(); + case HEIGHT -> colorFunction = (x, z) -> Color.getHSBColor(renderer.getFramework().getComplex().getHeightStream().get(x, z).floatValue(), 100, 100).getRGB(); + } + double x, z; int i, j; for (i = 0; i < resolution; i++) { @@ -41,7 +55,7 @@ public class IrisRenderer { for (j = 0; j < resolution; j++) { z = IrisInterpolation.lerp(sz, sz + size, (double) j / (double) (resolution)); - image.setRGB(i, j, renderer.draw(x, z).getRGB()); + image.setRGB(i, j, colorFunction.apply(x, z)); } } diff --git a/src/main/java/com/volmit/iris/manager/gui/IrisVision.java b/src/main/java/com/volmit/iris/manager/gui/IrisVision.java index 1b85b377f..cbe312b11 100644 --- a/src/main/java/com/volmit/iris/manager/gui/IrisVision.java +++ b/src/main/java/com/volmit/iris/manager/gui/IrisVision.java @@ -19,7 +19,13 @@ package com.volmit.iris.manager.gui; import com.volmit.iris.Iris; +import com.volmit.iris.generator.IrisEngine; +import com.volmit.iris.map.RenderType; +import com.volmit.iris.object.IrisBiome; +import com.volmit.iris.object.IrisRegion; +import com.volmit.iris.scaffold.engine.Engine; import com.volmit.iris.scaffold.engine.IrisAccess; +import com.volmit.iris.scaffold.parallel.MultiBurst; import com.volmit.iris.util.*; import org.bukkit.World; import org.bukkit.entity.Player; @@ -27,33 +33,45 @@ import org.bukkit.entity.Player; import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; +import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.function.BiFunction; -public class IrisVision extends JPanel implements MouseWheelListener { +public class IrisVision extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener { private static final long serialVersionUID = 2094606939770332040L; - private IrisRenderer renderer; + + private RenderType currentType = RenderType.BIOME; + private boolean help = true; + private boolean helpIgnored = false; + private boolean shift = false; + private boolean debug = false; + private boolean follow = false; + private boolean alt = false; private int posX = 0; + private IrisRenderer renderer; private World world; + private double velocity = 0; + private int lowq = 12; private int posZ = 0; private double scale = 128; private double mscale = 1D; private int w = 0; private int h = 0; - private double lx = Double.MAX_VALUE; - private double lz = Double.MAX_VALUE; + private double lx = 0; + private double lz = 0; private double ox = 0; private double oz = 0; + private double hx = 0; + private double hz = 0; private double oxp = 0; private double ozp = 0; + private Engine engine; double tfps = 240D; + int ltc = 3; private final RollingSequence rs = new RollingSequence(512); private final O m = new O<>(); private int tid = 0; @@ -61,7 +79,7 @@ public class IrisVision extends JPanel implements MouseWheelListener { private final KMap fastpositions = new KMap<>(); private final KSet working = new KSet<>(); private final KSet workingfast = new KSet<>(); - private final ExecutorService e = Executors.newFixedThreadPool(24, r -> { + private final ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), r -> { tid++; Thread t = new Thread(r); t.setName("Iris HD Renderer " + tid); @@ -75,7 +93,7 @@ public class IrisVision extends JPanel implements MouseWheelListener { return t; }); - private final ExecutorService eh = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), r -> { + private final ExecutorService eh = Executors.newFixedThreadPool(ltc, r -> { tid++; Thread t = new Thread(r); t.setName("Iris Renderer " + tid); @@ -89,30 +107,130 @@ public class IrisVision extends JPanel implements MouseWheelListener { return t; }); - public IrisVision() { + public IrisVision(JFrame frame) { m.set(8); - renderer = new IrisRenderer(null); rs.put(1); addMouseWheelListener(this); - addMouseMotionListener(new MouseMotionListener() { - @Override - public void mouseMoved(MouseEvent e) { - Point cp = e.getPoint(); - lx = (cp.getX()); - lz = (cp.getY()); - } + addMouseMotionListener(this); + frame.addKeyListener(this); + J.a(() -> { + J.sleep(10000); - @Override - public void mouseDragged(MouseEvent e) { - Point cp = e.getPoint(); - ox += (lx - cp.getX()) * scale; - oz += (lz - cp.getY()) * scale; - lx = cp.getX(); - lz = cp.getY(); + if (!helpIgnored && help) { + help = false; } }); } + @Override + public void mouseMoved(MouseEvent e) { + Point cp = e.getPoint(); + lx = (cp.getX()); + lz = (cp.getY()); + } + + @Override + public void mouseDragged(MouseEvent e) { + Point cp = e.getPoint(); + ox += (lx - cp.getX()) * scale; + oz += (lz - cp.getY()) * scale; + lx = cp.getX(); + lz = cp.getY(); + } + + public int getColor(double wx, double wz) { + BiFunction colorFunction = (d, dx) -> Color.black.getRGB(); + + switch (currentType) { + case BIOME, DECORATOR_LOAD, OBJECT_LOAD, LAYER_LOAD -> colorFunction = (x, z) -> engine.getFramework().getComplex().getTrueBiomeStream().get(x, z).getColor(engine, currentType).getRGB(); + case BIOME_LAND -> colorFunction = (x, z) -> engine.getFramework().getComplex().getLandBiomeStream().get(x, z).getColor(engine, currentType).getRGB(); + case BIOME_SEA -> colorFunction = (x, z) -> engine.getFramework().getComplex().getSeaBiomeStream().get(x, z).getColor(engine, currentType).getRGB(); + case REGION -> colorFunction = (x, z) -> engine.getFramework().getComplex().getRegionStream().get(x, z).getColor(engine.getFramework().getComplex(), currentType).getRGB(); + case CAVE_LAND -> colorFunction = (x, z) -> engine.getFramework().getComplex().getCaveBiomeStream().get(x, z).getColor(engine, currentType).getRGB(); + case HEIGHT -> colorFunction = (x, z) -> Color.getHSBColor(engine.getFramework().getComplex().getHeightStream().get(x, z).floatValue(), 100, 100).getRGB(); + } + + return colorFunction.apply(wx, wz); + } + + @Override + public void keyTyped(KeyEvent e) { + int currentMode = currentType.ordinal(); + + if (e.getKeyCode() == KeyEvent.VK_M) { + currentType = RenderType.values()[(currentMode+1) % RenderType.values().length]; + dump(); + } + + if (e.getKeyCode() == KeyEvent.VK_R) { + dump(); + return; + } + + if (e.getKeyCode() == KeyEvent.VK_EQUALS) { + + return; + } + if (e.getKeyCode() == KeyEvent.VK_MINUS) { + + return; + } + + + for(RenderType i : RenderType.values()) + { + if (e.getKeyChar() == String.valueOf(i.ordinal()+1).charAt(0)) { + if(i.ordinal() != currentMode) + { + currentType = i; + dump(); + return; + } + } + } + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + shift = true; + } else if (e.getKeyCode() == KeyEvent.VK_SEMICOLON) { + debug = true; + } else if (e.getKeyCode() == KeyEvent.VK_SLASH) { + help = true; + helpIgnored = true; + }else if (e.getKeyCode() == KeyEvent.VK_ALT) { + alt = true; + } + } + + @Override + public void keyReleased(KeyEvent e) { + + if (e.getKeyCode() == KeyEvent.VK_SEMICOLON) { + debug = false; + } else if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + shift = false; + } else if (e.getKeyCode() == KeyEvent.VK_SLASH) { + help = false; + helpIgnored = true; + }else if (e.getKeyCode() == KeyEvent.VK_ALT) { + alt = false; + } + + + if (e.getKeyCode() == KeyEvent.VK_F) { + Iris.info("FOLLOW TOGGLE"); + follow = !follow; + } + } + + private void dump() + { + positions.clear(); + fastpositions.clear(); + } + public BufferedImage getTile(KSet fg, int div, int x, int z, O m) { BlockPosition key = new BlockPosition((int) mscale, Math.floorDiv(x, div), Math.floorDiv(z, div)); fg.add(key); @@ -125,14 +243,14 @@ public class IrisVision extends JPanel implements MouseWheelListener { if (!working.contains(key) && working.size() < 9) { m.set(m.get() - 1); - if (m.get() >= 0) { + if (m.get() >= 0 && velocity < 50) { working.add(key); double mk = mscale; double mkd = scale; e.submit(() -> { PrecisionStopwatch ps = PrecisionStopwatch.start(); - BufferedImage b = renderer.render(x * mscale, z * mscale, div * mscale, div); + BufferedImage b = renderer.render(x * mscale, z * mscale, div * mscale, div, currentType); rs.put(ps.getMilliseconds()); working.remove(key); @@ -146,71 +264,88 @@ public class IrisVision extends JPanel implements MouseWheelListener { return fastpositions.get(key); } - if (workingfast.contains(key)) { + if (workingfast.contains(key) || workingfast.size() > Runtime.getRuntime().availableProcessors()) { return null; } - m.set(m.get() - 1); + workingfast.add(key); + double mk = mscale; + double mkd = scale; + eh.submit(() -> + { + PrecisionStopwatch ps = PrecisionStopwatch.start(); + BufferedImage b = renderer.render(x * mscale, z * mscale, div * mscale, div / lowq, currentType); + rs.put(ps.getMilliseconds()); + workingfast.remove(key); - if (m.get() >= 0) { - workingfast.add(key); - double mk = mscale; - double mkd = scale; - eh.submit(() -> - { - PrecisionStopwatch ps = PrecisionStopwatch.start(); - BufferedImage b = renderer.render(x * mscale, z * mscale, div * mscale, div / 12); - rs.put(ps.getMilliseconds()); - workingfast.remove(key); - - if (mk == mscale && mkd == scale) { - fastpositions.put(key, b); - } - }); - } + if (mk == mscale && mkd == scale) { + fastpositions.put(key, b); + } + }); return null; } private double getWorldX(double screenX) { - return (screenX + oxp) * mscale; + return (mscale * screenX) + ((oxp / scale) * mscale); } private double getWorldZ(double screenZ) { - return (screenZ + ozp) * mscale; + return (mscale * screenZ) + ((ozp / scale) * mscale); } private double getScreenX(double x) { - return (oxp + x) / mscale; + return (x / mscale) - ((oxp / scale)); } private double getScreenZ(double z) { - return (ozp + z) / mscale; + return (z / mscale) - ((ozp / scale)); } @Override public void paint(Graphics gx) { if (ox < oxp) { - oxp -= Math.abs(ox - oxp) * 0.36; + velocity = Math.abs(ox - oxp) * 0.06; + oxp -= velocity; } if (ox > oxp) { - oxp += Math.abs(oxp - ox) * 0.36; + velocity = Math.abs(oxp - ox) * 0.06; + oxp += velocity; } if (oz < ozp) { - ozp -= Math.abs(oz - ozp) * 0.36; + velocity = Math.abs(oz - ozp) * 0.06; + ozp -= velocity; } if (oz > ozp) { - ozp += Math.abs(ozp - oz) * 0.36; + velocity = Math.abs(ozp - oz) * 0.06; + ozp += velocity; } + if (lx < hx) { + hx -= Math.abs(lx - hx) * 0.06; + } + + if (lx > hx) { + hx += Math.abs(hx - lx) * 0.06; + } + + if (lz < hz) { + hz -= Math.abs(lz - hz) * 0.06; + } + + if (lz > hz) { + hz += Math.abs(hz - lz) * 0.06; + } + + lowq = Math.max(Math.min((int)M.lerp(8, 28, velocity / 1000D), 28), 8); PrecisionStopwatch p = PrecisionStopwatch.start(); Graphics2D g = (Graphics2D) gx; w = getWidth(); h = getHeight(); double vscale = scale; - scale = w / 16D; + scale = w / 12D; if (scale != vscale) { positions.clear(); @@ -248,10 +383,7 @@ public class IrisVision extends JPanel implements MouseWheelListener { } } - for (Player i : world.getPlayers()) { - g.setColor(Color.getHSBColor(RNG.r.f(), 1f, 1f)); - g.drawRect((int) getScreenX(i.getLocation().getX()), (int) getScreenZ(i.getLocation().getZ()), 4, 4); - } + renderOverlays(g); if (!isVisible()) { return; @@ -272,10 +404,135 @@ public class IrisVision extends JPanel implements MouseWheelListener { }); } - private static void createAndShowGUI(Renderer r, int s, World world) { + private void renderOverlays(Graphics2D g) { + if(help) + { + renderOverlayHelp(g); + } + + else if(debug) + { + renderOverlayDebug(g); + } + + renderHoverOverlay(g, shift); + + Player b = null; + + for(Player i : world.getPlayers()) + { + b = i; + renderPosition(g, i.getLocation().getX(), i.getLocation().getZ()); + } + + if(follow && b != null) + { + animateTo(b.getLocation().getX(), b.getLocation().getZ()); + drawCardTL(g, new KList<>("Following " + b.getName())); + } + } + + private void animateTo(double wx, double wz) { + double sx = getScreenX(wx); + double sz = getScreenZ(wz); + double cx = getWorldX(getWidth()/2); + double cz = getWorldZ(getHeight()/2); + ox += (wx - cx) * 0.77; + oz += (wz - cz) * 0.77; + } + + private void renderPosition(Graphics2D g, double x, double z) + { + g.setColor(Color.orange); + g.fillRoundRect((int)getScreenX(x) - 15, (int)getScreenZ(z) - 15, 30, 30, 15, 15); + g.setColor(Color.blue.brighter().brighter()); + g.fillRoundRect((int)getScreenX(x) - 10, (int)getScreenZ(z) - 10, 20, 20, 10, 10); + } + + private void renderHoverOverlay(Graphics2D g, boolean detailed) { + IrisBiome biome = engine.getFramework().getComplex().getTrueBiomeStream().get(getWorldX(hx), getWorldZ(hz)); + IrisRegion region = engine.getFramework().getComplex().getRegionStream().get(getWorldX(hx), getWorldZ(hz)); + KList l = new KList<>(); + l.add(biome.getName()); + if(detailed) + { + l.add("Block " + (int)getWorldX(hx) + ", " + (int)getWorldZ(hz)); + l.add("Chunk " + ((int)getWorldX(hx)>>4) + ", " + ((int)getWorldZ(hz)>>4)); + l.add("Region " + (((int)getWorldX(hx)>>4)>>5) + ", " + (((int)getWorldZ(hz)>>4)>>5)); + l.add("Key: " + biome.getLoadKey()); + l.add("File: " + biome.getLoadFile()); + l.add("Region: " + region.getName() + "(" + region.getLoadKey() + ")"); + } + + drawCardAt((float)hx, (float)hz, g, l); + } + + private void renderOverlayDebug(Graphics2D g) { + KList l = new KList<>(); + l.add("Velocity: " + velocity); + + drawCardTL(g, l); + } + + private void renderOverlayHelp(Graphics2D g) { + KList l = new KList<>(); + l.add("/ to show this help screen"); + l.add("R to repaint the screen"); + l.add("F to follow first player"); + l.add("+/- to Change Zoom"); + l.add("M to cycle render modes"); + + int ff = 0; + for (RenderType i : RenderType.values()) { + ff++; + l.add(ff + " to view " + Form.capitalizeWords(i.name().toLowerCase().replaceAll("\\Q_\\E", " "))); + } + + l.add("Shift for additional biome details (at cursor)"); + l.add("Shift + Click to teleport to location"); + l.add("Alt + Click to open biome in VSCode"); + drawCardTL(g, l); + } + + private void drawCardTL(Graphics2D g, KList text) + { + drawCardAt(0, 0, g, text); + } + + private void drawCardAt(float x, float y, Graphics2D g, KList text) + { + int h = 0; + int w = 0; + + for(String i : text) + { + h += g.getFontMetrics().getHeight(); + w = Math.max(w, g.getFontMetrics().stringWidth(i)); + } + + w += 28; + h += 28; + + g.setColor(Color.darkGray); + g.fillRect((int)x + 7 + 2, (int)y + 7 + 2, w + 7, h + 7); // Shadow + g.setColor(Color.gray); + g.fillRect((int)x + 7 + 1, (int)y + 7 + 1, w + 7, h + 7); // Shadow + g.setColor(Color.white); + g.fillRect((int)x + 7, (int)y + 7, w + 7, h + 7); + + g.setColor(Color.black); + int m = 0; + for(String i : text) + { + g.drawString(i, x + 14, y + 14 + (++m * g.getFontMetrics().getHeight())); + } + } + + private static void createAndShowGUI(Engine r, int s, World world) { JFrame frame = new JFrame("Vision"); - IrisVision nv = new IrisVision(); + IrisVision nv = new IrisVision(frame); nv.world = world; + nv.engine = r; nv.renderer = new IrisRenderer(r); frame.add(nv); frame.setSize(1440, 820); @@ -293,7 +550,7 @@ public class IrisVision extends JPanel implements MouseWheelListener { public static void launch(IrisAccess g, int i) { J.a(() -> - createAndShowGUI((x, z) -> g.getEngineAccess(i).draw(x, z), i, g.getCompound().getWorld())); + createAndShowGUI(g.getCompound().getEngine(i), i, g.getCompound().getWorld())); } public void mouseWheelMoved(MouseWheelEvent e) { diff --git a/src/main/java/com/volmit/iris/map/MapVision.java b/src/main/java/com/volmit/iris/map/MapVision.java index 72275296c..514d59262 100644 --- a/src/main/java/com/volmit/iris/map/MapVision.java +++ b/src/main/java/com/volmit/iris/map/MapVision.java @@ -54,11 +54,12 @@ public class MapVision extends JPanel { private boolean help = true; private boolean helpIgnored = false; - private boolean dirty = true; //Whether to repaint textures - private double scale = 1; private boolean shift = false; private boolean alt = false; + private boolean dirty = true; //Whether to repaint textures + private double scale = 1; + private final KMap tiles = new KMap<>(); private final Set visibleTiles = new ConcurrentSet<>(); //Tiles that are visible on screen diff --git a/src/main/java/com/volmit/iris/scaffold/hunk/io/HunkRegionSlice.java b/src/main/java/com/volmit/iris/scaffold/hunk/io/HunkRegionSlice.java index a8f6645b8..a3792144b 100644 --- a/src/main/java/com/volmit/iris/scaffold/hunk/io/HunkRegionSlice.java +++ b/src/main/java/com/volmit/iris/scaffold/hunk/io/HunkRegionSlice.java @@ -90,7 +90,7 @@ public class HunkRegionSlice { } public synchronized void save() { - BurstExecutor e = MultiBurst.burstAux.burst(); + BurstExecutor e = MultiBurst.burst.burst(); for (ChunkPosition i : save.copy()) { if (i == null) { continue; diff --git a/src/main/java/com/volmit/iris/scaffold/parallel/MultiBurst.java b/src/main/java/com/volmit/iris/scaffold/parallel/MultiBurst.java index 5d9ba0089..6a93bcd29 100644 --- a/src/main/java/com/volmit/iris/scaffold/parallel/MultiBurst.java +++ b/src/main/java/com/volmit/iris/scaffold/parallel/MultiBurst.java @@ -26,7 +26,6 @@ import java.util.concurrent.Executors; public class MultiBurst { public static final MultiBurst burst = new MultiBurst("Iris Burster", 10, Runtime.getRuntime().availableProcessors()); - public static final MultiBurst burstAux = new MultiBurst("Iris Aux Burster", 8, Runtime.getRuntime().availableProcessors()/2); private final ExecutorService service; private ExecutorService syncService; private int tid;