Scaffolding

This commit is contained in:
Daniel Mills 2020-03-20 10:17:51 -04:00
parent a97cb3df4f
commit cecbad2eb9
21 changed files with 3096 additions and 22 deletions

16
pom.xml
View File

@ -150,6 +150,22 @@
<version>1.15.1-R0.1-SNAPSHOT</version> <version>1.15.1-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>javax.vecmath</groupId>
<artifactId>vecmath</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.bukkit</groupId> <groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId> <artifactId>bukkit</artifactId>

View File

@ -4,6 +4,7 @@ import java.io.File;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
@ -18,6 +19,10 @@ import ninja.bytecode.iris.util.IO;
public class Iris extends JavaPlugin public class Iris extends JavaPlugin
{ {
public static Iris instance;
public static IrisDataManager data;
public static IrisHotloadManager hotloader;
public Iris() public Iris()
{ {
IO.delete(new File("iris")); IO.delete(new File("iris"));
@ -25,7 +30,9 @@ public class Iris extends JavaPlugin
public void onEnable() public void onEnable()
{ {
instance = this;
hotloader = new IrisHotloadManager();
data = new IrisDataManager(getDataFolder());
Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> Bukkit.getScheduler().scheduleSyncDelayedTask(this, () ->
{ {
for(World i : Bukkit.getWorlds()) for(World i : Bukkit.getWorlds())
@ -36,7 +43,7 @@ public class Iris extends JavaPlugin
} }
} }
World world = Bukkit.createWorld(new WorldCreator("iris/" + UUID.randomUUID()).generator(new IrisGenerator())); World world = Bukkit.createWorld(new WorldCreator("iris/" + UUID.randomUUID()).generator(new IrisGenerator("overworld")));
for(Player i : Bukkit.getOnlinePlayers()) for(Player i : Bukkit.getOnlinePlayers())
{ {
@ -48,6 +55,7 @@ public class Iris extends JavaPlugin
}, 5); }, 5);
} }
}); });
} }
public void onDisable() public void onDisable()
@ -64,6 +72,36 @@ public class Iris extends JavaPlugin
@Override @Override
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) public ChunkGenerator getDefaultWorldGenerator(String worldName, String id)
{ {
return new IrisGenerator(); return new IrisGenerator("overworld");
}
public static void msg(String string)
{
Bukkit.getConsoleSender().sendMessage(ChatColor.GREEN + "[Iris]: " + ChatColor.GRAY + string);
}
public static void warn(String string)
{
msg(ChatColor.YELLOW + string);
}
public static void error(String string)
{
msg(ChatColor.RED + string);
}
public static void verbose(String string)
{
msg(ChatColor.GRAY + string);
}
public static void success(String string)
{
msg(ChatColor.GREEN + string);
}
public static void info(String string)
{
msg(ChatColor.WHITE + string);
} }
} }

View File

