mirror of
https://github.com/minetest/minetest_game.git
synced 2024-11-15 22:40:19 +01:00
Redesign API for more flexible usage
This commit is contained in:
parent
a3f703da3e
commit
5c51eecd7f
33
game_api.txt
33
game_api.txt
|
@ -1147,3 +1147,36 @@ the log.
|
|||
that log corresponding actions
|
||||
* `def` See [Node definition]
|
||||
* `name` Description of the node in the log message
|
||||
|
||||
|
||||
Weather API
|
||||
-------
|
||||
|
||||
The weather API allows you to enable / disable weather effects programmatically
|
||||
and also to modify weather effects before they are applied to the player.
|
||||
|
||||
`weather.is_enabled()`
|
||||
|
||||
* Returns true if weather mod is enabled or false if disabled
|
||||
* Will return false regardless of whether the mod has been disabled via the settings or via `set_enabled`.
|
||||
* Will return true even if selected worldgen doesn't support cloud updates. This is the case for v6 and singlenode types.
|
||||
|
||||
`weather.set_enabled(enable)`
|
||||
|
||||
* `enable` Boolean. Set to `true` to enable weather globally or `false` to disable it.
|
||||
* Setting this to `false` is only advised if you want to disable the weather effects __permanently__ and for every player.
|
||||
Re-enabling effects later on will work but might conflict with other mods doing the same.
|
||||
Override `weather.on_update` if you want to disable temporarily or need a higher level of control.
|
||||
* If the `enable_weather` setting is set to `false` in minetest.conf then this function will __not__ do nothing.
|
||||
|
||||
`weather.on_update(player, overrides)`
|
||||
|
||||
* Override this function to manipulate weather effects before they are applied to the player.
|
||||
* Calling this function on its own will do nothing. You have to override it in order to modify its behavior.
|
||||
* `player` The player entity that is about to be updated
|
||||
* `overrides` Defines which changes are about to be made. It is a table consisting of the following values:
|
||||
* `overrides.clouds` A table (or `nil`) with cloud data following the same format as used for `player:set_clouds()`.
|
||||
* `overrides.lighting` A table (or `nil`) with lighting data following the same format as used for `player:set_lighting()`.
|
||||
* This function is expected to return a table in the same format as `overrides`.
|
||||
When overriding this function, the return value will be applied to the player instead of the original values.
|
||||
Setting `clouds` or `lighting` to `nil` will __prevent__ that table from getting updated.
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user