HUD: use the HUD API directly (#92)

Co-authored-by: luk3yx <luk3yx@users.noreply.github.com>
master
Maksym H 2022-08-29 21:20:56 +03:00 committed by GitHub
parent 7624c29d96
commit 6e76ef4320
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 134 additions and 233 deletions

View File

@ -1,167 +0,0 @@
--[[
From Better HUD mod
Copyright (C) BlockMen (2013-2016)
Copyright (C) MultiCraft Development Team (2019-2020)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3.0 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
]]
hud, hud_id = {}, {}
local items, sb_bg = {}, {}
local function throw_error(msg)
core.log("error", "HUD: " .. msg)
end
--
-- API
--
function hud.register(name, def)
if not name or not def then
throw_error("Not enough parameters given")
return false
end
if items[name] then
throw_error("A statbar with name " .. name .. " already exists")
return false
end
-- actually register
-- add background first since draworder is based on id
if def.hud_elem_type == "statbar" and def.background then
sb_bg[name] = table.copy(def)
sb_bg[name].text = def.background
if not def.autohide_bg and def.max then
sb_bg[name].number = def.max
end
end
-- add item itself
items[name] = def
return true
end
function hud.change_item(player, name, def)
if not player or not player:is_player() then
return false
end
if not name or not def then
throw_error("Not enough parameters given")
return false
end
local i_name = player:get_player_name() .. "_" .. name
local elem = hud_id[i_name]
local item = items[name]
if not elem then
-- throw_error("Given HUD element " .. dump(name) .. " does not exist")
return false
end
if def.number then
if item.hud_elem_type ~= "statbar" then
throw_error("Attempted to change an statbar HUD parameter for text HUD element " .. dump(name))
return false
end
if item.max and def.number > item.max then
def.number = item.max
end
player:hud_change(elem.id, "number", def.number)
-- hide background when set
if item.autohide_bg then
local bg = hud_id[i_name .. "_bg"]
if not bg then
throw_error("Given HUD element " .. dump(name) .. "_bg does not exist")
return false
end
local num = def.number ~= 0 and (item.max or item.number) or 0
player:hud_change(bg.id, "number", num)
end
elseif def.text then
player:hud_change(elem.id, "text", def.text)
elseif def.offset then
player:hud_change(elem.id, "offset", def.offset)
end
return true
end
function hud.remove_item(player, name)
if not player or not player:is_player() then
return false
end
if not name then
throw_error("Not enough parameters given")
return false
end
local i_name = player:get_player_name() .. "_" .. name
local elem = hud_id[i_name]
if not elem then
throw_error("Given HUD element " .. dump(name) .. " does not exist")
return false
end
player:hud_remove(elem.id)
return true
end
--
-- Add registered HUD items to joining players
--
-- Following code is placed here to keep HUD ids internal
local function add_hud_item(player, name, def)
if not player or not name or not def then
throw_error("Not enough parameters given")
return false
end
local i_name = player:get_player_name() .. "_" .. name
hud_id[i_name] = {}
hud_id[i_name].id = player:hud_add(def)
end
core.register_on_joinplayer(function(player)
-- add the backgrounds for statbars
for name, item in pairs(sb_bg) do
add_hud_item(player, name .. "_bg", item)
end
-- and finally the actual HUD items
for name, item in pairs(items) do
add_hud_item(player, name, item)
end
end)
core.register_on_leaveplayer(function(player)
local player_name = player:get_player_name()
for name, _ in pairs(sb_bg) do
sb_bg[player_name .. "_" .. name] = nil
end
for name, _ in pairs(items) do
hud_id[player_name .. "_" .. name] = nil
end
end)

View File

@ -25,7 +25,9 @@ or not core.settings:get_bool("enable_hunger") then
return
end
hunger = {}
hunger = {
hud = {}
}
local function get_setting(key, default)
local setting = core.settings:get("hunger." .. key)
@ -57,6 +59,7 @@ local settings = hunger.settings
local min, max = math.min, math.max
local vlength = vector.length
local tcopy = table.copy
local attribute = {
saturation = "hunger:level",
@ -83,9 +86,18 @@ function hunger.get_saturation(player)
return tonumber(player:get_meta():get_string(attribute.saturation))
end
function hunger.set_hud_level(player, level)
if not is_player(player) then
return
end
local hud = hunger.hud[player:get_player_name()]
player:hud_change(hud, "number", min(settings.visual_max, level))
end
function hunger.set_saturation(player, level)
player:get_meta():set_int(attribute.saturation, level)
hud.change_item(player, "hunger", {number = min(settings.visual_max, level)})
hunger.set_hud_level(player, level)
end
hunger.registered_on_update_saturations = {}
@ -145,14 +157,23 @@ function hunger.is_poisoned(player)
return poisoned and poisoned == "yes"
end
function hunger.set_hud_poisoned(player, poisoned)
if not is_player(player) then
return
end
local hud = hunger.hud[player:get_player_name()]
local texture = poisoned and "hunger_poisen.png" or "hunger.png"
player:hud_change(hud, "text", texture)
end
function hunger.set_poisoned(player, poisoned)
if not is_player(player) then
return
end
local texture = poisoned and "hunger_poisen.png" or "hunger.png"
hunger.set_hud_poisoned(player, poisoned)
local attr = poisoned and "yes" or "no"
hud.change_item(player, "hunger", {text = texture})
player:get_meta():set_string(attribute.poisoned, attr)
end
@ -298,9 +319,9 @@ local function health_tick()
player:set_hp(hp + settings.heal)
elseif is_starving then
player:set_hp(hp - settings.starve)
hud.change_item(player, "hunger", {number = 0})
hunger.set_hud_level(player, 0)
core.after(0.5, function()
hud.change_item(player, "hunger", {number = min(settings.visual_max, saturation)})
hunger.set_hud_level(player, min(settings.visual_max, saturation))
end)
end
end
@ -341,30 +362,37 @@ function hunger.item_eat(hp_change, user, poison)
end
end
hud.register("hunger", {
hunger.bar_definition = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
offset = {x = 8, y = -94},
size = {x = 24, y = 24},
text = "hunger.png",
background = "hunger_gone.png",
number = settings.visual_max
})
position = {x = 0.5, y = 1},
text = "hunger.png",
text2 = "hunger_gone.png",
number = settings.visual_max,
item = settings.visual_max,
size = {x = 24, y = 24},
offset = {x = -265, y = -126}
}
core.register_on_joinplayer(function(player)
local level = hunger.get_saturation(player) or settings.level_max
local level = hunger.get_saturation(player)
if not level then
level = settings.level_max
player:get_meta():set_int(attribute.saturation, level)
end
-- add HUD
if hunger.bar_definition then
local def = tcopy(hunger.bar_definition)
def.number = min(settings.visual_max, level)
hunger.hud[player:get_player_name()] = player:hud_add(def)
end
-- reset poisoned
hunger.set_poisoned(player, false)
-- set saturation
player:get_meta():set_int(attribute.saturation, level)
end)
-- we must manually update the HUD
if level < settings.visual_max then
core.after(1, function()
hud.change_item(player, "hunger", {number = min(settings.visual_max, level)})
end)
end
core.register_on_leaveplayer(function(player)
hunger.hud[player:get_player_name()] = nil
end)
local exhaust = hunger.exhaust_player

View File

@ -31,7 +31,6 @@ assert(loadfile(gamepath .. "falling.lua"))(builtin_shared)
dofile(gamepath .. "features.lua")
dofile(gamepath .. "voxelarea.lua")
dofile(gamepath .. "forceloading.lua")
dofile(gamepath .. "hud.lua")
dofile(gamepath .. "statbars.lua")
dofile(gamepath .. "knockback.lua")
dofile(gamepath .. "hunger.lua")

View File

@ -1,28 +1,44 @@
-- cache setting
local enable_damage = core.settings:get_bool("enable_damage")
local disable_health = false
local max = math.max
local tcopy = table.copy
local health_bar_definition = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
offset = {x = -247, y = -94},
size = {x = 24, y = 24},
text = "heart.png",
background = "heart_gone.png",
number = 20
position = {x = 0.5, y = 1},
text = "heart.png",
text2 = "heart_gone.png",
number = core.PLAYER_MAX_HP_DEFAULT,
item = core.PLAYER_MAX_HP_DEFAULT,
direction = 0,
size = {x = 24, y = 24},
offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)},
}
local breath_bar_definition = {
hud_elem_type = "statbar",
position = {x = 0.5, y = 1},
offset = {x = 8, y = -120},
size = {x = 24, y = 24},
text = "bubble.png",
number = 20
position = {x = 0.5, y = 1},
text = "bubble.png",
text2 = "bubble_gone.png",
number = core.PLAYER_MAX_BREATH_DEFAULT,
item = core.PLAYER_MAX_BREATH_DEFAULT * 2,
direction = 0,
size = {x = 24, y = 24},
offset = {x = 25, y= -(48 + 24 + 16)},
}
local hud_ids = {}
local function scaleToDefault(player, field)
-- Scale "hp" or "breath" to the default dimensions
local current = player["get_" .. field](player)
local nominal = core["PLAYER_MAX_" .. field:upper() .. "_DEFAULT"]
local max_display = max(nominal,
max(player:get_properties()[field .. "_max"], current))
return current / max_display * nominal
end
local function update_builtin_statbars(player)
local name = player:get_player_name()
@ -37,24 +53,45 @@ local function update_builtin_statbars(player)
-- our current flags are transmitted by sending them actively
player:hud_set_flags(flags)
end
local hud_id = hud_ids[name]
local hud = hud_ids[name]
if flags.healthbar and not disable_health then
hud.change_item(player, "health", {number = player:get_hp()})
end
if flags.breathbar and player:get_breath() < 10 then
local number = player:get_breath() * 2
if hud_id.id_breathbar == nil then
local hud_def = table.copy(breath_bar_definition)
if flags.healthbar and enable_damage then
local number = scaleToDefault(player, "hp")
if hud.id_healthbar == nil then
local hud_def = tcopy(health_bar_definition)
hud_def.number = number
hud_id.id_breathbar = player:hud_add(hud_def)
hud.id_healthbar = player:hud_add(hud_def)
else
player:hud_change(hud_id.id_breathbar, "number", number)
player:hud_change(hud.id_healthbar, "number", number)
end
elseif hud.id_healthbar then
player:hud_remove(hud.id_healthbar)
hud.id_healthbar = nil
end
elseif hud_id.id_breathbar then
player:hud_remove(hud_id.id_breathbar)
hud_id.id_breathbar = nil
local show_breathbar = flags.breathbar and enable_damage
local breath = player:get_breath()
local breath_max = player:get_properties().breath_max
if show_breathbar and breath <= breath_max then
local number = 2 * scaleToDefault(player, "breath")
if not hud.id_breathbar and breath < breath_max then
local hud_def = tcopy(breath_bar_definition)
hud_def.number = number
hud.id_breathbar = player:hud_add(hud_def)
elseif hud.id_breathbar then
player:hud_change(hud.id_breathbar, "number", number)
end
end
if hud.id_breathbar and (not show_breathbar or breath == breath_max) then
core.after(1, function(player_name, breath_bar)
local player = core.get_player_by_name(player_name)
if player then
player:hud_remove(breath_bar)
end
end, name, hud.id_breathbar)
hud.id_breathbar = nil
end
end
@ -73,7 +110,7 @@ local function player_event_handler(player,eventname)
local name = player:get_player_name()
if name == "" then
if name == "" or not hud_ids[name] then
return
end
@ -102,16 +139,25 @@ local function player_event_handler(player,eventname)
end
function core.hud_replace_builtin(hud_name, definition)
if hud_name == "health" then
disable_health = true
return true
end
if type(definition) ~= "table" or
definition.hud_elem_type ~= "statbar" then
return false
end
if hud_name == "health" then
health_bar_definition = definition
for name, ids in pairs(hud_ids) do
local player = core.get_player_by_name(name)
if player and ids.id_healthbar then
player:hud_remove(ids.id_healthbar)
ids.id_healthbar = nil
update_builtin_statbars(player)
end
end
return true
end
if hud_name == "breath" then
breath_bar_definition = definition
@ -131,13 +177,8 @@ end
-- Append "update_builtin_statbars" as late as possible
-- This ensures that the HUD is hidden when the flags are updated in this callback
if enable_damage then
core.register_on_mods_loaded(function()
if not disable_health then
hud.register("health", health_bar_definition)
core.register_on_joinplayer(update_builtin_statbars)
end
end)
core.register_on_leaveplayer(cleanup_builtin_statbars)
core.register_playerevent(player_event_handler)
end
core.register_on_mods_loaded(function()
core.register_on_joinplayer(update_builtin_statbars)
end)
core.register_on_leaveplayer(cleanup_builtin_statbars)
core.register_playerevent(player_event_handler)