add headless pregen to world creation

This commit is contained in:
Julian Krings 2024-08-22 20:31:24 +02:00
parent 26aae2b730
commit 4434cf6475
5 changed files with 154 additions and 36 deletions

View File

@ -103,6 +103,8 @@ public class CommandIris implements DecreeExecutor {
IrisDimension type, IrisDimension type,
@Param(description = "The seed to generate the world with", defaultValue = "1337") @Param(description = "The seed to generate the world with", defaultValue = "1337")
long seed, long seed,
@Param(description = "The radius of chunks to generate in headless mode (-1 to disable)", defaultValue = "10", aliases = "radius")
int headlessRadius,
@Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false") @Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false")
boolean vanillaheight boolean vanillaheight
) { ) {
@ -132,6 +134,7 @@ public class CommandIris implements DecreeExecutor {
.sender(sender()) .sender(sender())
.studio(false) .studio(false)
.smartVanillaHeight(vanillaheight) .smartVanillaHeight(vanillaheight)
.headlessRadius(headlessRadius)
.create(); .create();
} catch (Throwable e) { } catch (Throwable e) {
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details."); sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");

View File

@ -0,0 +1,87 @@
package com.volmit.iris.core.pregenerator;
public final class EmptyListener implements PregenListener {
public static final PregenListener INSTANCE = new EmptyListener();
private 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 onServerShutdown() {
}
@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

@ -83,6 +83,11 @@ public class IrisCreator {
*/ */
private boolean benchmark = false; private boolean benchmark = false;
private boolean smartVanillaHeight = false; private boolean smartVanillaHeight = 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 { public static boolean removeFromBukkitYml(String name) throws IOException {
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML); YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
@ -130,7 +135,6 @@ public class IrisCreator {
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name())); Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
} }
PlatformChunkGenerator access = null;
AtomicReference<World> world = new AtomicReference<>(); AtomicReference<World> world = new AtomicReference<>();
AtomicDouble pp = new AtomicDouble(0); AtomicDouble pp = new AtomicDouble(0);
O<Boolean> done = new O<>(); O<Boolean> done = new O<>();
@ -142,21 +146,26 @@ public class IrisCreator {
.studio(studio) .studio(studio)
.smartVanillaHeight(smartVanillaHeight) .smartVanillaHeight(smartVanillaHeight)
.create(); .create();
PlatformChunkGenerator access = (PlatformChunkGenerator) wc.generator();
if (access == null) {
throw new IrisException("Access is null. Something bad happened.");
}
access = (PlatformChunkGenerator) wc.generator(); try {
PlatformChunkGenerator finalAccess1 = access; access.prepareSpawnChunks(seed, headlessRadius);
} catch (Throwable e) {
J.a(() -> Iris.error("Failed to prepare spawn chunks for " + name);
{ e.printStackTrace();
}
J.a(() -> {
Supplier<Integer> g = () -> { Supplier<Integer> g = () -> {
if (finalAccess1 == null || finalAccess1.getEngine() == null) { if (access.getEngine() == null) {
return 0; return 0;
} }
return finalAccess1.getEngine().getGenerated(); return access.getEngine().getGenerated();
}; };
if (!benchmark) { if (!benchmark) {
if (finalAccess1 == null) return; int req = access.getSpawnChunks().join();
int req = finalAccess1.getSpawnChunks().join();
while (g.get() < req) { while (g.get() < req) {
double v = (double) g.get() / (double) req; double v = (double) g.get() / (double) req;
@ -180,10 +189,6 @@ public class IrisCreator {
e.printStackTrace(); e.printStackTrace();
} }
if (access == null) {
throw new IrisException("Access is null. Something bad happened.");
}
done.set(true); done.set(true);
if (sender.isPlayer() && !benchmark) { if (sender.isPlayer() && !benchmark) {

View File

@ -21,6 +21,8 @@ package com.volmit.iris.engine.platform;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS; 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.core.service.StudioSVC;
import com.volmit.iris.engine.IrisEngine; import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.data.chunk.TerrainChunk; import com.volmit.iris.engine.data.chunk.TerrainChunk;
@ -132,27 +134,26 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
if (initialized || !world.name().equals(event.getWorld().getName())) if (initialized || !world.name().equals(event.getWorld().getName()))
return; return;
world.setRawWorldSeed(event.getWorld().getSeed()); world.setRawWorldSeed(event.getWorld().getSeed());
Engine engine = getEngine(event.getWorld()); Engine engine = getEngine(event.getWorld());
if (engine == null) { if (engine == null) {
Iris.warn("Failed to get Engine!"); Iris.warn("Failed to get Engine!");
J.s(() -> { J.s(() -> {
Engine engine1 = getEngine(event.getWorld()); Engine engine1 = getEngine(event.getWorld());
if (engine1 != null) { if (engine1 != null) {
try { try {
INMS.get().inject(event.getWorld().getSeed(), engine1, event.getWorld()); INMS.get().inject(event.getWorld().getSeed(), engine1, event.getWorld());
Iris.info("Injected Iris Biome Source into " + event.getWorld().getName()); Iris.info("Injected Iris Biome Source into " + event.getWorld().getName());
initialized = true; initialized = true;
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
}, 10); }, 10);
} else { } else {
INMS.get().inject(event.getWorld().getSeed(), engine, event.getWorld()); INMS.get().inject(event.getWorld().getSeed(), engine, event.getWorld());
Iris.info("Injected Iris Biome Source into " + event.getWorld().getName()); Iris.info("Injected Iris Biome Source into " + event.getWorld().getName());
spawnChunks.complete(INMS.get().getSpawnChunkCount(event.getWorld())); spawnChunks.complete(INMS.get().getSpawnChunkCount(event.getWorld()));
initialized = true; initialized = true;
} }
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
@ -265,7 +266,10 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
} }
private Engine getEngine(WorldInfo world) { private Engine getEngine(WorldInfo world) {
return getEngine(world.getSeed());
}
private Engine getEngine(long seed) {
if (setup.get()) { if (setup.get()) {
return getEngine(); return getEngine();
} }
@ -278,7 +282,7 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
} }
getWorld().setRawWorldSeed(world.getSeed()); getWorld().setRawWorldSeed(seed);
setupEngine(); setupEngine();
setup.set(true); setup.set(true);
this.hotloader = studio ? new Looper() { this.hotloader = studio ? new Looper() {
@ -349,6 +353,23 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
getEngine(world); 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);
Iris.info("Generating " + world.name() + " in headless mode");
for (int x = -radius; x <= radius; x++) {
for (int z = -radius; z <= radius; z++) {
headless.generateChunk(x, z, EmptyListener.INSTANCE);
}
}
headless.close();
Iris.info("Done generating " + world.name() + " in headless mode");
}
@Override @Override
public void generateNoise(@NotNull WorldInfo world, @NotNull Random random, int x, int z, @NotNull ChunkGenerator.ChunkData d) { public void generateNoise(@NotNull WorldInfo world, @NotNull Random random, int x, int z, @NotNull ChunkGenerator.ChunkData d) {
try { try {

View File

@ -49,4 +49,6 @@ public interface PlatformChunkGenerator extends Hotloadable, DataProvider {
void touch(World world); void touch(World world);
CompletableFuture<Integer> getSpawnChunks(); CompletableFuture<Integer> getSpawnChunks();
void prepareSpawnChunks(long seed, int radius);
} }