From d1ba7c3db3a3d06b4b2b82bb0d043d7801f99d27 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 10 Apr 2024 18:24:00 +0200 Subject: [PATCH] Add API to weather mod Co-authored-by: Till Affeldt --- game_api.txt | 18 +++++++++++ mods/weather/api.lua | 32 ++++++++++++++++++++ mods/weather/init.lua | 70 ++++++++++++++++--------------------------- 3 files changed, 75 insertions(+), 45 deletions(-) create mode 100644 mods/weather/api.lua diff --git a/game_api.txt b/game_api.txt index e46ea6bd..9a7ef8fb 100644 --- a/game_api.txt +++ b/game_api.txt @@ -1169,3 +1169,21 @@ the log. * after logging the action, the original callback (if any) is called * `def` See [Node definition] * `name` Description of the node in the log message + + +Weather API +----------- + +The weather mod will constantly adjust weather effects seen by the player +(that is: cloud parameters and shadow intensity). +These can be influenced using this API. + +#### `weather.get = function(player)` + +* Returns the current weather effects seen by the player. + It returns a table with two keys: + * `clouds`: A table (or `nil`) with cloud data following the same format as used for `player:set_clouds()`. + * `lighting`: A table (or `nil`) with lighting data following the same format as used for `player:set_lighting()`. +* `player`: ObjectRef of the relevant player +* You can override this function to change the weather effects by simply returning different values. + Setting `clouds` or `lighting` in the result table to `nil` will *prevent* those from changing. diff --git a/mods/weather/api.lua b/mods/weather/api.lua new file mode 100644 index 00000000..818e26a3 --- /dev/null +++ b/mods/weather/api.lua @@ -0,0 +1,32 @@ +local CYCLE = 8 -- Time period of cyclic clouds update in seconds + +weather = {} + +-- default implementation is empty +function weather.get(player) + return {} +end + +local function do_update() + for _, player in ipairs(minetest.get_connected_players()) do + local params = weather.get(player) + assert(params ~= nil, "weather.get() must not return nil") + if params.clouds then + player:set_clouds(params.clouds) + end + if params.lighting then + player:set_lighting(params.lighting) + end + end +end + +local function cyclic_update() + do_update() + minetest.after(CYCLE, cyclic_update) +end +minetest.after(0, cyclic_update) + +-- Update on player join to instantly alter clouds from the default +minetest.register_on_joinplayer(function(player) + do_update() +end) diff --git a/mods/weather/init.lua b/mods/weather/init.lua index 7d6d9484..cc498694 100644 --- a/mods/weather/init.lua +++ b/mods/weather/init.lua @@ -1,10 +1,13 @@ +-- Always load the API +dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/api.lua") + -- Disable by mapgen or setting -local mg_name = minetest.get_mapgen_setting("mg_name") if minetest.settings:get_bool("enable_weather") == false then return end +local mg_name = minetest.get_mapgen_setting("mg_name") if mg_name == "v6" or mg_name == "singlenode" then -- set a default shadow intensity for mgv6 and singlenode minetest.register_on_joinplayer(function(player) @@ -14,10 +17,9 @@ if mg_name == "v6" or mg_name == "singlenode" then return end --- Parameters +-- Default implementation for noise based cloud appearance local TSCALE = 600 -- Time scale of noise variation in seconds -local CYCLE = 8 -- Time period of cyclic clouds update in seconds local np_density = { offset = 0.5, @@ -59,19 +61,11 @@ local np_speedz = { lacunarity = 2, } --- End parameters - - --- Initialise noise objects to nil - local nobj_density = nil local nobj_thickness = nil local nobj_speedx = nil local nobj_speedz = nil - --- Update clouds function - local function rangelim(value, lower, upper) return math.min(math.max(value, lower), upper) end @@ -88,7 +82,7 @@ do end end -local function update_clouds() +function weather.get(player) -- Adjusted time in seconds local time = math.floor(minetest.get_gametime() - t_offset) @@ -102,42 +96,28 @@ local function update_clouds() local n_speedx = nobj_speedx:get_2d({x = time, y = 0}) -- -1 to 1 local n_speedz = nobj_speedz:get_2d({x = time, y = 0}) -- -1 to 1 - for _, player in ipairs(minetest.get_connected_players()) do - -- Fallback to mid-value 50 for very old worlds - local humid = minetest.get_humidity(player:get_pos()) or 50 - -- Default and classic density value is 0.4, make this happen - -- at humidity midvalue 50 when n_density is at midvalue 0.5. - -- density_max = 0.25 at humid = 0. - -- density_max = 0.8 at humid = 50. - -- density_max = 1.35 at humid = 100. - local density_max = 0.8 + ((humid - 50) / 50) * 0.55 - -- Range limit density_max to always have occasional - -- small scattered clouds at extreme low humidity. - local density = rangelim(density_max, 0.2, 1.0) * n_density - player:set_clouds({ + -- Fallback to mid-value 50 for very old worlds + local humid = minetest.get_humidity(player:get_pos()) or 50 + -- Default and classic density value is 0.4, make this happen + -- at humidity midvalue 50 when n_density is at midvalue 0.5. + -- density_max = 0.25 at humid = 0. + -- density_max = 0.8 at humid = 50. + -- density_max = 1.35 at humid = 100. + local density_max = 0.8 + ((humid - 50) / 50) * 0.55 + -- Range limit density_max to always have occasional + -- small scattered clouds at extreme low humidity. + local density = rangelim(density_max, 0.2, 1.0) * n_density + + return { + clouds = { density = density, thickness = math.max(math.floor( rangelim(32 * humid / 100, 8, 32) * n_thickness ), 2), speed = {x = n_speedx * 4, z = n_speedz * 4}, - }) - -- now adjust the shadow intensity - player:set_lighting({ shadows = { intensity = 0.7 * (1 - density) } }) - end + }, + lighting = { + shadows = { intensity = 0.7 * (1 - density) } + } + } end - - -local function cyclic_update() - update_clouds() - minetest.after(CYCLE, cyclic_update) -end - - -minetest.after(0, cyclic_update) - - --- Update on player join to instantly alter clouds from the default - -minetest.register_on_joinplayer(function(player) - update_clouds() -end)