9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-31 04:46:40 +00:00

add headless to world creation

This commit is contained in:
Julian Krings
2025-01-29 16:36:04 +01:00
parent d32cc281e3
commit e8dd81b014
6 changed files with 812 additions and 663 deletions

View File

@@ -0,0 +1,80 @@
package com.volmit.iris.core.pregenerator;
public class EmptyListener implements PregenListener {
public static PregenListener INSTANCE = new EmptyListener();
@Override
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, int generated, int totalChunks, int chunksRemaining, long eta, long elapsed, String method) {
}
@Override
public void onChunkGenerating(int x, int z) {
}
@Override
public void onChunkGenerated(int x, int z) {
}
@Override
public void onRegionGenerated(int x, int z) {
}
@Override
public void onRegionGenerating(int x, int z) {
}
@Override
public void onChunkCleaned(int x, int z) {
}
@Override
public void onRegionSkipped(int x, int z) {
}
@Override
public void onNetworkStarted(int x, int z) {
}
@Override
public void onNetworkFailed(int x, int z) {
}
@Override
public void onNetworkReclaim(int revert) {
}
@Override
public void onNetworkGeneratedChunk(int x, int z) {
}
@Override
public void onNetworkDownloaded(int x, int z) {
}
@Override
public void onClose() {
}
@Override
public void onSaving() {
}
@Override
public void onChunkExistsInRegionGen(int x, int z) {
}
}

View File

@@ -39,7 +39,11 @@ public class HeadlessPregenMethod implements PregeneratorMethod {
private final MultiBurst burst;
public HeadlessPregenMethod(Engine engine) {
this.max = IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism());
this(engine, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism()));
}
public HeadlessPregenMethod(Engine engine, int threads) {
this.max = Math.max(threads, 4);
this.engine = engine;
this.headless = INMS.get().createHeadless(engine);
burst = new MultiBurst("HeadlessPregen", 8);

View File

@@ -83,6 +83,11 @@ public class IrisCreator {
* Benchmark mode
*/
private boolean benchmark = false;
/**
* Radius of chunks to pregenerate in the headless mode
* if set to -1, headless mode is disabled
*/
private int headlessRadius = 10;
public static boolean removeFromBukkitYml(String name) throws IOException {
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
@@ -126,7 +131,6 @@ public class IrisCreator {
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
}
PlatformChunkGenerator access;
AtomicReference<World> world = new AtomicReference<>();
AtomicDouble pp = new AtomicDouble(0);
O<Boolean> done = new O<>();
@@ -139,30 +143,56 @@ public class IrisCreator {
.create();
ServerConfigurator.installDataPacks(false);
access = (PlatformChunkGenerator) wc.generator();
PlatformChunkGenerator finalAccess1 = access;
PlatformChunkGenerator access = (PlatformChunkGenerator) wc.generator();
if (access == null) {
throw new IrisException("Access is null. Something bad happened.");
}
J.a(() ->
{
Supplier<Integer> g = () -> {
if (finalAccess1 == null || finalAccess1.getEngine() == null) {
return 0;
if (headlessRadius > 0) {
AtomicBoolean failed = new AtomicBoolean(false);
J.a(() -> {
int generated = access.getGenerated();
double total = Math.pow(headlessRadius * 2 + 1, 2);
while (generated < total) {
if (failed.get()) return;
double v = (double) generated / total;
if (sender.isPlayer()) {
sender.sendProgress(v, "Generating headless chunks");
J.sleep(16);
} else {
sender.sendMessage(C.WHITE + "Generating headless chunks " + Form.pc(v) + ((C.GRAY + " (" + ((int) total - generated) + " Left)")));
J.sleep(1000);
}
generated = access.getGenerated();
}
return finalAccess1.getEngine().getGenerated();
};
if(!benchmark) {
if (finalAccess1 == null) return;
int req = finalAccess1.getSpawnChunks().join();
});
while (g.get() < req) {
double v = (double) g.get() / (double) req;
try {
access.prepareSpawnChunks(seed, headlessRadius);
} catch (Throwable e) {
Iris.error("Failed to prepare spawn chunks for " + name);
e.printStackTrace();
failed.set(true);
}
}
J.a(() -> {
if(!benchmark) {
int req = access.getSpawnChunks().join();
int generated = access.getGenerated();
while (generated < req) {
double v = (double) generated / (double) req;
if (sender.isPlayer()) {
sender.sendProgress(v, "Generating");
J.sleep(16);
} else {
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - g.get()) + " Left)")));
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - generated) + " Left)")));
J.sleep(1000);
}
generated = access.getGenerated();
}
}
});

View File

@@ -21,6 +21,8 @@ package com.volmit.iris.engine.platform;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.pregenerator.EmptyListener;
import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.data.chunk.TerrainChunk;
@@ -32,10 +34,13 @@ import com.volmit.iris.engine.object.StudioMode;
import com.volmit.iris.engine.platform.studio.StudioGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.IrisBiomeStorage;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder;
import com.volmit.iris.util.io.ReactiveFolder;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper;
@@ -252,6 +257,10 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
}
private Engine getEngine(WorldInfo world) {
return getEngine(world.getSeed());
}
private Engine getEngine(long seed) {
if (setup.get()) {
return getEngine();
}
@@ -264,7 +273,7 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
}
getWorld().setRawWorldSeed(world.getSeed());
getWorld().setRawWorldSeed(seed);
setupEngine();
setup.set(true);
this.hotloader = studio ? new Looper() {
@@ -335,6 +344,21 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
getEngine(world);
}
@Override
public void prepareSpawnChunks(long seed, int radius) {
if (radius < 0 || new File(world.worldFolder(), "level.dat").exists())
return;
var engine = getEngine(seed);
var headless = new HeadlessPregenMethod(engine, 4);
for (int x = -radius; x <= radius; x++) {
for (int z = -radius; z <= radius; z++) {
headless.generateChunk(x, z, EmptyListener.INSTANCE);
}
}
headless.close();
}
@Override
public void generateNoise(@NotNull WorldInfo world, @NotNull Random random, int x, int z, @NotNull ChunkGenerator.ChunkData d) {
try {

View File

@@ -49,4 +49,12 @@ public interface PlatformChunkGenerator extends Hotloadable, DataProvider {
void touch(World world);
CompletableFuture<Integer> getSpawnChunks();
void prepareSpawnChunks(long seed, int radius);
default int getGenerated() {
Engine engine = getEngine();
if (engine == null) return 0;
return engine.getGenerated();
}
}