From f9e934fa1a5016f89a1dbb088799c22301bcc77b Mon Sep 17 00:00:00 2001 From: cyberpwn Date: Wed, 22 Sep 2021 12:54:06 -0400 Subject: [PATCH] Auto stash before revert of "Drop it " --- src/main/java/com/volmit/iris/Iris.java | 6 +- .../volmit/iris/core/gui/PregeneratorJob.java | 52 ++++++- .../core/pregenerator/IrisPregenerator.java | 5 + .../core/pregenerator/PregenListener.java | 2 + .../iris/core/pregenerator/PregenTask.java | 52 ++++++- .../methods/AsyncPregenMethod.java | 1 + .../methods/MedievalPregenMethod.java | 1 + .../syndicate/SyndicateServer.java | 5 + .../volmit/iris/core/tools/IrisToolbelt.java | 11 +- .../volmit/iris/engine/IrisWorldManager.java | 5 + .../volmit/iris/engine/framework/Engine.java | 10 ++ .../iris/engine/mantle/EngineMantle.java | 46 +++++- .../engine/platform/HeadlessGenerator.java | 33 +++- .../iris/util/format/MemoryMonitor.java | 147 ++++++++++++++++++ .../volmit/iris/util/mantle/MantleFlag.java | 4 +- .../volmit/iris/util/matter/MatterSlice.java | 4 +- .../volmit/iris/util/matter/MatterTest.java | 99 ------------ .../com/volmit/iris/util/nbt/mca/MCAFile.java | 14 ++ .../volmit/iris/util/nbt/mca/NBTWorld.java | 4 + 19 files changed, 376 insertions(+), 125 deletions(-) create mode 100644 src/main/java/com/volmit/iris/util/format/MemoryMonitor.java delete mode 100644 src/main/java/com/volmit/iris/util/matter/MatterTest.java diff --git a/src/main/java/com/volmit/iris/Iris.java b/src/main/java/com/volmit/iris/Iris.java index 3de7ab2b9..3a3b91acd 100644 --- a/src/main/java/com/volmit/iris/Iris.java +++ b/src/main/java/com/volmit/iris/Iris.java @@ -26,10 +26,7 @@ import com.volmit.iris.core.link.MythicMobsLink; import com.volmit.iris.core.link.OraxenLink; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.nms.INMS; -import com.volmit.iris.core.service.PreservationSVC; import com.volmit.iris.core.service.StudioSVC; -import com.volmit.iris.engine.object.IrisBiome; -import com.volmit.iris.engine.object.IrisBiomeCustom; import com.volmit.iris.engine.object.IrisCompat; import com.volmit.iris.engine.object.IrisDimension; import com.volmit.iris.engine.object.IrisWorld; @@ -37,10 +34,10 @@ import com.volmit.iris.engine.platform.BukkitChunkGenerator; import com.volmit.iris.engine.platform.DummyChunkGenerator; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; -import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.exceptions.IrisException; import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.Form; +import com.volmit.iris.util.format.MemoryMonitor; import com.volmit.iris.util.function.NastyRunnable; import com.volmit.iris.util.io.FileWatcher; import com.volmit.iris.util.io.IO; @@ -48,7 +45,6 @@ import com.volmit.iris.util.io.InstanceState; import com.volmit.iris.util.io.JarScanner; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.RNG; -import com.volmit.iris.util.matter.MatterTest; import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.plugin.IrisService; import com.volmit.iris.util.plugin.Metrics; diff --git a/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java b/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java index eb0af7c63..aa60b0f1c 100644 --- a/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java +++ b/src/main/java/com/volmit/iris/core/gui/PregeneratorJob.java @@ -25,12 +25,15 @@ import com.volmit.iris.core.pregenerator.PregenListener; import com.volmit.iris.core.pregenerator.PregenTask; import com.volmit.iris.core.pregenerator.PregeneratorMethod; import com.volmit.iris.engine.data.cache.Cache; +import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.format.Form; +import com.volmit.iris.util.format.MemoryMonitor; import com.volmit.iris.util.function.Consumer2; import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.Position2; +import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.Looper; @@ -44,6 +47,7 @@ import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.image.BufferedImage; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; @@ -51,11 +55,13 @@ public class PregeneratorJob implements PregenListener { private static final Color COLOR_EXISTS = parseColor("#4d7d5b"); private static final Color COLOR_BLACK = parseColor("#4d7d5b"); private static final Color COLOR_MANTLE = parseColor("#3c2773"); - private static final Color COLOR_GENERATING = parseColor("#0062ff"); + private static final Color COLOR_GENERATING = parseColor("#66967f"); private static final Color COLOR_NETWORK = parseColor("#a863c2"); private static final Color COLOR_NETWORK_GENERATING = parseColor("#836b8c"); - private static final Color COLOR_GENERATED = parseColor("#34eb93"); + private static final Color COLOR_GENERATED = parseColor("#65c295"); + private static final Color COLOR_CLEANED = parseColor("#34eb93"); public static PregeneratorJob instance; + private final MemoryMonitor monitor; private final PregenTask task; private final boolean saving; private final KList> onProgress = new KList<>(); @@ -65,10 +71,15 @@ public class PregeneratorJob implements PregenListener { private final Position2 max; private JFrame frame; private PregenRenderer renderer; + private int rgc = 0; + private ChronoLatch cl = new ChronoLatch(TimeUnit.MINUTES.toMillis(1)); private String[] info; + private Engine engine; - public PregeneratorJob(PregenTask task, PregeneratorMethod method) { + public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) { + this.engine = engine; instance = this; + monitor = new MemoryMonitor(50); saving = false; info = new String[]{"Initializing..."}; this.task = task; @@ -181,6 +192,7 @@ public class PregeneratorJob implements PregenListener { public void close() { J.a(() -> { try { + monitor.close(); J.sleep(3000); frame.setVisible(false); } catch (Throwable e) { @@ -220,6 +232,8 @@ public class PregeneratorJob implements PregenListener { "Speed: " + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m", Form.duration(eta, 2) + " Remaining " + " (" + Form.duration(elapsed, 2) + " Elapsed)", "Generation Method: " + method, + "Memory: " + Form.memSize(monitor.getUsedBytes(), 2) + " (" + Form.pc(monitor.getUsagePercent(), 0) + ") Pressure: " + Form.memSize(monitor.getPressure(), 0) + "/s", + }; for (Consumer i : onProgress) { @@ -229,17 +243,36 @@ public class PregeneratorJob implements PregenListener { @Override public void onChunkGenerating(int x, int z) { + if(engine != null) + { + return; + } + draw(x, z, COLOR_GENERATING); } @Override public void onChunkGenerated(int x, int z) { + if(engine != null) + { + draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8)); + return; + } + draw(x, z, COLOR_GENERATED); } @Override public void onRegionGenerated(int x, int z) { + shouldGc(); + rgc++; + } + private void shouldGc() { + if(cl.flip() && rgc > 16) + { + System.gc(); + } } @Override @@ -247,6 +280,11 @@ public class PregeneratorJob implements PregenListener { } + @Override + public void onChunkCleaned(int x, int z) { + //draw(x, z, COLOR_CLEANED); + } + @Override public void onRegionSkipped(int x, int z) { @@ -291,6 +329,12 @@ public class PregeneratorJob implements PregenListener { @Override public void onChunkExistsInRegionGen(int x, int z) { + if(engine != null) + { + draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8)); + return; + } + draw(x, z, COLOR_EXISTS); } @@ -347,7 +391,7 @@ public class PregeneratorJob implements PregenListener { l.unlock(); g.drawImage(image, 0, 0, getParent().getWidth(), getParent().getHeight(), (img, infoflags, x, y, width, height) -> true); g.setColor(Color.WHITE); - g.setFont(new Font("Hevetica", Font.BOLD, 28)); + g.setFont(new Font("Hevetica", Font.BOLD, 13)); String[] prog = job.getProgress(); int h = g.getFontMetrics().getHeight() + 5; int hh = 20; diff --git a/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java b/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java index affb2ca02..e0afec95f 100644 --- a/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java +++ b/src/main/java/com/volmit/iris/core/pregenerator/IrisPregenerator.java @@ -223,6 +223,11 @@ public class IrisPregenerator { listener.onRegionGenerating(x, z); } + @Override + public void onChunkCleaned(int x, int z) { + listener.onChunkCleaned(x, z); + } + @Override public void onRegionSkipped(int x, int z) { listener.onRegionSkipped(x, z); diff --git a/src/main/java/com/volmit/iris/core/pregenerator/PregenListener.java b/src/main/java/com/volmit/iris/core/pregenerator/PregenListener.java index 16b8d0b2c..52684f52f 100644 --- a/src/main/java/com/volmit/iris/core/pregenerator/PregenListener.java +++ b/src/main/java/com/volmit/iris/core/pregenerator/PregenListener.java @@ -29,6 +29,8 @@ public interface PregenListener { void onRegionGenerating(int x, int z); + void onChunkCleaned(int x, int z); + void onRegionSkipped(int x, int z); void onNetworkStarted(int x, int z); diff --git a/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java b/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java index 9b90d59e5..42fe6671f 100644 --- a/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java +++ b/src/main/java/com/volmit/iris/core/pregenerator/PregenTask.java @@ -18,20 +18,30 @@ package com.volmit.iris.core.pregenerator; +import com.volmit.iris.Iris; import com.volmit.iris.util.collection.KList; -import com.volmit.iris.util.mantle.Mantle; +import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.math.Position2; +import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.Spiraled; import com.volmit.iris.util.math.Spiraler; import lombok.Builder; import lombok.Data; +import org.checkerframework.checker.units.qual.K; +import java.util.Arrays; import java.util.Comparator; +import java.util.Set; +import java.util.function.Function; @Builder @Data public class PregenTask { - private static final KList order = computeChunkOrder(); + private static final Position2 ZERO = new Position2(0,0); + private static final KList ORDER_CENTER = computeChunkOrder(); + private static final KMap> ORDERS = new KMap<>(); + @Builder.Default private Position2 center = new Position2(0, 0); @Builder.Default @@ -39,12 +49,46 @@ public class PregenTask { @Builder.Default private int height = 1; - public static void iterateRegion(int xr, int zr, Spiraled s) { - for (Position2 i : order) { + public static void iterateRegion(int xr, int zr, Spiraled s, Position2 pull) { + for (Position2 i : ORDERS.computeIfAbsent(pull, PregenTask::computeOrder)) { s.on(i.getX() + (xr << 5), i.getZ() + (zr << 5)); } } + public static void iterateRegion(int xr, int zr, Spiraled s) { + iterateRegion(xr, zr, s, new Position2(0,0)); + } + + private static Position2 avg(Position2... c) + { + double x = 0; + double z = 0; + + for(Position2 i : c) + { + x += i.getX() * 15; + z += i.getZ() * 15; + } + + return new Position2((int)(x / c.length), (int)(z / c.length)); + } + + private static KList computeOrder(Position2 pull) { + KList p = new KList<>(); + new Spiraler(33, 33, (x, z) -> { + int xx = (x + 15); + int zz = (z + 15); + if (xx < 0 || xx > 31 || zz < 0 || zz > 31) { + return; + } + + p.add(new Position2(xx, zz)); + }).drain(); + p.sort(Comparator.comparing((i) -> i.distance(pull))); + + return p; + } + private static KList computeChunkOrder() { Position2 center = new Position2(15, 15); KList p = new KList<>(); diff --git a/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java index da06c00e0..249c21518 100644 --- a/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java +++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java @@ -70,6 +70,7 @@ public class AsyncPregenMethod implements PregeneratorMethod { try { PaperLib.getChunkAtAsync(world, x, z, true).get(); listener.onChunkGenerated(x, z); + listener.onChunkCleaned(x, z); } catch (Throwable e) { e.printStackTrace(); J.sleep(5); diff --git a/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java b/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java index 9fa31a387..47d911268 100644 --- a/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java +++ b/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java @@ -105,6 +105,7 @@ public class MedievalPregenMethod implements PregeneratorMethod { futures.add(J.sfut(() -> { world.getChunkAt(x, z); listener.onChunkGenerated(x, z); + listener.onChunkCleaned(x, z); })); } diff --git a/src/main/java/com/volmit/iris/core/pregenerator/syndicate/SyndicateServer.java b/src/main/java/com/volmit/iris/core/pregenerator/syndicate/SyndicateServer.java index 91b9f4778..5762de8b4 100644 --- a/src/main/java/com/volmit/iris/core/pregenerator/syndicate/SyndicateServer.java +++ b/src/main/java/com/volmit/iris/core/pregenerator/syndicate/SyndicateServer.java @@ -212,6 +212,11 @@ public class SyndicateServer extends Thread implements PregenListener { } + @Override + public void onChunkCleaned(int x, int z) { + + } + @Override public void onRegionSkipped(int x, int z) { diff --git a/src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java b/src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java index 9d9a42e1a..faf696db3 100644 --- a/src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java +++ b/src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java @@ -27,6 +27,7 @@ import com.volmit.iris.core.pregenerator.PregeneratorMethod; import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod; import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod; import com.volmit.iris.core.service.StudioSVC; +import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.object.IrisDimension; import com.volmit.iris.engine.platform.HeadlessGenerator; import com.volmit.iris.engine.platform.PlatformChunkGenerator; @@ -120,8 +121,8 @@ public class IrisToolbelt { * @param method the method to execute the task * @return the pregenerator job (already started) */ - public static PregeneratorJob pregenerate(PregenTask task, PregeneratorMethod method) { - return new PregeneratorJob(task, method); + public static PregeneratorJob pregenerate(PregenTask task, PregeneratorMethod method, Engine engine) { + return new PregeneratorJob(task, method, engine); } /** @@ -134,11 +135,11 @@ public class IrisToolbelt { */ public static PregeneratorJob pregenerate(PregenTask task, PlatformChunkGenerator gen) { if (gen.isHeadless()) { - return pregenerate(task, new HeadlessPregenMethod(((HeadlessGenerator) gen).getWorld(), (HeadlessGenerator) gen)); + return pregenerate(task, new HeadlessPregenMethod(((HeadlessGenerator) gen).getWorld(), (HeadlessGenerator) gen), gen.getEngine()); } return pregenerate(task, new HybridPregenMethod(gen.getEngine().getWorld().realWorld(), - IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism()))); + IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())), gen.getEngine()); } /** @@ -154,7 +155,7 @@ public class IrisToolbelt { return pregenerate(task, access(world)); } - return pregenerate(task, new HybridPregenMethod(world, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism()))); + return pregenerate(task, new HybridPregenMethod(world, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())), null); } /** diff --git a/src/main/java/com/volmit/iris/engine/IrisWorldManager.java b/src/main/java/com/volmit/iris/engine/IrisWorldManager.java index 6b21e2c2f..1a58d1f76 100644 --- a/src/main/java/com/volmit/iris/engine/IrisWorldManager.java +++ b/src/main/java/com/volmit/iris/engine/IrisWorldManager.java @@ -19,6 +19,7 @@ package com.volmit.iris.engine; import com.volmit.iris.Iris; +import com.volmit.iris.core.IrisSettings; import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.EngineAssignedWorldManager; @@ -41,6 +42,8 @@ import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.matter.MatterCavern; +import com.volmit.iris.util.matter.MatterFluidBody; import com.volmit.iris.util.matter.MatterMarker; import com.volmit.iris.util.plugin.Chunks; import com.volmit.iris.util.scheduling.ChronoLatch; @@ -49,6 +52,7 @@ import com.volmit.iris.util.scheduling.Looper; import lombok.Data; import lombok.EqualsAndHashCode; import org.bukkit.Chunk; +import org.bukkit.block.data.BlockData; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -460,6 +464,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager { public void onChunkLoad(Chunk e, boolean generated) { energy += 0.3; fixEnergy(); + getEngine().cleanupMantleChunk(e.getX(), e.getZ()); } private void spawn(IrisPosition block, IrisSpawner spawner, boolean initial) { diff --git a/src/main/java/com/volmit/iris/engine/framework/Engine.java b/src/main/java/com/volmit/iris/engine/framework/Engine.java index 57df8e62a..7805bab31 100644 --- a/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -19,6 +19,7 @@ package com.volmit.iris.engine.framework; import com.volmit.iris.Iris; +import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.gui.components.RenderType; import com.volmit.iris.core.gui.components.Renderer; import com.volmit.iris.core.loader.IrisData; @@ -60,6 +61,7 @@ import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.matter.MatterCavern; +import com.volmit.iris.util.matter.MatterFluidBody; import com.volmit.iris.util.matter.MatterUpdate; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; @@ -902,4 +904,12 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat Locator.region(r.getLoadKey()).find(player); } + + default void cleanupMantleChunk(int x, int z) + { + if(IrisSettings.get().getPerformance().isTrimMantleInStudio() || !isStudio()) + { + J.a(() -> getMantle().cleanupChunk(x, z)); + } + } } diff --git a/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java b/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java index c5817e4e2..75b0b18ca 100644 --- a/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java +++ b/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java @@ -18,6 +18,7 @@ package com.volmit.iris.engine.mantle; +import com.volmit.iris.Iris; import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.engine.IrisComplex; @@ -40,13 +41,17 @@ import com.volmit.iris.util.mantle.MantleChunk; import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.matter.Matter; import com.volmit.iris.util.matter.MatterCavern; +import com.volmit.iris.util.matter.MatterFluidBody; import com.volmit.iris.util.matter.MatterMarker; import com.volmit.iris.util.matter.slices.UpdateMatter; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; +import com.volmit.iris.util.scheduling.J; +import io.papermc.lib.PaperLib; import org.bukkit.block.TileState; import org.bukkit.block.data.BlockData; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; // TODO: MOVE PLACER OUT OF MATTER INTO ITS OWN THING @@ -207,11 +212,13 @@ public interface EngineMantle extends IObjectPlacer { int zz = j + z; burst.queue(() -> { IrisContext.touch(getEngine().getContext()); - MantleChunk mc = getMantle().getChunk(xx, zz); + getMantle().raiseFlag(xx, zz, MantleFlag.PLANNED, () -> { + MantleChunk mc = getMantle().getChunk(xx, zz); - for (MantleComponent k : getComponents()) { - generateMantleComponent(writer, xx, zz, k, mc); - } + for (MantleComponent k : getComponents()) { + generateMantleComponent(writer, xx, zz, k, mc); + } + }); }); } } @@ -262,4 +269,35 @@ public interface EngineMantle extends IObjectPlacer { MantleJigsawComponent getJigsawComponent(); MantleObjectComponent getObjectComponent(); + + default boolean isCovered(int x, int z) + { + int s = getRealRadius(); + + for (int i = -s; i <= s; i++) { + for (int j = -s; j <= s; j++) { + int xx = i + x; + int zz = j + z; + if(!getMantle().hasFlag(xx, zz, MantleFlag.PLANNED)) + { + return false; + } + } + } + + return true; + } + + default void cleanupChunk(int x, int z) + { + if(!getMantle().hasFlag(x, z, MantleFlag.CLEANED) && isCovered(x, z)) + { + getMantle().raiseFlag(x, z, MantleFlag.CLEANED, () -> { + getMantle().deleteChunkSlice(x, z, BlockData.class); + getMantle().deleteChunkSlice(x, z, String.class); + getMantle().deleteChunkSlice(x, z, MatterCavern.class); + getMantle().deleteChunkSlice(x, z, MatterFluidBody.class); + }); + } + } } diff --git a/src/main/java/com/volmit/iris/engine/platform/HeadlessGenerator.java b/src/main/java/com/volmit/iris/engine/platform/HeadlessGenerator.java index ef54955a4..fc0e579db 100644 --- a/src/main/java/com/volmit/iris/engine/platform/HeadlessGenerator.java +++ b/src/main/java/com/volmit/iris/engine/platform/HeadlessGenerator.java @@ -29,6 +29,7 @@ import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.EngineTarget; import com.volmit.iris.engine.object.HeadlessWorld; import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.documentation.RegionCoordinates; import com.volmit.iris.util.hunk.Hunk; @@ -40,6 +41,7 @@ import com.volmit.iris.util.nbt.mca.NBTWorld; import com.volmit.iris.util.nbt.tag.CompoundTag; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; +import com.volmit.iris.util.scheduling.J; import lombok.Data; import org.bukkit.Material; import org.bukkit.World; @@ -48,6 +50,8 @@ import org.bukkit.generator.ChunkGenerator; import java.io.File; import java.io.IOException; +import java.util.List; +import java.util.Set; import java.util.function.Consumer; @Data @@ -59,6 +63,7 @@ public class HeadlessGenerator implements PlatformChunkGenerator { private final MultiBurst burst; private final Engine engine; private final long rkey = RNG.r.lmax(); + private List last = new KList<>(); public HeadlessGenerator(HeadlessWorld world) { this(world, new IrisEngine(new EngineTarget(world.getWorld(), world.getDimension(), world.getDimension().getLoader()), world.isStudio())); @@ -124,9 +129,35 @@ public class HeadlessGenerator implements PlatformChunkGenerator { if (listener != null) { listener.onChunkGenerated(ii, jj); } - })); + }), avgLast(x, z)); + last.add(new Position2(x, z)); e.complete(); + + J.a(() -> PregenTask.iterateRegion(x, z, (ii, jj) -> { + getEngine().cleanupMantleChunk(ii, jj); + if (listener != null) { + listener.onChunkCleaned(ii, jj); + } + })); + } + + private Position2 avgLast(int x, int z) { + while(last.size() > 3) + { + last.remove(0); + } + + double xx = 0; + double zz = 0; + + for(Position2 i : last) + { + xx += 7 * (i.getX() - x); + zz += 7 * (i.getZ() - z); + } + + return new Position2((int)xx, (int)zz); } @RegionCoordinates diff --git a/src/main/java/com/volmit/iris/util/format/MemoryMonitor.java b/src/main/java/com/volmit/iris/util/format/MemoryMonitor.java new file mode 100644 index 000000000..a04146b8b --- /dev/null +++ b/src/main/java/com/volmit/iris/util/format/MemoryMonitor.java @@ -0,0 +1,147 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.format; + +import com.volmit.iris.Iris; +import com.volmit.iris.util.math.RollingSequence; +import com.volmit.iris.util.scheduling.ChronoLatch; +import com.volmit.iris.util.scheduling.Looper; + +public class MemoryMonitor { + private Looper looper; + private long usedMemory; + private long garbageMemory; + private long garbageLast; + private long garbageBin; + private long pressure; + private ChronoLatch cl; + private RollingSequence pressureAvg; + private Runtime runtime; + + public MemoryMonitor(int sampleDelay){ + this.runtime = Runtime.getRuntime(); + usedMemory = -1; + pressureAvg = new RollingSequence(Math.max(Math.min(100, 1000/sampleDelay), 3)); + garbageBin = 0; + garbageMemory = -1; + cl = new ChronoLatch(1000); + garbageLast = 0; + pressure = 0; + + looper = new Looper() { + @Override + protected long loop() { + sample(); + return sampleDelay; + } + }; + looper.setPriority(Thread.MIN_PRIORITY); + looper.setName("Memory Monitor"); + looper.start(); + } + + public long getGarbageBytes() + { + return garbageMemory; + } + + public long getUsedBytes() + { + return usedMemory; + } + + public long getMaxBytes() + { + return runtime.maxMemory(); + } + + public long getPressure() + { + return (long) pressureAvg.getAverage(); + } + + public double getUsagePercent() + { + return usedMemory / (double)getMaxBytes(); + } + + private void sample() { + long used = getVMUse(); + if(usedMemory == -1) + { + usedMemory = used; + garbageMemory = 0; + return; + } + + if(used < usedMemory) + { + usedMemory = used; + } + + else + { + garbageMemory = used - usedMemory; + } + + long g = garbageMemory - garbageLast; + + if(g >= 0) + { + garbageBin+= g; + garbageLast = garbageMemory; + } + + else + { + garbageMemory = 0; + garbageLast = 0; + } + + if(cl.flip()) + { + if(garbageMemory > 0) + { + pressure = garbageBin; + garbageBin = 0; + } + + else + { + pressure = 0; + garbageBin = 0; + } + } + + pressureAvg.put(pressure); + } + + private long getVMUse() { + return runtime.totalMemory() - runtime.freeMemory(); + } + + public void close() + { + if(looper != null) + { + looper.interrupt(); + looper = null; + } + } +} diff --git a/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java b/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java index d06982125..870884c18 100644 --- a/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java +++ b/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java @@ -29,7 +29,9 @@ public enum MantleFlag { REAL, CARVED, FLUID_BODIES, - INITIAL_SPAWNED_MARKER; + INITIAL_SPAWNED_MARKER, + CLEANED, + PLANNED; static StateList getStateList() { return new StateList(MantleFlag.values()); diff --git a/src/main/java/com/volmit/iris/util/matter/MatterSlice.java b/src/main/java/com/volmit/iris/util/matter/MatterSlice.java index c35797b0c..c5f96b185 100644 --- a/src/main/java/com/volmit/iris/util/matter/MatterSlice.java +++ b/src/main/java/com/volmit/iris/util/matter/MatterSlice.java @@ -152,7 +152,7 @@ public interface MatterSlice extends Hunk, PaletteType { default void write(DataOutputStream dos) throws IOException { dos.writeUTF(getType().getCanonicalName()); - if(IrisSettings.get().getPerformance().isUseExperimentalMantleMemoryCompression() && (this instanceof PaletteOrHunk f && f.isPalette())) + if((this instanceof PaletteOrHunk f && f.isPalette())) { PalettedContainer c = f.palette(); List palette = new ArrayList<>(); @@ -192,7 +192,7 @@ public interface MatterSlice extends Hunk, PaletteType { } default void read(DataInputStream din) throws IOException { - if(IrisSettings.get().getPerformance().isUseExperimentalMantleMemoryCompression() && (this instanceof PaletteOrHunk f && f.isPalette())) + if((this instanceof PaletteOrHunk f && f.isPalette())) { PalettedContainer c = new PalettedContainer<>(); List palette = new ArrayList<>(); diff --git a/src/main/java/com/volmit/iris/util/matter/MatterTest.java b/src/main/java/com/volmit/iris/util/matter/MatterTest.java deleted file mode 100644 index 1cc0c2e32..000000000 --- a/src/main/java/com/volmit/iris/util/matter/MatterTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Iris is a World Generator for Minecraft Bukkit Servers - * Copyright (c) 2021 Arcane Arts (Volmit Software) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.volmit.iris.util.matter; - -import com.volmit.iris.Iris; -import com.volmit.iris.core.IrisSettings; -import com.volmit.iris.util.collection.KList; -import com.volmit.iris.util.format.Form; -import com.volmit.iris.util.io.IO; -import com.volmit.iris.util.mantle.Mantle; -import com.volmit.iris.util.mantle.TectonicPlate; -import com.volmit.iris.util.math.RNG; -import com.volmit.iris.util.nbt.tag.ByteArrayTag; -import com.volmit.iris.util.scheduling.J; -import com.volmit.iris.util.scheduling.PrecisionStopwatch; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; - -public class MatterTest { - public static long memorySample() - { - Runtime rt = Runtime.getRuntime(); - System.gc(); - System.gc(); - return rt.totalMemory() - rt.freeMemory(); - } - - public static void test() - { - for(Thread i : Thread.getAllStackTraces().keySet()) - { - if(i.getId() != Thread.currentThread().getId()) - { - try { - i.wait(10000); - } catch (Throwable ignored) { - - } - } - } - - System.gc(); - System.gc(); - J.sleep(250); - - try { - - double ms = 0; - long a = memorySample(); - PrecisionStopwatch p = PrecisionStopwatch.start(); - IrisSettings.get().getPerformance().setUseExperimentalMantleMemoryCompression(true); - Mantle mantle = new Mantle(new File("mantle-test/legacy"), 256); - - for(int i = 0; i < 512; i++) - { - for(int j = 0; j < 255; j++) - { - for(int k = 0; k < 512; k++) - { - mantle.set(i,j,k,RNG.r.chance(0.5)); - mantle.set(i,j,k,RNG.r.chance(0.5)?"a" : "b"); - } - } - } - - ms += p.getMilliseconds(); - long b = memorySample() - a; - Iris.info("Memory: " + Form.memSize(b, 0) + " (" + Form.f(b) + " bytes)"); - p = PrecisionStopwatch.start(); - mantle.saveAll(); - mantle.close(); - ms+=p.getMilliseconds(); - Iris.info("Closed, done! took " + Form.duration(ms, 2)); - } catch (Throwable e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/com/volmit/iris/util/nbt/mca/MCAFile.java b/src/main/java/com/volmit/iris/util/nbt/mca/MCAFile.java index c2ba0ae87..a394b681a 100644 --- a/src/main/java/com/volmit/iris/util/nbt/mca/MCAFile.java +++ b/src/main/java/com/volmit/iris/util/nbt/mca/MCAFile.java @@ -18,12 +18,15 @@ package com.volmit.iris.util.nbt.mca; +import com.volmit.iris.core.pregenerator.syndicate.SyndicateServer; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.nbt.tag.CompoundTag; +import com.volmit.iris.util.scheduling.J; import java.io.IOException; import java.io.RandomAccessFile; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicReferenceArray; @SuppressWarnings("ALL") @@ -37,6 +40,7 @@ public class MCAFile { private final int regionX; private final int regionZ; private AtomicReferenceArray chunks; + private ConcurrentLinkedQueue afterSave; /** * MCAFile represents a world save file used by Minecraft to store world @@ -50,6 +54,7 @@ public class MCAFile { public MCAFile(int regionX, int regionZ) { this.regionX = regionX; this.regionZ = regionZ; + afterSave = new ConcurrentLinkedQueue<>(); } /** @@ -198,6 +203,11 @@ public class MCAFile { raf.seek(globalOffset * 4096L - 1); raf.write(0); } + + J.a(() -> { + afterSave.forEach(i -> i.run()); + }, 20); + return chunksWritten; } @@ -326,4 +336,8 @@ public class MCAFile { } return chunk.getBlockStateAt(blockX, blockY, blockZ); } + + public void afterSave(Runnable o) { + afterSave.add(o); + } } diff --git a/src/main/java/com/volmit/iris/util/nbt/mca/NBTWorld.java b/src/main/java/com/volmit/iris/util/nbt/mca/NBTWorld.java index a1c8072b6..11a51ea63 100644 --- a/src/main/java/com/volmit/iris/util/nbt/mca/NBTWorld.java +++ b/src/main/java/com/volmit/iris/util/nbt/mca/NBTWorld.java @@ -329,4 +329,8 @@ public class NBTWorld { public int size() { return loadedRegions.size(); } + + public boolean isLoaded(int x, int z) { + return loadedRegions.containsKey(Cache.key(x, z)); + } }