Add API to weather mod

Co-authored-by: Till Affeldt <t.affeldt@tu-braunschweig.de>
This commit is contained in:
sfan5 2024-04-10 18:24:00 +02:00
parent 16c663f87e
commit c21398dd5f
3 changed files with 75 additions and 45 deletions

View File

@ -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.

32
mods/weather/api.lua Normal file
View File

@ -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)

View File

@ -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)