@ -0,0 +1,104 @@
package ninja.bytecode.iris;
import java.io.File;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import com.google.gson.Gson;
import lombok.Getter;
import ninja.bytecode.iris.object.Dispersion;
import ninja.bytecode.iris.object.IrisBiome;
import ninja.bytecode.iris.object.IrisBiomePaletteLayer;
import ninja.bytecode.iris.object.IrisDimension;
import ninja.bytecode.iris.util.IO;
import ninja.bytecode.iris.util.JSONObject;
import ninja.bytecode.iris.util.ResourceLoader;
public class IrisDataManager
{
private File dataFolder;
private File packs;
@Getter
private ResourceLoader<IrisBiome> biomeLoader;
@Getter
private ResourceLoader<IrisDimension> dimensionLoader;
public void hotloaded()
{
packs.mkdirs();
this.biomeLoader = new ResourceLoader<>(packs, "biomes", "Biome", IrisBiome.class);
this.dimensionLoader = new ResourceLoader<>(packs, "dimensions", "Dimension", IrisDimension.class);
writeExamples();
}
public IrisDataManager(File dataFolder)
{
this.dataFolder = dataFolder;
this.packs = new File(dataFolder, "packs");
hotloaded();
}
private void writeExamples()
{
File examples = new File(dataFolder, "example");
examples.mkdirs();
IrisBiome biome = new IrisBiome();
biome.getLayers().clear();
IrisBiomePaletteLayer grass = new IrisBiomePaletteLayer();
grass.add("GRASS_BLOCK");
grass.setDispersion(Dispersion.SCATTER);
grass.setMinHeight(1);
grass.setMaxHeight(1);
IrisBiomePaletteLayer dirt = new IrisBiomePaletteLayer();
grass.add("DIRT");
grass.setDispersion(Dispersion.SCATTER);
grass.setMinHeight(1);
grass.setMaxHeight(2);
IrisBiomePaletteLayer dirtThick = new IrisBiomePaletteLayer();
grass.add("DIRT");
grass.add("COARSE_DIRT");
grass.setDispersion(Dispersion.WISPY);
grass.setMinHeight(1);
grass.setMaxHeight(3);
biome.getLayers().add(dirtThick);
biome.getLayers().add(dirt);
biome.getLayers().add(grass);
IrisDimension dim = new IrisDimension();
dim.getBiomes().add("a_biome");
String biomes = "";
String envs = "";
for(Biome i : Biome.values())
{
biomes += i.name() + "\n";
}
for(Environment i : Environment.values())
{
envs += i.name() + "\n";
}
try
{
new File(examples, "example-pack/biomes").mkdirs();
new File(examples, "example-pack/dimensions").mkdirs();
IO.writeAll(new File(examples, "biome-list.txt"), biomes);
IO.writeAll(new File(examples, "environment-list.txt"), envs);
IO.writeAll(new File(examples, "example-pack/biomes/a_biome.json"), new JSONObject(new Gson().toJson(biome)).toString(4));
IO.writeAll(new File(examples, "example-pack/dimensions/a_dimension.json"), new JSONObject(new Gson().toJson(dim)).toString(4));
}
catch(Throwable e)
{
}
}
}

View File

