mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-26 14:00:26 +00:00
add headless to world creation
This commit is contained in:
6 files changed
+812
-663
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-1
@@ -39,7 +39,11 @@ public class HeadlessPregenMethod implements PregeneratorMethod {
|
|||||||
private final MultiBurst burst;
|
private final MultiBurst burst;
|
||||||
|
|
||||||
public HeadlessPregenMethod(Engine engine) {
|
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.engine = engine;
|
||||||
this.headless = INMS.get().createHeadless(engine);
|
this.headless = INMS.get().createHeadless(engine);
|
||||||
burst = new MultiBurst("HeadlessPregen", 8);
|
burst = new MultiBurst("HeadlessPregen", 8);
|
||||||
|
|||||||
@@ -83,6 +83,11 @@ public class IrisCreator {
|
|||||||
* Benchmark mode
|
* Benchmark mode
|
||||||
*/
|
*/
|
||||||
private boolean benchmark = false;
|
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 {
|
public static boolean removeFromBukkitYml(String name) throws IOException {
|
||||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
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()));
|
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformChunkGenerator access;
|
|
||||||
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<>();
|
||||||
@@ -139,30 +143,56 @@ public class IrisCreator {
|
|||||||
.create();
|
.create();
|
||||||
ServerConfigurator.installDataPacks(false);
|
ServerConfigurator.installDataPacks(false);
|
||||||
|
|
||||||
access = (PlatformChunkGenerator) wc.generator();
|
PlatformChunkGenerator access = (PlatformChunkGenerator) wc.generator();
|
||||||
PlatformChunkGenerator finalAccess1 = access;
|
if (access == null) {
|
||||||
|
throw new IrisException("Access is null. Something bad happened.");
|
||||||
|
}
|
||||||
|
|
||||||
J.a(() ->
|
if (headlessRadius > 0) {
|
||||||
{
|
AtomicBoolean failed = new AtomicBoolean(false);
|
||||||
Supplier<Integer> g = () -> {
|
J.a(() -> {
|
||||||
if (finalAccess1 == null || finalAccess1.getEngine() == null) {
|
int generated = access.getGenerated();
|
||||||
return 0;
|
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) {
|
try {
|
||||||
double v = (double) g.get() / (double) req;
|
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()) {
|
if (sender.isPlayer()) {
|
||||||
sender.sendProgress(v, "Generating");
|
sender.sendProgress(v, "Generating");
|
||||||
J.sleep(16);
|
J.sleep(16);
|
||||||
} else {
|
} 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);
|
J.sleep(1000);
|
||||||
}
|
}
|
||||||
|
generated = access.getGenerated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -32,10 +34,13 @@ import com.volmit.iris.engine.object.StudioMode;
|
|||||||
import com.volmit.iris.engine.platform.studio.StudioGenerator;
|
import com.volmit.iris.engine.platform.studio.StudioGenerator;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.data.IrisBiomeStorage;
|
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.Hunk;
|
||||||
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
|
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
|
||||||
import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder;
|
import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder;
|
||||||
import com.volmit.iris.util.io.ReactiveFolder;
|
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.ChronoLatch;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.Looper;
|
import com.volmit.iris.util.scheduling.Looper;
|
||||||
@@ -252,6 +257,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();
|
||||||
}
|
}
|
||||||
@@ -264,7 +273,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() {
|
||||||
@@ -335,6 +344,21 @@ 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, 4);
|
||||||
|
|
||||||
|
for (int x = -radius; x <= radius; x++) {
|
||||||
|
for (int z = -radius; z <= radius; z++) {
|
||||||
|
headless.generateChunk(x, z, EmptyListener.INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headless.close();
|
||||||
|
}
|
||||||
|
|
||||||
@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 {
|
||||||
|
|||||||
@@ -49,4 +49,12 @@ 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);
|
||||||
|
|
||||||
|
default int getGenerated() {
|
||||||
|
Engine engine = getEngine();
|
||||||
|
if (engine == null) return 0;
|
||||||
|
return engine.getGenerated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user