Several changes to chunk generation operation.

Multiple values adjusted.

Pipeline changed.

Changed server start script to not wait for debugger.
This commit is contained in:
Harrison Deng 2020-05-02 19:22:17 -05:00
parent d8d0744350
commit 79edd9bf29
9 changed files with 99 additions and 70 deletions

View File

@ -14,12 +14,12 @@ public class IslandWorldMapper implements CoordinateValidatable {
private final SimplexOctaveGenerator noiseGenerator;
private final int noiseOctaves = 4;
private final float islandBlockGenerationPercent = 15f;
private final float islandBlockGenerationPercent = 0.32f;
private final double noiseFrequency = 1.7D;
private final double noiseAmplitude = 0.5D;
private final double scale = 0.004D;
private final float shoreFactor = 0.065f;
private final float shallowPortion = 0.01f;
private final float shoreFactor = 0.095f;
private final float shallowPortion = 0.07f;
private final double scale = 0.005D;
private final DepthFirstSearch dfs;
public IslandWorldMapper(long seed, Cache<Point2, Double> blockValueCache) {
@ -114,7 +114,7 @@ public class IslandWorldMapper implements CoordinateValidatable {
Double res = blockValueCache.get(p);
if (res == null) {
double shift = 2 * (islandBlockGenerationPercent / 100f);
double shift = 1f - 2f * islandBlockGenerationPercent;
double rawNoise = noiseGenerator.noise(worldX, worldZ, noiseFrequency, noiseAmplitude, true) - shift;
double maxNeg = -1 - shift;
double maxPos = 1 - shift;

View File

@ -18,7 +18,7 @@ public interface BiomeGenerator {
* It doesn't need to be populated on the first call as this method will be called once for every column in the chunk.
* However, if some biomes can be set without repetative calls, doing so will prevent this method from being called for those locals.
*
* @param biomesArray The array of biomes that are to be saturated.
* @param chunkBiomeSets The array of biomes that are to be saturated. First two arrays represent the x and y values, and the third represents the biome set.
* @param world The current world.
* @param chunkX The X coordinate of the chunk.
* @param chunkZ The Z coordinate of the chunk.
@ -30,5 +30,5 @@ public interface BiomeGenerator {
* @param chunkGenCache Cache for whether or not the chunk is generated.
* @param random A random that bukkit passes.
*/
public void generateBiomeColumn(Biome[][] biomesArray, World world, int chunkX, int chunkZ, int localX, int localZ, IslandWorldMapper mapper, BiomeSelector biomeSelector, TemperatureMapGenerator tempGenerator, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> chunkGenCache, Random random);
public void generateBiomeColumn(Biome[][][] chunkBiomeSets, World world, int chunkX, int chunkZ, int localX, int localZ, IslandWorldMapper mapper, BiomeSelector biomeSelector, TemperatureMapGenerator tempGenerator, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> chunkGenCache, Random random);
}

View File

@ -62,42 +62,43 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
return true;
});
Biome[][] biomes = new Biome[Utilities.CHUNK_SIZE][Utilities.CHUNK_SIZE];
Biome[][][] biomeSet = new Biome[Utilities.CHUNK_SIZE][Utilities.CHUNK_SIZE][4];
for (int x = 0; x < Utilities.CHUNK_SIZE; x++) {
for (int z = 0; z < Utilities.CHUNK_SIZE; z++) {
final int localX = x;
final int localZ = z;
if (biomes[localX][localZ] == null) {
biomeGenerator.generateBiomeColumn(biomes, world, chunkX, chunkZ, localX, localZ, mapper, biomeSelector,
temperatureMapGenerator, biomeCache, chunkExistenceCache, random);
final int worldX = Utilities.CHUNK_SIZE * chunkX + localX;
final int worldZ = Utilities.CHUNK_SIZE * chunkZ + localZ;
if (biomeSet[localX][localZ][0] == null) {
biomeGenerator.generateBiomeColumn(biomeSet, world, chunkX, chunkZ, localX, localZ, mapper, biomeSelector,
temperatureMapGenerator, biomeCache, chunkExistenceCache, new Random(seed + worldX + worldZ));
}
if (biomes[localX][localZ] == null) throw new IllegalStateException("Biome was null.");
if (biomeSet[localX][localZ][0] == null) throw new IllegalStateException("Biome was null.");
tasks.add(exBeta.submit(() -> {
for (int y = 0; y < maxHeight; y++) {
biomeGrid.setBiome(localX, y, localZ, biomes[localX][localZ]);
biomeGrid.setBiome(localX, y, localZ, biomeSet[localX][localZ][0]);
}
return true;
}));
final int worldX = Utilities.CHUNK_SIZE * chunkX + localX;
final int worldZ = Utilities.CHUNK_SIZE * chunkZ + localZ;
Biome currentBiome = biomes[localX][localZ];
int terrainHeight = heightShader.getTerrainHeight(worldX, worldZ, currentBiome);
Biome[] currentBiomeSet = biomeSet[localX][localZ];
int terrainHeight = heightShader.getTerrainHeight(worldX, worldZ, currentBiomeSet);
int currentTerrainHeight = terrainHeight;
int bedrockHeight = random.nextInt(5) + 1;
if (layerShader.hasSpecialLayers(currentBiome)) {
Material currentMaterial = layerShader.getMaterialForHeight(worldX, worldZ, currentTerrainHeight, currentBiome);
if (layerShader.hasSpecialLayers(currentBiomeSet[0])) {
Material currentMaterial = layerShader.getMaterialForHeight(worldX, worldZ, currentTerrainHeight, terrainHeight, currentBiomeSet[0]);
while (currentMaterial != null) {
chunkData.setBlock(localX, currentTerrainHeight, localZ, currentMaterial);
currentTerrainHeight --;
currentMaterial = layerShader.getMaterialForHeight(worldX, worldZ, currentTerrainHeight, terrainHeight, currentBiomeSet[0]);
}
} else {
int surfaceThickness = layerShader.getSurfaceThickness(worldX, worldZ, currentBiome);
int surfaceThickness = layerShader.getSurfaceThickness(worldX, worldZ, currentBiomeSet[0]);
currentTerrainHeight -= surfaceThickness;
chunkData.setRegion(localX, currentTerrainHeight, localZ, localX + 1, currentTerrainHeight + surfaceThickness, localZ + 1, layerShader.getSurfaceMaterial(currentBiome));
int transitionThickness = layerShader.getTransitionMaterialThickness(worldX, worldZ, currentBiome);
chunkData.setRegion(localX, currentTerrainHeight, localZ, localX + 1, currentTerrainHeight + surfaceThickness, localZ + 1, layerShader.getSurfaceMaterial(currentBiomeSet[0]));
int transitionThickness = layerShader.getTransitionMaterialThickness(worldX, worldZ, currentBiomeSet[0]);
currentTerrainHeight -= transitionThickness;
chunkData.setRegion(localX, currentTerrainHeight, localZ, localX + 1, currentTerrainHeight + transitionThickness, localZ + 1, layerShader.getTransitionMaterial(currentBiome));
chunkData.setRegion(localX, currentTerrainHeight, localZ, localX + 1, currentTerrainHeight + transitionThickness, localZ + 1, layerShader.getTransitionMaterial(currentBiomeSet[0]));
}
chunkData.setRegion(localX, bedrockHeight, localZ, localX + 1, currentTerrainHeight + 1, localZ + 1, Material.STONE);

View File

@ -25,14 +25,14 @@ class TemperatureMapGenerator {
public void setSeed(long seed) {
noiseGenerator = new SimplexOctaveGenerator(new Random(seed), 2);
noiseGenerator.setScale(0.005D);
noiseGenerator.setScale(0.001D);
}
public float getTemperature(int worldX, int worldZ) {
Point2 loc = new Point2(worldX/4, worldZ/4);
Float val = temperatureCache.get(loc);
if (val == null) {
val = (float) noiseGenerator.noise(worldX/4, worldZ/4, frequency, amplitude, true);
val = (float) noiseGenerator.noise(worldX, worldZ, frequency, amplitude, true);
temperatureCache.set(loc, val);
}
return val;

View File

@ -17,24 +17,24 @@ import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
public class UniBiomeIslandGenerator implements BiomeGenerator {
@Override
public void generateBiomeColumn(Biome[][] biomes, World world, int chunkX, int chunkZ, int localX, int localZ, IslandWorldMapper mapper, BiomeSelector biomeSelector, TemperatureMapGenerator tempGen, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> chunkGenCache, Random random) {
public void generateBiomeColumn(Biome[][][] chunkBiomeSets, World world, int chunkX, int chunkZ, int localX, int localZ, IslandWorldMapper mapper, BiomeSelector biomeSelector, TemperatureMapGenerator tempGen, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> chunkGenCache, Random random) {
int worldX = 16 * chunkX + localX;
int worldZ = 16 * chunkZ + localZ;
Point2 chunkCoords = Utilities.worldToChunkCoordinates(new Point2(worldX, worldZ));
chunkGenCache.set(chunkCoords, false);
//Check if we can just give it something in cache.
Biome[] biomeSet = attemptGetBiomeSet(world, worldX, worldZ, biomeCache, chunkGenCache);
Biome[] biomeSet = attemptGetBiomeSet(world, worldX, worldZ, biomeCache, chunkGenCache, null);
if (biomeSet != null) {
biomes[localX][localZ] = biomeSet[0];
chunkBiomeSets[localX][localZ] = biomeSet;
return;
}
//Fine, check if it's ocean.
if (!mapper.isIsland(worldX, worldZ)) {
biomeSet = new Biome[4];
biomeSet = chunkBiomeSets[localX][localZ];
biomeSet[0] = biomeSelector.getOceanBiome(tempGen.getTemperature(worldX, worldZ), random);
setCacheBiome(worldX, worldZ, biomeSet, biomes, biomeCache);
setCacheBiome(worldX, worldZ, biomeSet, chunkBiomeSets, biomeCache);
return;
}
@ -51,15 +51,19 @@ public class UniBiomeIslandGenerator implements BiomeGenerator {
if (islandInfo.shallow == null) islandInfo.shallow = biomeSelector.getOceanBiome(temp, random);
}
PropagatorInfo propInfo = new PropagatorInfo(islandInfo, biomes, new Point2(chunkX, chunkZ), mapper, biomeCache);
PropagatorInfo propInfo = new PropagatorInfo(islandInfo, chunkBiomeSets, new Point2(chunkX, chunkZ), mapper, biomeCache);
Flooder flooder = new Flooder(new Point2(worldX, worldZ), propInfo);
flooder.start();
}
private Biome[] attemptGetBiomeSet(World world, int worldX, int worldZ, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> existenceCache) {
private Biome[] attemptGetBiomeSet(World world, int worldX, int worldZ, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> existenceCache, Biome[][][] chunkBiomeSets) {
Point2 worldCoords = new Point2(worldX, worldZ);
Biome[] res = null;
if (chunkBiomeSets != null) {
Point2 localCoords = Utilities.worldToLocalChunkCoordinates(worldCoords);
return chunkBiomeSets[localCoords.x][localCoords.y];
}
res = biomeCache.get(worldCoords);
if (res != null) return res;
@ -79,11 +83,11 @@ public class UniBiomeIslandGenerator implements BiomeGenerator {
return res;
}
private void setCacheBiome(int worldX, int worldZ, Biome[] biomeSet, Biome[][] localBiomes, Cache<Point2, Biome[]> biomeCache) {
private void setCacheBiome(int worldX, int worldZ, Biome[] biomeSet, Biome[][][] localBiomes, Cache<Point2, Biome[]> biomeCache) {
Point2 worldCoords = new Point2(worldX, worldZ);
if (localBiomes != null) {
Point2 localCoords = Utilities.worldToLocalChunkCoordinates(worldCoords);
localBiomes[localCoords.x][localCoords.y] = biomeSet[0];
localBiomes[localCoords.x][localCoords.y] = biomeSet;
}
biomeCache.set(worldCoords, biomeSet);
}
@ -104,7 +108,7 @@ public class UniBiomeIslandGenerator implements BiomeGenerator {
@Override
public boolean isCoordinateTarget(int x, int y) {
Biome[] biomeSet = attemptGetBiomeSet(world, x, y, biomeCache, chunkGenCache);
Biome[] biomeSet = attemptGetBiomeSet(world, x, y, biomeCache, chunkGenCache, null);
if (biomeSet != null) {
main = biomeSet[1];
shore = biomeSet[2];
@ -125,12 +129,12 @@ public class UniBiomeIslandGenerator implements BiomeGenerator {
private class PropagatorInfo implements Floodable {
private final Biome shallow, shore, main;
private final Biome[][] biomes;
private final Biome[][][] biomes;
private final Point2 chunkCoords;
private final IslandWorldMapper mapper;
private final Cache<Point2, Biome[]> biomeCache;
public PropagatorInfo(IslandInfo islandInfo, Biome[][] biomes, Point2 chunkCoords, IslandWorldMapper mapper, Cache<Point2, Biome[]> biomeCache) {
public PropagatorInfo(IslandInfo islandInfo, Biome[][][] biomes, Point2 chunkCoords, IslandWorldMapper mapper, Cache<Point2, Biome[]> biomeCache) {
this.shallow = islandInfo.shallow;
this.shore = islandInfo.shore;
this.main = islandInfo.main;

View File

@ -19,31 +19,19 @@ public class WorldHeightShader {
this.seaLevel = seaLevel;
this.worldHeight = worldHeight;
this.minimumHeight = minimumHeight;
this.shader = new SimplexOctaveGenerator(new Random(seed - 1), 8);
this.shader.setScale(0.05d);
this.shader = new SimplexOctaveGenerator(new Random(seed/2), 8);
this.shader.setScale(0.03d);
}
public int getTerrainHeight(int worldX, int worldZ, Biome biome) {
public int getTerrainHeight(int worldX, int worldZ, Biome[] biomeSet) {
int height = 0;
String biomeName = biome.name().toLowerCase();
if (biomeName.contains("hills")) {
height = calculateTerrainHeight(worldX, worldZ, 30d);
} else if (biomeName.contains("mountains")) {
height = calculateTerrainHeight(worldX, worldZ, 70d);
} else if (biomeName.contains("plateau")) {
height = (int) Math.min(calculateTerrainHeight(worldX, worldZ, 50d), seaLevel + 30d);
} else if (biomeName.contains("modified")) {
height = calculateTerrainHeight(worldX, worldZ, 40d);
} else if (biomeName.contains("shattered")) {
height = calculateTerrainHeight(worldX, worldZ, 40d);
} else if (biomeName.contains("tall")) {
height = calculateTerrainHeight(worldX, worldZ, 30d);
} else if (biomeName.contains("stone")) {
height = calculateTerrainHeight(worldX, worldZ, 70d);
} else if (!biomeName.contains("ocean")) {
height = calculateTerrainHeight(worldX, worldZ, 10d);
String biomeName = biomeSet[0].name().toLowerCase();
if (!mapper.isLand(worldX, worldZ)) {
height = (int) calculateTerrainFactor(worldX, worldZ, seaLevel * 0.8d, 1.5d, 0.5d, 1d, 0.15d);
} else if (biomeName.contains("shore") || biomeName.contains("beach")) {
height = (int) (getIslandBiomeHeight(worldX, worldZ, biomeSet[1]));
} else {
height = calculateTerrainHeight(worldX, worldZ, seaLevel, 1d, 0.25d);
height = getIslandBiomeHeight(worldX, worldZ, biomeSet[0]) + 1;
}
if (height > worldHeight) throw new IllegalStateException("Resulting height is greater than world height! Biome this occurred on: " + biomeName);
@ -51,15 +39,42 @@ public class WorldHeightShader {
return height;
}
private int calculateTerrainHeight(int worldX, int worldZ, double heightFactor, double shift, double exaggerationFactor) {
int res = seaLevel;
double shapeValue = (shader.noise(worldX, worldZ, 1.5d, 0.05d, true) + shift) / (shift + 1d);
if (shift == 1d && exaggerationFactor != 1d) shapeValue = Math.pow(shapeValue, exaggerationFactor);
res += mapper.getWorldValue(worldX, worldZ) * (shapeValue * heightFactor);
private int getIslandBiomeHeight(int worldX, int worldZ, Biome biome) {
int res = 0;
String biomeName = biome.name().toLowerCase();
if (biomeName.contains("hills")) {
res = (int) calculateTerrainFactor(worldX, worldZ, 60d, 1.5d, 0.5d);
} else if (biomeName.contains("mountains")) {
res = (int) calculateTerrainFactor(worldX, worldZ, 200d, 1.9d, 0.5d);
} else if (biomeName.contains("plateau")) {
res = (int) Math.min(calculateTerrainFactor(worldX, worldZ, 60d), seaLevel + 30d);
} else if (biomeName.contains("modified")) {
res = (int) calculateTerrainFactor(worldX, worldZ, 80d);
} else if (biomeName.contains("shattered")) {
res = (int) calculateTerrainFactor(worldX, worldZ, 90d);
} else if (biomeName.contains("tall")) {
res = (int) calculateTerrainFactor(worldX, worldZ, 80d);
} else {
res = (int) calculateTerrainFactor(worldX, worldZ, 35d);
}
return res;
}
private int calculateTerrainHeight(int worldX, int worldZ, double heightFactor) {
return calculateTerrainHeight(worldX, worldZ, heightFactor, 0.75d, 1d);
private double calculateTerrainFactor(int worldX, int worldZ, double heightFactor, double freq, double amplitude, double shift, double exaggerationFactor) {
double res = seaLevel;
double shapeValue = (shader.noise(worldX, worldZ, freq, amplitude, true) + shift) / (shift + 1d);
if (shift == 1d && exaggerationFactor != 1d) shapeValue = Math.pow(shapeValue, exaggerationFactor);
double islandValue = mapper.getWorldValue(worldX, worldZ);
res += (islandValue) * (shapeValue * heightFactor);
return res;
}
private double calculateTerrainFactor(int worldX, int worldZ, double heightFactor, double freq, double amp) {
return calculateTerrainFactor(worldX, worldZ, heightFactor, freq, amp, 0.75d, 1d);
}
private double calculateTerrainFactor(int worldX, int worldZ, double heightFactor) {
return calculateTerrainFactor(worldX, worldZ, heightFactor, 1.6d, 0.5d);
}
}

View File

@ -33,7 +33,8 @@ public class WorldLayerShader {
public boolean hasSpecialLayers(Biome biome) {
String biomeName = biome.toString().toLowerCase();
return
biomeName.contains("badlands");
biomeName.contains("badlands") ||
biomeName.contains("snowy");
}
/**
@ -45,7 +46,7 @@ public class WorldLayerShader {
* @param biome the associated biome.
* @return the material for the layer. Returning null means no more special layers.
*/
public Material getMaterialForHeight(int worldX, int worldZ, int y, Biome biome) {
public Material getMaterialForHeight(int worldX, int worldZ, int y, int highestPoint, Biome biome) {
String biomeName = biome.toString().toLowerCase();
if (biomeName.contains("badlands")) {
int seedOffset = (worldX + worldZ) / 1000;
@ -66,6 +67,14 @@ public class WorldLayerShader {
return Material.TERRACOTTA;
}
}
} else if (biomeName.contains("snowy")) {
if (highestPoint == y) {
return Material.SNOW;
} else if (y >= highestPoint - getSurfaceThickness(worldX, worldZ, biome)) {
return getSurfaceMaterial(biome);
} else if (y >= highestPoint - getTransitionMaterialThickness(worldX, worldZ, biome)) {
return getTransitionMaterial(biome);
}
}
return null;
}
@ -106,6 +115,6 @@ public class WorldLayerShader {
}
public int getTransitionMaterialThickness(int worldX, int worldZ, Biome biome) {
return (int) (Math.abs(mapper.getWorldValue(worldX, worldZ)) * 10) + 6;
return (int) (Math.abs(mapper.getWorldValue(worldX, worldZ)) * 4) + 4;
}
}

View File

@ -58,7 +58,7 @@ public class UniBiomeIslandGeneratorTest {
TemperatureMapGenerator temperatureMapGenerator = new TemperatureMapGenerator(SEED);
BiomeGenerator biomeGenerator = new UniBiomeIslandGenerator();
Biome[][] biomes = new Biome[Utilities.CHUNK_SIZE][Utilities.CHUNK_SIZE];
Biome[][][] biomes = new Biome[Utilities.CHUNK_SIZE][Utilities.CHUNK_SIZE][4];
for (int localX = 0; localX < Utilities.CHUNK_SIZE; localX++) {
for (int localZ = 0; localZ < Utilities.CHUNK_SIZE; localZ++) {
if (biomes[localX][localZ] == null) {

View File

@ -1,5 +1,5 @@
write-Output "Attempting to start Paper test server."
$SID = Start-Process java -ArgumentList "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=25566", "-Xms512M", "-Xmx1G", "-jar", "paper-195.jar", "nogui" -PassThru
$SID = Start-Process java -ArgumentList "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=25566", "-Xms512M", "-Xmx1G", "-jar", "paper-195.jar", "nogui" -PassThru
$SID = $SID.Id
write-Output "Process started. PID is: $SID"