diff --git a/build.gradle b/build.gradle index 56565a25c..fa6bbe9dc 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ plugins { id "de.undercouch.download" version "5.0.1" } -version '3.5.1-1.19.2-1.21.3' +version '3.5.2-1.19.2-1.21.3' // ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED // ======================== WINDOWS ============================= diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java index 0ee273246..0abb77a15 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java @@ -172,7 +172,7 @@ public class CommandStudio implements DecreeExecutor { KList js = new KList<>(); BurstExecutor b = MultiBurst.burst.burst(); b.setMulticore(false); - int rad = engine.getMantle().getRealRadius(); + int rad = engine.getMantle().getRadius(); for (int i = -(radius + rad); i <= radius + rad; i++) { for (int j = -(radius + rad); j <= radius + rad; j++) { engine.getMantle().getMantle().deleteChunk(i + cx.getX(), j + cx.getZ()); diff --git a/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java b/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java index e5e1ed192..208bf71bd 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java @@ -18,28 +18,21 @@ package com.volmit.iris.engine; -import com.volmit.iris.Iris; +import com.volmit.iris.core.nms.container.Pair; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.mantle.MantleComponent; import com.volmit.iris.engine.mantle.components.*; -import com.volmit.iris.engine.object.*; 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.format.Form; import com.volmit.iris.util.mantle.Mantle; -import com.volmit.iris.util.parallel.BurstExecutor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.bukkit.util.BlockVector; +import lombok.*; import java.io.File; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; @Data @EqualsAndHashCode(exclude = "engine") @@ -47,8 +40,9 @@ import java.util.concurrent.atomic.AtomicInteger; public class IrisEngineMantle implements EngineMantle { private final Engine engine; private final Mantle mantle; - private final KList components; - private final int radius; + @Getter(AccessLevel.NONE) + private final KMap> components; + private final AtomicCache, Integer>>> componentsCache = new AtomicCache<>(); private final AtomicCache radCache = new AtomicCache<>(); private final MantleObjectComponent object; private final MantleJigsawComponent jigsaw; @@ -56,8 +50,7 @@ public class IrisEngineMantle implements EngineMantle { public IrisEngineMantle(Engine engine) { this.engine = engine; this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle"), engine.getTarget().getHeight()); - radius = radCache.aquire(this::computeParallaxSize); - components = new KList<>(); + components = new KMap<>(); registerComponent(new MantleCarvingComponent(this)); registerComponent(new MantleFluidBodyComponent(this)); jigsaw = new MantleJigsawComponent(this); @@ -67,9 +60,49 @@ public class IrisEngineMantle implements EngineMantle { registerComponent(new MantleStaticComponent(this)); } + @Override + public int getRadius() { + if (components.isEmpty()) return 0; + return getComponents().getFirst().getB(); + } + + @Override + public int getRealRadius() { + if (components.isEmpty()) return 0; + return getComponents().getLast().getB(); + } + + @Override + public KList, Integer>> getComponents() { + return componentsCache.aquire(() -> { + var list = components.keySet() + .stream() + .sorted() + .map(components::get) + .map(components -> { + int radius = components.stream() + .mapToInt(MantleComponent::getRadius) + .max() + .orElse(0); + return new Pair<>(components, radius); + }) + .collect(Collectors.toCollection(KList::new)); + + + int radius = 0; + for (var pair : list.reversed()) { + radius += pair.getB(); + pair.setB(Math.ceilDiv(radius, 16)); + } + + return list; + }); + } + @Override public void registerComponent(MantleComponent c) { - components.add(c); + components.computeIfAbsent(c.getPriority(), k -> new KList<>()).add(c); + componentsCache.reset(); } @Override @@ -81,259 +114,4 @@ public class IrisEngineMantle implements EngineMantle { public MantleObjectComponent getObjectComponent() { return object; } - - private KList getAllRegions() { - KList r = new KList<>(); - - for (String i : getEngine().getDimension().getRegions()) { - r.add(getEngine().getData().getRegionLoader().load(i)); - } - - return r; - } - - private KList getAllBiomes() { - KList r = new KList<>(); - - for (IrisRegion i : getAllRegions()) { - r.addAll(i.getAllBiomes(getEngine())); - } - - return r; - } - - private void warn(String ob, BlockVector bv) { - if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) { - Iris.warn("Object " + ob + " has a large size (" + bv + ") and may increase memory usage!"); - } - } - - private void warnScaled(String ob, BlockVector bv, double ms) { - if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) { - Iris.warn("Object " + ob + " has a large size (" + bv + ") and may increase memory usage! (Object scaled up to " + Form.pc(ms, 2) + ")"); - } - } - - private int computeParallaxSize() { - Iris.verbose("Calculating the Parallax Size in Parallel"); - AtomicInteger xg = new AtomicInteger(0); - AtomicInteger zg = new AtomicInteger(); - xg.set(0); - zg.set(0); - int jig = 0; - KSet objects = new KSet<>(); - KMap> scalars = new KMap<>(); - int x = xg.get(); - int z = zg.get(); - - if (getEngine().getDimension().isUseMantle()) { - KList r = getAllRegions(); - KList b = getAllBiomes(); - - for (IrisBiome i : b) { - for (IrisObjectPlacement j : i.getObjects()) { - if (j.getScale().canScaleBeyond()) { - scalars.put(j.getScale(), j.getPlace()); - } else { - objects.addAll(j.getPlace()); - } - } - - for (IrisJigsawStructurePlacement j : i.getJigsawStructures()) { - jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension()); - } - } - - for (IrisRegion i : r) { - for (IrisObjectPlacement j : i.getObjects()) { - if (j.getScale().canScaleBeyond()) { - scalars.put(j.getScale(), j.getPlace()); - } else { - objects.addAll(j.getPlace()); - } - } - - for (IrisJigsawStructurePlacement j : i.getJigsawStructures()) { - jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension()); - } - } - - for (IrisJigsawStructurePlacement j : getEngine().getDimension().getJigsawStructures()) { - jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension()); - } - - jig = Math.max(getEngine().getDimension().getStaticPlacements().getStructures().stream() - .mapToInt(p -> p.maxDimension(getData())) - .max() - .orElse(0), jig); - - getEngine().getDimension().getStaticPlacements().getObjects() - .stream() - .map(IrisStaticObjectPlacement::placement) - .forEach(j -> { - if (j.getScale().canScaleBeyond()) { - scalars.put(j.getScale(), j.getPlace()); - } else { - objects.addAll(j.getPlace()); - } - }); - - if (getEngine().getDimension().getStronghold() != null) { - try { - jig = Math.max(jig, getData().getJigsawStructureLoader().load(getEngine().getDimension().getStronghold()).getMaxDimension()); - } catch (Throwable e) { - Iris.reportError(e); - e.printStackTrace(); - } - } - - Iris.verbose("Checking sizes for " + Form.f(objects.size()) + " referenced objects."); - BurstExecutor e = getEngine().getTarget().getBurster().burst(objects.size()); - KMap sizeCache = new KMap<>(); - for (String i : objects) { - e.queue(() -> { - try { - BlockVector bv = sizeCache.computeIfAbsent(i, (k) -> { - try { - return IrisObject.sampleSize(getData().getObjectLoader().findFile(i)); - } catch (IOException ex) { - Iris.reportError(ex); - ex.printStackTrace(); - } - - return null; - }); - - if (bv == null) { - throw new RuntimeException(); - } - - warn(i, bv); - - synchronized (xg) { - xg.getAndSet(Math.max(bv.getBlockX(), xg.get())); - } - - synchronized (zg) { - zg.getAndSet(Math.max(bv.getBlockZ(), zg.get())); - } - } catch (Throwable ed) { - Iris.reportError(ed); - - } - }); - } - - for (Map.Entry> entry : scalars.entrySet()) { - double ms = entry.getKey().getMaximumScale(); - for (String j : entry.getValue()) { - e.queue(() -> { - try { - BlockVector bv = sizeCache.computeIfAbsent(j, (k) -> { - try { - return IrisObject.sampleSize(getData().getObjectLoader().findFile(j)); - } catch (IOException ioException) { - Iris.reportError(ioException); - ioException.printStackTrace(); - } - - return null; - }); - - if (bv == null) { - throw new RuntimeException(); - } - - warnScaled(j, bv, ms); - - synchronized (xg) { - xg.getAndSet((int) Math.max(Math.ceil(bv.getBlockX() * ms), xg.get())); - } - - synchronized (zg) { - zg.getAndSet((int) Math.max(Math.ceil(bv.getBlockZ() * ms), zg.get())); - } - } catch (Throwable ee) { - Iris.reportError(ee); - - } - }); - } - } - - e.complete(); - - x = xg.get(); - z = zg.get(); - - for (IrisDepositGenerator i : getEngine().getDimension().getDeposits()) { - int max = i.getMaxDimension(); - x = Math.max(max, x); - z = Math.max(max, z); - } - - for (IrisRegion v : r) { - for (IrisDepositGenerator i : v.getDeposits()) { - int max = i.getMaxDimension(); - x = Math.max(max, x); - z = Math.max(max, z); - } - } - - for (IrisBiome v : b) { - for (IrisDepositGenerator i : v.getDeposits()) { - int max = i.getMaxDimension(); - x = Math.max(max, x); - z = Math.max(max, z); - } - } - } else { - return 0; - } - - x = Math.max(z, x); - int u = x; - int c = Math.max(computeCarvingRange(), computeBodyRange()); - x = Math.max(jig, x); - x = Math.max(x, c); - x = (Math.max(x, 16) + 16) >> 4; - x = x % 2 == 0 ? x + 1 : x; - Iris.info("Mantle Size: " + x + " Chunks"); - Iris.info(" Object Mantle Size: " + u + " (" + ((Math.max(u, 16) + 16) >> 4) + ")"); - Iris.info(" Jigsaw Mantle Size: " + jig + " (" + ((Math.max(jig, 16) + 16) >> 4) + ")"); - Iris.info(" Carving Mantle Size: " + c + " (" + ((Math.max(c, 16) + 16) >> 4) + ")"); - return x; - } - - private int computeBodyRange() { - int m = 0; - - m = Math.max(m, getDimension().getFluidBodies().getMaxRange(getData())); - - for (IrisRegion i : getDimension().getAllRegions(getEngine())) { - m = Math.max(m, i.getFluidBodies().getMaxRange(getData())); - } - - for (IrisBiome i : getDimension().getAllBiomes(getEngine())) { - m = Math.max(m, i.getFluidBodies().getMaxRange(getData())); - } - - return m; - } - - private int computeCarvingRange() { - int m = 0; - - m = Math.max(m, getDimension().getCarving().getMaxRange(getData())); - - for (IrisRegion i : getDimension().getAllRegions(getEngine())) { - m = Math.max(m, i.getCarving().getMaxRange(getData())); - } - - for (IrisBiome i : getDimension().getAllBiomes(getEngine())) { - m = Math.max(m, i.getCarving().getMaxRange(getData())); - } - - return m; - } } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java b/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java index d8969636b..da5b11ae8 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java @@ -20,10 +20,10 @@ package com.volmit.iris.engine.mantle; import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.core.nms.container.Pair; import com.volmit.iris.engine.IrisComplex; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.EngineTarget; -import com.volmit.iris.engine.framework.SeedManager; import com.volmit.iris.engine.mantle.components.MantleJigsawComponent; import com.volmit.iris.engine.mantle.components.MantleObjectComponent; import com.volmit.iris.engine.object.IObjectPlacer; @@ -44,7 +44,6 @@ import com.volmit.iris.util.matter.*; import com.volmit.iris.util.matter.slices.UpdateMatter; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; -import org.bukkit.block.TileState; import org.bukkit.block.data.BlockData; import java.util.concurrent.TimeUnit; @@ -59,7 +58,9 @@ public interface EngineMantle extends IObjectPlacer { int getRadius(); - KList getComponents(); + int getRealRadius(); + + KList, Integer>> getComponents(); void registerComponent(MantleComponent c); @@ -187,39 +188,37 @@ public interface EngineMantle extends IObjectPlacer { return getEngine().burst(); } - default int getRealRadius() { - return (int) Math.ceil(getRadius() / 2D); - } - - @ChunkCoordinates default void generateMatter(int x, int z, boolean multicore, ChunkContext context) { - synchronized (this) { - if (!getEngine().getDimension().isUseMantle()) { - return; - } + if (!getEngine().getDimension().isUseMantle()) { + return; + } - int s = getRealRadius(); - BurstExecutor burst = burst().burst(multicore); - MantleWriter writer = getMantle().write(this, x, z, s * 2); - for (int i = -s; i <= s; i++) { - for (int j = -s; j <= s; j++) { - int xx = i + x; - int zz = j + z; - burst.queue(() -> { - IrisContext.touch(getEngine().getContext()); - getMantle().raiseFlag(xx, zz, MantleFlag.PLANNED, () -> { - MantleChunk mc = getMantle().getChunk(xx, zz); + try (MantleWriter writer = getMantle().write(this, x, z, getRadius() * 2)) { + var iterator = getComponents().iterator(); + while (iterator.hasNext()) { + var pair = iterator.next(); + int radius = pair.getB(); + boolean last = !iterator.hasNext(); + BurstExecutor burst = burst().burst(radius * 2 + 1); + burst.setMulticore(multicore); - for (MantleComponent k : getComponents()) { - generateMantleComponent(writer, xx, zz, k, mc, context); - } + for (int i = -radius; i <= radius; i++) { + for (int j = -radius; j <= radius; j++) { + int xx = x + i; + int zz = z + j; + MantleChunk mc = getMantle().getChunk(xx, zz); + + burst.queue(() -> { + IrisContext.touch(getEngine().getContext()); + pair.getA().forEach(k -> generateMantleComponent(writer, xx, zz, k, mc, context)); + if (last) mc.flag(MantleFlag.PLANNED, true); }); - }); + } } - } - burst.complete(); + burst.complete(); + } } } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/IrisMantleComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/IrisMantleComponent.java index 48e33957a..388518c0d 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/IrisMantleComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/IrisMantleComponent.java @@ -29,4 +29,5 @@ import lombok.ToString; public abstract class IrisMantleComponent implements MantleComponent { private final EngineMantle engineMantle; private final MantleFlag flag; + private final int priority; } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/MantleComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/MantleComponent.java index 10ab3c4b8..3c9c78dc5 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/MantleComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/MantleComponent.java @@ -26,11 +26,12 @@ import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.parallel.BurstExecutor; +import org.jetbrains.annotations.NotNull; -public interface MantleComponent { - default int getRadius() { - return getEngineMantle().getRealRadius(); - } +public interface MantleComponent extends Comparable { + int getPriority(); + + int getRadius(); default IrisData getData() { return getEngineMantle().getData(); @@ -62,4 +63,9 @@ public interface MantleComponent { @ChunkCoordinates void generateLayer(MantleWriter writer, int x, int z, ChunkContext context); + + @Override + default int compareTo(@NotNull MantleComponent o) { + return Integer.compare(getPriority(), o.getPriority()); + } } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/MantleWriter.java b/core/src/main/java/com/volmit/iris/engine/mantle/MantleWriter.java index b43b72f27..d4f08be48 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/MantleWriter.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/MantleWriter.java @@ -35,7 +35,6 @@ import com.volmit.iris.util.mantle.MantleChunk; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.matter.Matter; import lombok.Data; -import org.bukkit.block.TileState; import org.bukkit.block.data.BlockData; import org.bukkit.util.Vector; @@ -44,7 +43,7 @@ import java.util.List; import java.util.Set; @Data -public class MantleWriter implements IObjectPlacer { +public class MantleWriter implements IObjectPlacer, AutoCloseable { private final EngineMantle engineMantle; private final Mantle mantle; private final KMap cachedChunks; @@ -62,7 +61,7 @@ public class MantleWriter implements IObjectPlacer { for (int i = -radius; i <= radius; i++) { for (int j = -radius; j <= radius; j++) { - cachedChunks.put(Cache.key(i + x, j + z), mantle.getChunk(i + x, j + z)); + cachedChunks.put(Cache.key(i + x, j + z), mantle.getChunk(i + x, j + z).use()); } } } @@ -633,4 +632,12 @@ public class MantleWriter implements IObjectPlacer { return cx >= this.x - radius && cx <= this.x + radius && cz >= this.z - radius && cz <= this.z + radius; } + + @Override + public void close() { + cachedChunks.values().removeIf(c -> { + c.release(); + return true; + }); + } } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleCarvingComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleCarvingComponent.java index 09f37e7c6..31762626f 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleCarvingComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleCarvingComponent.java @@ -29,10 +29,14 @@ import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.math.RNG; +import lombok.Getter; +@Getter public class MantleCarvingComponent extends IrisMantleComponent { + private final int radius = computeRadius(); + public MantleCarvingComponent(EngineMantle engineMantle) { - super(engineMantle, MantleFlag.CARVED); + super(engineMantle, MantleFlag.CARVED, 0); } @Override @@ -56,4 +60,21 @@ public class MantleCarvingComponent extends IrisMantleComponent { private void carve(IrisCarving carving, MantleWriter writer, RNG rng, int cx, int cz) { carving.doCarving(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4); } + + private int computeRadius() { + var dimension = getDimension(); + int max = 0; + + max = Math.max(max, dimension.getCarving().getMaxRange(getData())); + + for (var i : dimension.getAllRegions(this::getData)) { + max = Math.max(max, i.getCarving().getMaxRange(getData())); + } + + for (var i : dimension.getAllBiomes(this::getData)) { + max = Math.max(max, i.getCarving().getMaxRange(getData())); + } + + return max; + } } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleFluidBodyComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleFluidBodyComponent.java index eba06d39d..bd45353c2 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleFluidBodyComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleFluidBodyComponent.java @@ -29,10 +29,14 @@ import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.math.RNG; +import lombok.Getter; +@Getter public class MantleFluidBodyComponent extends IrisMantleComponent { + private final int radius = computeRadius(); + public MantleFluidBodyComponent(EngineMantle engineMantle) { - super(engineMantle, MantleFlag.FLUID_BODIES); + super(engineMantle, MantleFlag.FLUID_BODIES, 0); } @Override @@ -56,4 +60,20 @@ public class MantleFluidBodyComponent extends IrisMantleComponent { private void generate(IrisFluidBodies bodies, MantleWriter writer, RNG rng, int cx, int cz) { bodies.generate(writer, rng, getEngineMantle().getEngine(), cx << 4, -1, cz << 4); } + + private int computeRadius() { + int max = 0; + + max = Math.max(max, getDimension().getFluidBodies().getMaxRange(getData())); + + for (IrisRegion i : getDimension().getAllRegions(this::getData)) { + max = Math.max(max, i.getFluidBodies().getMaxRange(getData())); + } + + for (IrisBiome i : getDimension().getAllBiomes(this::getData)) { + max = Math.max(max, i.getFluidBodies().getMaxRange(getData())); + } + + return max; + } } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java index ac091e346..25e44ca9e 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java @@ -34,15 +34,18 @@ import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer; import com.volmit.iris.util.noise.CNG; +import lombok.Getter; import org.jetbrains.annotations.Nullable; import java.util.List; public class MantleJigsawComponent extends IrisMantleComponent { + @Getter + private final int radius = computeRadius(); private final CNG cng; public MantleJigsawComponent(EngineMantle engineMantle) { - super(engineMantle, MantleFlag.JIGSAW); + super(engineMantle, MantleFlag.JIGSAW, 1); cng = NoiseStyle.STATIC.create(new RNG(jigsaw())); } @@ -168,4 +171,29 @@ public class MantleJigsawComponent extends IrisMantleComponent { private long jigsaw() { return getEngineMantle().getEngine().getSeedManager().getJigsaw(); } + + private int computeRadius() { + var dimension = getDimension(); + + KSet structures = new KSet<>(); + for (var placement : dimension.getJigsawStructures()) { + structures.add(placement.getStructure()); + } + for (var region : dimension.getAllRegions(this::getData)) { + for (var placement : region.getJigsawStructures()) { + structures.add(placement.getStructure()); + } + } + for (var biome : dimension.getAllBiomes(this::getData)) { + for (var placement : biome.getJigsawStructures()) { + structures.add(placement.getStructure()); + } + } + + int max = 0; + for (var structure : structures) { + max = Math.max(max, getData().getJigsawStructureLoader().load(structure).getMaxDimension()); + } + return max; + } } diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleObjectComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleObjectComponent.java index d8ee933f0..8a0514500 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleObjectComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleObjectComponent.java @@ -24,23 +24,35 @@ import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.mantle.IrisMantleComponent; import com.volmit.iris.engine.mantle.MantleWriter; import com.volmit.iris.engine.object.*; +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.context.ChunkContext; import com.volmit.iris.util.data.B; import com.volmit.iris.util.data.IrisBlockData; import com.volmit.iris.util.documentation.BlockCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates; +import com.volmit.iris.util.format.Form; import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.matter.MatterStructurePOI; import com.volmit.iris.util.noise.CNG; import com.volmit.iris.util.noise.NoiseType; +import com.volmit.iris.util.parallel.BurstExecutor; +import lombok.Getter; +import org.bukkit.util.BlockVector; +import java.io.IOException; +import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +@Getter public class MantleObjectComponent extends IrisMantleComponent { + private final int radius = computeRadius(); + public MantleObjectComponent(EngineMantle engineMantle) { - super(engineMantle, MantleFlag.OBJECT); + super(engineMantle, MantleFlag.OBJECT, 1); } @Override @@ -146,4 +158,112 @@ public class MantleObjectComponent extends IrisMantleComponent { return v; } + + private int computeRadius() { + var dimension = getDimension(); + + AtomicInteger xg = new AtomicInteger(); + AtomicInteger zg = new AtomicInteger(); + + KSet objects = new KSet<>(); + KMap> scalars = new KMap<>(); + for (var region : dimension.getAllRegions(this::getData)) { + for (var j : region.getObjects()) { + if (j.getScale().canScaleBeyond()) { + scalars.put(j.getScale(), j.getPlace()); + } else { + objects.addAll(j.getPlace()); + } + } + } + for (var biome : dimension.getAllBiomes(this::getData)) { + for (var j : biome.getObjects()) { + if (j.getScale().canScaleBeyond()) { + scalars.put(j.getScale(), j.getPlace()); + } else { + objects.addAll(j.getPlace()); + } + } + } + + BurstExecutor e = getEngineMantle().getTarget().getBurster().burst(objects.size()); + KMap sizeCache = new KMap<>(); + for (String i : objects) { + e.queue(() -> { + try { + BlockVector bv = sizeCache.computeIfAbsent(i, (k) -> { + try { + return IrisObject.sampleSize(getData().getObjectLoader().findFile(i)); + } catch (IOException ex) { + Iris.reportError(ex); + ex.printStackTrace(); + } + + return null; + }); + + if (bv == null) { + throw new RuntimeException(); + } + + if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) { + Iris.warn("Object " + i + " has a large size (" + bv + ") and may increase memory usage!"); + } + + synchronized (xg) { + xg.getAndSet(Math.max(bv.getBlockX(), xg.get())); + } + + synchronized (zg) { + zg.getAndSet(Math.max(bv.getBlockZ(), zg.get())); + } + } catch (Throwable ed) { + Iris.reportError(ed); + + } + }); + } + + for (Map.Entry> entry : scalars.entrySet()) { + double ms = entry.getKey().getMaximumScale(); + for (String j : entry.getValue()) { + e.queue(() -> { + try { + BlockVector bv = sizeCache.computeIfAbsent(j, (k) -> { + try { + return IrisObject.sampleSize(getData().getObjectLoader().findFile(j)); + } catch (IOException ioException) { + Iris.reportError(ioException); + ioException.printStackTrace(); + } + + return null; + }); + + if (bv == null) { + throw new RuntimeException(); + } + + if (Math.max(bv.getBlockX(), bv.getBlockZ()) > 128) { + Iris.warn("Object " + j + " has a large size (" + bv + ") and may increase memory usage! (Object scaled up to " + Form.pc(ms, 2) + ")"); + } + + synchronized (xg) { + xg.getAndSet((int) Math.max(Math.ceil(bv.getBlockX() * ms), xg.get())); + } + + synchronized (zg) { + zg.getAndSet((int) Math.max(Math.ceil(bv.getBlockZ() * ms), zg.get())); + } + } catch (Throwable ee) { + Iris.reportError(ee); + + } + }); + } + } + + e.complete(); + return Math.max(xg.get(), zg.get()); + } } diff --git a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java index 4ebe1d1c3..0e89c1162 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/Mantle.java @@ -471,6 +471,12 @@ public class Mantle { hyperLock.withLong(id, () -> { TectonicPlate m = loadedRegions.get(id); if (m != null) { + if (m.inUse()) { + Iris.debug("Tectonic Plate was added to unload while in use " + C.DARK_GREEN + m.getX() + " " + m.getZ()); + if (disableClear) toUnload.remove(id); + lastUse.put(id, M.ms()); + return; + } try { m.write(fileForRegion(dataFolder, id)); loadedRegions.remove(id); diff --git a/core/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java b/core/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java index 816896663..ce69c6bea 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java @@ -26,10 +26,12 @@ import com.volmit.iris.util.matter.IrisMatter; import com.volmit.iris.util.matter.Matter; import com.volmit.iris.util.matter.MatterSlice; import lombok.Getter; +import lombok.Synchronized; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicReferenceArray; @@ -44,6 +46,7 @@ public class MantleChunk { private final int z; private final AtomicIntegerArray flags; private final AtomicReferenceArray sections; + private final AtomicInteger ref = new AtomicInteger(); /** * Create a mantle chunk @@ -101,10 +104,25 @@ public class MantleChunk { } } + public boolean inUse() { + return ref.get() > 0; + } + + public MantleChunk use() { + ref.incrementAndGet(); + return this; + } + + public void release() { + ref.decrementAndGet(); + } + + @Synchronized public void flag(MantleFlag flag, boolean f) { flags.set(flag.ordinal(), f ? 1 : 0); } + @Synchronized public void raiseFlag(MantleFlag flag, Runnable r) { if (!isFlagged(flag)) { flag(flag, true); diff --git a/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java b/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java index f2bf590d6..efd724d5e 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java @@ -127,6 +127,15 @@ public class TectonicPlate { } } + public boolean inUse() { + for (int i = 0; i < chunks.length(); i++) { + MantleChunk chunk = chunks.get(i); + if (chunk != null && chunk.inUse()) + return true; + } + return false; + } + /** * Check if a chunk exists in this plate or not (same as get(x, z) != null) * @@ -180,14 +189,10 @@ public class TectonicPlate { */ @ChunkCoordinates public MantleChunk getOrCreate(int x, int z) { - MantleChunk chunk = get(x, z); - - if (chunk == null) { - chunk = new MantleChunk(sectionHeight, x & 31, z & 31); - chunks.set(index(x, z), chunk); - } - - return chunk; + return chunks.updateAndGet(index(x, z), chunk -> { + if (chunk != null) return chunk; + return new MantleChunk(sectionHeight, x & 31, z & 31); + }); } @ChunkCoordinates