Add Carpathian mapgen
parent
9c6525feb0
commit
4ac5660fde
|
@ -54,10 +54,10 @@ public class DefaultVersionFeatures implements VersionFeaturesFactory {
|
|||
|
||||
this.worldTypes = new WorldTypes(
|
||||
new WorldType[]{
|
||||
//WorldType.CARPATHIAN,
|
||||
WorldType.V7,
|
||||
WorldType.V6,
|
||||
WorldType.V5,
|
||||
WorldType.CARPATHIAN,
|
||||
WorldType.FLAT,
|
||||
//WorldType.FRACTAL
|
||||
}
|
||||
|
@ -75,9 +75,7 @@ public class DefaultVersionFeatures implements VersionFeaturesFactory {
|
|||
VersionFeature.<Integer> listBuilder()
|
||||
.init(commonLayers)
|
||||
.initExtend(
|
||||
LayerIds.MINETEST_OCEAN,
|
||||
LayerIds.MINETEST_RIVER,
|
||||
LayerIds.MINETEST_MOUNTAIN
|
||||
LayerIds.MINETEST_OCEAN
|
||||
).construct()
|
||||
);
|
||||
enabledLayers.put(WorldType.V7,
|
||||
|
@ -131,6 +129,10 @@ public class DefaultVersionFeatures implements VersionFeaturesFactory {
|
|||
WorldType.V5,
|
||||
(seed, mapgenParams, biomeProfile) -> new amidst.minetest.world.oracle.BiomeDataOracleV5(mapgenParams, biomeProfile, seed)
|
||||
),
|
||||
new AbstractMap.SimpleEntry<WorldType, TriFunction<Long, MapgenParams, BiomeProfileSelection, IBiomeDataOracle>>(
|
||||
WorldType.CARPATHIAN,
|
||||
(seed, mapgenParams, biomeProfile) -> new amidst.minetest.world.oracle.BiomeDataOracleCarpathian(mapgenParams, biomeProfile, seed)
|
||||
),
|
||||
new AbstractMap.SimpleEntry<WorldType, TriFunction<Long, MapgenParams, BiomeProfileSelection, IBiomeDataOracle>>(
|
||||
WorldType.FLAT,
|
||||
(seed, mapgenParams, biomeProfile) -> new amidst.minetest.world.oracle.BiomeDataOracleFlat(mapgenParams, biomeProfile, seed)
|
||||
|
|
|
@ -7,4 +7,10 @@ public class Constants {
|
|||
// a Minetest Chunk is 5 x 5 x 5 MapBlocks!
|
||||
public static final int MAP_BLOCKSIZE = 16;
|
||||
|
||||
// The absolute working limit is (2^15 - viewing_range).
|
||||
// I really don't want to make every algorithm to check if it's going near
|
||||
// the limit or not, so this is lower.
|
||||
// This is the maximum value the setting map_generation_limit can be
|
||||
public static final short MAX_MAP_GENERATION_LIMIT = 31000;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package amidst.minetest.world.mapgen;
|
||||
|
||||
import javax.vecmath.Vector3f;
|
||||
|
||||
import amidst.mojangapi.world.WorldType;
|
||||
import amidst.mojangapi.world.biome.BiomeColor;
|
||||
|
||||
// TODO: be able to import these values from map_meta.txt files
|
||||
public class MapgenCarpathianParams extends MapgenParams {
|
||||
|
||||
public static final int FLAG_CARPATHIAN_CAVERNS = 0x01;
|
||||
|
||||
public int spflags = FLAG_CARPATHIAN_CAVERNS;
|
||||
|
||||
public NoiseParams np_base = new NoiseParams(12, 1, new Vector3f(2557, 2557, 2557), 6538, (short)4, 0.8f, 0.5f);
|
||||
public NoiseParams np_height1 = new NoiseParams(0, 5, new Vector3f(251, 251, 251), 9613, (short)5, 0.5f, 2.0f);
|
||||
public NoiseParams np_height2 = new NoiseParams(0, 5, new Vector3f(383, 383, 383), 1949, (short)5, 0.5f, 2.0f);
|
||||
public NoiseParams np_height3 = new NoiseParams(0, 5, new Vector3f(509, 509, 509), 3211, (short)5, 0.5f, 2.0f);
|
||||
public NoiseParams np_height4 = new NoiseParams(0, 5, new Vector3f(631, 631, 631), 1583, (short)5, 0.5f, 2.0f);
|
||||
public NoiseParams np_hills_terrain = new NoiseParams(1, 1, new Vector3f(1301, 1301, 1301), 1692, (short)5, 0.5f, 2.0f);
|
||||
public NoiseParams np_ridge_terrain = new NoiseParams(1, 1, new Vector3f(1889, 1889, 1889), 3568, (short)5, 0.5f, 2.0f);
|
||||
public NoiseParams np_step_terrain = new NoiseParams(1, 1, new Vector3f(1889, 1889, 1889), 4157, (short)5, 0.5f, 2.0f);
|
||||
public NoiseParams np_hills = new NoiseParams(0, 3, new Vector3f(257, 257, 257), 6604, (short)6, 0.5f, 2.0f);
|
||||
public NoiseParams np_ridge_mnt = new NoiseParams(0, 12, new Vector3f(743, 743, 743), 5520, (short)6, 0.7f, 2.0f);
|
||||
public NoiseParams np_step_mnt = new NoiseParams(0, 8, new Vector3f(509, 509, 509), 2590, (short)6, 0.6f, 2.0f);
|
||||
public NoiseParams np_mnt_var = new NoiseParams(0, 1, new Vector3f(499, 499, 499), 2490, (short)5, 0.55f, 2.0f);
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String prefix = "mgcarpathian_";
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append("mgcarpathian_spflags = ");
|
||||
appendFlags(result, spflags, new String[] {"caverns"});
|
||||
result.append("\r\n");
|
||||
result.append(super.toString());
|
||||
result.append(np_base.toString( prefix +"np_base"));
|
||||
result.append(np_height1.toString( prefix +"np_height1"));
|
||||
result.append(np_height2.toString( prefix +"np_height2"));
|
||||
result.append(np_height3.toString( prefix +"np_height3"));
|
||||
result.append(np_height4.toString( prefix +"np_height4"));
|
||||
result.append(np_hills_terrain.toString(prefix +"np_hills_terrain"));
|
||||
result.append(np_ridge_terrain.toString(prefix +"np_ridge_terrain"));
|
||||
result.append(np_step_terrain.toString( prefix +"np_step_terrain"));
|
||||
result.append(np_hills.toString( prefix +"np_hills"));
|
||||
result.append(np_ridge_mnt.toString( prefix +"np_ridge_mnt"));
|
||||
result.append(np_step_mnt.toString( prefix +"np_step_mnt"));
|
||||
result.append(np_mnt_var.toString( prefix +"np_mnt_var"));
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldType getWorldType() {
|
||||
return WorldType.CARPATHIAN;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
package amidst.minetest.world.oracle;
|
||||
|
||||
import amidst.documentation.Immutable;
|
||||
import amidst.logging.AmidstLogger;
|
||||
import amidst.logging.AmidstMessageBox;
|
||||
import amidst.minetest.world.mapgen.Constants;
|
||||
import amidst.minetest.world.mapgen.InvalidNoiseParamsException;
|
||||
import amidst.minetest.world.mapgen.MapgenCarpathianParams;
|
||||
import amidst.minetest.world.mapgen.MapgenParams;
|
||||
import amidst.minetest.world.mapgen.MinetestBiome;
|
||||
import amidst.minetest.world.mapgen.Noise;
|
||||
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
|
||||
import amidst.mojangapi.world.coordinates.Resolution;
|
||||
import amidst.settings.biomeprofile.BiomeProfileSelection;
|
||||
|
||||
@Immutable
|
||||
public class BiomeDataOracleCarpathian extends MinetestBiomeDataOracle {
|
||||
private final MapgenCarpathianParams carpathianParams;
|
||||
|
||||
private Noise noise_base;
|
||||
private Noise noise_height1;
|
||||
private Noise noise_height2;
|
||||
private Noise noise_height3;
|
||||
private Noise noise_height4;
|
||||
private Noise noise_hills_terrain;
|
||||
private Noise noise_ridge_terrain;
|
||||
private Noise noise_step_terrain;
|
||||
private Noise noise_hills;
|
||||
private Noise noise_ridge_mnt;
|
||||
private Noise noise_step_mnt;
|
||||
private Noise noise_mnt_var;
|
||||
|
||||
private int grad_wl;
|
||||
|
||||
/**
|
||||
* @param mapgenCarpathianParams
|
||||
* @param biomeProfileSelection - if null then a default biomeprofile will be used
|
||||
* @param seed
|
||||
* @throws InvalidNoiseParamsException
|
||||
*/
|
||||
public BiomeDataOracleCarpathian(MapgenParams mapgenCarpathianParams, BiomeProfileSelection biomeProfileSelection, long seed) {
|
||||
|
||||
super(mapgenCarpathianParams, biomeProfileSelection, seed);
|
||||
|
||||
if (params instanceof MapgenCarpathianParams) {
|
||||
carpathianParams = (MapgenCarpathianParams)params;
|
||||
} else {
|
||||
AmidstLogger.error("Error: BiomeDataOracleCarpathian cannot cast params to CarpathianParams. Using defaults instead.");
|
||||
this.params = carpathianParams = new MapgenCarpathianParams();
|
||||
}
|
||||
|
||||
grad_wl = 1 - params.water_level;
|
||||
|
||||
try {
|
||||
// 2D noise
|
||||
noise_base = new Noise(carpathianParams.np_base, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_height1 = new Noise(carpathianParams.np_height1, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_height2 = new Noise(carpathianParams.np_height2, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_height3 = new Noise(carpathianParams.np_height3, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_height4 = new Noise(carpathianParams.np_height4, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_hills_terrain = new Noise(carpathianParams.np_hills_terrain, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_ridge_terrain = new Noise(carpathianParams.np_ridge_terrain, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_step_terrain = new Noise(carpathianParams.np_step_terrain, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_hills = new Noise(carpathianParams.np_hills, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_ridge_mnt = new Noise(carpathianParams.np_ridge_mnt, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
noise_step_mnt = new Noise(carpathianParams.np_step_mnt, this.seed, params.chunk_length_x, params.chunk_length_z);
|
||||
|
||||
//// 3D terrain noise
|
||||
// 1 up 1 down overgeneration
|
||||
noise_mnt_var = new Noise(carpathianParams.np_mnt_var, this.seed, params.chunk_length_x, params.chunk_length_y + 2, params.chunk_length_z);
|
||||
|
||||
} catch (InvalidNoiseParamsException ex) {
|
||||
AmidstLogger.error("Invalid carpathianParams from Minetest game. " + ex);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Steps function
|
||||
float getSteps(float noise)
|
||||
{
|
||||
float w = 0.5f;
|
||||
float k = (float) Math.floor(noise / w);
|
||||
float f = (noise - k * w) / w;
|
||||
float s = Math.min(2.f * f, 1.f);
|
||||
return (k + s) * w;
|
||||
}
|
||||
|
||||
float terrainLevelAtPoint(int x, int z)
|
||||
{
|
||||
float ground = Noise.NoisePerlin2D(noise_base.np, x, z, seed);
|
||||
float height1 = Noise.NoisePerlin2D(noise_height1.np, x, z, seed);
|
||||
float height2 = Noise.NoisePerlin2D(noise_height2.np, x, z, seed);
|
||||
float height3 = Noise.NoisePerlin2D(noise_height3.np, x, z, seed);
|
||||
float height4 = Noise.NoisePerlin2D(noise_height4.np, x, z, seed);
|
||||
float hter = Noise.NoisePerlin2D(noise_hills_terrain.np, x, z, seed);
|
||||
float rter = Noise.NoisePerlin2D(noise_ridge_terrain.np, x, z, seed);
|
||||
float ster = Noise.NoisePerlin2D(noise_step_terrain.np, x, z, seed);
|
||||
float n_hills = Noise.NoisePerlin2D(noise_hills.np, x, z, seed);
|
||||
float n_ridge_mnt = Noise.NoisePerlin2D(noise_ridge_mnt.np, x, z, seed);
|
||||
float n_step_mnt = Noise.NoisePerlin2D(noise_step_mnt.np, x, z, seed);
|
||||
|
||||
int height = -Constants.MAX_MAP_GENERATION_LIMIT;
|
||||
|
||||
int searchInc = 1;
|
||||
|
||||
for (short y = 1; y <= 200; y += searchInc) { // we're going to break out of this loop when y is close to surface_level
|
||||
float mnt_var = Noise.NoisePerlin3D(noise_mnt_var.np, x, y, z, seed);
|
||||
|
||||
// Gradient & shallow seabed
|
||||
int grad = (y < params.water_level) ? grad_wl + (params.water_level - y) * 3 : 1 - y;
|
||||
|
||||
// Hill/Mountain height (hilliness)
|
||||
// Java doesn't have inline functions, so expanding getLerp()
|
||||
// getLerp(float noise1, float noise2, float mod) = noise1 + mod * (noise2 - noise1);
|
||||
// was:
|
||||
// float hill1 = getLerp(height1, height2, mnt_var);
|
||||
// float hill2 = getLerp(height3, height4, mnt_var);
|
||||
// float hill3 = getLerp(height3, height2, mnt_var);
|
||||
// float hill4 = getLerp(height1, height4, mnt_var);
|
||||
float hill1 = height1 + mnt_var * (height2 - height1);
|
||||
float hill2 = height3 + mnt_var * (height4 - height3);
|
||||
float hill3 = height3 + mnt_var * (height2 - height3);
|
||||
float hill4 = height1 + mnt_var * (height4 - height1);
|
||||
float hilliness = Math.max(Math.min(hill1, hill2), Math.min(hill3, hill4));
|
||||
|
||||
// Rolling hills
|
||||
float hill_mnt = hilliness * (float)Math.pow(n_hills, 2.f);
|
||||
float hills = (float)Math.pow(hter, 3.f) * hill_mnt;
|
||||
|
||||
// Ridged mountains
|
||||
float ridge_mnt = hilliness * (1.f - Math.abs(n_ridge_mnt));
|
||||
float ridged_mountains = (float)Math.pow(rter, 3.f) * ridge_mnt;
|
||||
|
||||
// Step (terraced) mountains
|
||||
float step_mnt = hilliness * getSteps(n_step_mnt);
|
||||
float step_mountains = (float)Math.pow(ster, 3.f) * step_mnt;
|
||||
|
||||
// Final terrain level
|
||||
float mountains = hills + ridged_mountains + step_mountains;
|
||||
float surface_level = ground + mountains + grad;
|
||||
|
||||
height = (int)surface_level;
|
||||
if ((y + (searchInc / 2)) >= surface_level) {
|
||||
// Close enough.
|
||||
// (should be properly accurate at water level, but will lose accuracy with height)
|
||||
break;
|
||||
}
|
||||
if (y > 2 && searchInc < 12) searchInc += 2;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short populateArray(CoordinatesInWorld corner, short[][] result, boolean useQuarterResolution) {
|
||||
|
||||
// The Carpathian mapgen terrain is not yet stable.
|
||||
// See https://forum.minetest.net/viewtopic.php?f=18&t=19132
|
||||
|
||||
int width = result.length;
|
||||
if (width > 0) {
|
||||
Resolution resolution = Resolution.from(useQuarterResolution);
|
||||
int height = result[0].length;
|
||||
int left = (int) corner.getX();
|
||||
int top = (int) corner.getY();
|
||||
int shift = resolution.getShift();
|
||||
int step = resolution.getStep();
|
||||
int world_z;
|
||||
int world_x;
|
||||
short biomeValue;
|
||||
MinetestBiome[] biomes = getBiomeArray();
|
||||
|
||||
try {
|
||||
for (int y = 0; y < height; y++) {
|
||||
|
||||
world_z = top + (y << shift);
|
||||
world_x = left;
|
||||
|
||||
// Use -world_z because Minetest uses left-handed coordinates, while Minecraft
|
||||
// and Amidst use right-handed coordinates.
|
||||
world_z = -world_z;
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
|
||||
biomeValue = 0;
|
||||
|
||||
// Add the ocean bitplane
|
||||
int surface_y = (int)terrainLevelAtPoint(world_x, world_z);
|
||||
if (surface_y < carpathianParams.water_level) biomeValue |= BITPLANE_OCEAN;
|
||||
|
||||
// add the biome index
|
||||
// (mask the bitplanes in case the biome returned is -1 (NONE)
|
||||
biomeValue |= calcBiomeAtPoint(biomes, world_x, surface_y, world_z).getIndex() & MASK_BITPLANES;
|
||||
|
||||
result[x][y] = biomeValue;
|
||||
world_x += step;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AmidstLogger.error(e);
|
||||
AmidstMessageBox.displayError("Error", e);
|
||||
}
|
||||
}
|
||||
return MASK_BITPLANES;
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import java.io.Console;
|
|||
|
||||
import amidst.logging.AmidstLogger;
|
||||
import amidst.logging.AmidstMessageBox;
|
||||
import amidst.minetest.world.mapgen.DefaultBiomes;
|
||||
import amidst.minetest.world.mapgen.InvalidNoiseParamsException;
|
||||
import amidst.minetest.world.mapgen.MapgenParams;
|
||||
import amidst.minetest.world.mapgen.MapgenV6Params;
|
||||
|
|
|
@ -10,7 +10,6 @@ import amidst.minetest.world.mapgen.MinetestBiome;
|
|||
import amidst.minetest.world.mapgen.Noise;
|
||||
import amidst.mojangapi.world.coordinates.CoordinatesInWorld;
|
||||
import amidst.mojangapi.world.coordinates.Resolution;
|
||||
import amidst.settings.biomeprofile.BiomeProfile;
|
||||
import amidst.settings.biomeprofile.BiomeProfileSelection;
|
||||
|
||||
@Immutable
|
||||
|
@ -30,11 +29,6 @@ public class BiomeDataOracleV7 extends MinetestBiomeDataOracle {
|
|||
//private Noise noise_filler_depth; // commented out because it shouldn't been needed for the surface
|
||||
|
||||
|
||||
/**
|
||||
* Updated by onBiomeProfileUpdate event, can be null.
|
||||
*/
|
||||
private volatile BiomeProfile biomeProfile;
|
||||
|
||||
short mount_zero_level = 0;
|
||||
float float_mount_density = 0.6f;
|
||||
float float_mount_height = 128.0f;
|
||||
|
@ -191,10 +185,10 @@ public class BiomeDataOracleV7 extends MinetestBiomeDataOracle {
|
|||
|
||||
// Add the ocean bitplane
|
||||
int surface_y = (int)baseTerrainLevelAtPoint(world_x, world_z);
|
||||
if (surface_y < v7params.water_level) biomeValue |= BITPLANE_OCEAN;
|
||||
if (surface_y < params.water_level) biomeValue |= BITPLANE_OCEAN;
|
||||
|
||||
// Add the mountains bitplane
|
||||
int surfaceOrSeaLevel = Math.max(surface_y, v7params.water_level);
|
||||
int surfaceOrSeaLevel = Math.max(surface_y, params.water_level);
|
||||
float mnt_h_n = Math.max(Noise.NoisePerlin2D(noise_mount_height.np, world_x, world_z, seed), 1.0f);
|
||||
float density_gradient = -((float)(surfaceOrSeaLevel - mount_zero_level) / mnt_h_n);
|
||||
float mnt_n1 = Noise.NoisePerlin3D(noise_mountain.np, world_x, surfaceOrSeaLevel, world_z, seed);
|
||||
|
|
Loading…
Reference in New Issue