Rivers & Lakes

This commit is contained in:
Daniel Mills 2020-09-02 02:31:17 -04:00
parent 9be6e12a5c
commit 6d3a35517b
12 changed files with 260 additions and 52 deletions

View File

@ -114,7 +114,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
} }
KList<BlockData> layers = biome.generateLayers(rx, rz, masterRandom, height, height - getFluidHeight()); KList<BlockData> layers = biome.generateLayers(rx, rz, masterRandom, height, height - getFluidHeight());
KList<BlockData> seaLayers = biome.isSea() || biome.isShore() ? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height) : new KList<>(); KList<BlockData> seaLayers = biome.isAquatic() || biome.isShore() ? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height) : new KList<>();
boolean caverning = false; boolean caverning = false;
KList<Integer> cavernHeights = new KList<>(); KList<Integer> cavernHeights = new KList<>();
int lastCavernHeight = -1; int lastCavernHeight = -1;
@ -510,34 +510,33 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
double wz = getModifiedZ(x, z); double wz = getModifiedZ(x, z);
IrisRegion region = sampleRegion(x, z); IrisRegion region = sampleRegion(x, z);
double sh = region.getShoreHeight(wx, wz); double sh = region.getShoreHeight(wx, wz);
double shMax = getFluidHeight() + (sh / 2);
double shMin = getFluidHeight() - (sh / 2);
IrisBiome current = sampleBiome(x, z); IrisBiome current = sampleBiome(x, z);
InferredType aquaticType = current.isAquatic() ? (current.isSea() ? InferredType.SEA : current.isRiver() ? InferredType.RIVER : InferredType.LAKE) : InferredType.SEA;
boolean sea = height <= getFluidHeight();
boolean shore = height >= shMin && height <= shMax;
boolean land = height > getFluidHeight();
if(current.isShore() && height > sh) // Remove rivers, lakes & sea from land
if(current.isAquatic() && land)
{ {
return glBiome.generateData(InferredType.LAND, wx, wz, x, z, region); current = glBiome.generateData(InferredType.LAND, wx, wz, x, z, region);
} }
if(current.isShore() || current.isLand() && height <= getDimension().getFluidHeight()) // Remove land from underwater
if(current.isLand() && sea)
{ {
return glBiome.generateData(InferredType.SEA, wx, wz, x, z, region); current = glBiome.generateData(aquaticType, wx, wz, x, z, region);
} }
if(current.isSea() && height > getDimension().getFluidHeight()) // Add shores to land
if(shore)
{ {
return glBiome.generateData(InferredType.LAND, wx, wz, x, z, region); current = glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
} }
if(height <= getDimension().getFluidHeight()) return current;
{
return glBiome.generateData(InferredType.SEA, wx, wz, x, z, region);
}
if(height <= getDimension().getFluidHeight() + sh)
{
return glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
}
return glBiome.generateRegionData(wx, wz, x, z, region);
} }
public IrisBiome sampleCaveBiome(int x, int z) public IrisBiome sampleCaveBiome(int x, int z)
@ -586,22 +585,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
return focus(); return focus();
} }
return getCache().getBiome(x, z, () -> return getCache().getBiome(x, z, () -> sampleTrueBiomeBase(x, z, (int) Math.round(noise)));
{
double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z);
IrisRegion region = sampleRegion(x, z);
int height = (int) Math.round(noise);
double sh = region.getShoreHeight(wx, wz);
IrisBiome current = sampleTrueBiomeBase(x, z, height);
if(current.isSea() && height > getDimension().getFluidHeight() - sh)
{
return glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
}
return current;
});
} }
@Override @Override

View File

@ -10,6 +10,7 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.BiomeGrid; import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData; import org.bukkit.generator.ChunkGenerator.ChunkData;
import com.volmit.iris.Iris;
import com.volmit.iris.object.IrisBiome; import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.util.B; import com.volmit.iris.util.B;
import com.volmit.iris.util.HeightMap; import com.volmit.iris.util.HeightMap;
@ -118,6 +119,7 @@ public class AtomicSliver
{ {
return; return;
} }
setSilently(h, d); setSilently(h, d);
modified = true; modified = true;
lock.lock(); lock.lock();
@ -134,6 +136,7 @@ public class AtomicSliver
if(d == null) if(d == null)
{ {
Iris.warn("Null set at " + h + " of " + x + " " + z);
return; return;
} }
@ -361,14 +364,16 @@ public class AtomicSliver
return; return;
} }
lock.lock(); lock.lock();
for(int i = 0; i < 256; i++)
{ for(int i : block.keySet())
if(block.get(i) != null && !block.get(i).equals(AIR))
{ {
BlockData b = block.get(i); BlockData b = block.get(i);
if(b != null)
{
currentData.setBlock(x, i, z, b); currentData.setBlock(x, i, z, b);
} }
} }
lock.unlock(); lock.unlock();
} }

