implement Headless for 1.20.4

This commit is contained in:
CrazyDev22
2024-05-17 16:01:21 +02:00
parent 4576b95814
commit e1a0481cdf
12 changed files with 914 additions and 19 deletions

View File

@@ -150,10 +150,12 @@ public class CommandDeveloper implements DecreeExecutor {
@Decree(description = "Test")
public void packBenchmark(
@Param(description = "The pack to bench", aliases = {"pack"})
IrisDimension dimension
IrisDimension dimension,
@Param(description = "Headless", defaultValue = "false")
boolean headless
) {
Iris.info("test");
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1);
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1, headless);
}

View File

@@ -0,0 +1,22 @@
package com.volmit.iris.core.nms;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.documentation.RegionCoordinates;
import com.volmit.iris.util.parallel.MultiBurst;
import java.io.Closeable;
public interface IHeadless extends Closeable {
void saveAll();
@RegionCoordinates
boolean exists(int x, int z);
@RegionCoordinates
void generateRegion(MultiBurst burst, int x, int z, PregenListener listener);
@ChunkCoordinates
void generateChunk(int x, int z);
}

View File

@@ -22,6 +22,7 @@ import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.documentation.RegionCoordinates;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
@@ -119,4 +120,8 @@ public interface INMSBinding {
boolean registerDimension(String name, IrisDimension dimension);
void injectBukkit();
default IHeadless createHeadless(Engine engine) {
throw new IllegalStateException("Headless mode not supported");
}
}

View File