@ -2,6 +2,7 @@ package ninja.bytecode.iris;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.function.Function;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -11,17 +12,34 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
import ninja.bytecode.iris.layer.GenLayerBiome;
import ninja.bytecode.iris.object.IrisBiome;
import ninja.bytecode.iris.object.IrisDimension;
import ninja.bytecode.iris.util.BiomeResult;
import ninja.bytecode.iris.util.CNG; import ninja.bytecode.iris.util.CNG;
import ninja.bytecode.iris.util.PolygonGenerator.EnumPolygonGenerator; import ninja.bytecode.iris.util.IrisInterpolation;
import ninja.bytecode.iris.util.KList;
import ninja.bytecode.iris.util.RNG; import ninja.bytecode.iris.util.RNG;
public class IrisGenerator extends ChunkGenerator public class IrisGenerator extends ChunkGenerator
{ {
// TODO REMOVE OR FIND A BETTER PLACE
private BlockData STONE = Material.STONE.createBlockData();
private String dimensionName;
private GenLayerBiome glBiome;
private CNG terrainNoise;
private boolean initialized = false; private boolean initialized = false;
private CNG gen;
private EnumPolygonGenerator<BlockData> pog; public IrisGenerator(String dimensionName)
private BlockData[] d = {Material.RED_CONCRETE.createBlockData(), Material.GREEN_CONCRETE.createBlockData(), Material.BLUE_CONCRETE.createBlockData(), {
}; this.dimensionName = dimensionName;
}
public IrisDimension getDimension()
{
return Iris.data.getDimensionLoader().load(dimensionName);
}
public void onInit(World world, RNG rng) public void onInit(World world, RNG rng)
{ {
@ -31,8 +49,8 @@ public class IrisGenerator extends ChunkGenerator
} }
initialized = true; initialized = true;
gen = CNG.signature(rng.nextParallelRNG(0)); glBiome = new GenLayerBiome(this, rng.nextParallelRNG(1));
pog = new EnumPolygonGenerator<BlockData>(rng.nextParallelRNG(1), 0.1, 1, d, (c) -> c); terrainNoise = CNG.signature(rng.nextParallelRNG(2));
} }
@Override @Override
@ -42,26 +60,56 @@ public class IrisGenerator extends ChunkGenerator
} }
@Override @Override
public ChunkData generateChunkData(World world, Random no, int x, int z, BiomeGrid biome) public ChunkData generateChunkData(World world, Random no, int x, int z, BiomeGrid biomeGrid)
{ {
Iris.hotloader.check();
int i, j, k, height, depth;
double wx, wz, rx, rz, heightLow, heightHigh, heightExponent;
int fluidHeight = getDimension().getFluidHeight();
BiomeResult biomeResult;
IrisBiome biome;
RNG random = new RNG(world.getSeed()); RNG random = new RNG(world.getSeed());
onInit(world, random.nextParallelRNG(0)); onInit(world, random.nextParallelRNG(0));
ChunkData data = Bukkit.createChunkData(world); ChunkData data = Bukkit.createChunkData(world);
for(int i = 0; i < 16; i++) for(i = 0; i < 16; i++)
{ {
for(int j = 0; j < 16; j++) rx = (x * 16) + i;
wx = ((double) (x * 16) + i) / getDimension().getTerrainZoom();
for(j = 0; j < 16; j++)
{ {
double wx = (x * 16) + i; rz = (z * 16) + j;
double wz = (z * 16) + j; wz = ((double) (z * 16) + j) / getDimension().getTerrainZoom();
depth = 0;
biomeResult = glBiome.generateData(wx, wz);
biome = biomeResult.getBiome();
heightLow = interpolate(rx, rz, (b) -> b.getLowHeight());
heightHigh = interpolate(rx, rz, (b) -> b.getHighHeight());
heightExponent = interpolate(rx, rz, (b) -> b.getHeightExponent());
height = (int) Math.round(terrainNoise.fitDoubleExponent(heightLow, heightHigh, heightExponent, wx, wz)) + fluidHeight;
KList<BlockData> layers = biome.generateLayers(wx, wz, random, height);
data.setBlock(i, 0, j, pog.getChoice(wx, wz)); for(k = Math.max(height, fluidHeight); k >= 0; k--)
{
biomeGrid.setBiome(i, k, j, biome.getDerivative());
data.setBlock(i, k, j, layers.hasIndex(depth) ? layers.get(depth) : STONE);
depth++;
}
} }
} }
return data; return data;
} }
public double interpolate(double rx, double rz, Function<IrisBiome, Double> 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());
});
}
@Override @Override
public List<BlockPopulator> getDefaultPopulators(World world) public List<BlockPopulator> getDefaultPopulators(World world)
{ {

View File

@ -0,0 +1,57 @@
package ninja.bytecode.iris;
import java.io.File;
import org.bukkit.Bukkit;
import ninja.bytecode.iris.util.ChronoLatch;
import ninja.bytecode.iris.util.FileWatcher;
import ninja.bytecode.iris.util.KList;
public class IrisHotloadManager
{
private ChronoLatch latch;
private KList<FileWatcher> watchers;
public IrisHotloadManager()
{
watchers = new KList<>();
latch = new ChronoLatch(3000);
}
public void check()
{
if(!latch.flip())
{
return;
}
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () ->
{
boolean modified = false;
int c = 0;
for(FileWatcher i : watchers)
{
if(i.checkModified())
{
c++;
Iris.info("File Modified: " + i.getFile().getPath());
modified = true;
}
}
if(modified)
{
watchers.clear();
Iris.success("Hotloading Iris (" + c + " File" + (c == 1 ? "" : "s") + " changed)");
Iris.data.hotloaded();
}
});
}
public void track(File file)
{
watchers.add(new FileWatcher(file));
}
}

View File

@ -0,0 +1,36 @@
package ninja.bytecode.iris.layer;
import ninja.bytecode.iris.IrisGenerator;
import ninja.bytecode.iris.object.IrisBiome;
import ninja.bytecode.iris.util.BiomeResult;
import ninja.bytecode.iris.util.CellGenerator2D;
import ninja.bytecode.iris.util.GenLayer;
import ninja.bytecode.iris.util.KList;
import ninja.bytecode.iris.util.RNG;
public class GenLayerBiome extends GenLayer
{
private CellGenerator2D cells;
public GenLayerBiome(IrisGenerator iris, RNG rng)
{
super(iris, rng);
cells = new CellGenerator2D(rng.nextParallelRNG(2045662));
}
public KList<IrisBiome> getBiomes()
{
return iris.getDimension().buildBiomeList();
}
public BiomeResult generateData(double x, double z)
{
return new BiomeResult(getBiomes().get(cells.getIndex(x / iris.getDimension().getBiomeZoom(), z / iris.getDimension().getBiomeZoom(), getBiomes().size())), cells.getDistance(x / iris.getDimension().getBiomeZoom(), z / iris.getDimension().getBiomeZoom()));
}
@Override
public double generate(double x, double z)
{
return 0;
}
}

View File

@ -0,0 +1,10 @@
package ninja.bytecode.iris.object;
public enum Dispersion
{
SCATTER,
SIMPLEX,
CELLS,
WISPY,
ZEBRA
}

View File

@ -0,0 +1,9 @@
package ninja.bytecode.iris.object;
public enum InterpolationMethod
{
NONE,
BILINEAR,
BICUBIC,
HERMITE
}

View File

@ -0,0 +1,107 @@
package ninja.bytecode.iris.object;
import java.util.List;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import lombok.Data;
import ninja.bytecode.iris.util.CNG;
import ninja.bytecode.iris.util.KList;
import ninja.bytecode.iris.util.RNG;
@Data
public class IrisBiome
{
private String name = "A Biome";
private Biome derivative = Biome.THE_VOID;
private double highHeight = 7;
private double lowHeight = 1;
private double heightExponent = 1;
private KList<IrisBiomePaletteLayer> layers = new KList<IrisBiomePaletteLayer>().qadd(new IrisBiomePaletteLayer());
private transient KList<CNG> layerHeightGenerators;
private transient KList<CNG> layerSurfaceGenerators;
public KList<BlockData> generateLayers(double wx, double wz, RNG random, int maxDepth)
{
KList<BlockData> data = new KList<>();
for(int i = 0; i < layers.size(); i++)
{
CNG hgen = getLayerHeightGenerators(random).get(i);
CNG sgen = getLayerSurfaceGenerators(random).get(i);
int d = hgen.fit(layers.get(i).getMinHeight(), layers.get(i).getMaxHeight(), wx / layers.get(i).getTerrainZoom(), wz / layers.get(i).getTerrainZoom());
if(d < 0)
{
continue;
}
List<BlockData> palette = getLayers().get(i).getBlockData();
for(int j = 0; j < d; j++)
{
if(data.size() >= maxDepth)
{
break;
}
data.add(palette.get(sgen.fit(0, palette.size() - 1, (wx + j) / layers.get(i).getTerrainZoom(), (wz - j) / layers.get(i).getTerrainZoom())));
}
if(data.size() >= maxDepth)
{
break;
}
}
return data;
}
public KList<CNG> getLayerSurfaceGenerators(RNG rng)
{
synchronized(this)
{
if(layerSurfaceGenerators == null)
{
layerSurfaceGenerators = new KList<>();
synchronized(layerSurfaceGenerators)
{
int m = 91235;
for(IrisBiomePaletteLayer i : getLayers())
{
layerSurfaceGenerators.add(i.getGenerator(rng.nextParallelRNG((m += 3) * m * m * m)));
}
}
}
}
return layerSurfaceGenerators;
}
public KList<CNG> getLayerHeightGenerators(RNG rng)
{
synchronized(this)
{
if(layerHeightGenerators == null)
{
layerHeightGenerators = new KList<>();
synchronized(layerHeightGenerators)
{
int m = 7235;
for(IrisBiomePaletteLayer i : getLayers())
{
layerHeightGenerators.add(i.getGenerator(rng.nextParallelRNG((m++) * m * m * m)));
}
}
}
}
return layerHeightGenerators;
}
}

View File

@ -0,0 +1,85 @@
package ninja.bytecode.iris.object;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import lombok.Data;
import ninja.bytecode.iris.util.CNG;
import ninja.bytecode.iris.util.KList;
import ninja.bytecode.iris.util.KMap;
import ninja.bytecode.iris.util.RNG;
@Data
public class IrisBiomePaletteLayer
{
private Dispersion dispersion = Dispersion.WISPY;
private int minHeight = 1;
private int maxHeight = 1;
private double terrainZoom = 5;
private KList<String> palette = new KList<String>().qadd("GRASS_BLOCK");
private transient KMap<Long, CNG> layerGenerators;
private transient KList<BlockData> blockData;
public CNG getGenerator(RNG rng)
{
synchronized(this)
{
long key = rng.nextParallelRNG(1).nextLong();
if(layerGenerators == null)
{
layerGenerators = new KMap<>();
}
if(!layerGenerators.containsKey(key))
{
synchronized(layerGenerators)
{
layerGenerators.put(key, CNG.signature(rng.nextParallelRNG(minHeight + maxHeight + getBlockData().size())));
}
}
return layerGenerators.get(key);
}
}
public KList<String> add(String b)
{
palette.add(b);
return palette;
}
public KList<BlockData> getBlockData()
{
synchronized(this)
{
if(blockData == null)
{
blockData = new KList<>();
synchronized(blockData)
{
for(String i : palette)
{
try
{
Material m = Material.valueOf(i);
if(m != null)
{
blockData.add(m.createBlockData());
}
}
catch(Throwable e)
{
}
}
}
}
}
return blockData;
}
}

View File

@ -0,0 +1,48 @@
package ninja.bytecode.iris.object;
import org.bukkit.World.Environment;
import lombok.Data;
import ninja.bytecode.iris.Iris;
import ninja.bytecode.iris.util.KList;
@Data
public class IrisDimension
{
private String name = "A Dimension";
private InterpolationMethod interpolationFunction = InterpolationMethod.BILINEAR;
private double interpolationScale = 5.6;
private Environment environment = Environment.NORMAL;
private KList<String> biomes = new KList<>();
private int fluidHeight = 127;
private double biomeZoom = 5D;
private double terrainZoom = 2D;
private double roughnessZoom = 2D;
private int roughnessHeight = 3;
private transient KList<IrisBiome> biomeCache;
public KList<IrisBiome> buildBiomeList()
{
if(biomeCache == null)
{
synchronized(this)
{
biomeCache = new KList<>();
synchronized(biomeCache)
{
for(String i : biomes)
{
IrisBiome biome = Iris.data.getBiomeLoader().load(i);
if(biome != null)
{
biomeCache.add(biome);
}
}
}
}
}
return biomeCache;
}
}

View File

@ -0,0 +1,17 @@
package ninja.bytecode.iris.util;
import lombok.Data;
import ninja.bytecode.iris.object.IrisBiome;
@Data
public class BiomeResult
{
private IrisBiome biome;
private double distance;
public BiomeResult(IrisBiome biome, double distance)
{
this.biome = biome;
this.distance = distance;
}
}

View File

@ -25,6 +25,9 @@ public class CNG
private NoiseInjector injector; private NoiseInjector injector;
private RNG rng; private RNG rng;
private int oct; private int oct;
private double patch;
private double up;
private double down;
private double power; private double power;
public static CNG signature(RNG rng) public static CNG signature(RNG rng)
@ -32,14 +35,12 @@ public class CNG
//@builder //@builder
return new CNG(rng.nextParallelRNG(17), 1D, 8) return new CNG(rng.nextParallelRNG(17), 1D, 8)
.scale(0.012) .scale(0.012)
.amp(0.5)
.freq(1.1)
.fractureWith(new CNG(rng.nextParallelRNG(18), 1, 5) .fractureWith(new CNG(rng.nextParallelRNG(18), 1, 5)
.scale(0.018) .scale(0.018)
.child(new CNG(rng.nextParallelRNG(19), 0.745, 2) .child(new CNG(rng.nextParallelRNG(19), 1, 2)
.scale(0.1)) .scale(0.1))
.fractureWith(new CNG(rng.nextParallelRNG(20), 1, 3) .fractureWith(new CNG(rng.nextParallelRNG(20), 1, 3)
.scale(0.15), 24), 44); .scale(0.15), 24), 44).down(0.3).patch(2.5);
//@done //@done
} }
@ -62,6 +63,7 @@ public class CNG
freq = 1; freq = 1;
amp = 1; amp = 1;
scale = 1; scale = 1;
patch = 1;
fscale = 1; fscale = 1;
fracture = null; fracture = null;
generator = new SNG(random); generator = new SNG(random);
@ -116,12 +118,66 @@ public class CNG
return this; return this;
} }
public CNG patch(double c)
{
patch = c;
return this;
}
public CNG up(double c)
{
up = c;
return this;
}
public CNG down(double c)
{
down = c;
return this;
}
public CNG injectWith(NoiseInjector i) public CNG injectWith(NoiseInjector i)
{ {
injector = i; injector = i;
return this; return this;
} }
public int fit(int min, int max, double... dim)
{
if(min == max)
{
return min;
}
double noise = noise(dim);
return (int) Math.round(IrisInterpolation.lerp(min, max, noise));
}
public int fitDouble(double min, double max, double... dim)
{
if(min == max)
{
return (int) Math.round(min);
}
double noise = noise(dim);
return (int) Math.round(IrisInterpolation.lerp(min, max, noise));
}
public int fitDoubleExponent(double min, double max, double exponent, double... dim)
{
if(min == max)
{
return (int) Math.round(min);
}
double noise = noise(dim);
return (int) Math.round(IrisInterpolation.lerp(min, max, exponent == 1 ? noise : Math.pow(noise, exponent)));
}
public double noise(double... dim) public double noise(double... dim)
{ {
double f = fracture != null ? (fracture.noise(dim) - 0.5) * fscale : 0D; double f = fracture != null ? (fracture.noise(dim) - 0.5) * fscale : 0D;
@ -134,7 +190,7 @@ public class CNG
hits += oct; hits += oct;
if(children == null) if(children == null)
{ {
return n; return (n - down + up) * patch;
} }
for(CNG i : children) for(CNG i : children)
@ -144,7 +200,7 @@ public class CNG
m += r[1]; m += r[1];
} }
return n / m; return ((n / m) - down + up) * patch;
} }
public CNG pow(double power) public CNG pow(double power)

