This commit is contained in:
Daniel Mills
2020-07-19 04:09:42 -04:00
parent 5b8d812fc8
commit f995f6568c
9 changed files with 352 additions and 81 deletions

10
pom.xml
View File

@@ -147,7 +147,7 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.15.1-R0.1-SNAPSHOT</version> <version>1.16.1-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -174,7 +174,13 @@
<dependency> <dependency>
<groupId>org.bukkit</groupId> <groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId> <artifactId>bukkit</artifactId>
<version>1.15.1-R0.1-SNAPSHOT</version> <version>1.16.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit.craftbukkit</groupId>
<artifactId>cb-1.16.1</artifactId>
<version>1.16.1</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -101,7 +101,7 @@ public class Iris extends JavaPlugin implements BoardProvider
lines.add(ChatColor.GREEN + "Noise" + ChatColor.GRAY + ": " + Form.f((int) hits.getAverage())); lines.add(ChatColor.GREEN + "Noise" + ChatColor.GRAY + ": " + Form.f((int) hits.getAverage()));
lines.add(ChatColor.GREEN + "Parallax Regions" + ChatColor.GRAY + ": " + Form.f((int) g.getParallaxMap().getLoadedRegions().size())); lines.add(ChatColor.GREEN + "Parallax Regions" + ChatColor.GRAY + ": " + Form.f((int) g.getParallaxMap().getLoadedRegions().size()));
lines.add(ChatColor.GREEN + "Parallax Chunks" + ChatColor.GRAY + ": " + Form.f((int) g.getParallaxMap().getLoadedChunks().size())); lines.add(ChatColor.GREEN + "Parallax Chunks" + ChatColor.GRAY + ": " + Form.f((int) g.getParallaxMap().getLoadedChunks().size()));
lines.add(ChatColor.GREEN + "Sliver Buffer" + ChatColor.GRAY + ": " + Form.f((int) g.getSliverBuffer())); lines.add(ChatColor.GREEN + "BUD Requests" + ChatColor.GRAY + ": " + Form.f((int) g.getUpdateBlocks().size()));
if(er != null && b != null) if(er != null && b != null)
{ {

View File

@@ -8,6 +8,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.Iris;
import ninja.bytecode.iris.layer.GenLayerBiome; import ninja.bytecode.iris.layer.GenLayerBiome;
import ninja.bytecode.iris.object.InferredType;
import ninja.bytecode.iris.object.IrisBiome; import ninja.bytecode.iris.object.IrisBiome;
import ninja.bytecode.iris.object.IrisBiomeGeneratorLink; import ninja.bytecode.iris.object.IrisBiomeGeneratorLink;
import ninja.bytecode.iris.object.IrisGenerator; import ninja.bytecode.iris.object.IrisGenerator;
@@ -155,6 +156,36 @@ public abstract class BiomeChunkGenerator extends DimensionChunkGenerator
public BiomeResult sampleBiome(int x, int z) public BiomeResult sampleBiome(int x, int z)
{ {
if(!getDimension().getFocus().equals(""))
{
IrisBiome biome = Iris.data.getBiomeLoader().load(getDimension().getFocus());
for(String i : getDimension().getRegions())
{
IrisRegion reg = Iris.data.getRegionLoader().load(i);
if(reg.getLandBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.LAND);
break;
}
if(reg.getSeaBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.SEA);
break;
}
if(reg.getShoreBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.SHORE);
break;
}
}
return new BiomeResult(biome, 0);
}
ChunkPosition pos = new ChunkPosition(x, z); ChunkPosition pos = new ChunkPosition(x, z);
if(biomeHitCache.containsKey(pos)) if(biomeHitCache.containsKey(pos))

View File

@@ -1,5 +1,7 @@
package ninja.bytecode.iris.generator; package ninja.bytecode.iris.generator;
import java.lang.reflect.Method;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -14,6 +16,8 @@ import ninja.bytecode.iris.util.BiomeResult;
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class IrisChunkGenerator extends ParallaxChunkGenerator implements IrisContext public class IrisChunkGenerator extends ParallaxChunkGenerator implements IrisContext
{ {
private Method initLighting;
public IrisChunkGenerator(String dimensionName, int threads) public IrisChunkGenerator(String dimensionName, int threads)
{ {
super(dimensionName, threads); super(dimensionName, threads);
@@ -59,7 +63,7 @@ public class IrisChunkGenerator extends ParallaxChunkGenerator implements IrisCo
@Override @Override
protected void onChunkLoaded(Chunk c) protected void onChunkLoaded(Chunk c)
{ {
updateLights();
} }
@Override @Override

View File

@@ -1,21 +1,31 @@
package ninja.bytecode.iris.generator; package ninja.bytecode.iris.generator;
import java.util.concurrent.locks.ReentrantLock;
import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.Bisected.Half;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import ninja.bytecode.iris.Iris;
import ninja.bytecode.iris.object.InferredType;
import ninja.bytecode.iris.object.IrisBiome; import ninja.bytecode.iris.object.IrisBiome;
import ninja.bytecode.iris.object.IrisBiomeDecorator; import ninja.bytecode.iris.object.IrisBiomeDecorator;
import ninja.bytecode.iris.object.IrisRegion; import ninja.bytecode.iris.object.IrisRegion;
import ninja.bytecode.iris.object.atomics.AtomicSliver; import ninja.bytecode.iris.object.atomics.AtomicSliver;
import ninja.bytecode.iris.util.BiomeMap; import ninja.bytecode.iris.util.BiomeMap;
import ninja.bytecode.iris.util.BiomeResult; import ninja.bytecode.iris.util.BiomeResult;
import ninja.bytecode.iris.util.BlockPosition;
import ninja.bytecode.iris.util.RNG; import ninja.bytecode.iris.util.RNG;
import ninja.bytecode.shuriken.collections.KList; import ninja.bytecode.shuriken.collections.KList;
import ninja.bytecode.shuriken.collections.KSet;
import ninja.bytecode.shuriken.logging.L;
import ninja.bytecode.shuriken.math.M;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@@ -24,6 +34,10 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
protected static final BlockData AIR = Material.AIR.createBlockData(); protected static final BlockData AIR = Material.AIR.createBlockData();
protected static final BlockData STONE = Material.STONE.createBlockData(); protected static final BlockData STONE = Material.STONE.createBlockData();
protected static final BlockData WATER = Material.WATER.createBlockData(); protected static final BlockData WATER = Material.WATER.createBlockData();
private KList<BlockPosition> updateBlocks = new KList<>();
private ReentrantLock relightLock = new ReentrantLock();
private long lastUpdateRequest = M.ms();
private long lastChunkLoad = M.ms();
public TerrainChunkGenerator(String dimensionName, int threads) public TerrainChunkGenerator(String dimensionName, int threads)
{ {
@@ -35,75 +49,182 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
super.onInit(world, rng); super.onInit(world, rng);
} }
public void queueUpdate(int x, int y, int z)
{
if(M.ms() - lastUpdateRequest > 3000 && M.ms() - lastChunkLoad > 3000)
{
updateBlocks.clear();
}
updateBlocks.add(new BlockPosition(x, y, z));
lastUpdateRequest = M.ms();
}
public void updateLights()
{
if(M.ms() - lastUpdateRequest > 3000 && M.ms() - lastChunkLoad > 3000)
{
updateBlocks.clear();
}
for(BlockPosition i : updateBlocks.copy())
{
if(getWorld().isChunkLoaded(i.getChunkX(), i.getChunkZ()))
{
updateBlocks.remove(i);
Block b = getWorld().getBlockAt(i.getX(), i.getY(), i.getZ());
BlockData bd = b.getBlockData();
b.setBlockData(AIR, false);
b.setBlockData(bd, true);
}
}
while(updateBlocks.size() > 5000)
{
updateBlocks.remove(0);
}
lastChunkLoad = M.ms();
}
public void checkUnderwater(int x, int y, int z, BlockData d)
{
if(d.getMaterial().equals(Material.SEA_PICKLE) || d.getMaterial().equals(Material.SOUL_SAND) || d.getMaterial().equals(Material.MAGMA_BLOCK))
{
queueUpdate(x, y, z);
}
}
public void checkSurface(int x, int y, int z, BlockData d)
{
if(d.getMaterial().equals(Material.SEA_PICKLE) || d.getMaterial().equals(Material.TORCH) || d.getMaterial().equals(Material.REDSTONE_TORCH) || d.getMaterial().equals(Material.TORCH))
{
queueUpdate(x, y, z);
}
}
@Override @Override
protected void onGenerateColumn(int cx, int cz, int rx, int rz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap) protected void onGenerateColumn(int cx, int cz, int rx, int rz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap)
{ {
BlockData block; try
int fluidHeight = getDimension().getFluidHeight();
double ox = getModifiedX(rx, rz);
double oz = getModifiedZ(rx, rz);
double wx = getZoomed(ox);
double wz = getZoomed(oz);
int depth = 0;
double noise = getNoiseHeight(rx, rz);
int height = (int) Math.round(noise) + fluidHeight;
IrisBiome biome = sampleTrueBiome(rx, rz).getBiome();
KList<BlockData> layers = biome.generateLayers(wx, wz, masterRandom, height);
for(int k = Math.max(height, fluidHeight); k >= 0; k--)
{ {
boolean underwater = k > height && k <= fluidHeight; BlockData block;
int fluidHeight = getDimension().getFluidHeight();
double ox = getModifiedX(rx, rz);
double oz = getModifiedZ(rx, rz);
double wx = getZoomed(ox);
double wz = getZoomed(oz);
int depth = 0;
double noise = getNoiseHeight(rx, rz);
int height = (int) Math.round(noise) + fluidHeight;
IrisBiome biome = sampleTrueBiome(rx, rz).getBiome();
if(biomeMap != null) KList<BlockData> layers = biome.generateLayers(wx, wz, masterRandom, height);
for(int k = Math.max(height, fluidHeight); k >= 0; k--)
{ {
sliver.set(k, biome.getDerivative()); boolean underwater = k > height && k <= fluidHeight;
biomeMap.setBiome(x, z, biome);
}
if(underwater) if(biomeMap != null)
{
block = WATER;
}
else
{
block = layers.hasIndex(depth) ? layers.get(depth) : STONE;
depth++;
}
sliver.set(k, block);
if(k == Math.max(height, fluidHeight) && block.getMaterial().isSolid() && k < 255)
{
int j = 0;
for(IrisBiomeDecorator i : biome.getDecorators())
{ {
BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG(biome.hashCode() + j++), wx, wz); sliver.set(k, biome.getDerivative());
biomeMap.setBiome(x, z, biome);
}
if(d != null) if(underwater)
{
block = WATER;
}
else
{
block = layers.hasIndex(depth) ? layers.get(depth) : STONE;
depth++;
}
sliver.set(k, block);
if(k == height && block.getMaterial().isSolid() && k < fluidHeight && biome.isSea())
{
int j = 0;
for(IrisBiomeDecorator i : biome.getDecorators())
{ {
if(d instanceof Bisected && k < 254) BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG(biome.hashCode() + j++), wx, wz);
{
Bisected t = ((Bisected) d.clone());
t.setHalf(Half.TOP);
Bisected b = ((Bisected) d.clone());
b.setHalf(Half.BOTTOM);
sliver.set(k + 1, b);
sliver.set(k + 2, t);
}
else if(d != null)
{ {
sliver.set(k + 1, d); int stack = i.getHeight(getMasterRandom().nextParallelRNG(39456 + i.hashCode()), wx, wz);
}
break; if(stack == 1)
{
sliver.set(k + 1, d);
checkUnderwater(rx, k + 1, rz, d);
}
else if(k < fluidHeight - stack)
{
for(int l = 0; l < stack; l++)
{
sliver.set(k + l + 1, d);
checkUnderwater(rx, k + l + 1, rz, d);
}
}
break;
}
}
}
if(k == Math.max(height, fluidHeight) && block.getMaterial().isSolid() && k < 255 && !biome.isSea())
{
int j = 0;
for(IrisBiomeDecorator i : biome.getDecorators())
{
BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG(biome.hashCode() + j++), wx, wz);
if(d != null)
{
if(d instanceof Bisected && k < 254)
{
Bisected t = ((Bisected) d.clone());
t.setHalf(Half.TOP);
Bisected b = ((Bisected) d.clone());
b.setHalf(Half.BOTTOM);
sliver.set(k + 1, b);
sliver.set(k + 2, t);
}
else
{
int stack = i.getHeight(getMasterRandom().nextParallelRNG(39456 + i.hashCode()), wx, wz);
if(stack == 1)
{
sliver.set(k + 1, d);
}
else if(k < 255 - stack)
{
for(int l = 0; l < stack; l++)
{
sliver.set(k + l + 1, d);
}
}
}
break;
}
} }
} }
} }
} }
catch(Throwable e)
{
fail(e);
}
} }
protected double getNoiseHeight(int rx, int rz) protected double getNoiseHeight(int rx, int rz)
@@ -116,6 +237,36 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
public BiomeResult sampleTrueBiome(int x, int z) public BiomeResult sampleTrueBiome(int x, int z)
{ {
if(!getDimension().getFocus().equals(""))
{
IrisBiome biome = Iris.data.getBiomeLoader().load(getDimension().getFocus());
for(String i : getDimension().getRegions())
{
IrisRegion reg = Iris.data.getRegionLoader().load(i);
if(reg.getLandBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.LAND);
break;
}
if(reg.getSeaBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.SEA);
break;
}
if(reg.getShoreBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.SHORE);
break;
}
}
return new BiomeResult(biome, 0);
}
double wx = getModifiedX(x, z); double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z); double wz = getModifiedZ(x, z);
IrisRegion region = sampleRegion(x, z); IrisRegion region = sampleRegion(x, z);

