mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 18:23:06 +00:00
Scaffolding
This commit is contained in:
parent
a97cb3df4f
commit
cecbad2eb9
16
pom.xml
16
pom.xml
@ -150,6 +150,22 @@
|
||||
<version>1.15.1-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</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>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
|
@ -4,6 +4,7 @@ import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
@ -18,6 +19,10 @@ import ninja.bytecode.iris.util.IO;
|
||||
|
||||
public class Iris extends JavaPlugin
|
||||
{
|
||||
public static Iris instance;
|
||||
public static IrisDataManager data;
|
||||
public static IrisHotloadManager hotloader;
|
||||
|
||||
public Iris()
|
||||
{
|
||||
IO.delete(new File("iris"));
|
||||
@ -25,7 +30,9 @@ public class Iris extends JavaPlugin
|
||||
|
||||
public void onEnable()
|
||||
{
|
||||
|
||||
instance = this;
|
||||
hotloader = new IrisHotloadManager();
|
||||
data = new IrisDataManager(getDataFolder());
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(this, () ->
|
||||
{
|
||||
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())
|
||||
{
|
||||
@ -48,6 +55,7 @@ public class Iris extends JavaPlugin
|
||||
}, 5);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void onDisable()
|
||||
@ -64,6 +72,36 @@ public class Iris extends JavaPlugin
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
104
src/main/java/ninja/bytecode/iris/IrisDataManager.java
Normal file
104
src/main/java/ninja/bytecode/iris/IrisDataManager.java
Normal 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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package ninja.bytecode.iris;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -11,17 +12,34 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
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.PolygonGenerator.EnumPolygonGenerator;
|
||||
import ninja.bytecode.iris.util.IrisInterpolation;
|
||||
import ninja.bytecode.iris.util.KList;
|
||||
import ninja.bytecode.iris.util.RNG;
|
||||
|
||||
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 CNG gen;
|
||||
private EnumPolygonGenerator<BlockData> pog;
|
||||
private BlockData[] d = {Material.RED_CONCRETE.createBlockData(), Material.GREEN_CONCRETE.createBlockData(), Material.BLUE_CONCRETE.createBlockData(),
|
||||
};
|
||||
|
||||
public IrisGenerator(String dimensionName)
|
||||
{
|
||||
this.dimensionName = dimensionName;
|
||||
}
|
||||
|
||||
public IrisDimension getDimension()
|
||||
{
|
||||
return Iris.data.getDimensionLoader().load(dimensionName);
|
||||
}
|
||||
|
||||
public void onInit(World world, RNG rng)
|
||||
{
|
||||
@ -31,8 +49,8 @@ public class IrisGenerator extends ChunkGenerator
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
gen = CNG.signature(rng.nextParallelRNG(0));
|
||||
pog = new EnumPolygonGenerator<BlockData>(rng.nextParallelRNG(1), 0.1, 1, d, (c) -> c);
|
||||
glBiome = new GenLayerBiome(this, rng.nextParallelRNG(1));
|
||||
terrainNoise = CNG.signature(rng.nextParallelRNG(2));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,26 +60,56 @@ public class IrisGenerator extends ChunkGenerator
|
||||
}
|
||||
|
||||
@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());
|
||||
onInit(world, random.nextParallelRNG(0));
|
||||
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;
|
||||
double wz = (z * 16) + j;
|
||||
rz = (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;
|
||||
}
|
||||
|
||||
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
|
||||
public List<BlockPopulator> getDefaultPopulators(World world)
|
||||
{
|
||||
|
57
src/main/java/ninja/bytecode/iris/IrisHotloadManager.java
Normal file
57
src/main/java/ninja/bytecode/iris/IrisHotloadManager.java
Normal 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));
|
||||
}
|
||||
}
|
36
src/main/java/ninja/bytecode/iris/layer/GenLayerBiome.java
Normal file
36
src/main/java/ninja/bytecode/iris/layer/GenLayerBiome.java
Normal 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;
|
||||
}
|
||||
}
|
10
src/main/java/ninja/bytecode/iris/object/Dispersion.java
Normal file
10
src/main/java/ninja/bytecode/iris/object/Dispersion.java
Normal file
@ -0,0 +1,10 @@
|
||||
package ninja.bytecode.iris.object;
|
||||
|
||||
public enum Dispersion
|
||||
{
|
||||
SCATTER,
|
||||
SIMPLEX,
|
||||
CELLS,
|
||||
WISPY,
|
||||
ZEBRA
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package ninja.bytecode.iris.object;
|
||||
|
||||
public enum InterpolationMethod
|
||||
{
|
||||
NONE,
|
||||
BILINEAR,
|
||||
BICUBIC,
|
||||
HERMITE
|
||||
}
|
107
src/main/java/ninja/bytecode/iris/object/IrisBiome.java
Normal file
107
src/main/java/ninja/bytecode/iris/object/IrisBiome.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
48
src/main/java/ninja/bytecode/iris/object/IrisDimension.java
Normal file
48
src/main/java/ninja/bytecode/iris/object/IrisDimension.java
Normal 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;
|
||||
}
|
||||
}
|
17
src/main/java/ninja/bytecode/iris/util/BiomeResult.java
Normal file
17
src/main/java/ninja/bytecode/iris/util/BiomeResult.java
Normal 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;
|
||||
}
|
||||
}
|
@ -25,6 +25,9 @@ public class CNG
|
||||
private NoiseInjector injector;
|
||||
private RNG rng;
|
||||
private int oct;
|
||||
private double patch;
|
||||
private double up;
|
||||
private double down;
|
||||
private double power;
|
||||
|
||||
public static CNG signature(RNG rng)
|
||||
@ -32,14 +35,12 @@ public class CNG
|
||||
//@builder
|
||||
return new CNG(rng.nextParallelRNG(17), 1D, 8)
|
||||
.scale(0.012)
|
||||
.amp(0.5)
|
||||
.freq(1.1)
|
||||
.fractureWith(new CNG(rng.nextParallelRNG(18), 1, 5)
|
||||
.scale(0.018)
|
||||
.child(new CNG(rng.nextParallelRNG(19), 0.745, 2)
|
||||
.child(new CNG(rng.nextParallelRNG(19), 1, 2)
|
||||
.scale(0.1))
|
||||
.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
|
||||
}
|
||||
|
||||
@ -62,6 +63,7 @@ public class CNG
|
||||
freq = 1;
|
||||
amp = 1;
|
||||
scale = 1;
|
||||
patch = 1;
|
||||
fscale = 1;
|
||||
fracture = null;
|
||||
generator = new SNG(random);
|
||||
@ -116,12 +118,66 @@ public class CNG
|
||||
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)
|
||||
{
|
||||
injector = i;
|
||||
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)
|
||||
{
|
||||
double f = fracture != null ? (fracture.noise(dim) - 0.5) * fscale : 0D;
|
||||
@ -134,7 +190,7 @@ public class CNG
|
||||
hits += oct;
|
||||
if(children == null)
|
||||
{
|
||||
return n;
|
||||
return (n - down + up) * patch;
|
||||
}
|
||||
|
||||
for(CNG i : children)
|
||||
@ -144,7 +200,7 @@ public class CNG
|
||||
m += r[1];
|
||||
}
|
||||
|
||||
return n / m;
|
||||
return ((n / m) - down + up) * patch;
|
||||
}
|
||||
|
||||
public CNG pow(double power)
|
||||
|
54
src/main/java/ninja/bytecode/iris/util/CellGenerator2D.java
Normal file
54
src/main/java/ninja/bytecode/iris/util/CellGenerator2D.java
Normal 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));
|
||||
}
|
||||
}
|
2197
src/main/java/ninja/bytecode/iris/util/FastNoise.java
Normal file
2197
src/main/java/ninja/bytecode/iris/util/FastNoise.java
Normal file
File diff suppressed because it is too large
Load Diff
42
src/main/java/ninja/bytecode/iris/util/FileWatcher.java
Normal file
42
src/main/java/ninja/bytecode/iris/util/FileWatcher.java
Normal 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;
|
||||
}
|
||||
}
|
17
src/main/java/ninja/bytecode/iris/util/GenLayer.java
Normal file
17
src/main/java/ninja/bytecode/iris/util/GenLayer.java
Normal 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);
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package ninja.bytecode.iris.util;
|
||||
|
||||
import ninja.bytecode.iris.object.InterpolationMethod;
|
||||
|
||||
public class IrisInterpolation
|
||||
{
|
||||
public static double bezier(double t)
|
||||
@ -18,6 +20,11 @@ public class IrisInterpolation
|
||||
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)
|
||||
{
|
||||
return a + (bezier(f) * (b - a));
|
||||
@ -181,6 +188,26 @@ public class IrisInterpolation
|
||||
//@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)
|
||||
{
|
||||
int fx = (int) Math.floor(x / rad);
|
||||
|
@ -639,4 +639,10 @@ public class KList<T> extends ArrayList<T> implements List<T>
|
||||
remove(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
public KList<T> qadd(T t)
|
||||
{
|
||||
add(t);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -151,6 +151,11 @@ public class M
|
||||
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
|
||||
*
|
||||
|
95
src/main/java/ninja/bytecode/iris/util/ResourceLoader.java
Normal file
95
src/main/java/ninja/bytecode/iris/util/ResourceLoader.java
Normal 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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user