View File

@ -0,0 +1,54 @@
package ninja.bytecode.iris.util;
import lombok.Getter;
import lombok.Setter;
import ninja.bytecode.iris.util.FastNoise.CellularDistanceFunction;
import ninja.bytecode.iris.util.FastNoise.CellularReturnType;
import ninja.bytecode.iris.util.FastNoise.NoiseType;
public class CellGenerator2D
{
private FastNoise fn;
private FastNoise fd;
private CNG cng;
@Getter
@Setter
private double cellScale;
@Getter
@Setter
private double shuffle;
public CellGenerator2D(RNG rng)
{
shuffle = 128;
cellScale = 0.73;
cng = CNG.signature(rng.nextParallelRNG(3204));
RNG rx = rng.nextParallelRNG(8735652);
int s = rx.nextInt();
fn = new FastNoise(s);
fn.SetNoiseType(NoiseType.Cellular);
fn.SetCellularReturnType(CellularReturnType.CellValue);
fn.SetCellularDistanceFunction(CellularDistanceFunction.Natural);
fd = new FastNoise(s);
fd.SetNoiseType(NoiseType.Cellular);
fd.SetCellularReturnType(CellularReturnType.Distance2Sub);
fd.SetCellularDistanceFunction(CellularDistanceFunction.Natural);
}
public float getDistance(double x, double z)
{
return ((fd.GetCellular((float) ((x * cellScale) + (cng.noise(x, z) * shuffle)), (float) ((z * cellScale) + (cng.noise(z, x) * shuffle)))) + 1f) / 2f;
}
public float getValue(double x, double z, int possibilities)
{
return ((fn.GetCellular((float) ((x * cellScale) + (cng.noise(x, z) * shuffle)), (float) ((z * cellScale) + (cng.noise(z, x) * shuffle))) + 1f) / 2f) * (possibilities - 1);
}
public int getIndex(double x, double z, int possibilities)
{
return (int) Math.round(getValue(x, z, possibilities));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
package ninja.bytecode.iris.util;
import java.io.File;
import lombok.Getter;
public class FileWatcher
{
@Getter
private final File file;
private boolean exists;
private long lastModified;
private long size;
public FileWatcher(File file)
{
this.file = file;
readProperties();
}
private void readProperties()
{
exists = file.exists();
lastModified = exists ? file.lastModified() : -1;
size = exists ? file.length() : -1;
}
public boolean checkModified()
{
long m = lastModified;
long g = size;
boolean mod = false;
readProperties();
if(lastModified != m || g != size)
{
mod = true;
}
return mod;
}
}

View File

@ -0,0 +1,17 @@
package ninja.bytecode.iris.util;
import ninja.bytecode.iris.IrisGenerator;
public abstract class GenLayer
{
protected final RNG rng;
protected final IrisGenerator iris;
public GenLayer(IrisGenerator iris, RNG rng)
{
this.iris = iris;
this.rng = rng;
}
public abstract double generate(double x, double z);
}

View File

@ -1,5 +1,7 @@
package ninja.bytecode.iris.util; package ninja.bytecode.iris.util;
import ninja.bytecode.iris.object.InterpolationMethod;
public class IrisInterpolation public class IrisInterpolation
{ {
public static double bezier(double t) public static double bezier(double t)
@ -18,6 +20,11 @@ public class IrisInterpolation
return a + (f * (b - a)); return a + (f * (b - a));
} }
public static float lerpf(float a, float b, float f)
{
return a + (f * (b - a));
}
public static double lerpBezier(double a, double b, double f) public static double lerpBezier(double a, double b, double f)
{ {
return a + (bezier(f) * (b - a)); return a + (bezier(f) * (b - a));
@ -181,6 +188,26 @@ public class IrisInterpolation
//@done //@done
} }
public static double getNoise(InterpolationMethod method, int x, int z, double rad, NoiseProvider n)
{
if(method.equals(InterpolationMethod.BILINEAR))
{
return getBilinearNoise(x, z, rad, n);
}
else if(method.equals(InterpolationMethod.BICUBIC))
{
return getBicubicNoise(x, z, rad, n);
}
else if(method.equals(InterpolationMethod.HERMITE))
{
return getHermiteNoise(x, z, rad, n);
}
return n.noise(x, z);
}
public static double getHermiteNoise(int x, int z, double rad, NoiseProvider n) public static double getHermiteNoise(int x, int z, double rad, NoiseProvider n)
{ {
int fx = (int) Math.floor(x / rad); int fx = (int) Math.floor(x / rad);

View File

@ -639,4 +639,10 @@ public class KList<T> extends ArrayList<T> implements List<T>
remove(t); remove(t);
return this; return this;
} }
public KList<T> qadd(T t)
{
add(t);
return this;
}
} }

