diff --git a/pom.xml b/pom.xml
index a9f39c4bf..9c7451e83 100644
--- a/pom.xml
+++ b/pom.xml
@@ -127,6 +127,13 @@
1.16.1-R0.1-SNAPSHOT
provided
+
+
+ org.bukkit.craftbukkit
+ cb-1.16.2
+ 1.16.2
+ provided
+
org.projectlombok
diff --git a/src/main/java/com/volmit/iris/gen/atomics/AtomicMulticache.java b/src/main/java/com/volmit/iris/gen/atomics/AtomicMulticache.java
index 2e61b83f0..1a2936bb1 100644
--- a/src/main/java/com/volmit/iris/gen/atomics/AtomicMulticache.java
+++ b/src/main/java/com/volmit/iris/gen/atomics/AtomicMulticache.java
@@ -85,7 +85,7 @@ public class AtomicMulticache
private int getLimit()
{
- return 20000;
+ return 1024;
}
public double getHeight(int x, int z, Supplier g)
diff --git a/src/main/java/com/volmit/iris/gui/PregenGui.java b/src/main/java/com/volmit/iris/gui/PregenGui.java
new file mode 100644
index 000000000..ce3e5aa61
--- /dev/null
+++ b/src/main/java/com/volmit/iris/gui/PregenGui.java
@@ -0,0 +1,114 @@
+package com.volmit.iris.gui;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.util.ChunkPosition;
+import com.volmit.iris.util.J;
+import com.volmit.iris.util.KMap;
+import com.volmit.iris.util.M;
+import com.volmit.iris.util.PregenJob;
+
+public class PregenGui extends JPanel
+{
+ private PregenJob job;
+ private static final long serialVersionUID = 2094606939770332040L;
+ private KMap queue = new KMap<>();
+ private int res = 8192;
+ private BufferedImage image = new BufferedImage(res, res, BufferedImage.TYPE_INT_RGB);
+
+ public PregenGui()
+ {
+
+ }
+
+ @Override
+ public void paint(Graphics gx)
+ {
+ double minC = Math.floorDiv(job.min(), 16) - 4;
+ double maxC = Math.floorDiv(job.max(), 16) + 4;
+
+ Graphics2D g = (Graphics2D) gx;
+ Graphics2D bg = (Graphics2D) image.getGraphics();
+
+ for(ChunkPosition i : queue.k())
+ {
+ draw(i, queue.get(i), minC, maxC, bg);
+ }
+
+ queue.clear();
+
+ g.drawImage(image, 0, 0, getParent().getWidth(), getParent().getHeight(), new ImageObserver()
+ {
+ @Override
+ public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
+ {
+ return true;
+ }
+ });
+
+ J.a(() ->
+ {
+ J.sleep((long) 500);
+ repaint();
+ });
+ }
+
+ private void draw(ChunkPosition p, Color c, double minC, double maxC, Graphics2D bg)
+ {
+ double pw = M.lerpInverse(minC, maxC, p.getX());
+ double ph = M.lerpInverse(minC, maxC, p.getZ());
+ double pwa = M.lerpInverse(minC, maxC, p.getX() + 1);
+ double pha = M.lerpInverse(minC, maxC, p.getZ() + 1);
+ int x = (int) M.lerp(0, res, pw);
+ int z = (int) M.lerp(0, res, ph);
+ int xa = (int) M.lerp(0, res, pwa);
+ int za = (int) M.lerp(0, res, pha);
+ bg.setColor(c);
+ bg.fillRect(x, z, xa - x, za - z);
+ }
+
+ private static void createAndShowGUI(PregenJob j)
+ {
+ JFrame frame = new JFrame("Pregen View");
+ PregenGui nv = new PregenGui();
+ nv.job = j;
+ j.subscribe((c, b) -> nv.queue.put(c, b));
+ frame.add(nv);
+ frame.setSize(1440, 820);
+ frame.setVisible(true);
+ 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 e)
+ {
+
+ }
+ }
+ }
+
+ public static void launch(PregenJob g)
+ {
+ J.a(() ->
+ {
+ createAndShowGUI(g);
+ });
+ }
+}
diff --git a/src/main/java/com/volmit/iris/util/PregenJob.java b/src/main/java/com/volmit/iris/util/PregenJob.java
index 12e303576..674c98066 100644
--- a/src/main/java/com/volmit/iris/util/PregenJob.java
+++ b/src/main/java/com/volmit/iris/util/PregenJob.java
@@ -1,19 +1,21 @@
package com.volmit.iris.util;
+import java.awt.Color;
+
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.world.ChunkUnloadEvent;
import com.volmit.iris.Iris;
+import com.volmit.iris.gui.PregenGui;
-public class PregenJob
+public class PregenJob implements Listener
{
private World world;
private int size;
- private int mcaX;
- private int mcaZ;
- private int rcx;
- private int rcz;
private int total;
private int genned;
private boolean completed;
@@ -21,34 +23,63 @@ public class PregenJob
private PrecisionStopwatch s;
private ChronoLatch cl;
private ChronoLatch clx;
+ private ChronoLatch clf;
private MortarSender sender;
+ private int mcaWidth;
+ private int mcaX;
+ private int mcaZ;
+ private int chunkX;
+ private int chunkZ;
private Runnable onDone;
+ private Spiraler spiraler;
+ private Spiraler chunkSpiraler;
+ private boolean first;
+ private Consumer2 consumer;
public PregenJob(World world, int size, MortarSender sender, Runnable onDone)
{
this.s = PrecisionStopwatch.start();
+ Iris.instance.registerListener(this);
this.world = world;
this.size = size;
this.onDone = onDone;
world.getWorldBorder().setCenter(0, 0);
world.getWorldBorder().setWarningDistance(64);
world.getWorldBorder().setSize(size);
- mcaX = mca(min());
- mcaZ = mca(min());
- rcx = 0;
this.sender = sender;
cl = new ChronoLatch(3000);
- clx = new ChronoLatch(15000);
- rcz = 0;
+ clx = new ChronoLatch(20000);
+ clf = new ChronoLatch(30000);
total = (size / 16) * (size / 16);
genned = 0;
+ mcaWidth = Math.floorDiv(size >> 4, 8) + 8;
+ this.mcaX = 0;
+ this.mcaZ = 0;
+ this.chunkX = 0;
+ this.chunkZ = 0;
completed = false;
+ first = true;
+
+ chunkSpiraler = new Spiraler(8, 8, (x, z) ->
+ {
+ chunkX = (mcaX * 8) + x;
+ chunkZ = (mcaZ * 8) + z;
+ });
+
+ spiraler = new Spiraler(mcaWidth, mcaWidth, (x, z) ->
+ {
+ mcaX = x;
+ mcaZ = z;
+ chunkSpiraler.retarget(8, 8);
+ });
+
+ chunkSpiraler.setOffset(3, 3);
if(task != -1)
{
stop();
}
-
+ PregenGui.launch(this);
task = Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, this::onTick, 0, 0);
}
@@ -75,7 +106,7 @@ public class PregenJob
PrecisionStopwatch p = PrecisionStopwatch.start();
- while(p.getMilliseconds() < 1500)
+ while(p.getMilliseconds() < 5000)
{
tick();
}
@@ -99,141 +130,139 @@ public class PregenJob
public void tick()
{
- gen();
- nextPosition();
- }
-
- public void nextPosition()
- {
- int lx = mcaX;
- int lz = mcaZ;
- rcx++;
-
- if(rcx > 31)
+ if(completed)
{
- rcx = 0;
- rcz++;
-
- if(rcz > 31)
- {
- rcz = 0;
- mcaX++;
-
- if(mcaX > mca(Math.floorDiv(max(), 16)))
- {
- mcaX = mca(Math.floorDiv(min(), 16));
- mcaZ++;
-
- if(mcaZ > mca(Math.floorDiv(max(), 16)))
- {
- mcaZ = mca(Math.floorDiv(min(), 16));
- completed = true;
- stop();
- Iris.info("Pregen Completed!");
- if(sender.isPlayer() && sender.player().isOnline())
- {
- sender.sendMessage("Pregen Completed!");
- }
-
- for(Chunk i : world.getLoadedChunks())
- {
- i.unload(true);
- }
-
- Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "save-all");
- onDone.run();
- }
- }
-
- if(!completed)
- {
- try
- {
- verify(lx, lz);
- }
-
- catch(Throwable e)
- {
- e.printStackTrace();
- }
- }
- }
- }
- }
-
- private void verify(int lx, int lz) throws Throwable
- {
- for(int x = 0; x < 32; x++)
- {
- for(int z = 0; z < 32; z++)
- {
- if(isChunkWithin(x + (lx * 32), z + (lz * 32)))
- {
- Chunk c = world.getChunkAt(x + (lx * 32), z + (lz * 32));
- c.load(true);
- world.unloadChunkRequest(x + (lx * 32), z + (lz * 32));
- }
- }
+ return;
}
- saveAllRequest();
+ if(first)
+ {
+ sender.sendMessage("Pregen Started for " + Form.f((mcaWidth * mcaWidth)) + " Regions containing " + Form.f((mcaWidth * 16) * (mcaWidth * 16)) + " Chunks");
+ first = false;
+ spiraler.next();
+
+ while(chunkSpiraler.hasNext())
+ {
+ chunkSpiraler.next();
+
+ if(isChunkWithin(chunkX, chunkZ))
+ {
+ consumer.accept(new ChunkPosition(chunkX, chunkZ), Color.DARK_GRAY);
+ }
+ }
+
+ chunkSpiraler.retarget(8, 8);
+ }
+
+ if(chunkSpiraler.hasNext())
+ {
+ chunkSpiraler.next();
+ consumer.accept(new ChunkPosition(chunkX, chunkZ), Color.YELLOW);
+
+ if(isChunkWithin(chunkX, chunkZ))
+ {
+ world.loadChunk(chunkX, chunkZ);
+
+ if(consumer != null)
+ {
+ consumer.accept(new ChunkPosition(chunkX, chunkZ), Color.BLUE);
+ }
+ }
+
+ genned++;
+ }
+
+ else if(spiraler.hasNext())
+ {
+ saveAllRequest();
+ spiraler.next();
+ while(chunkSpiraler.hasNext())
+ {
+ chunkSpiraler.next();
+
+ if(isChunkWithin(chunkX, chunkZ))
+ {
+ consumer.accept(new ChunkPosition(chunkX, chunkZ), Color.DARK_GRAY);
+ }
+ }
+ chunkSpiraler.retarget(8, 8);
+ }
+
+ else
+ {
+ for(Chunk i : world.getLoadedChunks())
+ {
+ i.unload(true);
+ }
+
+ saveAll();
+ Iris.instance.unregisterListener(this);
+ completed = true;
+ sender.sendMessage("Pregen Completed!");
+ onDone.run();
+ }
}
public void saveAllRequest()
{
+ if(clf.flip())
+ {
+ int g = 0;
+
+ for(Chunk i : world.getLoadedChunks())
+ {
+ g++;
+
+ if(g > 1500)
+ {
+ i.unload(true);
+ }
+
+ else
+ {
+ world.unloadChunkRequest(i.getX(), i.getZ());
+ }
+ }
+ }
+
if(clx.flip())
{
saveAll();
}
}
+ @EventHandler
+ public void on(ChunkUnloadEvent e)
+ {
+ if(e.getWorld().equals(world) && isChunkWithin(e.getChunk().getX(), e.getChunk().getZ()))
+ {
+ consumer.accept(new ChunkPosition(e.getChunk().getX(), e.getChunk().getZ()), Color.GREEN);
+ }
+ }
+
public void saveAll()
{
+ int g = 0;
+
+ for(Chunk i : world.getLoadedChunks())
+ {
+ g++;
+
+ if(g > 1500)
+ {
+ i.unload(true);
+ }
+
+ else
+ {
+ world.unloadChunkRequest(i.getX(), i.getZ());
+ }
+ }
+
world.save();
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "save-all");
}
- public void gen()
- {
- try
- {
- if(isChunkWithin(rcx + minMCA(mcaX), rcz + minMCA(mcaZ)))
- {
- Chunk c = world.getChunkAt(rcx + minMCA(mcaX), rcz + minMCA(mcaZ));
- c.load(true);
- genned++;
- }
- }
-
- catch(Throwable e)
- {
- Iris.warn("Pregen Crash!");
- if(sender.isPlayer() && sender.player().isOnline())
- {
- sender.sendMessage("Pregen Completed!");
- }
-
- onDone.run();
- e.printStackTrace();
- stop();
- }
- }
-
- public int minMCA(int v)
- {
- return v << 5;
- }
-
- public int maxMCA(int v)
- {
- return (v << 5) + 31;
- }
-
- public int mca(int v)
- {
- return v >> 5;
- }
-
public int max()
{
return size / 2;
@@ -246,6 +275,11 @@ public class PregenJob
public boolean isChunkWithin(int x, int z)
{
- return Math.abs(z * 16) <= size / 2 && Math.abs(z * 16) <= size / 2;
+ return !(Math.abs(x << 4) > Math.floorDiv(size, 2) + 16 || Math.abs(z << 4) > Math.floorDiv(size, 2) + 16);
+ }
+
+ public void subscribe(Consumer2 s)
+ {
+ consumer = s;
}
}
diff --git a/src/main/java/com/volmit/iris/util/Spiraled.java b/src/main/java/com/volmit/iris/util/Spiraled.java
new file mode 100644
index 000000000..a606b3cc2
--- /dev/null
+++ b/src/main/java/com/volmit/iris/util/Spiraled.java
@@ -0,0 +1,7 @@
+package com.volmit.iris.util;
+
+@FunctionalInterface
+public interface Spiraled
+{
+ public void on(int x, int z);
+}
diff --git a/src/main/java/com/volmit/iris/util/Spiraler.java b/src/main/java/com/volmit/iris/util/Spiraler.java
new file mode 100644
index 000000000..8edfbaba2
--- /dev/null
+++ b/src/main/java/com/volmit/iris/util/Spiraler.java
@@ -0,0 +1,61 @@
+package com.volmit.iris.util;
+
+public class Spiraler
+{
+ int x, z, dx, dz, sizeX, sizeZ, t, maxI, i;
+ int ox, oz;
+ private Spiraled spiraled;
+
+ public Spiraler(int sizeX, int sizeZ, Spiraled spiraled)
+ {
+ ox = 0;
+ oz = 0;
+ this.spiraled = spiraled;
+ retarget(sizeX, sizeZ);
+ }
+
+ static void Spiral(int X, int Y)
+ {
+
+ }
+
+ public void setOffset(int ox, int oz)
+ {
+ this.ox = ox;
+ this.oz = oz;
+ }
+
+ public void retarget(int sizeX, int sizeZ)
+ {
+ this.sizeX = sizeX;
+ this.sizeZ = sizeZ;
+ x = z = dx = 0;
+ dz = -1;
+ i = 0;
+ t = Math.max(sizeX, sizeZ);
+ maxI = t * t;
+ }
+
+ public boolean hasNext()
+ {
+ return i < maxI;
+ }
+
+ public void next()
+ {
+ if((-sizeX / 2 <= x) && (x <= sizeX / 2) && (-sizeZ / 2 <= z) && (z <= sizeZ / 2))
+ {
+ spiraled.on(x + ox, z + ox);
+ }
+
+ if((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z)))
+ {
+ t = dx;
+ dx = -dz;
+ dz = t;
+ }
+ x += dx;
+ z += dz;
+ i++;
+ }
+}