This commit is contained in:
Daniel Mills 2020-09-03 16:15:09 -04:00
parent 607a7be337
commit 959a5b5c70
6 changed files with 353 additions and 130 deletions

View File

@ -127,6 +127,13 @@
<version>1.16.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit.craftbukkit</groupId>
<artifactId>cb-1.16.2</artifactId>
<version>1.16.2</version>
<scope>provided</scope>
</dependency>
<!-- Utilities -->
<dependency>
<groupId>org.projectlombok</groupId>

View File

@ -85,7 +85,7 @@ public class AtomicMulticache
private int getLimit()
{
return 20000;
return 1024;
}
public double getHeight(int x, int z, Supplier<Double> g)

View File

@ -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<ChunkPosition, Color> 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);
});
}
}

View File

@ -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<ChunkPosition, Color> 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();
if(completed)
{
return;
}
public void nextPosition()
if(first)
{
int lx = mcaX;
int lz = mcaZ;
rcx++;
sender.sendMessage("Pregen Started for " + Form.f((mcaWidth * mcaWidth)) + " Regions containing " + Form.f((mcaWidth * 16) * (mcaWidth * 16)) + " Chunks");
first = false;
spiraler.next();
if(rcx > 31)
while(chunkSpiraler.hasNext())
{
rcx = 0;
rcz++;
chunkSpiraler.next();
if(rcz > 31)
if(isChunkWithin(chunkX, chunkZ))
{
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!");
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);
}
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "save-all");
saveAll();
Iris.instance.unregisterListener(this);
completed = true;
sender.sendMessage("Pregen Completed!");
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));
}
}
}
saveAllRequest();
}
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<ChunkPosition, Color> s)
{
consumer = s;
}
}

View File

@ -0,0 +1,7 @@
package com.volmit.iris.util;
@FunctionalInterface
public interface Spiraled
{
public void on(int x, int z);
}

View File

@ -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++;
}
}