diff --git a/src/main/java/amidst/minetest/world/DefaultVersionFeatures.java b/src/main/java/amidst/minetest/world/DefaultVersionFeatures.java index 2c038623..fde991cc 100644 --- a/src/main/java/amidst/minetest/world/DefaultVersionFeatures.java +++ b/src/main/java/amidst/minetest/world/DefaultVersionFeatures.java @@ -58,6 +58,7 @@ public class DefaultVersionFeatures implements VersionFeaturesFactory { WorldType.V6, WorldType.V5, WorldType.CARPATHIAN, + WorldType.VALLEYS, WorldType.FLAT, WorldType.HALLELUJAH_MOUNTAINS, //WorldType.FRACTAL @@ -88,6 +89,15 @@ public class DefaultVersionFeatures implements VersionFeaturesFactory { LayerIds.MINETEST_MOUNTAIN ).construct() ); + enabledLayers.put(WorldType.VALLEYS, + VersionFeature. listBuilder() + .init(commonLayers) + .initExtend( + LayerIds.MINETEST_OCEAN, + LayerIds.MINETEST_OCEAN, + LayerIds.MINETEST_MOUNTAIN + ).construct() + ); enabledLayers.put(WorldType.V7, VersionFeature. listBuilder() .init(commonLayers) diff --git a/src/main/java/amidst/minetest/world/mapgen/MapgenValleysParams.java b/src/main/java/amidst/minetest/world/mapgen/MapgenValleysParams.java new file mode 100644 index 00000000..a1dd9b49 --- /dev/null +++ b/src/main/java/amidst/minetest/world/mapgen/MapgenValleysParams.java @@ -0,0 +1,68 @@ +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 MapgenValleysParams extends MapgenParams { + + public static final int FLAG_VALLEYS_ALT_CHILL = 0x01; + public static final int FLAG_VALLEYS_HUMID_RIVERS = 0x02; + + public int spflags = FLAG_VALLEYS_ALT_CHILL | FLAG_VALLEYS_HUMID_RIVERS; + + public NoiseParams np_cave1 = new NoiseParams(0, 12.0f, new Vector3f(61, 61, 61), 52534, (short)3, 0.5f, 2.0f); + public NoiseParams np_cave2 = new NoiseParams(0, 12.0f, new Vector3f(67, 67, 67), 10325, (short)3, 0.5f, 2.0f); + public NoiseParams np_filler_depth = new NoiseParams(0, 1.2f, new Vector3f(256, 256, 256), 1605, (short)3, 0.5f, 2.0f); + public NoiseParams np_inter_valley_fill = new NoiseParams(0, 1.0f, new Vector3f(256, 512, 256), 1993, (short)6, 0.8f, 2.0f); + public NoiseParams np_inter_valley_slope = new NoiseParams(0.5f, 0.5f, new Vector3f(128, 128, 128), 746, (short)1, 1.0f, 2.0f); + public NoiseParams np_rivers = new NoiseParams(0, 1.0f, new Vector3f(256, 256, 256), -6050, (short)5, 0.6f, 2.0f); + public NoiseParams np_massive_caves = new NoiseParams(0, 1.0f, new Vector3f(768, 256, 768), 59033, (short)6, 0.63f, 2.0f); + public NoiseParams np_terrain_height = new NoiseParams(-10, 50.0f, new Vector3f(1024, 1024, 1024), 5202, (short)6, 0.4f, 2.0f); + public NoiseParams np_valley_depth = new NoiseParams(5, 4.0f, new Vector3f(512, 512, 512), -1914, (short)1, 1.0f, 2.0f); + public NoiseParams np_valley_profile = new NoiseParams(0.6f, 0.5f, new Vector3f(512, 512, 512), 777, (short)1, 1.0f, 2.0f); + + public short large_cave_depth = -33; + public short massive_cave_depth = -256; // highest altitude of massive caves + public short altitude_chill = 90; // The altitude at which temperature drops by 20C. + public short lava_features = 0; // How often water will occur in caves. + public short river_depth = 4; // How deep to carve river channels. + public short river_size = 5; // How wide to make rivers. + public short water_features = 0; // How often water will occur in caves. + public float cave_width = 0.09f; + public short dungeon_ymin = -31000; + public short dungeon_ymax = 63; // No higher than surface mapchunks + + + @Override + public String toString() { + String prefix = "mgvalleys_"; + StringBuilder result = new StringBuilder(); + result.append(prefix + "spflags = "); + appendFlags(result, spflags, new String[] {"altitude_chill", "humid_rivers"}); + result.append("\r\n"); + result.append(super.toString()); + /* TODO + 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.VALLEYS; + } +} diff --git a/src/main/java/amidst/minetest/world/oracle/BiomeDataOracleValleys.java b/src/main/java/amidst/minetest/world/oracle/BiomeDataOracleValleys.java new file mode 100644 index 00000000..d63a1551 --- /dev/null +++ b/src/main/java/amidst/minetest/world/oracle/BiomeDataOracleValleys.java @@ -0,0 +1,154 @@ +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.MapgenParams; +import amidst.minetest.world.mapgen.MapgenValleysParams; +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 BiomeDataOracleValleys extends MinetestBiomeDataOracle { + private final MapgenValleysParams valleysParams; + + private Noise noise_cave1; + private Noise noise_cave2; + private Noise noise_filler_depth; + private Noise noise_inter_valley_fill; + private Noise noise_inter_valley_slope; + private Noise noise_rivers; + private Noise noise_massive_caves; + private Noise noise_terrain_height; + private Noise noise_valley_depth; + private Noise noise_valley_profile; + private int grad_wl; + + boolean humid_rivers; + boolean use_altitude_chill; + float humidity_adjust; + + + /** + * @param mapgenCarpathianParams + * @param biomeProfileSelection - if null then a default biomeprofile will be used + * @param seed + * @throws InvalidNoiseParamsException + */ + public BiomeDataOracleValleys(MapgenParams mapgenValleysParams, BiomeProfileSelection biomeProfileSelection, long seed) { + + super(mapgenValleysParams, biomeProfileSelection, seed); + + if (params instanceof MapgenValleysParams) { + valleysParams = (MapgenValleysParams)params; + } else { + AmidstLogger.error("Error: BiomeDataOracleCarpathian cannot cast params to CarpathianParams. Using defaults instead."); + this.params = valleysParams = new MapgenValleysParams(); + } + + grad_wl = 1 - params.water_level; + + try { + // 2D noise + noise_filler_depth = new Noise(valleysParams.np_filler_depth, this.seed, params.chunk_length_x, params.chunk_length_z); + noise_inter_valley_slope = new Noise(valleysParams.np_inter_valley_slope, this.seed, params.chunk_length_x, params.chunk_length_z); + noise_rivers = new Noise(valleysParams.np_rivers, this.seed, params.chunk_length_x, params.chunk_length_z); + noise_terrain_height = new Noise(valleysParams.np_terrain_height, this.seed, params.chunk_length_x, params.chunk_length_z); + noise_valley_depth = new Noise(valleysParams.np_valley_depth, this.seed, params.chunk_length_x, params.chunk_length_z); + noise_valley_profile = new Noise(valleysParams.np_valley_profile, this.seed, params.chunk_length_x, params.chunk_length_z); + + //// 3D terrain noise + // 1 up 1 down overgeneration + noise_inter_valley_fill = new Noise(valleysParams.np_inter_valley_fill, this.seed, params.chunk_length_x, params.chunk_length_y + 2, params.chunk_length_z); + // 1-down overgeneraion + noise_cave1 = new Noise(valleysParams.np_cave1, this.seed, params.chunk_length_x, params.chunk_length_y + 1, params.chunk_length_z); + noise_cave2 = new Noise(valleysParams.np_cave2, this.seed, params.chunk_length_x, params.chunk_length_y + 1, params.chunk_length_z); + noise_massive_caves = new Noise(valleysParams.np_massive_caves, this.seed, params.chunk_length_x, params.chunk_length_y + 1, params.chunk_length_z); + + } catch (InvalidNoiseParamsException ex) { + AmidstLogger.error("Invalid valleysParams from Minetest game. " + ex); + ex.printStackTrace(); + } + + humid_rivers = (valleysParams.spflags & MapgenValleysParams.FLAG_VALLEYS_HUMID_RIVERS) > 0; + use_altitude_chill = (valleysParams.spflags & MapgenValleysParams.FLAG_VALLEYS_ALT_CHILL) > 0; + } + + float terrainLevelAtPoint(int x, int z) + { + TerrainNoise tn; + + float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed); + float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed); + float inter_valley_slope = NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed); + + tn.x = x; + tn.z = z; + tn.terrain_height = NoisePerlin2D(&noise_terrain_height->np, x, z, seed); + tn.rivers = &rivers; + tn.valley = &valley; + tn.valley_profile = NoisePerlin2D(&noise_valley_profile->np, x, z, seed); + tn.slope = &inter_valley_slope; + tn.inter_valley_fill = 0.f; + + return adjustedTerrainLevelFromNoise(&tn); } + + @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 < valleysParams.water_level) biomeValue |= BITPLANE_OCEAN; + if (isMountains) biomeValue |= BITPLANE_MOUNTAIN; + + // 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; + } +} diff --git a/src/main/java/amidst/mojangapi/world/WorldType.java b/src/main/java/amidst/mojangapi/world/WorldType.java index ae1367e7..e29657be 100644 --- a/src/main/java/amidst/mojangapi/world/WorldType.java +++ b/src/main/java/amidst/mojangapi/world/WorldType.java @@ -22,6 +22,7 @@ public enum WorldType { // FLAT - can reuse the minecraft FLAT FRACTAL ("Fractal", "fractal", null), CARPATHIAN ("Carpathian", "carpathian", null), + VALLEYS ("Valleys", "valleys", null), HALLELUJAH_MOUNTAINS ("Hallelujah Mountains (mod)", "hallelujahmountains", null); // @formatter:on