- Added Lazy pregen as an option

This commit is contained in:
RePixelatedMC
2023-11-06 15:03:40 +01:00
parent 5004481685
commit 7afdbc2a53
5 changed files with 105 additions and 31 deletions
@@ -20,6 +20,7 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.gui.PregeneratorJob; import com.volmit.iris.core.gui.PregeneratorJob;
import com.volmit.iris.core.pregenerator.LazyPregenerator;
import com.volmit.iris.core.pregenerator.PregenTask; import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.decree.DecreeExecutor; import com.volmit.iris.util.decree.DecreeExecutor;
@@ -27,9 +28,12 @@ import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param; import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.Position2;
import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.io.File;
@Decree(name = "pregen", aliases = "pregenerate", description = "Pregenerate your Iris worlds!") @Decree(name = "pregen", aliases = "pregenerate", description = "Pregenerate your Iris worlds!")
public class CommandPregen implements DecreeExecutor { public class CommandPregen implements DecreeExecutor {
@Decree(description = "Pregenerate a world") @Decree(description = "Pregenerate a world")
@@ -39,8 +43,12 @@ public class CommandPregen implements DecreeExecutor {
@Param(description = "The world to pregen", contextual = true) @Param(description = "The world to pregen", contextual = true)
World world, World world,
@Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0") @Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0")
Vector center Vector center,
@Param(aliases = "method", description = "The pregen method that will get used. Lazy or Async", defaultValue = "async")
String method
) { ) {
if(method.equals("async") || method.equals("lazy")){
if (method.equalsIgnoreCase("async")) {
try { try {
if (sender().isPlayer() && access() == null) { if (sender().isPlayer() && access() == null) {
sender().sendMessage(C.RED + "The engine access for this world is null!"); sender().sendMessage(C.RED + "The engine access for this world is null!");
@@ -63,6 +71,41 @@ public class CommandPregen implements DecreeExecutor {
e.printStackTrace(); e.printStackTrace();
} }
} }
if (method.equalsIgnoreCase("lazy")) {
String worldName = world.getName();
try {
if (sender().isPlayer() && access() == null) {
sender().sendMessage(C.RED + "The engine access for this world is null!");
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
}
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
.world(worldName)
.healingPosition(0)
.healing(false)
.chunksPerMinute(999999999)
.radiusBlocks(radius)
.position(0)
.build();
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, new File("plugins/Iris/lazygen.json"));
pregenerator.start();
String msg = C.GREEN + "Pregen started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
sender().sendMessage(msg);
Iris.info(msg);
} catch (Throwable e) {
sender().sendMessage(C.RED + "Epic fail. See console.");
Iris.reportError(e);
e.printStackTrace();
}
}
} else {
sender().sendMessage(C.RED + "Please use a valid method.");
}
}
@Decree(description = "Stop the active pregeneration task", aliases = "x") @Decree(description = "Stop the active pregeneration task", aliases = "x")
public void stop() { public void stop() {
@@ -132,11 +132,6 @@ public class IrisPregenerator {
); );
} }
public static void shareData(){
long_generatedChunks = generated.get();
long_totalChunks = totalChunks.get();
}
public static long getLongGeneratedChunks() { public static long getLongGeneratedChunks() {
return long_generatedChunks; return long_generatedChunks;
} }
@@ -2,9 +2,12 @@ package com.volmit.iris.core.pregenerator;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO; import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.math.Spiraler; import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
@@ -20,6 +23,7 @@ import org.bukkit.event.world.WorldUnloadEvent;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class LazyPregenerator extends Thread implements Listener { public class LazyPregenerator extends Thread implements Listener {
private final LazyPregenJob job; private final LazyPregenJob job;
@@ -28,6 +32,11 @@ public class LazyPregenerator extends Thread implements Listener {
private final World world; private final World world;
private final long rate; private final long rate;
private final ChronoLatch latch; private final ChronoLatch latch;
private static AtomicInteger lazyGeneratedChunks;
private final AtomicInteger generatedLast;
private final AtomicInteger lazyTotalChunks;
private final AtomicLong startTime;
private final RollingSequence chunksPerSecond;
public LazyPregenerator(LazyPregenJob job, File destination) { public LazyPregenerator(LazyPregenJob job, File destination) {
this.job = job; this.job = job;
@@ -36,7 +45,15 @@ public class LazyPregenerator extends Thread implements Listener {
}).count(); }).count();
this.world = Bukkit.getWorld(job.getWorld()); this.world = Bukkit.getWorld(job.getWorld());
this.rate = Math.round((1D / (job.chunksPerMinute / 60D)) * 1000D); this.rate = Math.round((1D / (job.chunksPerMinute / 60D)) * 1000D);
this.latch = new ChronoLatch(60000); this.latch = new ChronoLatch(6000);
startTime = new AtomicLong(M.ms());
chunksPerSecond = new RollingSequence(10);
lazyGeneratedChunks = new AtomicInteger(0);
generatedLast = new AtomicInteger(0);
lazyTotalChunks = new AtomicInteger();
int radius = job.getRadiusBlocks();
lazyTotalChunks.set((int) Math.ceil(Math.pow((2.0 * radius) / 16, 2)));
} }
public LazyPregenerator(File file) throws IOException { public LazyPregenerator(File file) throws IOException {
@@ -81,17 +98,26 @@ public class LazyPregenerator extends Thread implements Listener {
public void tick() { public void tick() {
if (latch.flip()) { if (latch.flip()) {
long eta = computeETA();
save(); save();
Iris.info("LazyGen: " + world.getName() + " RTT: " + Form.duration((Math.pow((job.radiusBlocks / 16D), 2) / job.chunksPerMinute) * 60 * 1000, 2)); int secondGenerated = lazyGeneratedChunks.get() - generatedLast.get();
generatedLast.set(lazyGeneratedChunks.get());
secondGenerated = secondGenerated / 6;
chunksPerSecond.put(secondGenerated);
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(lazyGeneratedChunks.get()) + " of " + Form.f(lazyTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
//Iris.info("Debug: " + maxPosition);
//Iris.info("Debug1: " + job.getPosition());
// todo: Maxpos borked
} }
if (job.getPosition() >= maxPosition) { if (lazyGeneratedChunks.get() >= lazyTotalChunks.get()) {
if (job.isHealing()) { if (job.isHealing()) {
int pos = (job.getHealingPosition() + 1) % maxPosition; int pos = (job.getHealingPosition() + 1) % maxPosition;
job.setHealingPosition(pos); job.setHealingPosition(pos);
tickRegenerate(getChunk(pos)); tickRegenerate(getChunk(pos));
} else { } else {
Iris.verbose("Completed Lazy Gen!"); Iris.info("Completed Lazy Gen!");
interrupt(); interrupt();
} }
} else { } else {
@@ -101,6 +127,15 @@ public class LazyPregenerator extends Thread implements Listener {
} }
} }
private long computeETA() {
return (long) (lazyTotalChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
((lazyTotalChunks.get() - lazyGeneratedChunks.get()) * ((double) (M.ms() - startTime.get()) / (double) lazyGeneratedChunks.get())) :
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
((lazyTotalChunks.get() - lazyGeneratedChunks.get()) / chunksPerSecond.getAverage()) * 1000 //
);
}
private void tickGenerate(Position2 chunk) { private void tickGenerate(Position2 chunk) {
if (PaperLib.isPaper()) { if (PaperLib.isPaper()) {
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true).thenAccept((i) -> Iris.verbose("Generated Async " + chunk)); PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true).thenAccept((i) -> Iris.verbose("Generated Async " + chunk));
@@ -108,6 +143,7 @@ public class LazyPregenerator extends Thread implements Listener {
J.s(() -> world.getChunkAt(chunk.getX(), chunk.getZ())); J.s(() -> world.getChunkAt(chunk.getX(), chunk.getZ()));
Iris.verbose("Generated " + chunk); Iris.verbose("Generated " + chunk);
} }
lazyGeneratedChunks.addAndGet(1);
} }
private void tickRegenerate(Position2 chunk) { private void tickRegenerate(Position2 chunk) {
@@ -126,7 +126,7 @@ public class IrisPackBenchmarking {
int x = 0; int x = 0;
int z = 0; int z = 0;
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder() LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
.world("Benchmark") //.world("Benchmark")
.healingPosition(0) .healingPosition(0)
.healing(false) .healing(false)
.chunksPerMinute(3200) .chunksPerMinute(3200)
@@ -38,7 +38,7 @@ public class UtilsSFG {
if (incompatiblePlugins.get("Dynmap")) { if (incompatiblePlugins.get("Dynmap")) {
Iris.safeguard(C.RED + "Dynmap"); Iris.safeguard(C.RED + "Dynmap");
Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server."); Iris.safeguard(C.RED + "- The plugin Dynmap is not compatible with the server.");
Iris.safeguard(C.RED + "- If you want to have a map plugin like Dynmap, consider Bluemap or LiveAtlas."); Iris.safeguard(C.RED + "- If you want to have a map plugin like Dynmap, consider Bluemap.");
} }
if (incompatiblePlugins.get("TerraformGenerator") || incompatiblePlugins.get("Stratos")) { if (incompatiblePlugins.get("TerraformGenerator") || incompatiblePlugins.get("Stratos")) {
Iris.safeguard(C.YELLOW + "Terraform Generator / Stratos"); Iris.safeguard(C.YELLOW + "Terraform Generator / Stratos");