View File

@@ -1,9 +1,9 @@
package ninja.bytecode.iris.object; package ninja.bytecode.iris.object;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import lombok.Data; import lombok.Data;
import ninja.bytecode.iris.util.BlockDataTools;
import ninja.bytecode.iris.util.CNG; import ninja.bytecode.iris.util.CNG;
import ninja.bytecode.iris.util.RNG; import ninja.bytecode.iris.util.RNG;
import ninja.bytecode.shuriken.collections.KList; import ninja.bytecode.shuriken.collections.KList;
@@ -14,14 +14,39 @@ public class IrisBiomeDecorator
{ {
private Dispersion variance = Dispersion.SCATTER; private Dispersion variance = Dispersion.SCATTER;
private Dispersion dispersion = Dispersion.SCATTER; private Dispersion dispersion = Dispersion.SCATTER;
private Dispersion verticalVariance = Dispersion.SCATTER;
private int iterations = 5; private int iterations = 5;
private int stackMin = 1;
private int stackMax = 1;
private double zoom = 1; private double zoom = 1;
private double verticalZoom = 1;
private double chance = 0.1; private double chance = 0.1;
private KList<String> palette = new KList<String>().qadd("GRASS"); private KList<String> palette = new KList<String>().qadd("GRASS");
private transient KMap<Long, CNG> layerGenerators; private transient KMap<Long, CNG> layerGenerators;
private transient CNG heightGenerator;
private transient KList<BlockData> blockData; private transient KList<BlockData> blockData;
public int getHeight(RNG rng, double x, double z)
{
if(stackMin == stackMax)
{
return stackMin;
}
return getGenerator(rng).fit(stackMin, stackMax, x * (verticalVariance.equals(Dispersion.SCATTER) ? 1000D : 1D), z * (verticalVariance.equals(Dispersion.SCATTER) ? 1000D : 1D));
}
public CNG getHeightGenerator(RNG rng)
{
if(heightGenerator == null)
{
heightGenerator = CNG.signature(rng.nextParallelRNG(iterations + getBlockData().size() + stackMax + stackMin)).scale(1D / verticalZoom);
}
return heightGenerator;
}
public CNG getGenerator(RNG rng) public CNG getGenerator(RNG rng)
{ {
long key = rng.nextParallelRNG(1).nextLong(); long key = rng.nextParallelRNG(1).nextLong();
@@ -33,7 +58,7 @@ public class IrisBiomeDecorator
if(!layerGenerators.containsKey(key)) if(!layerGenerators.containsKey(key))
{ {
layerGenerators.put(key, CNG.signature(rng.nextParallelRNG(iterations + getBlockData().size()))); layerGenerators.put(key, CNG.signature(rng.nextParallelRNG(iterations + getBlockData().size())).scale(1D / zoom));
} }
return layerGenerators.get(key); return layerGenerators.get(key);
@@ -47,9 +72,32 @@ public class IrisBiomeDecorator
public BlockData getBlockData(RNG rng, double x, double z) public BlockData getBlockData(RNG rng, double x, double z)
{ {
if(getGenerator(rng) == null)
{
return null;
}
if(getBlockData() == null)
{
return null;
}
if(getBlockData().isEmpty())
{
return null;
}
if(getGenerator(rng).fitDoubleD(0D, 1D, x * (dispersion.equals(Dispersion.SCATTER) ? 1000D : 1D), z * (dispersion.equals(Dispersion.SCATTER) ? 1000D : 1D)) <= chance) if(getGenerator(rng).fitDoubleD(0D, 1D, x * (dispersion.equals(Dispersion.SCATTER) ? 1000D : 1D), z * (dispersion.equals(Dispersion.SCATTER) ? 1000D : 1D)) <= chance)
{ {
return getBlockData().get(getGenerator(rng.nextParallelRNG(53)).fit(0, getBlockData().size() - 1, x * (dispersion.equals(Dispersion.SCATTER) ? 1000D : 1D), z * (dispersion.equals(Dispersion.SCATTER) ? 1000D : 1D))); try
{
return getBlockData().get(getGenerator(rng.nextParallelRNG(53)).fit(0, getBlockData().size() - 1, x * (dispersion.equals(Dispersion.SCATTER) ? 1000D : 1D), z * (dispersion.equals(Dispersion.SCATTER) ? 1000D : 1D)));
}
catch(Throwable e)
{
}
} }
return null; return null;
@@ -62,18 +110,10 @@ public class IrisBiomeDecorator
blockData = new KList<>(); blockData = new KList<>();
for(String i : palette) for(String i : palette)
{ {
try BlockData bx = BlockDataTools.getBlockData(i);
if(bx != null)
{ {
Material m = Material.valueOf(i); blockData.add(bx);
if(m != null)
{
blockData.add(m.createBlockData());
}
}
catch(Throwable e)
{
} }
} }
} }

View File

@@ -20,6 +20,7 @@ public class IrisDimension extends IrisRegistrant
private Environment environment = Environment.NORMAL; private Environment environment = Environment.NORMAL;
private KList<String> regions = new KList<>(); private KList<String> regions = new KList<>();
private int fluidHeight = 63; private int fluidHeight = 63;
private String focus = "";
private double biomeZoom = 5D; private double biomeZoom = 5D;
private double terrainZoom = 2D; private double terrainZoom = 2D;
private double dimensionAngleDeg = 0; private double dimensionAngleDeg = 0;

View File

@@ -20,18 +20,28 @@ public class BlockDataTools
return bdc.get(bd).clone(); return bdc.get(bd).clone();
} }
BlockData bdx = parseBlockData(bd); try
if(bdx == null)
{ {
Iris.warn("Unknown Block Data '" + bd + "'"); BlockData bdx = parseBlockData(bd);
nulls.add(bd);
if(bdx == null)
{
Iris.warn("Unknown Block Data '" + bd + "'");
nulls.add(bd);
return bdx;
}
bdc.put(bd, bdx);
return bdx; return bdx;
} }
bdc.put(bd, bdx); catch(Throwable e)
{
Iris.warn("Unknown Block Data '" + bd + "'");
}
return bdx; return null;
} }
public static BlockData parseBlockData(String ix) public static BlockData parseBlockData(String ix)

View File

@@ -0,0 +1,28 @@
package ninja.bytecode.iris.util;
import lombok.Data;
@Data
public class BlockPosition
{
private int x;
private int y;
private int z;
public BlockPosition(int x, int y, int z)
{
this.x = x;
this.y = y;
this.z = z;
}
public int getChunkX()
{
return x >> 4;
}
public int getChunkZ()
{
return z >> 4;
}
}