1
0
mirror of https://github.com/minetest/minetest_game.git synced 2025-07-01 22:30:21 +02:00

Redesign API for more flexible usage

This commit is contained in:
Till Affeldt
2023-03-11 18:19:07 +01:00
parent a3f703da3e
commit 5c51eecd7f
2 changed files with 109 additions and 76 deletions

View File

@ -1,10 +1,10 @@
-- Check whether mod should be active
local mg_name = minetest.get_mapgen_setting("mg_name")
local mod_enabled = minetest.settings:get_bool("enable_weather", true)
local randomize_clouds = mod_enabled and mg_name ~= "v6" and mg_name ~= "singlenode"
local settings_enabled = minetest.settings:get_bool("enable_weather", true)
local randomize_clouds = mg_name ~= "v6" and mg_name ~= "singlenode"
-- global variable for API (see end of file)
weather = {}
local playerset = {}
-- Parameters
local TSCALE = 600 -- Time scale of noise variation in seconds
@ -70,11 +70,14 @@ local t_offset = math.random(0, 300000)
-- set a default shadow intensity for mgv6 and singlenode
local function set_default_lighting(players)
for playername, _ in pairs(players) do
local player = minetest.get_player_by_name(playername)
player:set_lighting({
for _, player in ipairs(players) do
local lighting = {
shadows = { intensity = 0.33 }
})
}
local overrides = weather.on_update(player, { lighting })
if overrides.lighting ~= nil then
player:set_lighting(overrides.lighting)
end
end
end
@ -98,8 +101,7 @@ local function update_weather(players)
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 playername, _ in pairs(players) do
local player = minetest.get_player_by_name(playername)
for _, player in ipairs(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
@ -109,7 +111,7 @@ local function update_weather(players)
-- density_max = 1.35 at humid = 100.
local density_max = 0.8 + ((humid - 50) / 50) * 0.55
local density = rangelim(density_max, 0.2, 1.0) * n_density
player:set_clouds({
local clouds = {
-- Range limit density_max to always have occasional
-- small scattered clouds at extreme low humidity.
density = density,
@ -117,84 +119,82 @@ local function update_weather(players)
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({
local lighting = {
shadows = { intensity = 0.7 * (1 - density) }
})
}
-- check for API overrides and then apply
local overrides = weather.on_update(player, { clouds, lighting })
if overrides ~= nil and overrides.clouds ~= nil then
player:set_clouds(overrides.clouds)
end
if overrides ~= nil and overrides.lighting ~= nil then
player:set_lighting(overrides.lighting)
end
end
end
local function purge_effects(player)
-- only reset potentially touched table values
if randomize_clouds then
player:set_clouds({
density = 0.4,
thickness = 16,
speed = { x = 0, z = -2 }
})
-- Update clouds periodically for all players
local timer = nil
local function cyclic_update()
local players = minetest.get_connected_players()
update_weather(players)
timer = minetest.after(CYCLE, cyclic_update)
end
timer = minetest.after(0, cyclic_update)
local function purge_effects()
-- stop timer for active cycle
if timer ~= nil then
timer:cancel()
timer = nil
end
player:set_lighting({
shadows = { intensity = 0 }
})
-- reset changed player tables to default values
for _, player in ipairs(minetest.get_connected_players()) do
if randomize_clouds then
player:set_clouds({})
end
-- NOTE: set_lighting doesn't allow empty table to reset
player:set_lighting({
shadows = {
intensity = 0
}
})
end
end
-- Define API hooks
-- override to set state for newly joined players
weather.enable_on_join = true
-- returns bool for whether weather is active
-- returns nil if player is offline or weather is disabled
weather.get_enabled = function(player)
if not mod_enabled or not player then
return
end
local playername = player:get_player_name()
return playerset[playername] or false
end
-- override weather generation for individual player
weather.set_enabled = function(player, enable)
local playername = player:get_player_name()
enable = enable or nil
if not mod_enabled or enable == playerset[playername] then
return
end
playerset[playername] = enable
if enable then
update_weather({ [playername] = true })
else
purge_effects(player)
end
end
-- End API hooks
-- skip event registration if mod is disabled
if not mod_enabled then
return
end
if randomize_clouds then
local function cyclic_update()
update_weather(playerset)
minetest.after(CYCLE, cyclic_update)
end
minetest.after(0, cyclic_update)
end
-- Update on player join to instantly alter clouds from the default
minetest.register_on_joinplayer(function(player)
if weather.enable_on_join then
local playername = player:get_player_name()
playerset[playername] = true
update_weather({ [playername] = true })
if weather.is_enabled() then
update_weather({ player })
end
end)
minetest.register_on_leaveplayer(function(player)
local playername = player:get_player_name()
playerset[playername] = nil
end)
-- Define API functions
local is_enabled = true
weather.is_enabled = function()
return settings_enabled and is_enabled
end
weather.set_enabled = function(enable)
if enable and not is_enabled then
-- restart stopped update cycle
cyclic_update()
elseif not enable and is_enabled then
-- stop update cycle and remove effects
purge_effects()
end
is_enabled = enable
end
weather.on_update = function(player, overrides)
return overrides
end
-- End API definition