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 cbe312b11..101358cd8 100644 --- a/src/main/java/com/volmit/iris/manager/gui/IrisVision.java +++ b/src/main/java/com/volmit/iris/manager/gui/IrisVision.java @@ -19,36 +19,48 @@ package com.volmit.iris.manager.gui; import com.volmit.iris.Iris; +import com.volmit.iris.generator.IrisComplex; 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.object.IrisRegistrant; 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.Location; import org.bukkit.World; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; import javax.imageio.ImageIO; import javax.swing.*; +import javax.swing.event.MouseInputListener; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.BiFunction; -public class IrisVision extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener { +public class IrisVision extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener, MouseInputListener { private static final long serialVersionUID = 2094606939770332040L; private RenderType currentType = RenderType.BIOME; private boolean help = true; private boolean helpIgnored = false; private boolean shift = false; + private Player player = null; private boolean debug = false; + private boolean control = false; + private boolean eco = false; + private boolean lowtile = false; private boolean follow = false; private boolean alt = false; private int posX = 0; @@ -63,6 +75,7 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene private int h = 0; private double lx = 0; private double lz = 0; + private KList lastEntities = new KList<>(); private double ox = 0; private double oz = 0; private double hx = 0; @@ -70,8 +83,10 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene private double oxp = 0; private double ozp = 0; private Engine engine; + private KMap notifications = new KMap<>(); double tfps = 240D; int ltc = 3; + private ChronoLatch centities = new ChronoLatch(1000); private final RollingSequence rs = new RollingSequence(512); private final O m = new O<>(); private int tid = 0; @@ -106,12 +121,14 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene return t; }); + private BufferedImage texture; public IrisVision(JFrame frame) { m.set(8); rs.put(1); addMouseWheelListener(this); addMouseMotionListener(this); + addMouseListener(this); frame.addKeyListener(this); J.a(() -> { J.sleep(10000); @@ -152,30 +169,115 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene return colorFunction.apply(wx, wz); } + + public void notify(String s) + { + notifications.put(s, M.ms() + 2500); + } @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(); + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + shift = true; + } + if (e.getKeyCode() == KeyEvent.VK_CONTROL) { + control = true; + }if (e.getKeyCode() == KeyEvent.VK_SEMICOLON) { + debug = true; + } if (e.getKeyCode() == KeyEvent.VK_SLASH) { + help = true; + helpIgnored = true; + } if (e.getKeyCode() == KeyEvent.VK_ALT) { + alt = true; + } + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SEMICOLON) { + debug = false; + } + if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + shift = false; + } + + if (e.getKeyCode() == KeyEvent.VK_CONTROL) { + control = false; + } + if (e.getKeyCode() == KeyEvent.VK_SLASH) { + help = false; + helpIgnored = true; + } if (e.getKeyCode() == KeyEvent.VK_ALT) { + alt = false; + } + + // Pushes + if (e.getKeyCode() == KeyEvent.VK_F) { + follow = !follow; + + if(player != null && follow) + { + notify("Following " + player.getName() + ". Press F to disable"); + } + + else if(follow) + { + notify("Can't follow, no one is in the world"); + follow = false; + } + + else + { + notify("Follow Off"); + } + + return; } if (e.getKeyCode() == KeyEvent.VK_R) { dump(); + notify("Refreshing Chunks"); return; } + if (e.getKeyCode() == KeyEvent.VK_P) { + lowtile = !lowtile; + dump(); + notify("Rendering "+(lowtile ? "Low" : "High")+" Quality Tiles"); + return; + } + if (e.getKeyCode() == KeyEvent.VK_E) { + eco = !eco; + dump(); + notify("Using " + (eco ? "60" : "Uncapped") + " FPS Limit"); + return; + } if (e.getKeyCode() == KeyEvent.VK_EQUALS) { - + mscale = mscale + ((0.044 * mscale) * -3); + mscale = Math.max(mscale, 0.00001); + dump(); return; } if (e.getKeyCode() == KeyEvent.VK_MINUS) { - + mscale = mscale + ((0.044 * mscale) * 3); + mscale = Math.max(mscale, 0.00001); + dump(); return; } + if (e.getKeyCode() == KeyEvent.VK_BACK_SLASH) { + mscale = 1D; + dump(); + notify("Zoom Reset"); + return; + } + + int currentMode = currentType.ordinal(); for(RenderType i : RenderType.values()) { @@ -184,44 +286,16 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene { currentType = i; dump(); + notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " "))); 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; + if (e.getKeyCode() == KeyEvent.VK_M) { + currentType = RenderType.values()[(currentMode+1) % RenderType.values().length]; + notify("Rendering " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " "))); + dump(); } } @@ -250,7 +324,7 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene e.submit(() -> { PrecisionStopwatch ps = PrecisionStopwatch.start(); - BufferedImage b = renderer.render(x * mscale, z * mscale, div * mscale, div, currentType); + BufferedImage b = renderer.render(x * mscale, z * mscale, div * mscale, div / (lowtile ? 3 : 1), currentType); rs.put(ps.getMilliseconds()); working.remove(key); @@ -304,41 +378,51 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene @Override public void paint(Graphics gx) { if (ox < oxp) { - velocity = Math.abs(ox - oxp) * 0.06; + velocity = Math.abs(ox - oxp) * 0.36; oxp -= velocity; } if (ox > oxp) { - velocity = Math.abs(oxp - ox) * 0.06; + velocity = Math.abs(oxp - ox) * 0.36; oxp += velocity; } if (oz < ozp) { - velocity = Math.abs(oz - ozp) * 0.06; + velocity = Math.abs(oz - ozp) * 0.36; ozp -= velocity; } if (oz > ozp) { - velocity = Math.abs(ozp - oz) * 0.06; + velocity = Math.abs(ozp - oz) * 0.36; ozp += velocity; } if (lx < hx) { - hx -= Math.abs(lx - hx) * 0.06; + hx -= Math.abs(lx - hx) * 0.36; } if (lx > hx) { - hx += Math.abs(hx - lx) * 0.06; + hx += Math.abs(hx - lx) * 0.36; } if (lz < hz) { - hz -= Math.abs(lz - hz) * 0.06; + hz -= Math.abs(lz - hz) * 0.36; } if (lz > hz) { - hz += Math.abs(hz - lz) * 0.06; + hz += Math.abs(hz - lz) * 0.36; } + if(centities.flip()) + { + J.s(() -> { + synchronized (lastEntities) + { + lastEntities.clear(); + lastEntities.addAll(world.getEntitiesByClass(LivingEntity.class)); + } + }); + } lowq = Math.max(Math.min((int)M.lerp(8, 28, velocity / 1000D), 28), 8); PrecisionStopwatch p = PrecisionStopwatch.start(); Graphics2D g = (Graphics2D) gx; @@ -383,6 +467,7 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene } } + hanleFollow(); renderOverlays(g); if (!isVisible()) { @@ -399,12 +484,21 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene J.a(() -> { - J.sleep(1); + J.sleep(eco ? 15 : 1); repaint(); }); } + private void hanleFollow() { + if(follow && player != null) + { + animateTo(player.getLocation().getX(), player.getLocation().getZ()); + } + } + private void renderOverlays(Graphics2D g) { + renderPlayer(g); + if(help) { renderOverlayHelp(g); @@ -415,8 +509,38 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene renderOverlayDebug(g); } - renderHoverOverlay(g, shift); + renderOverlayLegend(g); + renderHoverOverlay(g, shift); + if(!notifications.isEmpty()) + { + renderNotification(g); + } + } + + private void renderOverlayLegend(Graphics2D g) { + KList l = new KList<>(); + l.add("Zoom: " + Form.pc(mscale, 0)); + l.add("Blocks: " + Form.f((int)mscale * w) + " by " + Form.f((int)mscale * h)); + l.add("BPP: " + Form.f(mscale, 1)); + l.add("Render Mode: " + Form.capitalizeWords(currentType.name().toLowerCase().replaceAll("\\Q_\\E", " "))); + + drawCardBR(g, l); + } + + private void renderNotification(Graphics2D g) { + drawCardCB(g, notifications.k()); + + for(String i : notifications.k()) + { + if(M.ms() > notifications.get(i)) + { + notifications.remove(i); + } + } + } + + private void renderPlayer(Graphics2D g) { Player b = null; for(Player i : world.getPlayers()) @@ -425,35 +549,84 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene renderPosition(g, i.getLocation().getX(), i.getLocation().getZ()); } - if(follow && b != null) + synchronized (lastEntities) { - animateTo(b.getLocation().getX(), b.getLocation().getZ()); - drawCardTL(g, new KList<>("Following " + b.getName())); + double dist = Double.MAX_VALUE; + LivingEntity h = null; + + for(LivingEntity i : lastEntities) + { + if(i instanceof Player) + { + continue; + } + + renderMobPosition(g, i, i.getLocation().getX(), i.getLocation().getZ()); + if(shift) + { + double d = i.getLocation().distanceSquared(new Location(i.getWorld(), getWorldX(hx), i.getLocation().getY(), getWorldZ(hz))); + + if(d < dist) + { + dist = d; + h = i; + } + } + } + + if(h != null && shift) + { + g.setColor(Color.red); + g.fillRoundRect((int)getScreenX(h.getLocation().getX()) - 10, (int)getScreenZ(h.getLocation().getZ()) - 10, 20, 20, 20, 20); + KList k = new KList<>(); + k.add(Form.capitalizeWords(h.getType().name().toLowerCase(Locale.ROOT).replaceAll("\\Q_\\E", " ")) + h.getEntityId()); + + k.add("Pos: " + h.getLocation().getBlockX() + ", " + h.getLocation().getBlockY() + ", " + h.getLocation().getBlockZ()); + k.add("UUID: " + h.getUniqueId().toString()); + k.add("HP: " + h.getHealth() + " / " + h.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue()); + + drawCardTR(g, k); + } } + + player = b; } 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; + ox += (wx - cx); + oz += (wz - cz); } 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); + if(texture != null) + { + g.drawImage(texture, (int)getScreenX(x), (int)getScreenZ(z), 66, 66, (img, infoflags, xx, xy, width, height) -> true); + } + + else + { + g.setColor(Color.darkGray); + g.fillRoundRect((int)getScreenX(x) - 15, (int)getScreenZ(z) - 15, 30, 30, 15, 15); + g.setColor(Color.cyan.darker().darker()); + g.fillRoundRect((int)getScreenX(x) - 10, (int)getScreenZ(z) - 10, 20, 20, 10, 10); + } + } + + private void renderMobPosition(Graphics2D g, LivingEntity e, double x, double z) + { + g.setColor(Color.red.darker().darker()); + g.fillRoundRect((int)getScreenX(x) - 2, (int)getScreenZ(z) - 2, 4, 4, 4, 4); } 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()); + l.add("Biome: " + biome.getName()); + l.add("Region: " + region.getName() + "(" + region.getLoadKey() + ")"); if(detailed) { l.add("Block " + (int)getWorldX(hx) + ", " + (int)getWorldZ(hz)); @@ -461,17 +634,16 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene 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); + drawCardAt((float)hx, (float)hz, 0, 0, g, l); } private void renderOverlayDebug(Graphics2D g) { KList l = new KList<>(); - l.add("Velocity: " + velocity); - - drawCardTL(g, l); + l.add("Velocity: " + (int)velocity); + l.add("Center Pos: " + Form.f((int)getWorldX(getWidth()/2)) + ", " + Form.f((int)getWorldZ(getHeight()/2))); + drawCardBL(g, l); } private void renderOverlayHelp(Graphics2D g) { @@ -480,7 +652,10 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene l.add("R to repaint the screen"); l.add("F to follow first player"); l.add("+/- to Change Zoom"); + l.add("\\ to reset zoom to 1"); l.add("M to cycle render modes"); + l.add("P to toggle Tile Quality Mode"); + l.add("E to toggle Eco FPS Mode"); int ff = 0; for (RenderType i : RenderType.values()) { @@ -489,18 +664,77 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene } 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"); + l.add("CTRL + 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); + drawCardAt(0, 0, 0, 0, g, text); } - private void drawCardAt(float x, float y, Graphics2D g, KList text) + private void drawCardBR(Graphics2D g, KList text) { + drawCardAt(getWidth(), getHeight(), 1, 1, g, text); + } + + private void drawCardBL(Graphics2D g, KList text) + { + drawCardAt(0, getHeight(), 0, 1, g, text); + } + + private void drawCardTR(Graphics2D g, KList text) + { + drawCardAt(getWidth(), 0, 1, 0, g, text); + } + + private void open() + { + IrisComplex complex = engine.getFramework().getComplex(); + File r = null; + switch(currentType) + { + case BIOME, LAYER_LOAD, DECORATOR_LOAD, OBJECT_LOAD, HEIGHT -> r = complex.getTrueBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode(); + case BIOME_LAND -> r = complex.getLandBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode(); + case BIOME_SEA -> r = complex.getSeaBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode(); + case REGION -> r = complex.getRegionStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode(); + case CAVE_LAND -> r = complex.getCaveBiomeStream().get(getWorldX(hx), getWorldZ(hz)).openInVSCode(); + } + + notify("Opening " + r.getPath() + " in VSCode"); + } + + private void teleport() + { + J.s(() -> { + if(player != null) + { + double h = engine.getFramework().getComplex().getTrueHeightStream().get(getWorldX(hx), getWorldZ(hz)); + player.teleport(new Location(player.getWorld(), getWorldX(hx), h, getWorldZ(hz))); + notify("Teleporting to " + Form.f((int)getWorldX(hx)) +", " + Form.f((int)h) + ", " + Form.f((int)getWorldZ(hz))); + } + + else + { + notify("No player in world, can't teleport."); + } + }); + } + + private void drawCardCB(Graphics2D g, KList text) + { + drawCardAt(getWidth()/2, getHeight(), 0.5, 1, g, text); + } + + private void drawCardCT(Graphics2D g, KList text) + { + drawCardAt(getWidth()/2, 0, 0.5, 0, g, text); + } + + private void drawCardAt(float x, float y, double pushX, double pushZ, Graphics2D g, KList text) + { + g.setFont(new Font("Hevetica", Font.BOLD, 16)); int h = 0; int w = 0; @@ -513,18 +747,21 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene w += 28; h += 28; + int cw = (int) ((w+26) * pushX); + int ch = (int) ((h+26) * pushZ); + g.setColor(Color.darkGray); - g.fillRect((int)x + 7 + 2, (int)y + 7 + 2, w + 7, h + 7); // Shadow + g.fillRect((int)x + 7 + 2-cw , (int)y + 7 + 2-ch, 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.fillRect((int)x + 7 + 1-cw, (int)y + 7 + 1-ch, w + 7, h + 7); // Shadow g.setColor(Color.white); - g.fillRect((int)x + 7, (int)y + 7, w + 7, h + 7); + g.fillRect((int)x + 7-cw, (int)y + 7-ch, 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())); + g.drawString(i, x + 14-cw, y + 14 -ch + (++m * g.getFontMetrics().getHeight())); } } @@ -541,6 +778,7 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene if (file != null) { try { + nv.texture = ImageIO.read(file); frame.setIconImage(ImageIO.read(file)); } catch (IOException e) {Iris.reportError(e); @@ -565,4 +803,37 @@ public class IrisVision extends JPanel implements MouseWheelListener, KeyListene mscale = mscale + ((0.044 * mscale) * notches); mscale = Math.max(mscale, 0.00001); } + + @Override + public void mouseClicked(MouseEvent e) { + if(control) + { + teleport(); + } + + else if(alt) + { + open(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } } diff --git a/src/main/java/com/volmit/iris/object/IrisRegistrant.java b/src/main/java/com/volmit/iris/object/IrisRegistrant.java index 26fceaa04..91c792d8e 100644 --- a/src/main/java/com/volmit/iris/object/IrisRegistrant.java +++ b/src/main/java/com/volmit/iris/object/IrisRegistrant.java @@ -18,9 +18,11 @@ package com.volmit.iris.object; +import com.volmit.iris.Iris; import com.volmit.iris.manager.IrisDataManager; import lombok.Data; +import java.awt.*; import java.io.File; @Data @@ -30,4 +32,15 @@ public class IrisRegistrant { private transient String loadKey; private transient File loadFile; + + public File openInVSCode() + { + try { + Desktop.getDesktop().open(getLoadFile()); + } catch (Throwable e) { + Iris.reportError(e); + } + + return getLoadFile(); + } } 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 a3792144b..1bfdcd096 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 @@ -43,7 +43,7 @@ public class HunkRegionSlice { private final String key; private final KMap> loadedChunks; private final KMap lastUse; - private final KList save; + private final KSet save; private final int height; public HunkRegionSlice(int height, Function3> factory, HunkIOAdapter adapter, CompoundTag compound, String key) { @@ -53,7 +53,7 @@ public class HunkRegionSlice { this.factory = factory; this.adapter = adapter; this.compound = compound; - this.save = new KList<>(); + this.save = new KSet<>(); this.key = key; this.lastUse = new KMap<>(); } @@ -246,7 +246,7 @@ public class HunkRegionSlice { public Hunk getRW(int x, int z) { return lock.withResult(x, z, () -> { - save.addIfMissing(new ChunkPosition(x, z)); + save.add(new ChunkPosition(x, z)); return get(x, z); }); } diff --git a/src/main/java/com/volmit/iris/util/KSet.java b/src/main/java/com/volmit/iris/util/KSet.java index 92bff8aa3..c3dd63d07 100644 --- a/src/main/java/com/volmit/iris/util/KSet.java +++ b/src/main/java/com/volmit/iris/util/KSet.java @@ -39,4 +39,8 @@ public class KSet extends HashSet { public KSet(int initialCapacity) { super(initialCapacity); } + + public KSet copy() { + return new KSet(this); + } }