mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-17 22:32:04 +00:00
- Fixed LazyPregenerator.java and improved it. ( Speed decrease on server restart when lazy starts the job up dont know why)
- Mem leak fix only works when there is 1 iris world for now ( working on it ) + A capped performance limit still very alpha like seems stable tho. - Disabled HotDropWorldSVC acts a bit weird sometimes.
This commit is contained in:
@@ -34,6 +34,7 @@ import org.bukkit.World;
|
|||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
@Decree(name = "lazypregen", aliases = "lazy", description = "Pregenerate your Iris worlds!")
|
@Decree(name = "lazypregen", aliases = "lazy", description = "Pregenerate your Iris worlds!")
|
||||||
public class CommandLazyPregen implements DecreeExecutor {
|
public class CommandLazyPregen implements DecreeExecutor {
|
||||||
@@ -53,6 +54,14 @@ public class CommandLazyPregen implements DecreeExecutor {
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
worldName = world.getName();
|
worldName = world.getName();
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File lazyFile = new File(worldDirectory, "lazygen.json");
|
||||||
|
if (lazyFile.exists()) {
|
||||||
|
sender().sendMessage(C.BLUE + "Lazy pregen is already in progress");
|
||||||
|
Iris.info(C.YELLOW + "Lazy pregen is already in progress");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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!");
|
||||||
@@ -69,7 +78,6 @@ public class CommandLazyPregen implements DecreeExecutor {
|
|||||||
.silent(silent)
|
.silent(silent)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
File worldDirectory = new File(Bukkit.getWorldContainer(), worldName);
|
|
||||||
File lazyGenFile = new File(worldDirectory, "lazygen.json");
|
File lazyGenFile = new File(worldDirectory, "lazygen.json");
|
||||||
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, lazyGenFile);
|
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, lazyGenFile);
|
||||||
pregenerator.start();
|
pregenerator.start();
|
||||||
@@ -85,20 +93,26 @@ public class CommandLazyPregen implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
@Decree(description = "Stop the active pregeneration task", aliases = "x")
|
||||||
public void stop() {
|
public void stop(
|
||||||
|
@Param(aliases = "world", description = "The world to pause")
|
||||||
|
World world
|
||||||
|
) throws IOException {
|
||||||
if (LazyPregenerator.getInstance() != null) {
|
if (LazyPregenerator.getInstance() != null) {
|
||||||
LazyPregenerator.getInstance().shutdownInstance();
|
LazyPregenerator.getInstance().shutdownInstance(world);
|
||||||
Iris.info( C.BLUE + "Shutting down all Lazy Pregens");
|
sender().sendMessage(C.LIGHT_PURPLE + "Closed lazygen instance for " + world.getName());
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
@Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"})
|
||||||
public void pause() {
|
public void pause(
|
||||||
|
@Param(aliases = "world", description = "The world to pause")
|
||||||
|
World world
|
||||||
|
) {
|
||||||
if (LazyPregenerator.getInstance() != null) {
|
if (LazyPregenerator.getInstance() != null) {
|
||||||
LazyPregenerator.getInstance().setPausedLazy();
|
LazyPregenerator.getInstance().setPausedLazy(world);
|
||||||
sender().sendMessage(C.GREEN + "Paused/unpaused Lazy Pregen, now: " + (LazyPregenerator.getInstance().isPausedLazy() ? "Paused" : "Running") + ".");
|
sender().sendMessage(C.GREEN + "Paused/unpaused Lazy Pregen, now: " + (LazyPregenerator.getInstance().isPausedLazy(world) ? "Paused" : "Running") + ".");
|
||||||
} else {
|
} else {
|
||||||
sender().sendMessage(C.YELLOW + "No active Lazy Pregen tasks to pause/unpause.");
|
sender().sendMessage(C.YELLOW + "No active Lazy Pregen tasks to pause/unpause.");
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ 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.core.IrisSettings;
|
|
||||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
|
||||||
import com.volmit.iris.util.format.C;
|
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;
|
||||||
@@ -11,11 +9,8 @@ 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.RollingSequence;
|
||||||
import com.volmit.iris.util.math.Spiraler;
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
|
||||||
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;
|
||||||
import io.lumine.mythic.bukkit.utils.lib.jooq.False;
|
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -25,23 +20,26 @@ import org.bukkit.World;
|
|||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class LazyPregenerator extends Thread implements Listener {
|
public class LazyPregenerator extends Thread implements Listener {
|
||||||
@Getter
|
@Getter
|
||||||
private static LazyPregenerator instance;
|
private static LazyPregenerator instance;
|
||||||
private final LazyPregenJob job;
|
private final LazyPregenJob job;
|
||||||
private final File destination;
|
private final File destination;
|
||||||
private final int maxPosition;
|
private final int maxPosition;
|
||||||
private final World world;
|
private World world;
|
||||||
private final long rate;
|
private final long rate;
|
||||||
private final ChronoLatch latch;
|
private final ChronoLatch latch;
|
||||||
private static AtomicInteger lazyGeneratedChunks;
|
private static AtomicInteger lazyGeneratedChunks;
|
||||||
@@ -49,6 +47,10 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
private final AtomicInteger lazyTotalChunks;
|
private final AtomicInteger lazyTotalChunks;
|
||||||
private final AtomicLong startTime;
|
private final AtomicLong startTime;
|
||||||
private final RollingSequence chunksPerSecond;
|
private final RollingSequence chunksPerSecond;
|
||||||
|
private final RollingSequence chunksPerMinute;
|
||||||
|
|
||||||
|
// A map to keep track of jobs for each world
|
||||||
|
private static final Map<String, LazyPregenJob> jobs = new HashMap<>();
|
||||||
|
|
||||||
public LazyPregenerator(LazyPregenJob job, File destination) {
|
public LazyPregenerator(LazyPregenJob job, File destination) {
|
||||||
this.job = job;
|
this.job = job;
|
||||||
@@ -56,13 +58,15 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||||
}).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.getChunksPerMinute() / 60D)) * 1000D);
|
||||||
this.latch = new ChronoLatch(6000);
|
this.latch = new ChronoLatch(15000);
|
||||||
startTime = new AtomicLong(M.ms());
|
this.startTime = new AtomicLong(M.ms());
|
||||||
chunksPerSecond = new RollingSequence(10);
|
this.chunksPerSecond = new RollingSequence(10);
|
||||||
|
this.chunksPerMinute = new RollingSequence(10);
|
||||||
lazyGeneratedChunks = new AtomicInteger(0);
|
lazyGeneratedChunks = new AtomicInteger(0);
|
||||||
generatedLast = new AtomicInteger(0);
|
this.generatedLast = new AtomicInteger(0);
|
||||||
lazyTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
|
this.lazyTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
|
||||||
|
jobs.put(job.getWorld(), job);
|
||||||
LazyPregenerator.instance = this;
|
LazyPregenerator.instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +77,6 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
public static void loadLazyGenerators() {
|
public static void loadLazyGenerators() {
|
||||||
for (World i : Bukkit.getWorlds()) {
|
for (World i : Bukkit.getWorlds()) {
|
||||||
File lazygen = new File(i.getWorldFolder(), "lazygen.json");
|
File lazygen = new File(i.getWorldFolder(), "lazygen.json");
|
||||||
|
|
||||||
if (lazygen.exists()) {
|
if (lazygen.exists()) {
|
||||||
try {
|
try {
|
||||||
LazyPregenerator p = new LazyPregenerator(lazygen);
|
LazyPregenerator p = new LazyPregenerator(lazygen);
|
||||||
@@ -107,15 +110,17 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
LazyPregenJob job = jobs.get(world.getName());
|
||||||
if (latch.flip() && !job.paused) {
|
if (latch.flip() && !job.paused) {
|
||||||
long eta = computeETA();
|
long eta = computeETA();
|
||||||
save();
|
save();
|
||||||
int secondGenerated = lazyGeneratedChunks.get() - generatedLast.get();
|
int secondGenerated = lazyGeneratedChunks.get() - generatedLast.get();
|
||||||
generatedLast.set(lazyGeneratedChunks.get());
|
generatedLast.set(lazyGeneratedChunks.get());
|
||||||
secondGenerated = secondGenerated / 6;
|
secondGenerated = secondGenerated / 15;
|
||||||
chunksPerSecond.put(secondGenerated);
|
chunksPerSecond.put(secondGenerated);
|
||||||
|
chunksPerMinute.put(secondGenerated * 60);
|
||||||
if (!job.isSilent()) {
|
if (!job.isSilent()) {
|
||||||
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("LazyGen: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(lazyGeneratedChunks.get()) + " of " + Form.f(lazyTotalChunks.get()) + " " + Form.f((int) chunksPerMinute.getAverage()) + "/m ETA: " + Form.duration((double) eta, 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,12 +143,8 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long computeETA() {
|
private long computeETA() {
|
||||||
return (long) (lazyTotalChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
|
return (long) ((lazyTotalChunks.get() - lazyGeneratedChunks.get()) / chunksPerMinute.getAverage()) * 1000;
|
||||||
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
|
// todo broken
|
||||||
((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 final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||||
@@ -154,7 +155,10 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
if (PaperLib.isPaper()) {
|
if (PaperLib.isPaper()) {
|
||||||
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
|
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true)
|
||||||
.thenAccept((i) -> {
|
.thenAccept((i) -> {
|
||||||
|
LazyPregenJob j = jobs.get(world.getName());
|
||||||
|
if (!j.paused) {
|
||||||
Iris.verbose("Generated Async " + chunk);
|
Iris.verbose("Generated Async " + chunk);
|
||||||
|
}
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -201,23 +205,64 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public void setPausedLazy(){
|
|
||||||
if (!job.paused) {
|
public static void setPausedLazy(World world) {
|
||||||
save();
|
// todo: doesnt actually pause
|
||||||
Iris.info(C.BLUE + "LazyGen: " + C.IRIS + world + C.BLUE + " Paused");
|
LazyPregenJob job = jobs.get(world.getName());
|
||||||
job.setPaused(true);
|
if (isPausedLazy(world)){
|
||||||
|
job.paused = false;
|
||||||
} else {
|
} else {
|
||||||
Iris.info(C.BLUE + "LazyGen: " + C.IRIS + world + C.BLUE + " Resumes");
|
job.paused = true;
|
||||||
job.setPaused(false);
|
}
|
||||||
|
|
||||||
|
if ( job.paused) {
|
||||||
|
Iris.info(C.BLUE + "LazyGen: " + C.IRIS + world.getName() + C.BLUE + " Paused");
|
||||||
|
} else {
|
||||||
|
Iris.info(C.BLUE + "LazyGen: " + C.IRIS + world.getName() + C.BLUE + " Resumed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public boolean isPausedLazy(){
|
|
||||||
return job.isPaused();
|
public static boolean isPausedLazy(World world) {
|
||||||
|
LazyPregenJob job = jobs.get(world.getName());
|
||||||
|
return job != null && job.isPaused();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdownInstance(World world) throws IOException {
|
||||||
|
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
||||||
|
LazyPregenJob job = jobs.get(world.getName());
|
||||||
|
File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName());
|
||||||
|
File lazyFile = new File(worldDirectory, "lazygen.json");
|
||||||
|
|
||||||
|
if (job == null) {
|
||||||
|
Iris.error("No Lazygen job found for world: " + world.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!job.isPaused()) {
|
||||||
|
job.setPaused(true);
|
||||||
}
|
}
|
||||||
public void shutdownInstance() {
|
|
||||||
save();
|
save();
|
||||||
|
jobs.remove(world.getName());
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (lazyFile.exists()){
|
||||||
|
lazyFile.delete();
|
||||||
|
J.sleep(1000);
|
||||||
|
}
|
||||||
|
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed.");
|
||||||
|
}
|
||||||
|
}.runTaskLater(Iris.instance, 20L);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Iris.error("Failed to shutdown Lazygen for " + world.getName());
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
saveNow();
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void saveNow() throws IOException {
|
public void saveNow() throws IOException {
|
||||||
IO.writeAll(this.destination, new Gson().toJson(job));
|
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||||
@@ -232,7 +277,7 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
@Builder.Default
|
@Builder.Default
|
||||||
private boolean healing = false;
|
private boolean healing = false;
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private int chunksPerMinute = 32; // 48 hours is roughly 5000 radius
|
private int chunksPerMinute = 32;
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private int radiusBlocks = 5000;
|
private int radiusBlocks = 5000;
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
@@ -243,3 +288,4 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
boolean paused = false;
|
boolean paused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class HotDropWorldSVC implements IrisService {
|
|||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
this.plugin = Iris.instance;
|
this.plugin = Iris.instance;
|
||||||
initializeWatchService();
|
// initializeWatchService();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,68 +1,120 @@
|
|||||||
package com.volmit.iris.core.service;
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
|
||||||
import com.volmit.iris.util.format.C;
|
|
||||||
import com.volmit.iris.util.format.Form;
|
|
||||||
import com.volmit.iris.util.mantle.TectonicPlate;
|
|
||||||
import com.volmit.iris.util.math.M;
|
|
||||||
import com.volmit.iris.util.misc.getHardware;
|
import com.volmit.iris.util.misc.getHardware;
|
||||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
|
||||||
import com.volmit.iris.util.parallel.HyperLock;
|
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.Looper;
|
import com.volmit.iris.util.scheduling.Looper;
|
||||||
import io.papermc.lib.PaperLib;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import static com.volmit.iris.util.mantle.Mantle.tectonicLimit;
|
import static com.volmit.iris.util.mantle.Mantle.tectonicLimit;
|
||||||
|
|
||||||
public class IrisEngineSVC implements IrisService {
|
public class IrisEngineSVC implements IrisService {
|
||||||
private JavaPlugin plugin;
|
private JavaPlugin plugin;
|
||||||
public Looper ticker;
|
public Looper ticker1;
|
||||||
|
public Looper ticker2;
|
||||||
|
public Looper engineTicker;
|
||||||
|
public World selectedWorld;
|
||||||
public List<World> IrisWorlds = new ArrayList<>();
|
public List<World> IrisWorlds = new ArrayList<>();
|
||||||
public List<World> corruptedIrisWorlds = new ArrayList<>();
|
public List<World> corruptedIrisWorlds = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
this.plugin = Iris.instance;
|
this.plugin = Iris.instance;
|
||||||
this.IrisStartup();
|
tectonicLimit.set(2);
|
||||||
|
long t = getHardware.getProcessMemory();
|
||||||
|
for (; t > 250; ) {
|
||||||
|
tectonicLimit.getAndAdd(1);
|
||||||
|
t = t - 250;
|
||||||
|
}
|
||||||
|
tectonicLimit.set(10); // DEBUG CODE
|
||||||
this.IrisEngine();
|
this.IrisEngine();
|
||||||
ticker.start();
|
engineTicker.start();
|
||||||
|
ticker1.start();
|
||||||
|
ticker2.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final AtomicReference<World> selectedWorldRef = new AtomicReference<>();
|
||||||
|
|
||||||
|
public CompletableFuture<World> initializeAsync() {
|
||||||
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
|
World selectedWorld = null;
|
||||||
|
while (selectedWorld == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
IrisWorlds.clear();
|
||||||
|
for (World w : Bukkit.getServer().getWorlds()) {
|
||||||
|
if (IrisToolbelt.access(w) != null) {
|
||||||
|
IrisWorlds.add(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!IrisWorlds.isEmpty()) {
|
||||||
|
Random rand = new Random();
|
||||||
|
int randomIndex = rand.nextInt(IrisWorlds.size());
|
||||||
|
selectedWorld = IrisWorlds.get(randomIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedWorld == null) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selectedWorld;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void IrisEngine(){
|
public void IrisEngine(){
|
||||||
ticker = new Looper() {
|
engineTicker = new Looper() {
|
||||||
@Override
|
@Override
|
||||||
protected long loop() {
|
protected long loop() {
|
||||||
try {
|
try {
|
||||||
for (World world : IrisWorlds) {
|
World world = selectedWorldRef.get();
|
||||||
Engine engine = IrisToolbelt.access(world).getEngine();
|
PlatformChunkGenerator generator = IrisToolbelt.access(world);
|
||||||
|
if(generator == null) {
|
||||||
|
initializeAsync().thenAcceptAsync(foundWorld -> selectedWorldRef.set(foundWorld));
|
||||||
|
} else {
|
||||||
|
selectedWorld = world;
|
||||||
}
|
}
|
||||||
PlatformChunkGenerator generator = IrisToolbelt.access(Bukkit.getWorld("localmemtest"));
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
ticker1 = new Looper() {
|
||||||
|
@Override
|
||||||
|
protected long loop() {
|
||||||
|
try {
|
||||||
|
World world = selectedWorld;
|
||||||
|
PlatformChunkGenerator generator = IrisToolbelt.access(world);
|
||||||
|
if(generator != null) {
|
||||||
|
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||||
if (generator != null && generator.getEngine() != null) {
|
if (generator != null && generator.getEngine() != null) {
|
||||||
Engine engine = generator.getEngine();
|
|
||||||
engine.getMantle().trim();
|
engine.getMantle().trim();
|
||||||
} else {
|
} else {
|
||||||
Iris.info("localmemtest is nullmem");
|
Iris.info("something is null 1");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
@@ -73,38 +125,36 @@ public class IrisEngineSVC implements IrisService {
|
|||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
public void IrisStartup(){
|
ticker2 = new Looper() {
|
||||||
tectonicLimit.set(2);
|
@Override
|
||||||
long t = getHardware.getProcessMemory();
|
protected long loop() {
|
||||||
for (; t > 250; ) {
|
try {
|
||||||
tectonicLimit.getAndAdd(1);
|
World world = selectedWorld;
|
||||||
t = t - 250;
|
PlatformChunkGenerator generator = IrisToolbelt.access(world);
|
||||||
}
|
if(generator != null) {
|
||||||
tectonicLimit.set(10); // DEBUG CODE
|
Engine engine = IrisToolbelt.access(world).getEngine();
|
||||||
|
if (generator != null && generator.getEngine() != null) {
|
||||||
for (World w : Bukkit.getServer().getWorlds()) {
|
engine.getMantle().unloadTectonicPlate();
|
||||||
File container = Bukkit.getWorldContainer();
|
|
||||||
Bukkit.getWorldContainer();
|
|
||||||
if(IrisToolbelt.access(w) != null){
|
|
||||||
IrisWorlds.add(w);
|
|
||||||
} else {
|
} else {
|
||||||
File worldDirectory = new File(container, w.getName());
|
Iris.info("something is null 2");
|
||||||
File IrisWorldTest = new File(worldDirectory, "Iris");
|
|
||||||
if (IrisWorldTest.exists()){
|
|
||||||
if(IrisToolbelt.access(w) == null){
|
|
||||||
corruptedIrisWorlds.add(w);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
return 1000;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
ticker.interrupt();
|
ticker1.interrupt();
|
||||||
|
ticker2.interrupt();
|
||||||
|
engineTicker.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -178,6 +178,9 @@ public interface EngineMantle extends IObjectPlacer {
|
|||||||
default void trim() {
|
default void trim() {
|
||||||
getMantle().trim(TimeUnit.SECONDS.toMillis(IrisSettings.get().getPerformance().getMantleKeepAlive()));
|
getMantle().trim(TimeUnit.SECONDS.toMillis(IrisSettings.get().getPerformance().getMantleKeepAlive()));
|
||||||
}
|
}
|
||||||
|
default void unloadTectonicPlate(){
|
||||||
|
getMantle().unloadTectonicPlate();
|
||||||
|
}
|
||||||
|
|
||||||
default MultiBurst burst() {
|
default MultiBurst burst() {
|
||||||
return getEngine().burst();
|
return getEngine().burst();
|
||||||
|
|||||||
@@ -91,12 +91,6 @@ public class Mantle {
|
|||||||
loadedRegions = new KMap<>();
|
loadedRegions = new KMap<>();
|
||||||
lastUse = new KMap<>();
|
lastUse = new KMap<>();
|
||||||
ioBurst = MultiBurst.burst;
|
ioBurst = MultiBurst.burst;
|
||||||
if (!ioTectonicUnload.get()) {
|
|
||||||
this.unloadTectonicPlate();
|
|
||||||
if (!ticker.isAlive()) {
|
|
||||||
ticker.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Iris.debug("Opened The Mantle " + C.DARK_AQUA + dataFolder.getAbsolutePath());
|
Iris.debug("Opened The Mantle " + C.DARK_AQUA + dataFolder.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +415,7 @@ public class Mantle {
|
|||||||
if (closed.get()) {
|
if (closed.get()) {
|
||||||
throw new RuntimeException("The Mantle is closed");
|
throw new RuntimeException("The Mantle is closed");
|
||||||
}
|
}
|
||||||
Iris.info(C.BLUE + "TECTONIC TRIM HAS RUN");
|
Iris.debug(C.BLUE + "TECTONIC TRIM HAS RUN");
|
||||||
if (IrisSettings.get().getPerformance().getAggressiveTectonicThreshold() == -1) {
|
if (IrisSettings.get().getPerformance().getAggressiveTectonicThreshold() == -1) {
|
||||||
forceAggressiveThreshold.set(tectonicLimit.get());
|
forceAggressiveThreshold.set(tectonicLimit.get());
|
||||||
} else {
|
} else {
|
||||||
@@ -493,12 +487,10 @@ public class Mantle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void unloadTectonicPlate() {
|
public synchronized void unloadTectonicPlate() {
|
||||||
ticker = new Looper() {
|
|
||||||
protected long loop() {
|
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
Iris.info(C.DARK_BLUE + "TECTONIC UNLOAD HAS RUN");
|
Iris.debug(C.DARK_BLUE + "TECTONIC UNLOAD HAS RUN");
|
||||||
int threadCount = 1;
|
int threadCount = 1;
|
||||||
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
|
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
|
||||||
List<Long> toUnloadList;
|
List<Long> toUnloadList;
|
||||||
@@ -537,11 +529,8 @@ public class Mantle {
|
|||||||
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
|
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return Math.max(0, 1000-(System.currentTimeMillis()-time));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ioTectonicUnload.set(true);
|
ioTectonicUnload.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user