diff --git a/src/main/java/com/volmit/iris/engine/IrisEngine.java b/src/main/java/com/volmit/iris/engine/IrisEngine.java index 225c3a795..fa0eb8e15 100644 --- a/src/main/java/com/volmit/iris/engine/IrisEngine.java +++ b/src/main/java/com/volmit/iris/engine/IrisEngine.java @@ -423,14 +423,21 @@ public class IrisEngine extends BlockPopulator implements Engine { switch (getDimension().getTerrainMode()) { case NORMAL -> { getMantle().generateMatter(x >> 4, z >> 4, multicore); - getTerrainActuator().actuate(x, z, vblocks, multicore); - getBiomeActuator().actuate(x, z, vbiomes, multicore); - getCaveModifier().modify(x, z, vblocks, multicore); - getRavineModifier().modify(x, z, vblocks, multicore); - getPostModifier().modify(x, z, vblocks, multicore); - getDecorantActuator().actuate(x, z, blocks, multicore); - getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, blocks, multicore); - getDepositModifier().modify(x, z, blocks, multicore); + burst().burst( + () ->getTerrainActuator().actuate(x, z, vblocks, multicore), + () ->getBiomeActuator().actuate(x, z, vbiomes, multicore) + ); + burst().burst( + () ->getCaveModifier().modify(x, z, vblocks, multicore), + ()->getDecorantActuator().actuate(x, z, blocks, multicore), + ()->getRavineModifier().modify(x, z, vblocks, multicore), + ()->getPostModifier().modify(x, z, vblocks, multicore) + ); + burst().burst( + ()->getDecorantActuator().actuate(x, z, blocks, multicore), + ()->getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, blocks, multicore), + ()->getDepositModifier().modify(x, z, blocks, multicore) + ); } case ISLANDS -> { getTerrainActuator().actuate(x, z, vblocks, multicore); diff --git a/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java b/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java index b19098805..819b0f227 100644 --- a/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java +++ b/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java @@ -53,6 +53,7 @@ import org.bukkit.util.BlockVector; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -63,8 +64,6 @@ public class IrisEngineMantle implements EngineMantle { private final KList components; private final int radius; private final AtomicCache radCache = new AtomicCache<>(); - private ProceduralStream> featureChunkStream; - private ProceduralStream> featureStream; public IrisEngineMantle(Engine engine) { this.engine = engine; @@ -74,21 +73,6 @@ public class IrisEngineMantle implements EngineMantle { registerComponent(new MantleFeatureComponent(this)); registerComponent(new MantleJigsawComponent(this)); registerComponent(new MantleObjectComponent(this)); - featureChunkStream = ProceduralStream.of((x, z) - -> EngineMantle.super.getFeaturesInChunk(x.intValue(), z.intValue()), - Interpolated.of((i) -> 0D, (i) -> new KList())).cache2D(2048); - featureStream = ProceduralStream.of(EngineMantle.super::forEachFeature, - Interpolated.of((i) -> 0D, (i) -> new KList())).cache2D(8192); - } - - @ChunkCoordinates - public KList getFeaturesInChunk(int x, int z) { - return featureChunkStream.get(x, z); - } - - @BlockCoordinates - public KList forEachFeature(double x, double z) { - return featureStream.get(x, z); } @Override diff --git a/src/main/java/com/volmit/iris/engine/IrisWorldManager.java b/src/main/java/com/volmit/iris/engine/IrisWorldManager.java index 81e6f7dab..c36f20cf5 100644 --- a/src/main/java/com/volmit/iris/engine/IrisWorldManager.java +++ b/src/main/java/com/volmit/iris/engine/IrisWorldManager.java @@ -211,7 +211,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager { .shuffleCopy(RNG.r).stream() .filter(this::canSpawn), getData().getSpawnerLoader().streamAll(getEngine().getMantle() - .getFeaturesInChunk(c).stream() + .forEachFeature(c).stream() .flatMap((o) -> o.getFeature().getEntitySpawners().stream())) .filter(this::canSpawn)) .filter((i) -> i.isValid(biome)) @@ -294,6 +294,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager { private KList spawnRandomly(List types) { KList rarityTypes = new KList<>(); int totalRarity = 0; + for (IrisEntitySpawn i : types) { totalRarity += IRare.get(i); } @@ -344,7 +345,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager { public void onChunkLoad(Chunk e, boolean generated) { if (generated) { energy += 1.2; - spawnIn(e, true); + J.a(() -> spawnIn(e, true), RNG.r.i(5, 50)); } else { energy += 0.3; } 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 0a3e8e02b..816880e04 100644 --- a/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -243,7 +243,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat updateLighting(x, y, z, c); } } - }, MantleFlag.UPDATE); + }); getMetrics().getUpdates().put(p.getMilliseconds()); } 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 9da22e093..1a072b7db 100644 --- a/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java +++ b/src/main/java/com/volmit/iris/engine/mantle/EngineMantle.java @@ -34,12 +34,14 @@ import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.hunk.Hunk; import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.noise.CNG; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; import org.bukkit.Chunk; import org.bukkit.block.TileState; import org.bukkit.block.data.BlockData; +import java.util.List; import java.util.concurrent.*; import java.util.function.Consumer; @@ -51,7 +53,7 @@ public interface EngineMantle extends IObjectPlacer { Engine getEngine(); - Integer getRadius(); + int getRadius(); KList getComponents(); @@ -166,15 +168,7 @@ public interface EngineMantle extends IObjectPlacer { } default int getRealRadius() { - try { - return (int) Math.ceil(getRadius().get() / 2D); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - - return 0; + return (int) Math.ceil(getRadius() / 2D); } @@ -195,8 +189,8 @@ public interface EngineMantle extends IObjectPlacer { BurstExecutor burst = burst().burst(); for (int i = -s; i <= s; i++) { - int xx = i + x; for (int j = -s; j <= s; j++) { + int xx = i + x; int zz = j + z; burst.queue(() -> { getComponents().forEach((f) -> generateMantleComponent(xx, zz, f, c)); @@ -229,20 +223,23 @@ public interface EngineMantle extends IObjectPlacer { @BlockCoordinates default void updateBlock(int x, int y, int z) { - getMantle().flag(x >> 4, z >> 4, MantleFlag.UPDATE, true); getMantle().set(x, y, z, true); } @ChunkCoordinates - default KList getFeaturesInChunk(Chunk c) { + default List getFeaturesInChunk(Chunk c) { return getFeaturesInChunk(c.getX(), c.getZ()); } @ChunkCoordinates - default KList getFeaturesInChunk(int x, int z) { - KList pos = new KList<>(); - getMantle().iterateChunk(x, z, IrisFeaturePositional.class, (a, b, c, f) -> pos.add(f), MantleFlag.FEATURE); - return pos; + default List getFeaturesInChunk(int x, int z) { + return getMantle().getChunk(x, z).getFeatures(); + } + + + @ChunkCoordinates + default KList forEachFeature(Chunk c) { + return forEachFeature((c.getX() << 4) + 8, (c.getZ() << 4) + 8); } @BlockCoordinates @@ -267,7 +264,7 @@ public interface EngineMantle extends IObjectPlacer { for (i = -s; i <= s; i++) { for (j = -s; j <= s; j++) { try { - for (IrisFeaturePositional k : getFeaturesInChunk(i + cx, j + cx)) { + for (IrisFeaturePositional k : getFeaturesInChunk(i + cx, j + cz)) { if (k.shouldFilter(x, z, getEngine().getComplex().getRng(), getData())) { pos.add(k); } diff --git a/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java b/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java index 9462ca83a..b93907542 100644 --- a/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java +++ b/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java @@ -18,6 +18,8 @@ package com.volmit.iris.engine.mantle.components; +import com.google.gson.Gson; +import com.volmit.iris.Iris; import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.engine.jigsaw.PlannedStructure; import com.volmit.iris.engine.mantle.EngineMantle; @@ -27,24 +29,29 @@ import com.volmit.iris.engine.object.biome.IrisBiome; import com.volmit.iris.engine.object.feature.IrisFeaturePositional; import com.volmit.iris.engine.object.jigsaw.IrisJigsawStructure; import com.volmit.iris.engine.object.jigsaw.IrisJigsawStructurePlacement; +import com.volmit.iris.engine.object.noise.NoiseStyle; import com.volmit.iris.engine.object.regional.IrisRegion; import com.volmit.iris.util.documentation.BlockCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.math.Position2; import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; import java.util.List; import java.util.function.Consumer; public class MantleJigsawComponent extends IrisMantleComponent { + private final CNG cng; + public MantleJigsawComponent(EngineMantle engineMantle) { super(engineMantle, MantleFlag.JIGSAW); + cng = NoiseStyle.STATIC.create(new RNG()); } @Override public void generateLayer(int x, int z, Consumer post) { - RNG rng = new RNG(Cache.key(x, z) + seed()); + RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z)); int xxx = 8 + (x << 4); int zzz = 8 + (z << 4); IrisRegion region = getComplex().getRegionStream().get(xxx, zzz); @@ -109,7 +116,6 @@ public class MantleJigsawComponent extends IrisMantleComponent { if (structure.getFeature().getBlockRadius() == 32) { structure.getFeature().setBlockRadius((double) structure.getMaxDimension() / 3); } - getMantle().set(position.getX(), 0, position.getZ(), new IrisFeaturePositional(position.getX(), position.getZ(), structure.getFeature())); } diff --git a/src/main/java/com/volmit/iris/engine/object/feature/IrisFeaturePositional.java b/src/main/java/com/volmit/iris/engine/object/feature/IrisFeaturePositional.java index dc686bb91..0edd0b49b 100644 --- a/src/main/java/com/volmit/iris/engine/object/feature/IrisFeaturePositional.java +++ b/src/main/java/com/volmit/iris/engine/object/feature/IrisFeaturePositional.java @@ -19,6 +19,7 @@ package com.volmit.iris.engine.object.feature; import com.google.gson.Gson; +import com.volmit.iris.Iris; import com.volmit.iris.core.project.loader.IrisData; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.object.annotations.Desc; @@ -63,7 +64,18 @@ public class IrisFeaturePositional { private static double BLOCK = 1D / 256D; // TODO: WARNING HEIGHT public static IrisFeaturePositional read(DataInputStream s) throws IOException { - return new Gson().fromJson(s.readUTF(), IrisFeaturePositional.class); + String sx = s.readUTF(); + try + { + return new Gson().fromJson(sx, IrisFeaturePositional.class); + } + + catch(Throwable e) + { + Iris.error(sx); + e.printStackTrace(); + throw new IOException(e); + } } public void write(DataOutputStream s) throws IOException { diff --git a/src/main/java/com/volmit/iris/util/hunk/storage/MappedSyncHunk.java b/src/main/java/com/volmit/iris/util/hunk/storage/MappedSyncHunk.java new file mode 100644 index 000000000..ee2a79228 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/hunk/storage/MappedSyncHunk.java @@ -0,0 +1,123 @@ +/* + * 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.hunk.storage; + +import com.volmit.iris.util.collection.KMap; +import com.volmit.iris.util.function.Consumer4; +import com.volmit.iris.util.function.Consumer4IO; +import com.volmit.iris.util.hunk.Hunk; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings({"DefaultAnnotationParam", "Lombok"}) +@Data +@EqualsAndHashCode(callSuper = false) +public class MappedSyncHunk extends StorageHunk implements Hunk { + private final Map data; + + public MappedSyncHunk(int w, int h, int d) { + super(w, h, d); + data = new HashMap<>(); + } + + public int getEntryCount() { + return data.size(); + } + + public boolean isMapped() { + return true; + } + + public boolean isEmpty() { + synchronized(data) + { + return data.isEmpty(); + } + } + + @Override + public void setRaw(int x, int y, int z, T t) { + synchronized(data) { + if (t == null) { + data.remove(index(x, y, z)); + return; + } + + data.put(index(x, y, z), t); + } + } + + private Integer index(int x, int y, int z) { + return (z * getWidth() * getHeight()) + (y * getWidth()) + x; + } + + @Override + public synchronized Hunk iterateSync(Consumer4 c) { + synchronized(data) + { + int idx, z; + + for (Map.Entry g : data.entrySet()) { + idx = g.getKey(); + z = idx / (getWidth() * getHeight()); + idx -= (z * getWidth() * getHeight()); + c.accept(idx % getWidth(), idx / getWidth(), z, g.getValue()); + } + + return this; + } + } + + @Override + public synchronized Hunk iterateSyncIO(Consumer4IO c) throws IOException { + synchronized(data) + { + int idx, z; + + for (Map.Entry g : data.entrySet()) { + idx = g.getKey(); + z = idx / (getWidth() * getHeight()); + idx -= (z * getWidth() * getHeight()); + c.accept(idx % getWidth(), idx / getWidth(), z, g.getValue()); + } + + return this; + } + } + + @Override + public void empty(T b) { + synchronized(data) + { + data.clear(); + } + } + + @Override + public T getRaw(int x, int y, int z) { + synchronized(data) + { + return data.get(index(x, y, z)); + } + } +} diff --git a/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/src/main/java/com/volmit/iris/util/mantle/Mantle.java index 3265aaef7..38535fb5e 100644 --- a/src/main/java/com/volmit/iris/util/mantle/Mantle.java +++ b/src/main/java/com/volmit/iris/util/mantle/Mantle.java @@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList; import com.volmit.iris.Iris; import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.engine.object.basic.IrisPosition; +import com.volmit.iris.engine.object.feature.IrisFeaturePositional; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.documentation.BlockCoordinates; @@ -115,6 +116,12 @@ public class Mantle { } } + @ChunkCoordinates + public MantleChunk getChunk(int x, int z) + { + return get(x>>5, z>>5).getOrCreate(x & 31, z & 31); + } + /** * Flag or unflag a chunk * @param x the chunk x @@ -146,22 +153,15 @@ public class Mantle { * @param z the chunk z * @param type the type of data to iterate * @param iterator the iterator (x,y,z,data) -> do stuff - * @param requiredFlags any required flags that must be met for this chunk to be iterated * @param the type of data to iterate */ @ChunkCoordinates - public void iterateChunk(int x, int z, Class type, Consumer4 iterator, MantleFlag... requiredFlags) { + public void iterateChunk(int x, int z, Class type, Consumer4 iterator) { if(!hasTectonicPlate(x >> 5, z >> 5)) { return; } - for (MantleFlag i : requiredFlags) { - if (!hasFlag(x, z, i)) { - return; - } - } - get(x >> 5, z >> 5).getOrCreate(x & 31, z & 31).iterate(type, iterator); } @@ -206,11 +206,20 @@ public class Mantle { return; } - Matter matter = get((x >> 4) >> 5, (z >> 4) >> 5) - .getOrCreate((x >> 4) & 31, (z >> 4) & 31) - .getOrCreate(y >> 4); - matter.slice(matter.getClass(t)) - .set(x & 15, y & 15, z & 15, t); + if(t instanceof IrisFeaturePositional) + { + get((x >> 4) >> 5, (z >> 4) >> 5) + .getOrCreate((x >> 4) & 31, (z >> 4) & 31).addFeature((IrisFeaturePositional) t); + } + + else + { + Matter matter = get((x >> 4) >> 5, (z >> 4) >> 5) + .getOrCreate((x >> 4) & 31, (z >> 4) & 31) + .getOrCreate(y >> 4); + matter.slice(matter.getClass(t)) + .set(x & 15, y & 15, z & 15, t); + } } /** @@ -235,7 +244,7 @@ public class Mantle { throw new RuntimeException("The Mantle is closed"); } - if(!hasTectonicPlate(x >> 5, z >> 5)) + if(!hasTectonicPlate((x >> 4) >> 5, (z >> 4) >> 5)) { return null; } diff --git a/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java b/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java index 85d248508..7675d78cc 100644 --- a/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java +++ b/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java @@ -18,17 +18,22 @@ package com.volmit.iris.util.mantle; +import com.volmit.iris.engine.object.feature.IrisFeaturePositional; +import com.volmit.iris.util.data.Varint; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.function.Consumer4; import com.volmit.iris.util.matter.IrisMatter; import com.volmit.iris.util.matter.Matter; import com.volmit.iris.util.matter.MatterSlice; +import com.volmit.iris.util.matter.slices.ZoneMatter; import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.MultiBurst; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicReferenceArray; @@ -37,8 +42,10 @@ import java.util.concurrent.atomic.AtomicReferenceArray; * Mantle Chunks are fully atomic & thread safe */ public class MantleChunk { + private static final ZoneMatter zm = new ZoneMatter(); private final AtomicIntegerArray flags; private final AtomicReferenceArray sections; + private final CopyOnWriteArrayList features; /** * Create a mantle chunk @@ -49,6 +56,7 @@ public class MantleChunk { public MantleChunk(int sectionHeight) { sections = new AtomicReferenceArray<>(sectionHeight); flags = new AtomicIntegerArray(MantleFlag.values().length); + features = new CopyOnWriteArrayList<>(); for (int i = 0; i < flags.length(); i++) { flags.set(i, 0); @@ -76,6 +84,13 @@ public class MantleChunk { sections.set(i, Matter.read(din)); } } + + short v = din.readShort(); + + for(int i = 0; i < v; i++) + { + features.add(zm.readNode(din)); + } } public void flag(MantleFlag flag, boolean f) { @@ -169,6 +184,13 @@ public class MantleChunk { dos.writeBoolean(false); } } + + dos.writeShort(features.size()); + + for(IrisFeaturePositional i : features) + { + zm.writeNode(i, dos); + } } private void trimSlice(int i) { @@ -186,26 +208,6 @@ public class MantleChunk { } } - public void iterate(Class type, Consumer4 iterator, BurstExecutor burst) { - for (int i = 0; i < sections.length(); i++) { - int finalI = i; - burst.queue(() -> { - int bs = (finalI << 4); - Matter matter = get(finalI); - - if (matter != null) { - MatterSlice t = matter.getSlice(type); - - if (t != null) { - t.iterateSync((a, b, c, f) -> iterator.accept(a, b + bs, c, f)); - } - } - }); - } - - burst.complete(); - } - public void iterate(Class type, Consumer4 iterator) { for (int i = 0; i < sections.length(); i++) { int bs = (i << 4); @@ -220,4 +222,12 @@ public class MantleChunk { } } } + + public void addFeature(IrisFeaturePositional t) { + features.add(t); + } + + public List getFeatures() { + return features; + } } diff --git a/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java b/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java index b78a32f2f..6df695c21 100644 --- a/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java +++ b/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java @@ -19,9 +19,11 @@ package com.volmit.iris.util.mantle; import com.volmit.iris.Iris; +import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.Form; +import com.volmit.iris.util.hunk.storage.ArrayHunk; import com.volmit.iris.util.scheduling.PrecisionStopwatch; import java.io.*; @@ -140,7 +142,7 @@ public class TectonicPlate { @ChunkCoordinates private int index(int x, int z) { - return (x & 0x1F) + (z & 0x1F) * 32; + return Cache.to1D(x, z, 0, 32, 32); } /** diff --git a/src/main/java/com/volmit/iris/util/matter/slices/ZoneMatter.java b/src/main/java/com/volmit/iris/util/matter/slices/ZoneMatter.java index 6201b08f1..652ac391f 100644 --- a/src/main/java/com/volmit/iris/util/matter/slices/ZoneMatter.java +++ b/src/main/java/com/volmit/iris/util/matter/slices/ZoneMatter.java @@ -18,6 +18,7 @@ package com.volmit.iris.util.matter.slices; +import com.volmit.iris.Iris; import com.volmit.iris.engine.object.feature.IrisFeaturePositional; import com.volmit.iris.util.matter.Sliced;