View File

@ -22,20 +22,28 @@ public class GenLayerBiome extends GenLayer
{ {
private CNG regionGenerator; private CNG regionGenerator;
private CNG bridgeGenerator; private CNG bridgeGenerator;
private RNG lakeRandom;
private RNG riverRandom;
private BiomeDataProvider seaProvider; private BiomeDataProvider seaProvider;
private BiomeDataProvider landProvider; private BiomeDataProvider landProvider;
private BiomeDataProvider shoreProvider; private BiomeDataProvider shoreProvider;
private BiomeDataProvider caveProvider; private BiomeDataProvider caveProvider;
private BiomeDataProvider riverProvider;
private BiomeDataProvider lakeProvider;
private DimensionChunkGenerator iris; private DimensionChunkGenerator iris;
public GenLayerBiome(DimensionChunkGenerator iris, RNG rng) public GenLayerBiome(DimensionChunkGenerator iris, RNG rng)
{ {
super(iris, rng); super(iris, rng);
this.iris = iris; this.iris = iris;
riverRandom = iris.getMasterRandom().nextParallelRNG(-324778);
lakeRandom = iris.getMasterRandom().nextParallelRNG(-868778);
seaProvider = new BiomeDataProvider(this, InferredType.SEA, rng); seaProvider = new BiomeDataProvider(this, InferredType.SEA, rng);
landProvider = new BiomeDataProvider(this, InferredType.LAND, rng); landProvider = new BiomeDataProvider(this, InferredType.LAND, rng);
shoreProvider = new BiomeDataProvider(this, InferredType.SHORE, rng); shoreProvider = new BiomeDataProvider(this, InferredType.SHORE, rng);
caveProvider = new BiomeDataProvider(this, InferredType.CAVE, rng); caveProvider = new BiomeDataProvider(this, InferredType.CAVE, rng);
riverProvider = new BiomeDataProvider(this, InferredType.RIVER, rng);
lakeProvider = new BiomeDataProvider(this, InferredType.LAKE, rng);
regionGenerator = iris.getDimension().getRegionStyle().create(rng.nextParallelRNG(1188519)).bake().scale(1D / iris.getDimension().getRegionZoom()); regionGenerator = iris.getDimension().getRegionStyle().create(rng.nextParallelRNG(1188519)).bake().scale(1D / iris.getDimension().getRegionZoom());
bridgeGenerator = iris.getDimension().getContinentalStyle().create(rng.nextParallelRNG(1541462)).bake().scale(1D / iris.getDimension().getContinentZoom()); bridgeGenerator = iris.getDimension().getContinentalStyle().create(rng.nextParallelRNG(1541462)).bake().scale(1D / iris.getDimension().getContinentZoom());
} }
@ -86,6 +94,16 @@ public class GenLayerBiome extends GenLayer
return caveProvider; return caveProvider;
} }
else if(type.equals(InferredType.RIVER))
{
return riverProvider;
}
else if(type.equals(InferredType.LAKE))
{
return lakeProvider;
}
else else
{ {
Iris.error("Cannot find a BiomeDataProvider for type " + type.name()); Iris.error("Cannot find a BiomeDataProvider for type " + type.name());
@ -99,12 +117,13 @@ public class GenLayerBiome extends GenLayer
return generateData(getType(bx, bz, regionData), bx, bz, rawX, rawZ, regionData); return generateData(getType(bx, bz, regionData), bx, bz, rawX, rawZ, regionData);
} }
public InferredType getType(double bx, double bz, IrisRegion regionData) public InferredType getType(double bx, double bz, IrisRegion region)
{ {
double x = bx; double x = bx;
double z = bz; double z = bz;
double c = iris.getDimension().getLandChance(); double c = iris.getDimension().getLandChance();
InferredType bridge; InferredType bridge;
if(c >= 1) if(c >= 1)
{ {
bridge = InferredType.LAND; bridge = InferredType.LAND;
@ -117,6 +136,16 @@ public class GenLayerBiome extends GenLayer
bridge = bridgeGenerator.fitDouble(0, 1, x, z) < c ? InferredType.LAND : InferredType.SEA; bridge = bridgeGenerator.fitDouble(0, 1, x, z) < c ? InferredType.LAND : InferredType.SEA;
if(bridge.equals(InferredType.LAND) && region.isLake(lakeRandom, x, z))
{
bridge = InferredType.LAKE;
}
if(bridge.equals(InferredType.LAND) && region.isRiver(riverRandom, x, z))
{
bridge = InferredType.RIVER;
}
return bridge; return bridge;
} }

View File

@ -16,6 +16,12 @@ public enum InferredType
@DontObfuscate @DontObfuscate
CAVE, CAVE,
@DontObfuscate
RIVER,
@DontObfuscate
LAKE,
@DontObfuscate @DontObfuscate
DEFER; DEFER;
} }

