Skip to content

Commit

Permalink
Add API to weather mod
Browse files Browse the repository at this point in the history
Co-authored-by: Till Affeldt <[email protected]>
  • Loading branch information
sfan5 and t-affeldt committed May 12, 2024
1 parent 31133a3 commit d1ba7c3
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 45 deletions.
18 changes: 18 additions & 0 deletions game_api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 32 additions & 0 deletions mods/weather/api.lua
Original file line number Diff line number Diff line change
@@ -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)
70 changes: 25 additions & 45 deletions mods/weather/init.lua
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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)

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

0 comments on commit d1ba7c3

Please sign in to comment.