mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-17 06:11:06 +00:00
- Added Lazy pregen as an option
This commit is contained in:
@@ -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,29 +43,68 @@ 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
|
||||||
) {
|
) {
|
||||||
try {
|
if(method.equals("async") || method.equals("lazy")){
|
||||||
if (sender().isPlayer() && access() == null) {
|
if (method.equalsIgnoreCase("async")) {
|
||||||
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
try {
|
||||||
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
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.");
|
||||||
|
}
|
||||||
|
radius = Math.max(radius, 1024);
|
||||||
|
int w = (radius >> 9 + 1) * 2;
|
||||||
|
IrisToolbelt.pregenerate(PregenTask
|
||||||
|
.builder()
|
||||||
|
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
|
||||||
|
.width(w)
|
||||||
|
.height(w)
|
||||||
|
.build(), world);
|
||||||
|
String msg = C.GREEN + "Pregen started in " + C.GOLD + world.getName() + 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
radius = Math.max(radius, 1024);
|
if (method.equalsIgnoreCase("lazy")) {
|
||||||
int w = (radius >> 9 + 1) * 2;
|
String worldName = world.getName();
|
||||||
IrisToolbelt.pregenerate(PregenTask
|
try {
|
||||||
.builder()
|
if (sender().isPlayer() && access() == null) {
|
||||||
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
|
sender().sendMessage(C.RED + "The engine access for this world is null!");
|
||||||
.width(w)
|
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||||
.height(w)
|
}
|
||||||
.build(), world);
|
|
||||||
String msg = C.GREEN + "Pregen started in " + C.GOLD + world.getName() + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
|
||||||
sender().sendMessage(msg);
|
.world(worldName)
|
||||||
Iris.info(msg);
|
.healingPosition(0)
|
||||||
} catch (Throwable e) {
|
.healing(false)
|
||||||
sender().sendMessage(C.RED + "Epic fail. See console.");
|
.chunksPerMinute(999999999)
|
||||||
Iris.reportError(e);
|
.radiusBlocks(radius)
|
||||||
e.printStackTrace();
|
.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")
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user