View File

@ -151,6 +151,11 @@ public class M
return (T) Double.valueOf(Math.min(max.doubleValue(), Math.max(min.doubleValue(), value.doubleValue()))); return (T) Double.valueOf(Math.min(max.doubleValue(), Math.max(min.doubleValue(), value.doubleValue())));
} }
public static int iclip(int value, int min, int max)
{
return Math.min(max, Math.max(min, value));
}
/** /**
* Get true or false based on random percent * Get true or false based on random percent
* *

View File

@ -0,0 +1,95 @@
package ninja.bytecode.iris.util;
import java.io.File;
import com.google.gson.Gson;
import ninja.bytecode.iris.Iris;
public class ResourceLoader<T>
{
private File root;
private String folderName;
private String resourceTypeName;
private KMap<String, T> loadCache;
private KList<File> folderCache;
private Class<? extends T> objectClass;
public ResourceLoader(File root, String folderName, String resourceTypeName, Class<? extends T> objectClass)
{
this.objectClass = objectClass;
this.resourceTypeName = resourceTypeName;
this.root = root;
this.folderName = folderName;
loadCache = new KMap<>();
}
public T load(String name)
{
String key = name + "-" + objectClass.getCanonicalName();
if(loadCache.containsKey(key))
{
return loadCache.get(key);
}
for(File i : getFolders())
{
for(File j : i.listFiles())
{
if(j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name))
{
try
{
T t = new Gson().fromJson(IO.readAll(j), objectClass);
loadCache.put(key, t);
Iris.hotloader.track(j);
Iris.info("Loading " + resourceTypeName + ": " + j.getPath());
return t;
}
catch(Throwable e)
{
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
}
}
}
}
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
return null;
}
public KList<File> getFolders()
{
if(folderCache == null)
{
folderCache = new KList<>();
for(File i : root.listFiles())
{
if(i.isDirectory())
{
for(File j : i.listFiles())
{
if(j.isDirectory() && j.getName().equals(folderName))
{
folderCache.add(j);
break;
}
}
}
}
}
return folderCache;
}
public void clearCache()
{
loadCache.clear();
folderCache = null;
}
}