EinsDreiDreiSieben/mods/futil/minetest/hud_manager.lua

172 lines
4.3 KiB
Lua

--[[
local my_hud = futil.define_hud("my_mod:my_hud", {
period = 1,
catchup = nil, -- not currently supported
name_field = nil, -- in case you want to override the id field
enabled_by_default = nil, -- set to true to enable by default
get_hud_data = function()
-- get data that's identical for all players
-- passed to get_hud_def
end,
get_hud_def = function(player, data)
return {}
end,
})
my_hud:toggle_enabled(player)
]]
local f = string.format
local ManagedHud = futil.class1()
function ManagedHud:_init(hud_name, def)
self.name = hud_name
self._name_field = def.name_field or ((def.type or def.hud_elem_type) == "waypoint" and "text2" or "name")
self._period = def.period
self._get_hud_data = def.get_hud_data
self._get_hud_def = def.get_hud_def
self._enabled_by_default = def.enabled_by_default
self._hud_id_by_player_name = {}
self._hud_enabled_key = f("hud_manager:%s_enabled", hud_name)
self._hud_name = f("hud_manager:%s", hud_name)
end
function ManagedHud:is_enabled(player)
local meta = player:get_meta()
local value = meta:get(self._hud_enabled_key)
if value == nil then
return self._enabled_by_default
else
return minetest.is_yes(value)
end
end
function ManagedHud:set_enabled(player, value)
local meta = player:get_meta()
if minetest.is_yes(value) then
meta:set_string(self._hud_enabled_key, "y")
else
meta:set_string(self._hud_enabled_key, "n")
end
end
function ManagedHud:toggle_enabled(player)
local meta = player:get_meta()
local enabled = not self:is_enabled(player)
if enabled then
meta:set_string(self._hud_enabled_key, "y")
else
meta:set_string(self._hud_enabled_key, "n")
end
return enabled
end
function ManagedHud:update(player, data)
local is_enabled = self:is_enabled(player)
local player_name = player:get_player_name()
local hud_id = self._hud_id_by_player_name[player_name]
local old_hud_def
if hud_id then
old_hud_def = player:hud_get(hud_id)
if old_hud_def and old_hud_def[self._name_field] == self._hud_name then
if not is_enabled then
player:hud_remove(hud_id)
self._hud_id_by_player_name[player_name] = nil
return
end
else
-- hud_id is bad
hud_id = nil
old_hud_def = nil
end
end
if is_enabled then
local new_hud_def = self._get_hud_def(player, data)
if not new_hud_def then
if hud_id then
player:hud_remove(hud_id)
self._hud_id_by_player_name[player_name] = nil
end
return
elseif new_hud_def[self._name_field] and new_hud_def[self._name_field] ~= self._hud_name then
error(f("you cannot specify the value of the %q field, this is generated", self._name_field))
end
if old_hud_def then
for k, v in pairs(new_hud_def) do
if k == "position" or k == "scale" or k == "align" or k == "offset" then
v = futil.vector.v2f_to_float_32(v)
end
if not futil.equals(old_hud_def[k], v) and k ~= "type" and k ~= "hud_elem_type" then
player:hud_change(hud_id, k, v)
end
end
else
new_hud_def[self._name_field] = self._hud_name
hud_id = player:hud_add(new_hud_def)
end
end
self._hud_id_by_player_name[player_name] = hud_id
end
futil.defined_huds = {}
function futil.define_hud(hud_name, def)
if futil.defined_huds[hud_name] then
error(f("hud %s already exists", hud_name))
end
local hud = ManagedHud(hud_name, def)
futil.defined_huds[hud_name] = hud
return hud
end
-- TODO: register_hud instead of define_hud, plus alias the old
local function update_hud(hud, players)
local data
if hud._get_hud_data then
local is_any_enabled = false
for i = 1, #players do
if hud:is_enabled(players[i]) then
is_any_enabled = true
break
end
end
if is_any_enabled then
data = hud._get_hud_data()
end
end
for i = 1, #players do
hud:update(players[i], data)
end
end
-- TODO refactor to use futil.register_globalstep for each hud, to allow use of catchup mechanics
-- ... why would HUD updates need catchup mechanics?
local elapsed_by_hud_name = {}
minetest.register_globalstep(function(dtime)
local players = minetest.get_connected_players()
if #players == 0 then
return
end
for hud_name, hud in pairs(futil.defined_huds) do
if hud._period then
local elapsed = (elapsed_by_hud_name[hud_name] or 0) + dtime
if elapsed < hud._period then
elapsed_by_hud_name[hud_name] = elapsed
else
elapsed_by_hud_name[hud_name] = 0
update_hud(hud, players)
end
else
update_hud(hud, players)
end
end
end)