View File

@ -438,6 +438,29 @@ public class IrisBiome extends IrisRegistrant implements IRare
return inferredType.equals(InferredType.SEA); return inferredType.equals(InferredType.SEA);
} }
public boolean isLake()
{
if(inferredType == null)
{
return false;
}
return inferredType.equals(InferredType.LAKE);
}
public boolean isRiver()
{
if(inferredType == null)
{
return false;
}
return inferredType.equals(InferredType.RIVER);
}
public boolean isAquatic()
{
return isSea() || isLake() || isRiver();
}
public boolean isShore() public boolean isShore()
{ {
if(inferredType == null) if(inferredType == null)

View File

@ -101,6 +101,14 @@ public class IrisDimension extends IrisRegistrant
@Desc("The placement style of biomes") @Desc("The placement style of biomes")
private IrisGeneratorStyle caveBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); private IrisGeneratorStyle caveBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
@DontObfuscate
@Desc("The placement style of biomes")
private IrisGeneratorStyle riverBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
@DontObfuscate
@Desc("The placement style of biomes")
private IrisGeneratorStyle lakeBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
@DontObfuscate @DontObfuscate
@Desc("The placement style of biomes") @Desc("The placement style of biomes")
private IrisGeneratorStyle islandBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); private IrisGeneratorStyle islandBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
@ -755,6 +763,10 @@ public class IrisDimension extends IrisRegistrant
{ {
case CAVE: case CAVE:
return caveBiomeStyle; return caveBiomeStyle;
case LAKE:
return lakeBiomeStyle;
case RIVER:
return riverBiomeStyle;
case LAND: case LAND:
return landBiomeStyle; return landBiomeStyle;
case SEA: case SEA:

View File

@ -15,7 +15,6 @@ import lombok.Data;
@Data @Data
public class IrisGeneratorStyle public class IrisGeneratorStyle
{ {
@Required @Required
@DontObfuscate @DontObfuscate
@Desc("The chance is 1 in CHANCE per interval") @Desc("The chance is 1 in CHANCE per interval")
@ -53,6 +52,12 @@ public class IrisGeneratorStyle
this.style = s; this.style = s;
} }
public IrisGeneratorStyle zoomed(double z)
{
this.zoom = z;
return this;
}
public CNG create(RNG rng) public CNG create(RNG rng)
{ {
return cng.aquire(() -> return cng.aquire(() ->

View File

@ -322,22 +322,19 @@ public class IrisObject extends IrisRegistrant
return -1; return -1;
} }
if(config.isBore() && !config.getMode().equals(ObjectPlaceMode.PAINT)) if(config.isBore())
{ {
for(int i = x - Math.floorDiv(w, 2); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0); i++) for(int i = x - Math.floorDiv(w, 2); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0); i++)
{ {
for(int j = y - Math.floorDiv(h, 2) - config.getBoarExtendMinY(); j <= y + Math.floorDiv(h, 2) + config.getBoarExtendMaxY() - (h % 2 == 0 ? 1 : 0); j++) for(int j = y - Math.floorDiv(h, 2) - config.getBoarExtendMinY(); j <= y + Math.floorDiv(h, 2) + config.getBoarExtendMaxY() - (h % 2 == 0 ? 1 : 0); j++)
{ {
for(int k = z - Math.floorDiv(d, 2); k <= z + Math.floorDiv(d, 2) - (d % 2 == 0 ? 1 : 0); k++) for(int k = z - Math.floorDiv(d, 2); k <= z + Math.floorDiv(d, 2) - (d % 2 == 0 ? 1 : 0); k++)
{
if(!B.isAir(placer.get(i, j, k)))
{ {
placer.set(i, j, k, AIR); placer.set(i, j, k, AIR);
} }
} }
} }
} }
}
for(BlockVector g : blocks.keySet()) for(BlockVector g : blocks.keySet())
{ {

View File

@ -87,6 +87,16 @@ public class IrisRegion extends IrisRegistrant implements IRare
@Desc("How large shore biomes are in this region") @Desc("How large shore biomes are in this region")
private double shoreBiomeZoom = 1; private double shoreBiomeZoom = 1;
@MinNumber(0.0001)
@DontObfuscate
@Desc("How large lake biomes are in this region")
private double lakeBiomeZoom = 1;
@MinNumber(0.0001)
@DontObfuscate
@Desc("How large river biomes are in this region")
private double riverBiomeZoom = 1;
@MinNumber(0.0001) @MinNumber(0.0001)
@DontObfuscate @DontObfuscate
@Desc("How large sea biomes are in this region") @Desc("How large sea biomes are in this region")
@ -129,6 +139,18 @@ public class IrisRegion extends IrisRegistrant implements IRare
@Desc("A list of root-level biomes in this region. Don't specify child biomes of other biomes here. Just the root parents.") @Desc("A list of root-level biomes in this region. Don't specify child biomes of other biomes here. Just the root parents.")
private KList<String> shoreBiomes = new KList<>(); private KList<String> shoreBiomes = new KList<>();
@RegistryListBiome
@ArrayType(min = 1, type = String.class)
@DontObfuscate
@Desc("A list of root-level biomes in this region. Don't specify child biomes of other biomes here. Just the root parents.")
private KList<String> riverBiomes = new KList<>();
@RegistryListBiome
@ArrayType(min = 1, type = String.class)
@DontObfuscate
@Desc("A list of root-level biomes in this region. Don't specify child biomes of other biomes here. Just the root parents.")
private KList<String> lakeBiomes = new KList<>();
@RegistryListBiome @RegistryListBiome
@ArrayType(min = 1, type = String.class) @ArrayType(min = 1, type = String.class)
@DontObfuscate @DontObfuscate
@ -149,13 +171,99 @@ public class IrisRegion extends IrisRegistrant implements IRare
@Desc("Define regional deposit generators that add onto the global deposit generators") @Desc("Define regional deposit generators that add onto the global deposit generators")
private KList<IrisDepositGenerator> deposits = new KList<>(); private KList<IrisDepositGenerator> deposits = new KList<>();
@DontObfuscate
@Desc("The style of rivers")
private IrisGeneratorStyle riverStyle = NoiseStyle.VASCULAR_THIN.style().zoomed(7.77);
@DontObfuscate
@Desc("The style of lakes")
private IrisGeneratorStyle lakeStyle = NoiseStyle.CELLULAR_IRIS_THICK.style();
@DontObfuscate
@Desc("The style of river chances")
private IrisGeneratorStyle riverChanceStyle = NoiseStyle.SIMPLEX.style().zoomed(4);
@DontObfuscate
@Desc("Generate lakes in this region")
private boolean lakes = true;
@DontObfuscate
@Desc("Generate rivers in this region")
private boolean rivers = true;
@MinNumber(1)
@DontObfuscate
@Desc("Generate lakes in this region")
private int lakeRarity = 22;
@MinNumber(1)
@DontObfuscate
@Desc("Generate rivers in this region")
private int riverRarity = 3;
@MinNumber(0)
@MaxNumber(1)
@DontObfuscate
@Desc("Generate rivers in this region")
private double riverThickness = 0.1;
private transient AtomicCache<KList<String>> cacheRidge = new AtomicCache<>(); private transient AtomicCache<KList<String>> cacheRidge = new AtomicCache<>();
private transient AtomicCache<KList<String>> cacheSpot = new AtomicCache<>(); private transient AtomicCache<KList<String>> cacheSpot = new AtomicCache<>();
private transient AtomicCache<CNG> shoreHeightGenerator = new AtomicCache<>(); private transient AtomicCache<CNG> shoreHeightGenerator = new AtomicCache<>();
private transient AtomicCache<KList<IrisBiome>> realLandBiomes = new AtomicCache<>(); private transient AtomicCache<KList<IrisBiome>> realLandBiomes = new AtomicCache<>();
private transient AtomicCache<KList<IrisBiome>> realLakeBiomes = new AtomicCache<>();
private transient AtomicCache<KList<IrisBiome>> realRiverBiomes = new AtomicCache<>();
private transient AtomicCache<KList<IrisBiome>> realSeaBiomes = new AtomicCache<>(); private transient AtomicCache<KList<IrisBiome>> realSeaBiomes = new AtomicCache<>();
private transient AtomicCache<KList<IrisBiome>> realShoreBiomes = new AtomicCache<>(); private transient AtomicCache<KList<IrisBiome>> realShoreBiomes = new AtomicCache<>();
private transient AtomicCache<KList<IrisBiome>> realCaveBiomes = new AtomicCache<>(); private transient AtomicCache<KList<IrisBiome>> realCaveBiomes = new AtomicCache<>();
private transient AtomicCache<CNG> lakeGen = new AtomicCache<>();
private transient AtomicCache<CNG> riverGen = new AtomicCache<>();
private transient AtomicCache<CNG> riverChanceGen = new AtomicCache<>();
public boolean isRiver(RNG rng, double x, double z)
{
if(!isRivers())
{
return false;
}
if(getRiverBiomes().isEmpty())
{
return false;
}
if(getRiverChanceGen().aquire(() -> getRiverChanceStyle().create(rng)).fit(1, getRiverRarity(), x, z) != 1)
{
return false;
}
if(getRiverGen().aquire(() -> getRiverStyle().create(rng)).fitDouble(0, 1, x, z) < getRiverThickness())
{
return true;
}
return false;
}
public boolean isLake(RNG rng, double x, double z)
{
if(!isLakes())
{
return false;
}
if(getLakeBiomes().isEmpty())
{
return false;
}
if(getLakeGen().aquire(() -> getLakeStyle().create(rng)).fit(1, getLakeRarity(), x, z) == 1)
{
return true;
}
return false;
}
public double getBiomeZoom(InferredType t) public double getBiomeZoom(InferredType t)
{ {
@ -163,6 +271,10 @@ public class IrisRegion extends IrisRegistrant implements IRare
{ {
case CAVE: case CAVE:
return caveBiomeZoom; return caveBiomeZoom;
case LAKE:
return lakeBiomeZoom;
case RIVER:
return riverBiomeZoom;
case LAND: case LAND:
return landBiomeZoom; return landBiomeZoom;
case SEA: case SEA:
@ -263,6 +375,16 @@ public class IrisRegion extends IrisRegistrant implements IRare
return getRealCaveBiomes(g); return getRealCaveBiomes(g);
} }
else if(type.equals(InferredType.LAKE))
{
return getRealLakeBiomes(g);
}
else if(type.equals(InferredType.RIVER))
{
return getRealRiverBiomes(g);
}
return new KList<>(); return new KList<>();
} }
@ -281,6 +403,36 @@ public class IrisRegion extends IrisRegistrant implements IRare
}); });
} }
public KList<IrisBiome> getRealLakeBiomes(ContextualChunkGenerator g)
{
return realLakeBiomes.aquire(() ->
{
KList<IrisBiome> realLakeBiomes = new KList<>();
for(String i : getLakeBiomes())
{
realLakeBiomes.add((g == null ? Iris.globaldata : g.getData()).getBiomeLoader().load(i));
}
return realLakeBiomes;
});
}
public KList<IrisBiome> getRealRiverBiomes(ContextualChunkGenerator g)
{
return realRiverBiomes.aquire(() ->
{
KList<IrisBiome> realRiverBiomes = new KList<>();
for(String i : getRiverBiomes())
{
realRiverBiomes.add((g == null ? Iris.globaldata : g.getData()).getBiomeLoader().load(i));
}
return realRiverBiomes;
});
}
public KList<IrisBiome> getRealShoreBiomes(ContextualChunkGenerator g) public KList<IrisBiome> getRealShoreBiomes(ContextualChunkGenerator g)
{ {
return realShoreBiomes.aquire(() -> return realShoreBiomes.aquire(() ->

View File

@ -130,11 +130,6 @@ public class IrisStructurePlacement
if(t != null) if(t != null)
{ {
if(height >= 0)
{
t.getPlacement().setBore(true);
}
IrisObject o = null; IrisObject o = null;
for(IrisRareObject l : t.getTile().getRareObjects()) for(IrisRareObject l : t.getTile().getRareObjects())

View File

@ -26,7 +26,7 @@ public class IrisStructureTile
@DontObfuscate @DontObfuscate
@Desc("The place mode for this tile") @Desc("The place mode for this tile")
private ObjectPlaceMode placeMode = ObjectPlaceMode.PAINT; private ObjectPlaceMode placeMode = ObjectPlaceMode.CENTER_HEIGHT;
@Required @Required
@DontObfuscate @DontObfuscate