mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-18 23:01:07 +00:00
Fast pregen
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
+11
-13
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user