@@ -0,0 +1,96 @@
package com.volmit.iris.core.pregenerator.methods;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IHeadless;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.parallel.MultiBurst;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.Future;
public class HeadlessPregenMethod implements PregeneratorMethod {
private final Engine engine;
private final IHeadless headless;
private final MultiBurst burst;
private final KList<Future<?>> futures;
public HeadlessPregenMethod(Engine engine) {
this.engine = engine;
this.headless = INMS.get().createHeadless(engine);
this.burst = new MultiBurst("Iris Headless", Thread.MAX_PRIORITY);
this.futures = new KList<>();
}
@Override
public void init() {}
@Override
public void close() {
waitForChunksPartial(0);
burst.close();
headless.saveAll();
try {
headless.close();
} catch (IOException e) {
Iris.error("Failed to close headless");
e.printStackTrace();
}
}
@Override
public void save() {
headless.saveAll();
}
@Override
public boolean supportsRegions(int x, int z, PregenListener listener) {
return false;
}
@Override
public String getMethod(int x, int z) {
return "Headless";
}
@Override
public void generateRegion(int x, int z, PregenListener listener) {}
@Override
public void generateChunk(int x, int z, PregenListener listener) {
futures.removeIf(Future::isDone);
waitForChunksPartial(512);
futures.add(burst.complete(() -> {
listener.onChunkGenerating(x, z);
headless.generateChunk(x, z);
listener.onChunkGenerated(x, z);
}));
}
@Override
public Mantle getMantle() {
return engine.getMantle().getMantle();
}
private void waitForChunksPartial(int maxWaiting) {
futures.removeWhere(Objects::isNull);
while (futures.size() > maxWaiting) {
try {
Future<?> i = futures.remove(0);
if (i == null) {
continue;
}
i.get();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}

View File

@@ -2,9 +2,17 @@ package com.volmit.iris.core.tools;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod;
import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisWorld;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.exceptions.IrisException;
@@ -36,13 +44,16 @@ public class IrisPackBenchmarking {
public static boolean benchmarkInProgress = false;
private IrisDimension IrisDimension;
private int radius;
private final boolean headless;
private boolean finished = false;
private Engine engine;
PrecisionStopwatch stopwatch;
public IrisPackBenchmarking(IrisDimension dimension, int r) {
public IrisPackBenchmarking(IrisDimension dimension, int r, boolean headless) {
instance = this;
this.IrisDimension = dimension;
this.radius = r;
this.headless = headless;
runBenchmark();
}
@@ -52,12 +63,12 @@ public class IrisPackBenchmarking {
service.submit(() -> {
Iris.info("Setting up benchmark environment ");
benchmarkInProgress = true;
File file = new File("benchmark");
File file = new File(Bukkit.getWorldContainer(), "benchmark");
if (file.exists()) {
deleteDirectory(file.toPath());
}
createBenchmark();
while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) {
engine = createBenchmark();
while (!headless && !IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) {
J.sleep(1000);
Iris.debug("Iris PackBenchmark: Waiting...");
}
@@ -75,7 +86,6 @@ public class IrisPackBenchmarking {
public void finishedBenchmark(KList<Integer> cps) {
try {
String time = Form.duration(stopwatch.getMillis());
Engine engine = IrisToolbelt.access(Bukkit.getWorld("benchmark")).getEngine();
Iris.info("-----------------");
Iris.info("Results:");
Iris.info("- Total time: " + time);
@@ -88,8 +98,8 @@ public class IrisPackBenchmarking {
File profilers = new File("plugins" + File.separator + "Iris" + File.separator + "packbenchmarks");
profilers.mkdir();
File results = new File("plugins " + File.separator + "Iris", IrisDimension.getName() + LocalDateTime.now(Clock.systemDefaultZone()) + ".txt");
results.createNewFile();
File results = new File("plugins" + File.separator + "Iris", IrisDimension.getName() + " " + LocalDateTime.now(Clock.systemDefaultZone()).toString().replace(':', '-') + ".txt");
results.getParentFile().mkdirs();
KMap<String, Double> metrics = engine.getMetrics().pull();
try (FileWriter writer = new FileWriter(results)) {
writer.write("-----------------\n");
@@ -123,15 +133,32 @@ public class IrisPackBenchmarking {
e.printStackTrace();
}
}
private void createBenchmark(){
private Engine createBenchmark(){
try {
IrisToolbelt.createWorld()
if (headless) {
IrisWorld world = IrisWorld.builder()
.name("benchmark")
.minHeight(IrisDimension.getMinHeight())
.maxHeight(IrisDimension.getMaxHeight())
.seed(1337)
.worldFolder(new File(Bukkit.getWorldContainer(), "benchmark"))
.environment(IrisDimension.getEnvironment())
.build();
Iris.service(StudioSVC.class).installIntoWorld(
Iris.getSender(),
IrisDimension.getLoadKey(),
world.worldFolder());
var data = IrisData.get(new File(world.worldFolder(), "iris/pack"));
var dim = data.getDimensionLoader().load(IrisDimension.getLoadKey());
return new IrisEngine(new EngineTarget(world, dim, data), false);
}
return IrisToolbelt.access(IrisToolbelt.createWorld()
.dimension(IrisDimension.getName())
.name("benchmark")
.seed(1337)
.studio(false)
.benchmark(true)
.create();
.create()).getEngine();
} catch (IrisException e) {
throw new RuntimeException(e);
}
@@ -146,8 +173,8 @@ public class IrisPackBenchmarking {
.center(new Position2(x, z))
.width(5)
.height(5)
.build(), Bukkit.getWorld("benchmark")
);
.build(), headless ? new HeadlessPregenMethod(engine) : new HybridPregenMethod(engine.getWorld().realWorld(),
IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())), engine);
}
private double calculateAverage(KList<Integer> list) {

View File

@@ -286,6 +286,13 @@ public class IrisEngine implements Engine {
return generated.get();
}
@Override
public void addGenerated() {
if (generated.incrementAndGet() == 661) {
J.a(() -> getData().savePrefetch(this));
}
}
@Override
public double getGeneratedPerSecond() {
if (perSecondLatch.flip()) {
@@ -468,11 +475,7 @@ public class IrisEngine implements Engine {
getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.REAL, true);
getMetrics().getTotal().put(p.getMilliseconds());
generated.incrementAndGet();
if (generated.get() == 661) {
J.a(() -> getData().savePrefetch(this));
}
addGenerated();
} catch (Throwable e) {
Iris.reportError(e);
fail("Failed to generate " + x + ", " + z, e);

View File

@@ -577,6 +577,8 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
int getGenerated();
void addGenerated();
default <T> IrisPosition lookForStreamResult(T find, ProceduralStream<T> stream, Function2<T, T, Boolean> matcher, long timeout) {
AtomicInteger checked = new AtomicInteger();
AtomicLong time = new AtomicLong(M.ms());