diff --git a/core/src/main/java/com/volmit/iris/core/service/BoardSVC.java b/core/src/main/java/com/volmit/iris/core/service/BoardSVC.java index 05cc8dc60..e5557b023 100644 --- a/core/src/main/java/com/volmit/iris/core/service/BoardSVC.java +++ b/core/src/main/java/com/volmit/iris/core/service/BoardSVC.java @@ -40,6 +40,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; public class BoardSVC implements IrisService, BoardProvider { private final KMap boards = new KMap<>(); @@ -104,11 +105,11 @@ public List getLines(Player player) { @Data public static class PlayerBoard { private final Player player; - private final KList lines; + private final CopyOnWriteArrayList lines; public PlayerBoard(Player player) { this.player = player; - this.lines = new KList<>(); + this.lines = new CopyOnWriteArrayList<>(); update(); } diff --git a/core/src/main/java/com/volmit/iris/engine/modifier/IrisDepositModifier.java b/core/src/main/java/com/volmit/iris/engine/modifier/IrisDepositModifier.java index 0f8d192f4..037f77d8d 100644 --- a/core/src/main/java/com/volmit/iris/engine/modifier/IrisDepositModifier.java +++ b/core/src/main/java/com/volmit/iris/engine/modifier/IrisDepositModifier.java @@ -20,10 +20,7 @@ import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.EngineAssignedModifier; -import com.volmit.iris.engine.object.IrisBiome; -import com.volmit.iris.engine.object.IrisDepositGenerator; -import com.volmit.iris.engine.object.IrisObject; -import com.volmit.iris.engine.object.IrisRegion; +import com.volmit.iris.engine.object.*; import com.volmit.iris.util.context.ChunkContext; import com.volmit.iris.util.data.B; import com.volmit.iris.util.data.HeightMap; @@ -45,26 +42,26 @@ public IrisDepositModifier(Engine engine) { @Override public void onModify(int x, int z, Hunk output, boolean multicore, ChunkContext context) { PrecisionStopwatch p = PrecisionStopwatch.start(); - generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16), multicore, context); + generateDeposits(output, Math.floorDiv(x, 16), Math.floorDiv(z, 16), multicore, context); getEngine().getMetrics().getDeposit().put(p.getMilliseconds()); } - public void generateDeposits(RNG rx, Hunk terrain, int x, int z, boolean multicore, ChunkContext context) { - RNG ro = rx.nextParallelRNG(x * x).nextParallelRNG(z * z); + public void generateDeposits(Hunk terrain, int x, int z, boolean multicore, ChunkContext context) { IrisRegion region = context.getRegion().get(7, 7); IrisBiome biome = context.getBiome().get(7, 7); BurstExecutor burst = burst().burst(multicore); + long seed = x * 341873128712L + z * 132897987541L; for (IrisDepositGenerator k : getDimension().getDeposits()) { - burst.queue(() -> generate(k, terrain, ro, x, z, false, context)); + burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(seed), x, z, false, context)); } for (IrisDepositGenerator k : region.getDeposits()) { - burst.queue(() -> generate(k, terrain, ro, x, z, false, context)); + burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(seed), x, z, false, context)); } for (IrisDepositGenerator k : biome.getDeposits()) { - burst.queue(() -> generate(k, terrain, ro, x, z, false, context)); + burst.queue(() -> generate(k, terrain, rng.nextParallelRNG(seed), x, z, false, context)); } burst.complete(); } @@ -74,45 +71,48 @@ public void generate(IrisDepositGenerator k, Hunk data, RNG rng, int } public void generate(IrisDepositGenerator k, Hunk data, RNG rng, int cx, int cz, boolean safe, HeightMap he, ChunkContext context) { - for (int l = 0; l < rng.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) { + if (k.getSpawnChance() < rng.d()) + return; + + for (int l = 0; l < rng.i(k.getMinPerChunk(), k.getMaxPerChunk() + 1); l++) { + if (k.getPerClumpSpawnChance() < rng.d()) + continue; + IrisObject clump = k.getClump(rng, getData()); - int af = (int) Math.floor(clump.getW() / 2D); - int bf = (int) Math.floor(16D - (clump.getW() / 2D)); + int dim = clump.getW(); + int min = dim / 2; + int max = (int) (16D - dim / 2D); - if (af > bf || af < 0 || bf > 15) { - af = 6; - bf = 9; + if (min > max || min < 0 || max > 15) { + min = 6; + max = 9; } - af = Math.max(af - 1, 0); - int x = rng.i(af, bf); - int z = rng.i(af, bf); + int x = rng.i(min, max + 1); + int z = rng.i(min, max + 1); int height = (he != null ? he.getHeight((cx << 4) + x, (cz << 4) + z) : (int) (Math.round( context.getHeight().get(x, z) ))) - 7; - if (height <= 0) { - return; - } + if (height <= 0) + continue; - int i = Math.max(0, k.getMinHeight()); + int minY = Math.max(0, k.getMinHeight()); // TODO: WARNING HEIGHT - int a = Math.min(height, Math.min(getEngine().getHeight(), k.getMaxHeight())); + int maxY = Math.min(height, Math.min(getEngine().getHeight(), k.getMaxHeight())); - if (i >= a) { - return; - } + if (minY >= maxY) + continue; - int h = rng.i(i, a); + int y = rng.i(minY, maxY + 1); - if (h > k.getMaxHeight() || h < k.getMinHeight() || h > height - 2) { - return; - } + if (y > k.getMaxHeight() || y < k.getMinHeight() || y > height - 2) + continue; for (BlockVector j : clump.getBlocks().keySet()) { int nx = j.getBlockX() + x; - int ny = j.getBlockY() + h; + int ny = j.getBlockY() + y; int nz = j.getBlockZ() + z; if (ny > height || nx > 15 || nx < 0 || ny > getEngine().getHeight() || ny < 0 || nz < 0 || nz > 15) { diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisDepositGenerator.java b/core/src/main/java/com/volmit/iris/engine/object/IrisDepositGenerator.java index 9958f8032..271b54ded 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisDepositGenerator.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisDepositGenerator.java @@ -22,13 +22,14 @@ import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.object.annotations.*; import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.collection.KSet; +import com.volmit.iris.util.math.BlockPosition; import com.volmit.iris.util.math.RNG; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import org.bukkit.block.data.BlockData; -import org.bukkit.util.BlockVector; @Snippet("deposit") @Accessors(chain = true) @@ -69,6 +70,14 @@ public class IrisDepositGenerator { @MaxNumber(2048) @Desc("The minimum amount of clumps per chunk") private int minPerChunk = 0; + @MinNumber(0) + @MaxNumber(1) + @Desc("The change of the deposit spawning in a chunk") + private double spawnChance = 1; + @MinNumber(0) + @MaxNumber(1) + @Desc("The change of the a clump spawning in a chunk") + private double perClumpSpawnChance = 1; @Required @ArrayType(min = 1, type = IrisBlockData.class) @Desc("The palette of blocks to be used in this deposit generator") @@ -90,35 +99,62 @@ public IrisObject getClump(RNG rng, IrisData rdata) { return objectsf; }); - return objects.get(rng.i(0, objects.size() - 1)); + return objects.get(rng.i(0, objects.size())); } public int getMaxDimension() { - return Math.min(11, (int) Math.round(Math.pow(maxSize, 1D / 3D))); + return Math.min(11, (int) Math.ceil(Math.cbrt(maxSize))); } private IrisObject generateClumpObject(RNG rngv, IrisData rdata) { - int s = rngv.i(minSize, maxSize); - int dim = Math.min(11, (int) Math.round(Math.pow(maxSize, 1D / 3D))); - int w = dim / 2; - IrisObject o = new IrisObject(dim, dim, dim); - + int s = rngv.i(minSize, maxSize + 1); if (s == 1) { + IrisObject o = new IrisObject(1, 1, 1); o.getBlocks().put(o.getCenter(), nextBlock(rngv, rdata)); - } else { - while (s > 0) { - s--; - BlockVector ang = new BlockVector(rngv.i(-w, w), rngv.i(-w, w), rngv.i(-w, w)); - BlockVector pos = o.getCenter().clone().add(ang).toBlockVector(); - o.getBlocks().put(pos, nextBlock(rngv, rdata)); + return o; + } + + int dim = Math.min(11, (int) Math.ceil(Math.cbrt(s))); + IrisObject o = new IrisObject(dim, dim, dim); + + int volume = dim * dim * dim; + if (s >= volume) { + int x = 0, y = 0, z = 0; + + while (z < dim) { + o.setUnsigned(x++, y, z, nextBlock(rngv, rdata)); + + if (x == dim) { + x = 0; + y++; + } + + if (y == dim) { + y = 0; + z++; + } } + return o; + } + + KSet set = new KSet<>(); + while (s > 0) { + BlockPosition ang = new BlockPosition( + rngv.i(0, dim), + rngv.i(0, dim), + rngv.i(0, dim) + ); + if (!set.add(ang)) continue; + + s--; + o.setUnsigned(ang.getX(), ang.getY(), ang.getZ(), nextBlock(rngv, rdata)); } return o; } private BlockData nextBlock(RNG rngv, IrisData rdata) { - return getBlockData(rdata).get(rngv.i(0, getBlockData(rdata).size() - 1)); + return getBlockData(rdata).get(rngv.i(0, getBlockData(rdata).size())); } public KList getBlockData(IrisData rdata) { diff --git a/core/src/main/java/com/volmit/iris/util/documentation/Exclusive.java b/core/src/main/java/com/volmit/iris/util/documentation/Exclusive.java new file mode 100644 index 000000000..c7202aab4 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/documentation/Exclusive.java @@ -0,0 +1,7 @@ +package com.volmit.iris.util.documentation; + +/** + * This Argument is exclusive + */ +public @interface Exclusive { +} diff --git a/core/src/main/java/com/volmit/iris/util/documentation/Inclusive.java b/core/src/main/java/com/volmit/iris/util/documentation/Inclusive.java new file mode 100644 index 000000000..5e4f27599 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/util/documentation/Inclusive.java @@ -0,0 +1,7 @@ +package com.volmit.iris.util.documentation; + +/** + * This Argument is inclusive + */ +public @interface Inclusive { +} diff --git a/core/src/main/java/com/volmit/iris/util/math/RNG.java b/core/src/main/java/com/volmit/iris/util/math/RNG.java index d74680b09..0c735854a 100644 --- a/core/src/main/java/com/volmit/iris/util/math/RNG.java +++ b/core/src/main/java/com/volmit/iris/util/math/RNG.java @@ -18,6 +18,9 @@ package com.volmit.iris.util.math; +import com.volmit.iris.util.documentation.Exclusive; +import com.volmit.iris.util.documentation.Inclusive; + import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Random; @@ -89,11 +92,11 @@ public boolean b(double percent) { return d() > percent; } - public short si(int lowerBound, int upperBound) { + public short si(@Inclusive int lowerBound, @Inclusive int upperBound) { return (short) (lowerBound + (nextFloat() * ((upperBound - lowerBound) + 1))); } - public short si(int upperBound) { + public short si(@Inclusive int upperBound) { return si(0, upperBound); } @@ -101,11 +104,11 @@ public short si() { return si(1); } - public float f(float lowerBound, float upperBound) { + public float f(@Inclusive float lowerBound, @Exclusive float upperBound) { return lowerBound + (nextFloat() * ((upperBound - lowerBound))); } - public float f(float upperBound) { + public float f(@Exclusive float upperBound) { return f(0, upperBound); } @@ -113,7 +116,7 @@ public float f() { return f(1); } - public double d(double lowerBound, double upperBound) { + public double d(@Inclusive double lowerBound, @Exclusive double upperBound) { if (lowerBound > upperBound) { return M.lerp(upperBound, lowerBound, nextDouble()); } @@ -121,7 +124,7 @@ public double d(double lowerBound, double upperBound) { return M.lerp(lowerBound, upperBound, nextDouble()); } - public double d(double upperBound) { + public double d(@Exclusive double upperBound) { return d(0, upperBound); } @@ -129,19 +132,19 @@ public double d() { return d(1); } - public int i(int lowerBound, int upperBound) { + public int i(@Inclusive int lowerBound, @Exclusive int upperBound) { return (int) Math.floor(d(lowerBound, upperBound)); } - public int i(int upperBound) { + public int i(@Exclusive int upperBound) { return i(Math.min(upperBound, 0), Math.max(0, upperBound)); } - public long l(long lowerBound, long upperBound) { + public long l(@Inclusive long lowerBound, @Exclusive long upperBound) { return Math.round(d(lowerBound, upperBound)); } - public long l(long upperBound) { + public long l(@Exclusive long upperBound) { return l(0, upperBound); }