diff --git a/plains.json b/plains.json new file mode 100644 index 000000000..960520677 --- /dev/null +++ b/plains.json @@ -0,0 +1,69 @@ +{ + "children": [], + "decorators": [], + "objects": [], + "name": "Plains", + "layers": [ + { + "minHeight": 1, + "terrainZoom": 5, + "maxHeight": 3, + "palette": [ + "GRASS_BLOCK" + ], + "dispersion": "SCATTER" + }, + { + "minHeight": 1, + "terrainZoom": 5, + "maxHeight": 1, + "palette": [ + "DIRT" + ], + "dispersion": "SCATTER" + }, + { + "minHeight": 1, + "terrainZoom": 5, + "maxHeight": 3, + "palette": [ + "DIRT", + "COARSE_DIRT" + ], + "dispersion": "SCATTER" + }, + { + "minHeight": 6, + "terrainZoom": 5, + "maxHeight": 2341, + "palette": [ + "STONE", + "ANDESITE", + "STONE" + ], + "dispersion": "SCATTER" + } + ], + "childShrinkFactor": 1.55, + "derivative": "THE_VOID", + "auxiliaryGenerators": [ + { + "offsetX": 0, + "offsetZ": 0.01, + "min": 1, + "seed": 1336, + "max": 5, + "zoom": 3.065 + }, + { + "offsetX": 0, + "offsetZ": 0, + "min": 1.01, + "seed": 1339, + "max": 2, + "zoom": 1.6 + } + ], + "highHeight": 3.66669, + "lowHeight": 31.5 +} \ No newline at end of file diff --git a/src/main/java/ninja/bytecode/iris/Iris.java b/src/main/java/ninja/bytecode/iris/Iris.java index 178fc0790..b138a297b 100644 --- a/src/main/java/ninja/bytecode/iris/Iris.java +++ b/src/main/java/ninja/bytecode/iris/Iris.java @@ -25,7 +25,7 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.util.Vector; -import ninja.bytecode.iris.generator.IrisGenerator; +import ninja.bytecode.iris.generator.IrisChunkGenerator; import ninja.bytecode.iris.object.IrisBiome; import ninja.bytecode.iris.object.IrisDimension; import ninja.bytecode.iris.object.IrisObject; @@ -84,15 +84,13 @@ public class Iris extends JavaPlugin implements BoardProvider World world = player.getWorld(); List lines = new ArrayList<>(); - if(world.getGenerator() instanceof IrisGenerator) + if(world.getGenerator() instanceof IrisChunkGenerator) { - IrisGenerator g = (IrisGenerator) world.getGenerator(); + IrisChunkGenerator g = (IrisChunkGenerator) world.getGenerator(); int x = player.getLocation().getBlockX(); int z = player.getLocation().getBlockZ(); - IrisDimension dim = g.getDimension(); - BiomeResult er = g.getBiome(x, z); + BiomeResult er = g.sampleTrueBiome(x, z); IrisBiome b = er != null ? er.getBiome() : null; - int fh = dim.getFluidHeight(); 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) + ""); @@ -106,8 +104,8 @@ public class Iris extends JavaPlugin implements BoardProvider { lines.add(ChatColor.GREEN + "Biome" + ChatColor.GRAY + ": " + b.getName()); lines.add(ChatColor.GREEN + "File" + ChatColor.GRAY + ": " + b.getLoadKey() + ".json"); - lines.add(ChatColor.GREEN + "Height" + ChatColor.GRAY + ": " + (int) (b.getLowHeight() + fh) + " - " + (int) (b.getHighHeight() + fh) + " (" + (int) (b.getHighHeight() - b.getLowHeight()) + ")"); } + lines.add("&7&m-----------------"); } @@ -479,7 +477,7 @@ public class Iris extends JavaPlugin implements BoardProvider imsg(i, "Creating Iris " + dimm + "..."); } - IrisGenerator gx = new IrisGenerator(dimm, 16); + IrisChunkGenerator gx = new IrisChunkGenerator(dimm, 16); O done = new O(); done.set(false); @@ -531,7 +529,7 @@ public class Iris extends JavaPlugin implements BoardProvider @Override public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { - return new IrisGenerator("overworld", 16); + return new IrisChunkGenerator("overworld", 16); } public static void msg(String string) diff --git a/src/main/java/ninja/bytecode/iris/IrisContext.java b/src/main/java/ninja/bytecode/iris/IrisContext.java index b742a5435..b855bd1c9 100644 --- a/src/main/java/ninja/bytecode/iris/IrisContext.java +++ b/src/main/java/ninja/bytecode/iris/IrisContext.java @@ -32,4 +32,6 @@ public interface IrisContext public int getHeight(int x, int z); public World getWorld(); + + public void onHotloaded(); } diff --git a/src/main/java/ninja/bytecode/iris/IrisDataManager.java b/src/main/java/ninja/bytecode/iris/IrisDataManager.java index 257097546..10b1b51cc 100644 --- a/src/main/java/ninja/bytecode/iris/IrisDataManager.java +++ b/src/main/java/ninja/bytecode/iris/IrisDataManager.java @@ -11,7 +11,8 @@ import lombok.Data; import ninja.bytecode.iris.object.IrisBiome; import ninja.bytecode.iris.object.IrisBiomeDecorator; import ninja.bytecode.iris.object.IrisDimension; -import ninja.bytecode.iris.object.IrisNoiseLayer; +import ninja.bytecode.iris.object.IrisGenerator; +import ninja.bytecode.iris.object.IrisNoiseGenerator; import ninja.bytecode.iris.object.IrisObjectPlacement; import ninja.bytecode.iris.object.IrisRegion; import ninja.bytecode.iris.util.IO; @@ -27,6 +28,7 @@ public class IrisDataManager private ResourceLoader biomeLoader; private ResourceLoader regionLoader; private ResourceLoader dimensionLoader; + private ResourceLoader generatorLoader; private ObjectResourceLoader objectLoader; public void hotloaded() @@ -35,6 +37,7 @@ public class IrisDataManager this.regionLoader = new ResourceLoader<>(packs, "regions", "Region", IrisRegion.class); this.biomeLoader = new ResourceLoader<>(packs, "biomes", "Biome", IrisBiome.class); this.dimensionLoader = new ResourceLoader<>(packs, "dimensions", "Dimension", IrisDimension.class); + this.generatorLoader = new ResourceLoader<>(packs, "generators", "Generator", IrisGenerator.class); this.objectLoader = new ObjectResourceLoader(packs, "objects", "Object"); writeExamples(); } @@ -68,9 +71,29 @@ public class IrisDataManager new File(examples, "example-pack/regions").mkdirs(); new File(examples, "example-pack/biomes").mkdirs(); new File(examples, "example-pack/dimensions").mkdirs(); + new File(examples, "example-pack/generators").mkdirs(); IO.writeAll(new File(examples, "biome-list.txt"), biomes); IO.writeAll(new File(examples, "environment-list.txt"), envs); + IrisGenerator gen = new IrisGenerator(); + IrisNoiseGenerator n = new IrisNoiseGenerator(); + n.setSeed(1000); + IrisNoiseGenerator nf = new IrisNoiseGenerator(); + nf.setIrisBased(false); + nf.setOctaves(3); + nf.setOpacity(16); + nf.setZoom(24); + nf.setSeed(44); + n.getFracture().add(nf); + IrisNoiseGenerator nf2 = new IrisNoiseGenerator(); + nf2.setIrisBased(false); + nf2.setOctaves(8); + nf2.setOpacity(24); + nf2.setZoom(64); + nf2.setSeed(55); + n.getFracture().add(nf2); + gen.getComposite().add(n); + IrisDimension dim = new IrisDimension(); IrisRegion region = new IrisRegion(); @@ -86,7 +109,6 @@ public class IrisDataManager o.getPlace().add("schematic2"); IrisBiome biome = new IrisBiome(); - biome.getAuxiliaryGenerators().add(new IrisNoiseLayer()); biome.getChildren().add("another_biome"); biome.getDecorators().add(new IrisBiomeDecorator()); biome.getObjects().add(o); @@ -94,6 +116,7 @@ public class IrisDataManager IO.writeAll(new File(examples, "example-pack/biomes/example-biome.json"), new JSONObject(new Gson().toJson(biome)).toString(4)); IO.writeAll(new File(examples, "example-pack/regions/example-region.json"), new JSONObject(new Gson().toJson(region)).toString(4)); IO.writeAll(new File(examples, "example-pack/dimensions/example-dimension.json"), new JSONObject(new Gson().toJson(dim)).toString(4)); + IO.writeAll(new File(examples, "example-pack/generators/example-generator.json"), new JSONObject(new Gson().toJson(gen)).toString(4)); } catch(Throwable e) diff --git a/src/main/java/ninja/bytecode/iris/IrisHotloadManager.java b/src/main/java/ninja/bytecode/iris/IrisHotloadManager.java index 361afc24c..12fbd538e 100644 --- a/src/main/java/ninja/bytecode/iris/IrisHotloadManager.java +++ b/src/main/java/ninja/bytecode/iris/IrisHotloadManager.java @@ -19,7 +19,7 @@ public class IrisHotloadManager latch = new ChronoLatch(3000); } - public void check() + public void check(IrisContext ch) { if(!latch.flip()) { @@ -46,6 +46,7 @@ public class IrisHotloadManager watchers.clear(); Iris.success("Hotloading Iris (" + c + " File" + (c == 1 ? "" : "s") + " changed)"); Iris.data.hotloaded(); + ch.onHotloaded(); } }); } diff --git a/src/main/java/ninja/bytecode/iris/IrisSettings.java b/src/main/java/ninja/bytecode/iris/IrisSettings.java new file mode 100644 index 000000000..659796717 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/IrisSettings.java @@ -0,0 +1,9 @@ +package ninja.bytecode.iris; + +import lombok.Data; + +@Data +public class IrisSettings +{ + private int threads = 16; +} diff --git a/src/main/java/ninja/bytecode/iris/generator/BiomeChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/BiomeChunkGenerator.java index 1ecaddb61..852a2ec9f 100644 --- a/src/main/java/ninja/bytecode/iris/generator/BiomeChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/BiomeChunkGenerator.java @@ -1,32 +1,147 @@ package ninja.bytecode.iris.generator; -import java.util.function.Function; +import java.util.concurrent.locks.ReentrantLock; import org.bukkit.World; import lombok.Data; import lombok.EqualsAndHashCode; +import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.layer.GenLayerBiome; import ninja.bytecode.iris.object.IrisBiome; +import ninja.bytecode.iris.object.IrisBiomeGeneratorLink; +import ninja.bytecode.iris.object.IrisGenerator; import ninja.bytecode.iris.object.IrisRegion; import ninja.bytecode.iris.util.BiomeResult; +import ninja.bytecode.iris.util.CNG; +import ninja.bytecode.iris.util.ChunkPosition; import ninja.bytecode.iris.util.IrisInterpolation; import ninja.bytecode.iris.util.RNG; +import ninja.bytecode.shuriken.collections.KList; +import ninja.bytecode.shuriken.collections.KMap; +import ninja.bytecode.shuriken.math.M; @Data @EqualsAndHashCode(callSuper = false) public abstract class BiomeChunkGenerator extends DimensionChunkGenerator { + protected ReentrantLock regLock; + protected KMap generators; protected GenLayerBiome glBiome; + protected CNG masterFracture; + protected KMap biomeHitCache; public BiomeChunkGenerator(String dimensionName) { super(dimensionName); + generators = new KMap<>(); + regLock = new ReentrantLock(); + biomeHitCache = new KMap<>(); } public void onInit(World world, RNG rng) { + loadGenerators(); glBiome = new GenLayerBiome(this, masterRandom.nextParallelRNG(1)); + masterFracture = CNG.signature(rng.nextParallelRNG(13)).scale(0.12); + } + + public void onHotloaded() + { + biomeHitCache = new KMap<>(); + generators.clear(); + loadGenerators(); + } + + public void registerGenerator(IrisGenerator g) + { + regLock.lock(); + if(g.getLoadKey() == null || generators.containsKey(g.getLoadKey())) + { + regLock.unlock(); + return; + } + + regLock.unlock(); + generators.put(g.getLoadKey(), g); + } + + protected double getBiomeHeight(double rx, double rz) + { + double h = 0; + + for(IrisGenerator i : generators.values()) + { + h += interpolateGenerator(rx, rz, i); + } + + return h; + } + + protected double interpolateGenerator(double rx, double rz, IrisGenerator gen) + { + double hi = IrisInterpolation.getNoise(gen.getInterpolationFunction(), (int) Math.round(rx), (int) Math.round(rz), gen.getInterpolationScale(), (xx, zz) -> + { + IrisBiome b = sampleBiome((int) xx, (int) zz).getBiome(); + + for(IrisBiomeGeneratorLink i : b.getGenerators()) + { + if(i.getGenerator().equals(gen.getLoadKey())) + { + return i.getMin(); + } + } + + return getDimension().getFluidHeight(); + }); + + double lo = IrisInterpolation.getNoise(gen.getInterpolationFunction(), (int) Math.round(rx), (int) Math.round(rz), gen.getInterpolationScale(), (xx, zz) -> + { + IrisBiome b = sampleBiome((int) xx, (int) zz).getBiome(); + + for(IrisBiomeGeneratorLink i : b.getGenerators()) + { + if(i.getGenerator().equals(gen.getLoadKey())) + { + return i.getMax(); + } + } + + return getDimension().getFluidHeight(); + }); + + return M.lerp(lo, hi, gen.getHeight(rx, rz, world.getSeed() + 239945)); + } + + protected void loadGenerators() + { + KList touch = new KList<>(); + KList loadQueue = new KList<>(); + + for(String i : getDimension().getRegions()) + { + IrisRegion r = Iris.data.getRegionLoader().load(i); + + if(r != null) + { + loadQueue.addAll(r.getLandBiomes()); + loadQueue.addAll(r.getSeaBiomes()); + loadQueue.addAll(r.getShoreBiomes()); + } + } + + while(!loadQueue.isEmpty()) + { + String next = loadQueue.pop(); + + if(!touch.contains(next)) + { + touch.add(next); + IrisBiome biome = Iris.data.getBiomeLoader().load(next); + biome.getGenerators().forEach((i) -> registerGenerator(i.getCachedGenerator())); + loadQueue.addAll(biome.getChildren()); + } + } } public IrisRegion sampleRegion(int x, int z) @@ -38,38 +153,19 @@ public abstract class BiomeChunkGenerator extends DimensionChunkGenerator public BiomeResult sampleBiome(int x, int z) { + ChunkPosition pos = new ChunkPosition(x, z); + + if(biomeHitCache.containsKey(pos)) + { + return biomeHitCache.get(pos); + } + double wx = getModifiedX(x, z); double wz = getModifiedZ(x, z); IrisRegion region = glBiome.getRegion(wx, wz); - return glBiome.generateRegionData(wx, wz, region); - } + BiomeResult res = glBiome.generateRegionData(wx, wz, region); + biomeHitCache.put(pos, res); - protected double interpolateAuxiliaryHeight(double rx, double rz) - { - return IrisInterpolation.getNoise(getDimension().getInterpolationAuxiliaryFunction(), (int) Math.round(rx), (int) Math.round(rz), getDimension().getInterpolationAuxiliaryScale(), (xx, zz) -> - { - double xv = xx / getDimension().getTerrainZoom(); - double zv = zz / getDimension().getTerrainZoom(); - BiomeResult neighborResult = glBiome.generateData(xv, zv); - return neighborResult.getBiome().getAuxiliaryHeight(xv, zv, getWorld().getSeed() * 3923); - }); - } - - protected double interpolateHeight(double rx, double rz, Function property) - { - return IrisInterpolation.getNoise(getDimension().getInterpolationFunction(), (int) Math.round(rx), (int) Math.round(rz), getDimension().getInterpolationScale(), (xx, zz) -> - { - BiomeResult neighborResult = glBiome.generateData(xx / getDimension().getTerrainZoom(), zz / getDimension().getTerrainZoom()); - return property.apply(neighborResult.getBiome()); - }); - } - - protected double interpolateSurface(double rx, double rz, Function property) - { - return IrisInterpolation.getNoise(getDimension().getInterpolationSurfaceFunction(), (int) Math.round(rx), (int) Math.round(rz), getDimension().getInterpolationSurfaceScale(), (xx, zz) -> - { - BiomeResult neighborResult = glBiome.generateData(xx / getDimension().getTerrainZoom(), zz / getDimension().getTerrainZoom()); - return property.apply(neighborResult.getBiome()); - }); + return res; } } diff --git a/src/main/java/ninja/bytecode/iris/generator/ContextualChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/ContextualChunkGenerator.java index b306231d0..7bdc889f9 100644 --- a/src/main/java/ninja/bytecode/iris/generator/ContextualChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/ContextualChunkGenerator.java @@ -186,7 +186,7 @@ public abstract class ContextualChunkGenerator extends ChunkGenerator implements { return super.canSpawn(world, x, z); } - + protected ChunkData generateChunkDataFailure(World world, Random no, int x, int z, BiomeGrid biomeGrid) { ChunkData c = Bukkit.createChunkData(world); @@ -231,7 +231,7 @@ public abstract class ContextualChunkGenerator extends ChunkGenerator implements this.world = world; } - Iris.hotloader.check(); + Iris.hotloader.check((IrisContext) this); if(this instanceof IrisContext) { @@ -260,6 +260,11 @@ public abstract class ContextualChunkGenerator extends ChunkGenerator implements return generateChunkDataFailure(world, no, x, z, biomeGrid); } + + public void onHotloaded() + { + + } protected void fail(Throwable e) { diff --git a/src/main/java/ninja/bytecode/iris/generator/DimensionChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/DimensionChunkGenerator.java index 33409913c..1b325d3b1 100644 --- a/src/main/java/ninja/bytecode/iris/generator/DimensionChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/DimensionChunkGenerator.java @@ -31,12 +31,18 @@ public abstract class DimensionChunkGenerator extends ContextualChunkGenerator public double getModifiedX(int rx, int rz) { - return (getDimension().cosRotate() * rx) + (-getDimension().sinRotate() * rz) + getDimension().getCoordFracture(masterRandom, 39392).fitDoubleD(-getDimension().getCoordFractureDistance() / 2, getDimension().getCoordFractureDistance() / 2, rx, rz); + return (getDimension().cosRotate() * rx) + + (-getDimension().sinRotate() * rz) + + + getDimension().getCoordFracture(masterRandom, 39392).fitDoubleD(-getDimension().getCoordFractureDistance() / 2, getDimension().getCoordFractureDistance() / 2, rx, rz); } public double getModifiedZ(int rx, int rz) { - return (getDimension().sinRotate() * rx) + (getDimension().cosRotate() * rz) + getDimension().getCoordFracture(masterRandom, 39392).fitDoubleD(-getDimension().getCoordFractureDistance() / 2, getDimension().getCoordFractureDistance() / 2, rx, rz); + return (getDimension().sinRotate() * rx) + + (getDimension().cosRotate() * rz) + + + getDimension().getCoordFracture(masterRandom, 39392).fitDoubleD(-getDimension().getCoordFractureDistance() / 2, getDimension().getCoordFractureDistance() / 2, rx, rz); } public double getZoomed(double modified) diff --git a/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java b/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java similarity index 88% rename from src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java rename to src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java index ce0632f96..f7c34a3f7 100644 --- a/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/IrisChunkGenerator.java @@ -12,9 +12,9 @@ import ninja.bytecode.iris.util.BiomeResult; @Data @EqualsAndHashCode(callSuper = false) -public class IrisGenerator extends ParallaxChunkGenerator implements IrisContext +public class IrisChunkGenerator extends ParallaxChunkGenerator implements IrisContext { - public IrisGenerator(String dimensionName, int threads) + public IrisChunkGenerator(String dimensionName, int threads) { super(dimensionName, threads); } diff --git a/src/main/java/ninja/bytecode/iris/generator/ParallaxChunkGenerator.java b/src/main/java/ninja/bytecode/iris/generator/ParallaxChunkGenerator.java index 4bf11b25f..c62be1ab4 100644 --- a/src/main/java/ninja/bytecode/iris/generator/ParallaxChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/ParallaxChunkGenerator.java @@ -120,6 +120,8 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple @Override protected void onPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, BiomeMap biomeMap) { + biomeHitCache.clear(); + if(getDimension().isPlaceObjects()) { onGenerateParallax(random, 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 30ea5c474..4ae994c17 100644 --- a/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/TerrainChunkGenerator.java @@ -11,7 +11,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.CNG; import ninja.bytecode.iris.util.RNG; import ninja.bytecode.shuriken.collections.KList; @@ -22,7 +21,6 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator protected static final BlockData AIR = Material.AIR.createBlockData(); protected static final BlockData STONE = Material.STONE.createBlockData(); protected static final BlockData WATER = Material.WATER.createBlockData(); - protected CNG terrainNoise; public TerrainChunkGenerator(String dimensionName, int threads) { @@ -32,7 +30,6 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator public void onInit(World world, RNG rng) { super.onInit(world, rng); - terrainNoise = CNG.signature(masterRandom.nextParallelRNG(2)); } @Override @@ -77,13 +74,10 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator protected double getNoiseHeight(int rx, int rz) { - double ox = getModifiedX(rx, rz); - double oz = getModifiedZ(rx, rz); - double wx = getZoomed(ox); - double wz = getZoomed(oz); - double lo = interpolateHeight(ox, oz, (b) -> b.getLowHeight()); - double hi = interpolateSurface(ox, oz, (b) -> b.getHighHeight()); - return lo + (terrainNoise.fitDoubleD(0, hi - lo, wx, wz)) + interpolateAuxiliaryHeight(rx, rz); + double wx = getZoomed(rx); + double wz = getZoomed(rz); + + return getBiomeHeight(wx, wz); } public BiomeResult sampleTrueBiome(int x, int z) diff --git a/src/main/java/ninja/bytecode/iris/object/IrisBiome.java b/src/main/java/ninja/bytecode/iris/object/IrisBiome.java index f2fe54f77..d270cb82c 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisBiome.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisBiome.java @@ -7,6 +7,7 @@ import org.bukkit.block.data.BlockData; import lombok.Data; import lombok.EqualsAndHashCode; +import ninja.bytecode.iris.generator.BiomeChunkGenerator; import ninja.bytecode.iris.util.CNG; import ninja.bytecode.iris.util.CellGenerator; import ninja.bytecode.iris.util.RNG; @@ -15,18 +16,16 @@ import ninja.bytecode.shuriken.logging.L; @Data @EqualsAndHashCode(callSuper = false) -public class IrisBiome extends IrisRegisteredObject +public class IrisBiome extends IrisRegistrant { private String name = "A Biome"; private Biome derivative = Biome.THE_VOID; - private double highHeight = 3; - private double lowHeight = 1; private double childShrinkFactor = 1.5; private KList children = new KList<>(); private KList layers = new KList().qadd(new IrisBiomePaletteLayer()); private KList decorators = new KList(); private KList objects = new KList(); - private KList auxiliaryGenerators = new KList(); + private KList generators = new KList().qadd(new IrisBiomeGeneratorLink()); private transient ReentrantLock lock = new ReentrantLock(); private transient CellGenerator childrenCell; private transient InferredType inferredType; @@ -38,22 +37,16 @@ public class IrisBiome extends IrisRegisteredObject } - public double getAuxiliaryHeight(double rx, double rz, long superSeed) + public double getHeight(double x, double z, long seed) { - if(auxiliaryGenerators.isEmpty()) + double height = 0; + + for(IrisBiomeGeneratorLink i : generators) { - return 0; + height += i.getHeight(x, z, seed); } - int hc = hashCode(); - double h = 0; - - for(IrisNoiseLayer i : auxiliaryGenerators) - { - h += i.getNoise(superSeed + hc, rx, rz); - } - - return h; + return Math.max(0, Math.min(height, 255)); } public CellGenerator getChildrenGenerator(RNG random, int sig, double scale) diff --git a/src/main/java/ninja/bytecode/iris/object/IrisBiomeGeneratorLink.java b/src/main/java/ninja/bytecode/iris/object/IrisBiomeGeneratorLink.java new file mode 100644 index 000000000..be314e480 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/object/IrisBiomeGeneratorLink.java @@ -0,0 +1,47 @@ +package ninja.bytecode.iris.object; + +import lombok.Data; +import net.md_5.bungee.api.ChatColor; +import ninja.bytecode.iris.Iris; +import ninja.bytecode.iris.generator.BiomeChunkGenerator; +import ninja.bytecode.iris.util.IrisInterpolation; + +@Data +public class IrisBiomeGeneratorLink +{ + private String generator = "default"; + private int min = 0; + private int max = 0; + private transient IrisGenerator gen; + + public IrisBiomeGeneratorLink() + { + + } + + public IrisGenerator getCachedGenerator() + { + if(gen == null) + { + gen = Iris.data.getGeneratorLoader().load(getGenerator()); + + if(gen == null) + { + gen = new IrisGenerator(); + } + + Iris.success("Registered Generator " + ChatColor.WHITE + gen.getLoadKey()); + } + + return gen; + } + + public double getHeight(double x, double z, long seed) + { + double g = getCachedGenerator().getHeight(x, z, seed); + g = g < 0 ? 0 : g; + g = g > 1 ? 1 : g; + + return IrisInterpolation.lerp(min, max, g); + } +} diff --git a/src/main/java/ninja/bytecode/iris/object/IrisDimension.java b/src/main/java/ninja/bytecode/iris/object/IrisDimension.java index a457823d9..2a165f786 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisDimension.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisDimension.java @@ -10,15 +10,13 @@ import ninja.bytecode.shuriken.collections.KList; @Data @EqualsAndHashCode(callSuper = false) -public class IrisDimension extends IrisRegisteredObject +public class IrisDimension extends IrisRegistrant { private String name = "A Dimension"; private InterpolationMethod interpolationFunction = InterpolationMethod.BICUBIC; private double interpolationScale = 63; private InterpolationMethod interpolationSurfaceFunction = InterpolationMethod.BICUBIC; private double interpolationSurfaceScale = 4; - private InterpolationMethod interpolationAuxiliaryFunction = InterpolationMethod.BICUBIC; - private double interpolationAuxiliaryScale = 7; private Environment environment = Environment.NORMAL; private KList regions = new KList<>(); private int fluidHeight = 127; diff --git a/src/main/java/ninja/bytecode/iris/object/IrisGenerator.java b/src/main/java/ninja/bytecode/iris/object/IrisGenerator.java new file mode 100644 index 000000000..f4d76cf71 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/object/IrisGenerator.java @@ -0,0 +1,45 @@ +package ninja.bytecode.iris.object; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import ninja.bytecode.shuriken.collections.KList; + +@Data +@EqualsAndHashCode(callSuper = false) +public class IrisGenerator extends IrisRegistrant +{ + private double zoom = 1; + private double opacity = 1; + private double offsetX = 0; + private double offsetZ = 0; + private long seed = 1; + private InterpolationMethod interpolationFunction = InterpolationMethod.BICUBIC; + private double interpolationScale = 7; + private KList composite = new KList(); + + public double getMax() + { + return opacity; + } + + public double getHeight(double rx, double rz, long superSeed) + { + if(composite.isEmpty()) + { + return 0; + } + + int hc = hashCode(); + double h = 0; + double tp = 0; + + for(IrisNoiseGenerator i : composite) + { + tp += i.getOpacity(); + h += i.getNoise(seed + superSeed + hc, (rx + offsetX) / zoom, (rz + offsetZ) / zoom); + } + + return (h / tp) * opacity; + } + +} diff --git a/src/main/java/ninja/bytecode/iris/object/IrisNoiseGenerator.java b/src/main/java/ninja/bytecode/iris/object/IrisNoiseGenerator.java new file mode 100644 index 000000000..75c57c3ee --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/object/IrisNoiseGenerator.java @@ -0,0 +1,89 @@ +package ninja.bytecode.iris.object; + +import java.util.concurrent.locks.ReentrantLock; + +import lombok.Data; +import ninja.bytecode.iris.util.CNG; +import ninja.bytecode.iris.util.IrisInterpolation; +import ninja.bytecode.iris.util.RNG; +import ninja.bytecode.shuriken.collections.KList; + +@Data +public class IrisNoiseGenerator +{ + private double zoom = 1; + private double opacity = 1; + private double offsetX = 0; + private double offsetY = 0; + private double offsetZ = 0; + private long seed = 0; + private boolean parametric = false; + private boolean bezier = false; + private boolean sinCentered = false; + private double exponent = 1; + private boolean enabled = true; + private boolean irisBased = true; + private int octaves = 1; + private KList fracture = new KList<>(); + + private transient ReentrantLock lock; + private transient CNG generator; + + public IrisNoiseGenerator() + { + lock = new ReentrantLock(); + } + + public IrisNoiseGenerator(boolean enabled) + { + this(); + this.enabled = enabled; + } + + protected CNG getGenerator(long superSeed) + { + if(generator == null) + { + lock.lock(); + generator = irisBased ? CNG.signature(new RNG(superSeed + 33955677 - seed)) : new CNG(new RNG(superSeed + 33955677 - seed), 1D, octaves); + lock.unlock(); + } + + return generator; + } + + public double getMax() + { + return getOffsetY() + opacity; + } + + public double getNoise(long superSeed, double xv, double zv) + { + if(!enabled) + { + return offsetY; + } + + double x = xv; + double z = zv; + int g = 33; + + for(IrisNoiseGenerator i : fracture) + { + if(i.isEnabled()) + { + x += i.getNoise(superSeed + seed + g, xv, zv); + z -= i.getNoise(superSeed + seed + g, zv, xv); + } + g += 819; + } + + double n = getGenerator(superSeed).fitDoubleD(0, opacity, (x / zoom) + offsetX, (z / zoom) + offsetZ); + n = (exponent != 1 ? Math.pow(n, exponent) : n) + offsetY; + n = parametric ? IrisInterpolation.parametric(n, 1) : n; + n = bezier ? IrisInterpolation.bezier(n) : n; + n = sinCentered ? IrisInterpolation.sinCenter(n) : n; + + return n; + } +} diff --git a/src/main/java/ninja/bytecode/iris/object/IrisNoiseLayer.java b/src/main/java/ninja/bytecode/iris/object/IrisNoiseLayer.java deleted file mode 100644 index 441d8a259..000000000 --- a/src/main/java/ninja/bytecode/iris/object/IrisNoiseLayer.java +++ /dev/null @@ -1,41 +0,0 @@ -package ninja.bytecode.iris.object; - -import java.util.concurrent.locks.ReentrantLock; - -import ninja.bytecode.iris.util.CNG; -import ninja.bytecode.iris.util.RNG; - -public class IrisNoiseLayer -{ - private double zoom = 1; - private double offsetX = 0; - private double offsetZ = 0; - private long seed = 0; - private double min = 0; - private double max = 10; - - private transient ReentrantLock lock; - private transient CNG generator; - - public IrisNoiseLayer() - { - lock = new ReentrantLock(); - } - - protected CNG getGenerator(long superSeed) - { - if(generator == null) - { - lock.lock(); - generator = CNG.signature(new RNG(superSeed + 33955677 - seed)); - lock.unlock(); - } - - return generator; - } - - public double getNoise(long superSeed, double x, double z) - { - return getGenerator(superSeed).fitDoubleD(min, max, (x / zoom) + offsetX, (z / zoom) + offsetZ); - } -} diff --git a/src/main/java/ninja/bytecode/iris/object/IrisObject.java b/src/main/java/ninja/bytecode/iris/object/IrisObject.java index 41d00758a..ffaed4e47 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisObject.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisObject.java @@ -22,7 +22,7 @@ import ninja.bytecode.shuriken.collections.KMap; @Data @EqualsAndHashCode(callSuper = false) -public class IrisObject extends IrisRegisteredObject +public class IrisObject extends IrisRegistrant { private KMap blocks; private int w; diff --git a/src/main/java/ninja/bytecode/iris/object/IrisRegion.java b/src/main/java/ninja/bytecode/iris/object/IrisRegion.java index 0a3b083a0..1b2cddff5 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisRegion.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisRegion.java @@ -10,7 +10,7 @@ import ninja.bytecode.shuriken.collections.KList; @Data @EqualsAndHashCode(callSuper = false) -public class IrisRegion extends IrisRegisteredObject +public class IrisRegion extends IrisRegistrant { private String name = "A Region"; private double shoreRatio = 0.13; diff --git a/src/main/java/ninja/bytecode/iris/object/IrisRegisteredObject.java b/src/main/java/ninja/bytecode/iris/object/IrisRegistrant.java similarity index 73% rename from src/main/java/ninja/bytecode/iris/object/IrisRegisteredObject.java rename to src/main/java/ninja/bytecode/iris/object/IrisRegistrant.java index 6bbe10e80..51d608f85 100644 --- a/src/main/java/ninja/bytecode/iris/object/IrisRegisteredObject.java +++ b/src/main/java/ninja/bytecode/iris/object/IrisRegistrant.java @@ -3,7 +3,7 @@ package ninja.bytecode.iris.object; import lombok.Data; @Data -public class IrisRegisteredObject +public class IrisRegistrant { private String loadKey; } diff --git a/src/main/java/ninja/bytecode/iris/objectproperty/ObjectProperty.java b/src/main/java/ninja/bytecode/iris/objectproperty/ObjectProperty.java deleted file mode 100644 index 9aa7702aa..000000000 --- a/src/main/java/ninja/bytecode/iris/objectproperty/ObjectProperty.java +++ /dev/null @@ -1,42 +0,0 @@ -package ninja.bytecode.iris.objectproperty; - -import java.lang.reflect.Field; - -import lombok.Data; - -@Data -public class ObjectProperty -{ - private Class type; - private String fieldName; - private String name; - private String description; - private Object instance; - private Field field; - - public ObjectProperty(Class type, String fieldName) throws Throwable - { - this.type = type; - this.fieldName = fieldName; - field = type.getDeclaredField(name); - field.setAccessible(true); - - if(field.isAnnotationPresent(Property.class)) - { - Property p = field.getAnnotation(Property.class); - name = p.name(); - description = p.description(); - } - } - - public void set(T value) throws Throwable - { - field.set(instance, value); - } - - @SuppressWarnings("unchecked") - public T get() throws Throwable - { - return (T) field.get(instance); - } -} diff --git a/src/main/java/ninja/bytecode/iris/objectproperty/PropertyObject.java b/src/main/java/ninja/bytecode/iris/objectproperty/PropertyObject.java deleted file mode 100644 index fd08cc652..000000000 --- a/src/main/java/ninja/bytecode/iris/objectproperty/PropertyObject.java +++ /dev/null @@ -1,16 +0,0 @@ -package ninja.bytecode.iris.objectproperty; - -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.*; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -@Retention(RUNTIME) -@Target(TYPE) -public @interface PropertyObject -{ - String name(); - - String description(); -} diff --git a/src/main/java/ninja/bytecode/iris/util/BiomeDominance.java b/src/main/java/ninja/bytecode/iris/util/BiomeDominance.java new file mode 100644 index 000000000..e6e9a2664 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/BiomeDominance.java @@ -0,0 +1,9 @@ +package ninja.bytecode.iris.util; + +import ninja.bytecode.iris.object.IrisBiome; +import ninja.bytecode.shuriken.collections.KMap; + +public class BiomeDominance extends KMap +{ + private static final long serialVersionUID = 9055245062942178392L; +} diff --git a/src/main/java/ninja/bytecode/iris/util/BiomeResult.java b/src/main/java/ninja/bytecode/iris/util/BiomeResult.java index 91c81e61d..5d41802b5 100644 --- a/src/main/java/ninja/bytecode/iris/util/BiomeResult.java +++ b/src/main/java/ninja/bytecode/iris/util/BiomeResult.java @@ -14,4 +14,9 @@ public class BiomeResult this.biome = biome; this.distance = distance; } + + public boolean is(BiomeResult r) + { + return biome.getName().equals(r.biome.getName()); + } } \ No newline at end of file diff --git a/src/main/java/ninja/bytecode/iris/util/ObjectResourceLoader.java b/src/main/java/ninja/bytecode/iris/util/ObjectResourceLoader.java index a032c0d26..e04d5cf49 100644 --- a/src/main/java/ninja/bytecode/iris/util/ObjectResourceLoader.java +++ b/src/main/java/ninja/bytecode/iris/util/ObjectResourceLoader.java @@ -91,7 +91,7 @@ public class ObjectResourceLoader extends ResourceLoader } lock.lock(); - for(File i : getFolders()) + for(File i : getFolders(name)) { for(File j : i.listFiles()) { diff --git a/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java b/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java index 82a690e7f..4c2561316 100644 --- a/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java +++ b/src/main/java/ninja/bytecode/iris/util/ResourceLoader.java @@ -6,15 +6,16 @@ import java.util.concurrent.locks.ReentrantLock; import com.google.gson.Gson; import ninja.bytecode.iris.Iris; -import ninja.bytecode.iris.object.IrisRegisteredObject; +import ninja.bytecode.iris.object.IrisRegistrant; import ninja.bytecode.shuriken.collections.KList; import ninja.bytecode.shuriken.collections.KMap; -public class ResourceLoader +public class ResourceLoader { protected File root; protected String folderName; protected String resourceTypeName; + protected KMap folderMapCache; protected KMap loadCache; protected KList folderCache; protected Class objectClass; @@ -23,6 +24,7 @@ public class ResourceLoader public ResourceLoader(File root, String folderName, String resourceTypeName, Class objectClass) { lock = new ReentrantLock(); + folderMapCache = new KMap<>(); this.objectClass = objectClass; this.resourceTypeName = resourceTypeName; this.root = root; @@ -62,7 +64,7 @@ public class ResourceLoader } lock.lock(); - for(File i : getFolders()) + for(File i : getFolders(name)) { for(File j : i.listFiles()) { @@ -111,9 +113,55 @@ public class ResourceLoader return folderCache; } + public KList getFolders(String rc) + { + KList folders = getFolders().copy(); + + if(rc.contains(":")) + { + for(File i : folders.copy()) + { + if(!rc.startsWith(i.getName() + ":")) + { + folders.remove(i); + } + } + } + + return folders; + } + public void clearCache() { loadCache.clear(); folderCache = null; } + + public File fileFor(T b) + { + for(File i : getFolders()) + { + for(File j : i.listFiles()) + { + if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(b.getLoadKey())) + { + return j; + } + } + + File file = new File(i, b.getLoadKey() + ".json"); + + if(file.exists()) + { + return file; + } + } + + return null; + } + + public boolean isLoaded(String next) + { + return loadCache.containsKey(next); + } }