Biomes: Add 'get heat', 'get humidity', 'get biome data' APIs
authorparamat <paramat@users.noreply.github.com>
Fri, 22 Sep 2017 11:38:55 +0000 (12:38 +0100)
committerparamat <mat.gregory@virginmedia.com>
Tue, 16 Jan 2018 08:47:07 +0000 (08:47 +0000)
'get biome data' returns biome id, heat and humidity.
Clean up nearby lines in lua_api.txt.

doc/lua_api.txt
src/mapgen/mg_biome.cpp
src/mapgen/mg_biome.h
src/script/lua_api/l_mapgen.cpp
src/script/lua_api/l_mapgen.h

index da4655682c1436f8e15a07fcaeb8ee4d0a614e41..d7ea7f79f1fd5c9135a20bc245905910843e8195 100644 (file)
@@ -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
index b562084e3a2efd30afa59e6feaf1db6ecac69576..2273be280978bd6e360a016242ee9e10621d55ff 100644 (file)
@@ -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)
 {
index ac606e9351d137c7b0ee5a20e286b81c6e53b716..a2bfaf5b90f3eb4cf1c28a9f5db31d327f174306 100644 (file)
@@ -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;
 
index b526111d4737b9466979a338fc7c1a7607f5b8c0..db517b942c9f04c89a37f465fc44ff2e3a194aa5 100644 (file)
@@ -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);
index 89b825be2cd622c8a5e79ae358078b71508db2a8..f6a821b4e026605060a66dd943a182757c4cdacf 100644 (file)
@@ -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);