diff --git a/src/main/java/ninja/bytecode/iris/Iris.java b/src/main/java/ninja/bytecode/iris/Iris.java index 573df929d..72f07f376 100644 --- a/src/main/java/ninja/bytecode/iris/Iris.java +++ b/src/main/java/ninja/bytecode/iris/Iris.java @@ -113,22 +113,23 @@ public class Iris extends JavaPlugin implements BoardProvider int x = player.getLocation().getBlockX(); int z = player.getLocation().getBlockZ(); BiomeResult er = g.sampleTrueBiome(x, z); - BiomeResult erx = g.sampleBiome(x, z); IrisBiome b = er != null ? er.getBiome() : null; - IrisBiome bx = erx != null ? erx.getBiome() : null; lines.add("&7&m-----------------"); lines.add(ChatColor.GREEN + "Speed" + ChatColor.GRAY + ": " + ChatColor.BOLD + "" + ChatColor.GRAY + Form.f(g.getMetrics().getPerSecond().getAverage(), 0) + "/s " + Form.duration(g.getMetrics().getTotal().getAverage(), 1) + ""); lines.add(ChatColor.GREEN + "Loss" + ChatColor.GRAY + ": " + ChatColor.BOLD + "" + ChatColor.GRAY + Form.duration(g.getMetrics().getLoss().getAverage(), 4) + ""); lines.add(ChatColor.GREEN + "Generators" + ChatColor.GRAY + ": " + Form.f(CNG.creates)); lines.add(ChatColor.GREEN + "Noise" + ChatColor.GRAY + ": " + Form.f((int) hits.getAverage())); - lines.add(ChatColor.GREEN + "Parallax Regions" + ChatColor.GRAY + ": " + Form.f((int) g.getParallaxMap().getLoadedRegions().size())); lines.add(ChatColor.GREEN + "Parallax Chunks" + ChatColor.GRAY + ": " + Form.f((int) g.getParallaxMap().getLoadedChunks().size())); + lines.add(ChatColor.GREEN + "Objects" + ChatColor.GRAY + ": " + Form.f(Iris.data.getObjectLoader().count())); + lines.add(ChatColor.GREEN + "Biomes" + ChatColor.GRAY + ": " + Form.f(Iris.data.getBiomeLoader().count())); + lines.add(ChatColor.GREEN + "Regions" + ChatColor.GRAY + ": " + Form.f(Iris.data.getRegionLoader().count())); + lines.add(ChatColor.GREEN + "Height" + ChatColor.GRAY + ": " + (int) g.getTerrainHeight(x, z) + " (" + (int) g.getTerrainWaterHeight(x, z) + ")"); + lines.add(ChatColor.GREEN + "Height" + ChatColor.GRAY + ": " + (int) g.getTerrainHeight(x, z) + " (" + (int) g.getTerrainWaterHeight(x, z) + ")"); if(er != null && b != null) { lines.add(ChatColor.GREEN + "Biome" + ChatColor.GRAY + ": " + b.getName()); - lines.add(ChatColor.GREEN + "Real" + ChatColor.GRAY + ": " + bx.getName()); - lines.add(ChatColor.GREEN + "File" + ChatColor.GRAY + ": " + b.getLoadKey() + ".json"); + lines.add(ChatColor.GREEN + "File" + ChatColor.GRAY + ": " + b.getLoadKey()); } lines.add("&7&m-----------------"); diff --git a/src/main/java/ninja/bytecode/iris/generator/BiomeChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/BiomeChunkGenerator.java index e9fed2c8d..06560857f 100644 --- a/src/main/java/ninja/bytecode/iris/generator/BiomeChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/BiomeChunkGenerator.java @@ -36,6 +36,7 @@ public abstract class BiomeChunkGenerator extends DimensionChunkGenerator private KMap biomeHitCache; private KMap ceilingBiomeHitCache; protected ChronoLatch cwarn = new ChronoLatch(1000); + private IrisBiome[] biomeCache; public BiomeChunkGenerator(String dimensionName) { @@ -45,6 +46,7 @@ public abstract class BiomeChunkGenerator extends DimensionChunkGenerator regLock = new ReentrantLock(); biomeHitCache = new KMap<>(); ceilingBiomeHitCache = new KMap<>(); + biomeCache = new IrisBiome[256]; } public void onInit(World world, RNG rng) @@ -54,15 +56,25 @@ public abstract class BiomeChunkGenerator extends DimensionChunkGenerator masterFracture = CNG.signature(rng.nextParallelRNG(13)).scale(0.12); } + protected IrisBiome getCachedBiome(int x, int z) + { + return biomeCache[(z << 4) | x]; + } + + protected void cacheBiome(int x, int z, IrisBiome b) + { + biomeCache[(z << 4) | x] = b; + } + public KMap getBiomeHitCache() { return getDimension().isInverted() ? ceilingBiomeHitCache : biomeHitCache; } @Override - public void onHotloaded() + public void onHotload() { - super.onHotloaded(); + super.onHotload(); biomeHitCache = new KMap<>(); ceilingBiomeHitCache = new KMap<>(); loadGenerators(); diff --git a/src/main/java/ninja/bytecode/iris/generator/CeilingChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/CeilingChunkGenerator.java index 3296ebadf..a2d17e3ee 100644 --- a/src/main/java/ninja/bytecode/iris/generator/CeilingChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/CeilingChunkGenerator.java @@ -11,6 +11,9 @@ import ninja.bytecode.iris.util.RNG; public abstract class CeilingChunkGenerator extends ParallaxChunkGenerator { protected boolean generatingCeiling = false; + protected boolean ceilingCached = false; + protected IrisDimension cacheCeiling = null; + protected IrisDimension cacheFloor = null; public CeilingChunkGenerator(String dimensionName, int threads) { @@ -38,6 +41,15 @@ public abstract class CeilingChunkGenerator extends ParallaxChunkGenerator } } + @Override + public void onHotload() + { + super.onHotload(); + ceilingCached = false; + cacheCeiling = null; + cacheFloor = null; + } + private void targetFloor() { generatingCeiling = false; @@ -61,11 +73,21 @@ public abstract class CeilingChunkGenerator extends ParallaxChunkGenerator public IrisDimension getFloorDimension() { - return super.getDimension(); + if(cacheFloor != null) + { + return cacheFloor; + } + + return cacheFloor = super.getDimension(); } public IrisDimension getCeilingDimension() { + if(ceilingCached) + { + return cacheCeiling; + } + if(getFloorDimension().getCeiling().isEmpty()) { return null; @@ -78,6 +100,9 @@ public abstract class CeilingChunkGenerator extends ParallaxChunkGenerator c.setInverted(true); } + ceilingCached = true; + cacheCeiling = c; + return c; } diff --git a/src/main/java/ninja/bytecode/iris/generator/ContextualChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/ContextualChunkGenerator.java index 7bdc889f9..143641778 100644 --- a/src/main/java/ninja/bytecode/iris/generator/ContextualChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/ContextualChunkGenerator.java @@ -260,10 +260,10 @@ public abstract class ContextualChunkGenerator extends ChunkGenerator implements return generateChunkDataFailure(world, no, x, z, biomeGrid); } - - public void onHotloaded() + + public void onHotload() { - + } protected void fail(Throwable e) diff --git a/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java index ddd4ffe38..2359e7af5 100644 --- a/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java @@ -63,7 +63,7 @@ public class IrisChunkGenerator extends CeilingChunkGenerator implements IrisCon @Override protected void onChunkLoaded(Chunk c) { - updateLights(); + } @Override @@ -83,4 +83,10 @@ public class IrisChunkGenerator extends CeilingChunkGenerator implements IrisCon { } + + @Override + public void onHotloaded() + { + onHotload(); + } } diff --git a/src/main/java/ninja/bytecode/iris/generator/ParallaxChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/ParallaxChunkGenerator.java index f3cb3815a..b9c2fdf3d 100644 --- a/src/main/java/ninja/bytecode/iris/generator/ParallaxChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/ParallaxChunkGenerator.java @@ -76,12 +76,13 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple @Override public int getHighest(int x, int z) { - return sampleSliver(x, z).getHighestBlock(); + return getHighest(x, z, false); } - public int getHighestGround(int x, int z) + @Override + public int getHighest(int x, int z, boolean ignoreFluid) { - return sampleSliver(x, z).getHighestGround(); + return (int) Math.round(ignoreFluid ? getTerrainHeight(x, z) : getTerrainWaterHeight(x, z)); } @Override @@ -150,6 +151,7 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple if(getDimension().isPlaceObjects()) { onGenerateParallax(random, x, z); + injectBiomeSky(x, z, grid); getParallaxChunk(x, z).inject(data); setSliverBuffer(getSliverCache().size()); getParallaxChunk(x, z).setWorldGenerated(true); @@ -161,6 +163,39 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple super.onPostParallaxPostGenerate(random, x, z, data, grid, height, biomeMap); } + protected void injectBiomeSky(int x, int z, BiomeGrid grid) + { + if(getDimension().isInverted()) + { + return; + } + + int rx; + int rz; + + for(int i = 0; i < 16; i++) + { + rx = (x * 16) + i; + for(int j = 0; j < 16; j++) + { + rz = (z * 16) + j; + + int min = sampleSliver(rx, rz).getHighestBiome(); + int max = getParallaxSliver(rx, rz).getHighestBlock(); + + if(min < max) + { + IrisBiome biome = getCachedBiome(i, j); + + for(int g = min; g <= max; g++) + { + grid.setBiome(i, g, j, biome.getSkyBiome(masterRandom, rz, g, rx)); + } + } + } + } + } + protected void onGenerateParallax(RNG random, int x, int z) { String key = "par." + x + "." + "z"; diff --git a/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java index 1a5cd282c..453f2425b 100644 --- a/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java @@ -1,10 +1,7 @@ package ninja.bytecode.iris.generator; -import java.util.concurrent.locks.ReentrantLock; - import org.bukkit.Material; import org.bukkit.World; -import org.bukkit.block.Block; import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.BlockData; @@ -18,7 +15,6 @@ import ninja.bytecode.iris.object.IrisRegion; import ninja.bytecode.iris.object.atomics.AtomicSliver; import ninja.bytecode.iris.util.BiomeMap; import ninja.bytecode.iris.util.BiomeResult; -import ninja.bytecode.iris.util.BlockPosition; import ninja.bytecode.iris.util.HeightMap; import ninja.bytecode.iris.util.RNG; import ninja.bytecode.shuriken.collections.KList; @@ -29,8 +25,6 @@ import ninja.bytecode.shuriken.math.M; public abstract class TerrainChunkGenerator extends ParallelChunkGenerator { protected static final BlockData AIR = Material.AIR.createBlockData(); - private KList updateBlocks = new KList<>(); - private ReentrantLock relightLock = new ReentrantLock(); private long lastUpdateRequest = M.ms(); private long lastChunkLoad = M.ms(); private GenLayerCave glCave; @@ -48,60 +42,6 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator glCave = new GenLayerCave(this, rng.nextParallelRNG(238948)); } - public void queueUpdate(int x, int y, int z) - { - if(M.ms() - lastUpdateRequest > 3000 && M.ms() - lastChunkLoad > 3000) - { - updateBlocks.clear(); - } - - updateBlocks.add(new BlockPosition(x, y, z)); - lastUpdateRequest = M.ms(); - } - - public void updateLights() - { - if(M.ms() - lastUpdateRequest > 3000 && M.ms() - lastChunkLoad > 3000) - { - updateBlocks.clear(); - } - - for(BlockPosition i : updateBlocks.copy()) - { - if(getWorld().isChunkLoaded(i.getChunkX(), i.getChunkZ())) - { - updateBlocks.remove(i); - Block b = getWorld().getBlockAt(i.getX(), i.getY(), i.getZ()); - BlockData bd = b.getBlockData(); - b.setBlockData(AIR, false); - b.setBlockData(bd, true); - } - } - - while(updateBlocks.size() > 5000) - { - updateBlocks.remove(0); - } - - lastChunkLoad = M.ms(); - } - - public void checkUnderwater(int x, int y, int z, BlockData d) - { - if(d.getMaterial().equals(Material.SEA_PICKLE) || d.getMaterial().equals(Material.SOUL_SAND) || d.getMaterial().equals(Material.MAGMA_BLOCK)) - { - queueUpdate(x, y, z); - } - } - - public void checkSurface(int x, int y, int z, BlockData d) - { - if(d.getMaterial().equals(Material.SEA_PICKLE) || d.getMaterial().equals(Material.TORCH) || d.getMaterial().equals(Material.REDSTONE_TORCH) || d.getMaterial().equals(Material.TORCH)) - { - queueUpdate(x, y, z); - } - } - @Override protected void onGenerateColumn(int cx, int cz, int rx, int rz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap) { @@ -119,8 +59,9 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator IrisBiome biome = sampleTrueBiome(rx, rz).getBiome(); KList layers = biome.generateLayers(wx, wz, masterRandom, height); KList seaLayers = biome.isSea() ? biome.generateSeaLayers(wx, wz, masterRandom, fluidHeight - height) : new KList<>(); + cacheBiome(x, z, biome); - for(int k = Math.max(height, fluidHeight); k < 255; k++) + for(int k = Math.max(height, fluidHeight); k < Math.max(height, fluidHeight) + 3; k++) { if(k < Math.max(height, fluidHeight) + 3) { @@ -129,14 +70,6 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator sliver.set(k, biome.getGroundBiome(masterRandom, rz, k, rx)); } } - - else if(!getDimension().isInverted()) - { - if(biomeMap != null) - { - sliver.set(k, biome.getSkyBiome(masterRandom, rx, k, rz)); - } - } } for(int k = Math.max(height, fluidHeight); k >= 0; k--) @@ -177,7 +110,6 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator if(stack == 1) { sliver.set(k + 1, d); - checkUnderwater(rx, k + 1, rz, d); } else if(k < fluidHeight - stack) @@ -185,7 +117,6 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator for(int l = 0; l < stack; l++) { sliver.set(k + l + 1, d); - checkUnderwater(rx, k + l + 1, rz, d); } } @@ -330,4 +261,19 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator return (int) Math.round(noise) + fluidHeight; } + + public int getFluidHeight() + { + return getDimension().getFluidHeight(); + } + + public double getTerrainHeight(int x, int z) + { + return getNoiseHeight(x, z) + getFluidHeight(); + } + + public double getTerrainWaterHeight(int x, int z) + { + return Math.max(getTerrainHeight(x, z), getFluidHeight()); + } } diff --git a/src/main/java/ninja/bytecode/iris/object/IrisBiome.java b/src/main/java/ninja/bytecode/iris/object/IrisBiome.java index 02e2ba4bc..1c46998e8 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisBiome.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisBiome.java @@ -60,7 +60,7 @@ public class IrisBiome extends IrisRegistrant @Desc("Define biome deposit generators that add onto the existing regional and global deposit generators") private KList deposits = new KList<>(); - + private transient ReentrantLock lock = new ReentrantLock(); private transient CellGenerator childrenCell; private transient InferredType inferredType; @@ -258,16 +258,16 @@ public class IrisBiome extends IrisRegistrant public Biome getSkyBiome(RNG rng, double x, double y, double z) { - if(biomeSkyScatter.isEmpty()) - { - return getGroundBiome(rng, x, y, z); - } - if(biomeSkyScatter.size() == 1) { return biomeSkyScatter.get(0); } + if(biomeSkyScatter.isEmpty()) + { + return getGroundBiome(rng, x, y, z); + } + return biomeSkyScatter.get(getBiomeGenerator(rng).fit(0, biomeSkyScatter.size() - 1, x, y, z)); } diff --git a/src/main/java/ninja/bytecode/iris/object/IrisDepositGenerator.java b/src/main/java/ninja/bytecode/iris/object/IrisDepositGenerator.java index 5cd12068d..c23cec4e3 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisDepositGenerator.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisDepositGenerator.java @@ -83,6 +83,7 @@ public class IrisDepositGenerator rot.setYAxis(yc); rot.setZAxis(zc); p.setRotation(rot); + p.setUnderwater(true); return p; } @@ -145,8 +146,22 @@ public class IrisDepositGenerator public void generate(int x, int z, RNG rng, ParallaxChunkGenerator g) { IrisObject clump = getClump(rng); - int height = (int) (g.getHighestGround(x, z) - (clump.getH() * 1.5)); - int h = rng.i(Math.max(0, minHeight), Math.min(height, Math.min(256, maxHeight))); + int height = (int) (Math.round(g.getTerrainHeight(x, z))); + int i = Math.max(0, minHeight); + int a = Math.min(height, Math.min(256, maxHeight)); + + if(i >= a) + { + return; + } + + int h = rng.i(i, a); + + if(h > maxHeight || h < minHeight) + { + return; + } + clump.place(x, h, z, g, config, rng); } } diff --git a/src/main/java/ninja/bytecode/iris/object/IrisDimension.java b/src/main/java/ninja/bytecode/iris/object/IrisDimension.java index db118c24a..2a4150e4a 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisDimension.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisDimension.java @@ -139,6 +139,11 @@ public class IrisDimension extends IrisRegistrant public BlockData getRock(RNG rng, double x, double y, double z) { + if(getRockData().size() == 1) + { + return getRockData().get(0); + } + if(rockLayerGenerator == null) { cacheRockGenerator(rng); @@ -199,6 +204,11 @@ public class IrisDimension extends IrisRegistrant public BlockData getFluid(RNG rng, double x, double y, double z) { + if(getFluidData().size() == 1) + { + return getFluidData().get(0); + } + if(fluidLayerGenerator == null) { cacheFluidGenerator(rng); diff --git a/src/main/java/ninja/bytecode/iris/object/IrisObject.java b/src/main/java/ninja/bytecode/iris/object/IrisObject.java index d9f04dfb5..02ca93f30 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisObject.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisObject.java @@ -131,7 +131,7 @@ public class IrisObject extends IrisRegistrant int spinx = rng.imax() / 1000; int spiny = rng.imax() / 1000; int spinz = rng.imax() / 1000; - int y = yv < 0 ? placer.getHighest(x, z) + config.getRotation().rotate(new BlockVector(0, getCenter().getBlockY(), 0), yf, xf, spinx, spiny, spinz).getBlockY() : yv; + int y = yv < 0 ? placer.getHighest(x, z, config.isUnderwater()) + config.getRotation().rotate(new BlockVector(0, getCenter().getBlockY(), 0), yf, xf, spinx, spiny, spinz).getBlockY() : yv; KMap heightmap = config.getSnow() > 0 ? new KMap<>() : null; for(BlockVector g : blocks.k()) diff --git a/src/main/java/ninja/bytecode/iris/object/IrisObjectPlacement.java b/src/main/java/ninja/bytecode/iris/object/IrisObjectPlacement.java index 8327e3fcd..75f5b40af 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisObjectPlacement.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisObjectPlacement.java @@ -30,6 +30,9 @@ public class IrisObjectPlacement @Desc("If the chance check passes, place this many in a single chunk") private int density = 1; + @Desc("If set to true, objects will place on the terrain height, ignoring the water surface.") + private boolean underwater = false; + public IrisObjectPlacement() { diff --git a/src/main/java/ninja/bytecode/iris/object/atomics/AtomicSliver.java b/src/main/java/ninja/bytecode/iris/object/atomics/AtomicSliver.java index d915e7425..4c1bc5cee 100644 --- a/src/main/java/ninja/bytecode/iris/object/atomics/AtomicSliver.java +++ b/src/main/java/ninja/bytecode/iris/object/atomics/AtomicSliver.java @@ -4,7 +4,6 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import org.bukkit.Material; import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; import org.bukkit.generator.ChunkGenerator.BiomeGrid; @@ -22,7 +21,6 @@ public class AtomicSliver private KMap block; private KMap biome; private int highestBlock = 0; - private int highestGround = 0; private int highestBiome = 0; private int x; private int z; @@ -44,11 +42,6 @@ public class AtomicSliver block.put(h, d); highestBlock = h > highestBlock ? h : highestBlock; - - if(!d.getMaterial().equals(Material.WATER) && !d.getMaterial().equals(Material.LAVA)) - { - highestGround = h > highestGround ? h : highestGround; - } } public void setSilently(int h, BlockData d) @@ -104,8 +97,7 @@ public class AtomicSliver this.block = new KMap(); int h = din.readByte() - Byte.MIN_VALUE; highestBlock = h; - highestGround = din.readByte() - Byte.MIN_VALUE; - + for(int i = 0; i <= h; i++) { block.put(i, BlockDataTools.getBlockData(din.readUTF())); @@ -115,7 +107,6 @@ public class AtomicSliver public void write(DataOutputStream dos) throws IOException { dos.writeByte(highestBlock + Byte.MIN_VALUE); - dos.writeByte(highestGround + Byte.MIN_VALUE); for(int i = 0; i <= highestBlock; i++) { diff --git a/src/main/java/ninja/bytecode/iris/util/IObjectPlacer.java b/src/main/java/ninja/bytecode/iris/util/IObjectPlacer.java index 4c2aa21c8..509fd43bb 100644 --- a/src/main/java/ninja/bytecode/iris/util/IObjectPlacer.java +++ b/src/main/java/ninja/bytecode/iris/util/IObjectPlacer.java @@ -6,9 +6,11 @@ public interface IObjectPlacer { public int getHighest(int x, int z); + public int getHighest(int x, int z, boolean ignoreFluid); + public void set(int x, int y, int z, BlockData d); public BlockData get(int x, int y, int z); - + public boolean isPreventingDecay(); } diff --git a/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java b/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java index 4c2561316..dd303bf41 100644 --- a/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java +++ b/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java @@ -32,6 +32,11 @@ public class ResourceLoader loadCache = new KMap<>(); } + public long count() + { + return loadCache.size(); + } + protected T loadFile(File j, String key, String name) { try