Fast pregen

This commit is contained in:
RePixelatedMC
2024-08-02 23:17:52 +02:00
parent 488b76d1d2
commit cad679a808
6 changed files with 85 additions and 32 deletions
@@ -237,6 +237,11 @@ public class PregeneratorJob implements PregenListener {
draw(x, z, COLOR_GENERATING); draw(x, z, COLOR_GENERATING);
} }
@Override
public void onServerShutdown() {
}
@Override @Override
public void onChunkGenerated(int x, int z) { public void onChunkGenerated(int x, int z) {
if (engine != null) { if (engine != null) {
@@ -251,6 +256,27 @@ public class PregeneratorJob implements PregenListener {
public void onRegionGenerated(int x, int z) { public void onRegionGenerated(int x, int z) {
shouldGc(); shouldGc();
rgc++; rgc++;
// Each region is 32x32 chunks
for (int chunkOffsetX = 0; chunkOffsetX < 32; chunkOffsetX++) {
for (int chunkOffsetZ = 0; chunkOffsetZ < 32; chunkOffsetZ++) {
// Calculate actual chunk coordinates
int chunkX = (x << 5) + chunkOffsetX;
int chunkZ = (z << 5) + chunkOffsetZ;
if (engine != null) {
// Calculate the center block of the chunk
int centerBlockX = (chunkX << 4) + 8;
int centerBlockZ = (chunkZ << 4) + 8;
// Draw the chunk
draw(chunkX, chunkZ, engine.draw(centerBlockX, centerBlockZ));
} else {
// If engine is null, use the default color
draw(chunkX, chunkZ, COLOR_GENERATED);
}
}
}
} }
private void shouldGc() { private void shouldGc() {
@@ -18,11 +18,9 @@
package com.volmit.iris.core.pregenerator; package com.volmit.iris.core.pregenerator;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.IHeadless;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import com.volmit.iris.core.pack.IrisPack;
import com.volmit.iris.core.tools.IrisPackBenchmarking; import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
@@ -33,7 +31,6 @@ import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.M; 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.misc.E;
import com.volmit.iris.util.nbt.mca.Chunk; import com.volmit.iris.util.nbt.mca.Chunk;
import com.volmit.iris.util.nbt.mca.MCAFile; import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil; import com.volmit.iris.util.nbt.mca.MCAUtil;
@@ -44,7 +41,11 @@ import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper; import com.volmit.iris.util.scheduling.Looper;
import org.bukkit.World; import org.bukkit.World;
import java.io.File; import java.io.*;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean; 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;
@@ -54,6 +55,7 @@ import java.util.regex.Pattern;
public class IrisPregenerator { public class IrisPregenerator {
private final String saveFile = "regions.json";
private final PregenTask task; private final PregenTask task;
private final PregeneratorMethod generator; private final PregeneratorMethod generator;
private final PregenListener listener; private final PregenListener listener;
@@ -71,14 +73,14 @@ public class IrisPregenerator {
private final AtomicLong startTime; private final AtomicLong startTime;
private final ChronoLatch minuteLatch; private final ChronoLatch minuteLatch;
private final AtomicReference<String> currentGeneratorMethod; private final AtomicReference<String> currentGeneratorMethod;
private final KSet<Position2> generatedRegions; private Set<Position2> generatedRegions;
private final KSet<Position2> retry; private final KSet<Position2> retry;
private final KSet<Position2> net; private final KSet<Position2> net;
private final ChronoLatch cl; private final ChronoLatch cl;
private final ChronoLatch saveLatch = new ChronoLatch(30000); private final ChronoLatch saveLatch = new ChronoLatch(30000);
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) { public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
generatedRegions = new KSet<>(); generatedRegions = ConcurrentHashMap.newKeySet();
this.listener = listenify(listener); this.listener = listenify(listener);
cl = new ChronoLatch(5000); cl = new ChronoLatch(5000);
this.shutdown = new AtomicBoolean(false); this.shutdown = new AtomicBoolean(false);
@@ -97,6 +99,7 @@ public class IrisPregenerator {
generatedLast = new AtomicInteger(0); generatedLast = new AtomicInteger(0);
generatedLastMinute = new AtomicInteger(0); generatedLastMinute = new AtomicInteger(0);
totalChunks = new AtomicInteger(0); totalChunks = new AtomicInteger(0);
loadCompletedRegions();
IrisToolbelt.access(generator.getWorld()).getEngine().saveEngineData(); IrisToolbelt.access(generator.getWorld()).getEngine().saveEngineData();
task.iterateRegions((_a, _b) -> totalChunks.addAndGet(1024)); task.iterateRegions((_a, _b) -> totalChunks.addAndGet(1024));
startTime = new AtomicLong(M.ms()); startTime = new AtomicLong(M.ms());
@@ -183,6 +186,7 @@ public class IrisPregenerator {
generator.close(); generator.close();
ticker.interrupt(); ticker.interrupt();
listener.onClose(); listener.onClose();
saveCompletedRegions();
Mantle mantle = getMantle(); Mantle mantle = getMantle();
if (mantle != null) { if (mantle != null) {
mantle.trim(0, 0); mantle.trim(0, 0);
@@ -239,6 +243,7 @@ public class IrisPregenerator {
Position2 pos = new Position2(x, z); Position2 pos = new Position2(x, z);
if (generatedRegions.contains(pos)) { if (generatedRegions.contains(pos)) {
listener.onRegionGenerated(x,z);
return; return;
} }
@@ -281,6 +286,31 @@ public class IrisPregenerator {
generator.supportsRegions(x, z, listener); generator.supportsRegions(x, z, listener);
} }
public void saveCompletedRegions() {
Gson gson = new Gson();
try (Writer writer = new FileWriter(generator.getWorld().getWorldFolder().getPath() + "/" + saveFile)) {
gson.toJson(new HashSet<>(generatedRegions), writer);
} catch (IOException e) {
e.printStackTrace();
}
}
public void loadCompletedRegions() {
Gson gson = new Gson();
try (Reader reader = new FileReader(generator.getWorld().getWorldFolder().getPath() + "/" + saveFile)) {
Type setType = new TypeToken<HashSet<Position2>>(){}.getType();
Set<Position2> loadedSet = gson.fromJson(reader, setType);
if (loadedSet != null) {
generatedRegions.clear();
generatedRegions.addAll(loadedSet);
}
} catch (FileNotFoundException e) {
// all fine
} catch (IOException e) {
e.printStackTrace();
}
}
public void pause() { public void pause() {
paused.set(true); paused.set(true);
} }
@@ -301,6 +331,11 @@ public class IrisPregenerator {
listener.onChunkGenerating(x, z); listener.onChunkGenerating(x, z);
} }
@Override
public void onServerShutdown() {
}
@Override @Override
public void onChunkGenerated(int x, int z) { public void onChunkGenerated(int x, int z) {
listener.onChunkGenerated(x, z); listener.onChunkGenerated(x, z);
@@ -309,6 +344,9 @@ public class IrisPregenerator {
@Override @Override
public void onRegionGenerated(int x, int z) { public void onRegionGenerated(int x, int z) {
generatedRegions.add(new Position2(x, z));
saveCompletedRegions();
generated.addAndGet(1024); // todo. not like this.
listener.onRegionGenerated(x, z); listener.onRegionGenerated(x, z);
} }
@@ -23,6 +23,8 @@ public interface PregenListener {
void onChunkGenerating(int x, int z); void onChunkGenerating(int x, int z);
void onServerShutdown();
void onChunkGenerated(int x, int z); void onChunkGenerated(int x, int z);
void onRegionGenerated(int x, int z); void onRegionGenerated(int x, int z);
@@ -36,10 +36,8 @@ import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@@ -47,6 +45,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
private final World world; private final World world;
private final Engine engine; private final Engine engine;
private final MultiBurst burst; private final MultiBurst burst;
private final KList<Future<?>> future; private final KList<Future<?>> future;
private final Map<Chunk, Long> lastUse; private final Map<Chunk, Long> lastUse;
@@ -85,15 +84,14 @@ public class AsyncPregenMethod implements PregeneratorMethod {
private void completeChunk(int x, int z, PregenListener listener) { private void completeChunk(int x, int z, PregenListener listener) {
try { try {
if (!engine.exists(x,z)) { future.add(PaperLib.getChunkAtAsync(world, x, z, true).thenApply((i) -> {
future.add(PaperLib.getChunkAtAsync(world, x, z, true).thenApply((i) -> { if (i == null) return 0;
if (i == null) return 0; lastUse.put(i, M.ms());
lastUse.put(i, M.ms()); listener.onChunkGenerated(x, z);
listener.onChunkGenerated(x, z); listener.onChunkCleaned(x, z);
listener.onChunkCleaned(x, z); return 0;
return 0; }));
}));
}
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -73,7 +73,6 @@ import java.util.concurrent.locks.ReentrantLock;
@EqualsAndHashCode(exclude = "context") @EqualsAndHashCode(exclude = "context")
@ToString(exclude = "context") @ToString(exclude = "context")
public class IrisEngine implements Engine { public class IrisEngine implements Engine {
private Set<String> chunks = ConcurrentHashMap.newKeySet();
private final AtomicInteger bud; private final AtomicInteger bud;
private final AtomicInteger buds; private final AtomicInteger buds;
private final AtomicInteger generated; private final AtomicInteger generated;
@@ -137,7 +136,6 @@ public class IrisEngine implements Engine {
failing = false; failing = false;
closed = false; closed = false;
art = J.ar(this::tickRandomPlayer, 0); art = J.ar(this::tickRandomPlayer, 0);
chunks = getEngineData().getGeneratedChunks();
setupEngine(); setupEngine();
Iris.debug("Engine Initialized " + getCacheID()); Iris.debug("Engine Initialized " + getCacheID());
} }
@@ -288,7 +286,6 @@ public class IrisEngine implements Engine {
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json"); File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json");
f.getParentFile().mkdirs(); f.getParentFile().mkdirs();
try { try {
getEngineData().addGeneratedChunk(chunks);
IO.writeAll(f, new Gson().toJson(getEngineData())); IO.writeAll(f, new Gson().toJson(getEngineData()));
Iris.debug("Saved Engine Data"); Iris.debug("Saved Engine Data");
} catch (IOException e) { } catch (IOException e) {
@@ -311,7 +308,6 @@ public class IrisEngine implements Engine {
public void addGenerated(int x, int z) { public void addGenerated(int x, int z) {
try { try {
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json"); File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json");
chunks.add(x + "," + z);
if (generated.incrementAndGet() == 661) { if (generated.incrementAndGet() == 661) {
J.a(() -> getData().savePrefetch(this)); J.a(() -> getData().savePrefetch(this));
} }
@@ -515,11 +511,6 @@ public class IrisEngine implements Engine {
bud.incrementAndGet(); bud.incrementAndGet();
} }
@Override
public boolean exists(int x, int z) {
return chunks.contains(x + "," + z);
}
@Override @Override
public IrisBiome getFocus() { public IrisBiome getFocus() {
if (getDimension().getFocus() == null || getDimension().getFocus().trim().isEmpty()) { if (getDimension().getFocus() == null || getDimension().getFocus().trim().isEmpty()) {
@@ -266,8 +266,6 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
void blockUpdatedMetric(); void blockUpdatedMetric();
boolean exists(int x, int z);
@ChunkCoordinates @ChunkCoordinates
@Override @Override
default void updateChunk(Chunk c) { default void updateChunk(Chunk c) {