From d45e5da8ca808e552123bcd94e76b0b435a6ea79 Mon Sep 17 00:00:00 2001 From: paramat Date: Fri, 22 Sep 2017 12:38:55 +0100 Subject: [PATCH] Biomes: Add 'get heat', 'get humidity', 'get biome data' APIs 'get biome data' returns biome id, heat and humidity. Clean up nearby lines in lua_api.txt. --- doc/lua_api.txt | 107 ++++++++++++++-------- src/mapgen/mg_biome.cpp | 60 ++++++++++++- src/mapgen/mg_biome.h | 7 ++ src/script/lua_api/l_mapgen.cpp | 153 +++++++++++++++++++++++++++++++- src/script/lua_api/l_mapgen.h | 14 ++- 5 files changed, 302 insertions(+), 39 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index da4655682..d7ea7f79f 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2816,58 +2816,93 @@ and `minetest.auth_reload` call the authentication handler. * Return voxel manipulator object. * Loads the manipulator from the map if positions are passed. * `minetest.set_gen_notify(flags, {deco_ids})` - * Set the types of on-generate notifications that should be collected - * `flags` is a flag field with the available flags: `dungeon`, `temple`, `cave_begin`, - `cave_end`, `large_cave_begin`, `large_cave_end`, `decoration` - * The second parameter is a list of IDS of decorations which notification is requested for -* `get_gen_notify()`: returns a flagstring and a table with the `deco_id`s + * Set the types of on-generate notifications that should be collected. + * `flags` is a flag field with the available flags: + * dungeon + * temple + * cave_begin + * cave_end + * large_cave_begin + * large_cave_end + * decoration + * The second parameter is a list of IDS of decorations which notification + is requested for. +* `get_gen_notify()` + * Returns a flagstring and a table with the `deco_id`s. * `minetest.get_mapgen_object(objectname)` * Return requested mapgen object if available (see "Mapgen objects") +* `minetest.get_heat(pos)` + * Returns the heat at the position, or `nil` on failure. +* `minetest.get_humidity(pos)` + * Returns the humidity at the position, or `nil` on failure. +* `minetest.get_biome_data(pos)` + * Returns a table containing: + * `biome` the biome id of the biome at that position + * `heat` the heat at the position + * `humidity` the humidity at the position + * Or returns `nil` on failure. * `minetest.get_biome_id(biome_name)` - * Returns the biome id, as used in the biomemap Mapgen object, for a - given biome_name string. -* `minetest.get_mapgen_params()` Returns mapgen parameters, a table containing - `mgname`, `seed`, `chunksize`, `water_level`, and `flags`. - * Deprecated: use `minetest.get_mapgen_setting(name)` instead + * Returns the biome id, as used in the biomemap Mapgen object and returned + by `minetest.get_biome_data(pos)`, for a given biome_name string. +* `minetest.get_mapgen_params()` + * Deprecated: use `minetest.get_mapgen_setting(name)` instead. + * Returns a table containing: + * `mgname` + * `seed` + * `chunksize` + * `water_level` + * `flags` * `minetest.set_mapgen_params(MapgenParams)` - * Deprecated: use `minetest.set_mapgen_setting(name, value, override)` instead - * Set map generation parameters - * Function cannot be called after the registration period; only initialization - and `on_mapgen_init` - * Takes a table as an argument with the fields `mgname`, `seed`, `water_level`, - and `flags`. - * Leave field unset to leave that parameter unchanged - * `flags` contains a comma-delimited string of flags to set, - or if the prefix `"no"` is attached, clears instead. - * `flags` is in the same format and has the same options as `mg_flags` in `minetest.conf` + * Deprecated: use `minetest.set_mapgen_setting(name, value, override)` + instead. + * Set map generation parameters. + * Function cannot be called after the registration period; only + initialization and `on_mapgen_init`. + * Takes a table as an argument with the fields: + * `mgname` + * `seed` + * `chunksize` + * `water_level` + * `flags` + * Leave field unset to leave that parameter unchanged. + * `flags` contains a comma-delimited string of flags to set, or if the + prefix `"no"` is attached, clears instead. + * `flags` is in the same format and has the same options as `mg_flags` in + `minetest.conf`. * `minetest.get_mapgen_setting(name)` - * Gets the *active* mapgen setting (or nil if none exists) in string format with the following - order of precedence: + * Gets the *active* mapgen setting (or nil if none exists) in string + format with the following order of precedence: 1) Settings loaded from map_meta.txt or overrides set during mod execution 2) Settings set by mods without a metafile override 3) Settings explicitly set in the user config file, minetest.conf 4) Settings set as the user config default * `minetest.get_mapgen_setting_noiseparams(name)` - * Same as above, but returns the value as a NoiseParams table if the setting `name` exists - and is a valid NoiseParams + * Same as above, but returns the value as a NoiseParams table if the + setting `name` exists and is a valid NoiseParams. * `minetest.set_mapgen_setting(name, value, [override_meta])` - * Sets a mapgen param to `value`, and will take effect if the corresponding mapgen setting - is not already present in map_meta.txt. - * `override_meta` is an optional boolean (default: `false`). If this is set to true, - the setting will become the active setting regardless of the map metafile contents. - * Note: to set the seed, use `"seed"`, not `"fixed_map_seed"` + * Sets a mapgen param to `value`, and will take effect if the corresponding + mapgen setting is not already present in map_meta.txt. + * `override_meta` is an optional boolean (default: `false`). If this is set + to true, the setting will become the active setting regardless of the map + metafile contents. + * Note: to set the seed, use `"seed"`, not `"fixed_map_seed"`. * `minetest.set_mapgen_setting_noiseparams(name, value, [override_meta])` - * Same as above, except value is a NoiseParams table. + * Same as above, except value is a NoiseParams table. * `minetest.set_noiseparams(name, noiseparams, set_default)` - * Sets the noiseparams setting of `name` to the noiseparams table specified in `noiseparams`. - * `set_default` is an optional boolean (default: `true`) that specifies whether the setting - should be applied to the default config or current active config -* `minetest.get_noiseparams(name)`: returns a table of the noiseparams for name + * Sets the noiseparams setting of `name` to the noiseparams table specified + in `noiseparams`. + * `set_default` is an optional boolean (default: `true`) that specifies + whether the setting should be applied to the default config or current + active config. +* `minetest.get_noiseparams(name)` + * Returns a table of the noiseparams for name. * `minetest.generate_ores(vm, pos1, pos2)` - * Generate all registered ores within the VoxelManip `vm` and in the area from `pos1` to `pos2`. + * Generate all registered ores within the VoxelManip `vm` and in the area + from `pos1` to `pos2`. * `pos1` and `pos2` are optional and default to mapchunk minp and maxp. * `minetest.generate_decorations(vm, pos1, pos2)` - * Generate all registered decorations within the VoxelManip `vm` and in the area from `pos1` to `pos2`. + * Generate all registered decorations within the VoxelManip `vm` and in the + area from `pos1` to `pos2`. * `pos1` and `pos2` are optional and default to mapchunk minp and maxp. * `minetest.clear_objects([options])` * Clear all objects in the environment diff --git a/src/mapgen/mg_biome.cpp b/src/mapgen/mg_biome.cpp index b562084e3..2273be280 100644 --- a/src/mapgen/mg_biome.cpp +++ b/src/mapgen/mg_biome.cpp @@ -84,8 +84,66 @@ void BiomeManager::clear() m_objects.resize(1); } -//////////////////////////////////////////////////////////////////////////////// +// For BiomeGen type 'BiomeGenOriginal' +float BiomeManager::getHeatAtPosOriginal(v3s16 pos, NoiseParams &np_heat, + NoiseParams &np_heat_blend, u64 seed) +{ + return + NoisePerlin2D(&np_heat, pos.X, pos.Z, seed) + + NoisePerlin2D(&np_heat_blend, pos.X, pos.Z, seed); +} + + +// For BiomeGen type 'BiomeGenOriginal' +float BiomeManager::getHumidityAtPosOriginal(v3s16 pos, NoiseParams &np_humidity, + NoiseParams &np_humidity_blend, u64 seed) +{ + return + NoisePerlin2D(&np_humidity, pos.X, pos.Z, seed) + + NoisePerlin2D(&np_humidity_blend, pos.X, pos.Z, seed); +} + + +// For BiomeGen type 'BiomeGenOriginal' +Biome *BiomeManager::getBiomeFromNoiseOriginal(float heat, float humidity, s16 y) +{ + Biome *biome_closest = nullptr; + Biome *biome_closest_blend = nullptr; + float dist_min = FLT_MAX; + float dist_min_blend = FLT_MAX; + + for (size_t i = 1; i < getNumObjects(); i++) { + Biome *b = (Biome *)getRaw(i); + if (!b || y > b->y_max + b->vertical_blend || y < b->y_min) + continue; + + float d_heat = heat - b->heat_point; + float d_humidity = humidity - b->humidity_point; + float dist = (d_heat * d_heat) + (d_humidity * d_humidity); + + if (y <= b->y_max) { // Within y limits of biome b + if (dist < dist_min) { + dist_min = dist; + biome_closest = b; + } + } else if (dist < dist_min_blend) { // Blend area above biome b + dist_min_blend = dist; + biome_closest_blend = b; + } + } + + mysrand(y + (heat - humidity) * 2); + if (biome_closest_blend && + myrand_range(0, biome_closest_blend->vertical_blend) >= + y - biome_closest_blend->y_max) + return biome_closest_blend; + + return (biome_closest) ? biome_closest : (Biome *)getRaw(BIOME_NONE); +} + + +//////////////////////////////////////////////////////////////////////////////// void BiomeParamsOriginal::readParams(const Settings *settings) { diff --git a/src/mapgen/mg_biome.h b/src/mapgen/mg_biome.h index ac606e935..a2bfaf5b9 100644 --- a/src/mapgen/mg_biome.h +++ b/src/mapgen/mg_biome.h @@ -225,6 +225,13 @@ public: virtual void clear(); + // For BiomeGen type 'BiomeGenOriginal' + float getHeatAtPosOriginal(v3s16 pos, NoiseParams &np_heat, + NoiseParams &np_heat_blend, u64 seed); + float getHumidityAtPosOriginal(v3s16 pos, NoiseParams &np_humidity, + NoiseParams &np_humidity_blend, u64 seed); + Biome *getBiomeFromNoiseOriginal(float heat, float humidity, s16 y); + private: Server *m_server; diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index b526111d4..db517b942 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -463,7 +463,7 @@ size_t get_biome_list(lua_State *L, int index, /////////////////////////////////////////////////////////////////////////////// // get_biome_id(biomename) -// returns the biome id used in biomemap +// returns the biome id as used in biomemap and returned by 'get_biome_data()' int ModApiMapgen::l_get_biome_id(lua_State *L) { NO_MAP_LOCK_REQUIRED; @@ -488,6 +488,154 @@ int ModApiMapgen::l_get_biome_id(lua_State *L) } +// get_heat(pos) +// returns the heat at the position +int ModApiMapgen::l_get_heat(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + v3s16 pos = read_v3s16(L, 1); + + NoiseParams np_heat; + NoiseParams np_heat_blend; + + MapSettingsManager *settingsmgr = + getServer(L)->getEmergeManager()->map_settings_mgr; + + if (!settingsmgr->getMapSettingNoiseParams("mg_biome_np_heat", + &np_heat) || + !settingsmgr->getMapSettingNoiseParams("mg_biome_np_heat_blend", + &np_heat_blend)) + return 0; + + std::string value; + if (!settingsmgr->getMapSetting("seed", &value)) + return 0; + std::istringstream ss(value); + u64 seed; + ss >> seed; + + BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr; + if (!bmgr) + return 0; + + float heat = bmgr->getHeatAtPosOriginal(pos, np_heat, np_heat_blend, seed); + if (!heat) + return 0; + + lua_pushnumber(L, heat); + + return 1; +} + + +// get_humidity(pos) +// returns the humidity at the position +int ModApiMapgen::l_get_humidity(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + v3s16 pos = read_v3s16(L, 1); + + NoiseParams np_humidity; + NoiseParams np_humidity_blend; + + MapSettingsManager *settingsmgr = + getServer(L)->getEmergeManager()->map_settings_mgr; + + if (!settingsmgr->getMapSettingNoiseParams("mg_biome_np_humidity", + &np_humidity) || + !settingsmgr->getMapSettingNoiseParams("mg_biome_np_humidity_blend", + &np_humidity_blend)) + return 0; + + std::string value; + if (!settingsmgr->getMapSetting("seed", &value)) + return 0; + std::istringstream ss(value); + u64 seed; + ss >> seed; + + BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr; + if (!bmgr) + return 0; + + float humidity = bmgr->getHumidityAtPosOriginal(pos, np_humidity, + np_humidity_blend, seed); + if (!humidity) + return 0; + + lua_pushnumber(L, humidity); + + return 1; +} + + +// get_biome_data(pos) +// returns a table containing the biome id, heat and humidity at the position +int ModApiMapgen::l_get_biome_data(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + v3s16 pos = read_v3s16(L, 1); + + NoiseParams np_heat; + NoiseParams np_heat_blend; + NoiseParams np_humidity; + NoiseParams np_humidity_blend; + + MapSettingsManager *settingsmgr = + getServer(L)->getEmergeManager()->map_settings_mgr; + + if (!settingsmgr->getMapSettingNoiseParams("mg_biome_np_heat", + &np_heat) || + !settingsmgr->getMapSettingNoiseParams("mg_biome_np_heat_blend", + &np_heat_blend) || + !settingsmgr->getMapSettingNoiseParams("mg_biome_np_humidity", + &np_humidity) || + !settingsmgr->getMapSettingNoiseParams("mg_biome_np_humidity_blend", + &np_humidity_blend)) + return 0; + + std::string value; + if (!settingsmgr->getMapSetting("seed", &value)) + return 0; + std::istringstream ss(value); + u64 seed; + ss >> seed; + + BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr; + if (!bmgr) + return 0; + + float heat = bmgr->getHeatAtPosOriginal(pos, np_heat, np_heat_blend, seed); + if (!heat) + return 0; + + float humidity = bmgr->getHumidityAtPosOriginal(pos, np_humidity, + np_humidity_blend, seed); + if (!humidity) + return 0; + + Biome *biome = (Biome *)bmgr->getBiomeFromNoiseOriginal(heat, humidity, pos.Y); + if (!biome || biome->index == OBJDEF_INVALID_INDEX) + return 0; + + lua_newtable(L); + + lua_pushinteger(L, biome->index); + lua_setfield(L, -2, "biome"); + + lua_pushnumber(L, heat); + lua_setfield(L, -2, "heat"); + + lua_pushnumber(L, humidity); + lua_setfield(L, -2, "humidity"); + + return 1; +} + + // get_mapgen_object(objectname) // returns the requested object used during map generation int ModApiMapgen::l_get_mapgen_object(lua_State *L) @@ -1520,6 +1668,9 @@ int ModApiMapgen::l_serialize_schematic(lua_State *L) void ModApiMapgen::Initialize(lua_State *L, int top) { API_FCT(get_biome_id); + API_FCT(get_heat); + API_FCT(get_humidity); + API_FCT(get_biome_data); API_FCT(get_mapgen_object); API_FCT(get_mapgen_params); diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index 89b825be2..f6a821b4e 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -25,9 +25,21 @@ class ModApiMapgen : public ModApiBase { private: // get_biome_id(biomename) - // returns the biome id used in biomemap + // returns the biome id as used in biomemap and returned by 'get_biome_data()' static int l_get_biome_id(lua_State *L); + // get_heat(pos) + // returns the heat at the position + static int l_get_heat(lua_State *L); + + // get_humidity(pos) + // returns the humidity at the position + static int l_get_humidity(lua_State *L); + + // get_biome_data(pos) + // returns a table containing the biome id, heat and humidity at the position + static int l_get_biome_data(lua_State *L); + // get_mapgen_object(objectname) // returns the requested object used during map generation static int l_get_mapgen_object(lua_State *L);