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

View File

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

View File

@ -1,28 +1,44 @@
-- cache setting -- cache setting
local enable_damage = core.settings:get_bool("enable_damage") 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 = { local health_bar_definition = {
hud_elem_type = "statbar", hud_elem_type = "statbar",
position = {x = 0.5, y = 1}, position = {x = 0.5, y = 1},
offset = {x = -247, y = -94}, text = "heart.png",
size = {x = 24, y = 24}, text2 = "heart_gone.png",
text = "heart.png", number = core.PLAYER_MAX_HP_DEFAULT,
background = "heart_gone.png", item = core.PLAYER_MAX_HP_DEFAULT,
number = 20 direction = 0,
size = {x = 24, y = 24},
offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)},
} }
local breath_bar_definition = { local breath_bar_definition = {
hud_elem_type = "statbar", hud_elem_type = "statbar",
position = {x = 0.5, y = 1}, position = {x = 0.5, y = 1},
offset = {x = 8, y = -120}, text = "bubble.png",
size = {x = 24, y = 24}, text2 = "bubble_gone.png",
text = "bubble.png", number = core.PLAYER_MAX_BREATH_DEFAULT,
number = 20 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 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 function update_builtin_statbars(player)
local name = player:get_player_name() 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 -- our current flags are transmitted by sending them actively
player:hud_set_flags(flags) player:hud_set_flags(flags)
end end
local hud_id = hud_ids[name] local hud = hud_ids[name]
if flags.healthbar and not disable_health then if flags.healthbar and enable_damage then
hud.change_item(player, "health", {number = player:get_hp()}) local number = scaleToDefault(player, "hp")
end if hud.id_healthbar == nil then
local hud_def = tcopy(health_bar_definition)
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)
hud_def.number = number hud_def.number = number
hud_id.id_breathbar = player:hud_add(hud_def) hud.id_healthbar = player:hud_add(hud_def)
else 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 end
elseif hud_id.id_breathbar then
player:hud_remove(hud_id.id_breathbar) local show_breathbar = flags.breathbar and enable_damage
hud_id.id_breathbar = nil
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
end end
@ -73,7 +110,7 @@ local function player_event_handler(player,eventname)
local name = player:get_player_name() local name = player:get_player_name()
if name == "" then if name == "" or not hud_ids[name] then
return return
end end
@ -102,16 +139,25 @@ local function player_event_handler(player,eventname)
end end
function core.hud_replace_builtin(hud_name, definition) function core.hud_replace_builtin(hud_name, definition)
if hud_name == "health" then
disable_health = true
return true
end
if type(definition) ~= "table" or if type(definition) ~= "table" or
definition.hud_elem_type ~= "statbar" then definition.hud_elem_type ~= "statbar" then
return false return false
end 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 if hud_name == "breath" then
breath_bar_definition = definition breath_bar_definition = definition
@ -131,13 +177,8 @@ end
-- Append "update_builtin_statbars" as late as possible -- Append "update_builtin_statbars" as late as possible
-- This ensures that the HUD is hidden when the flags are updated in this callback -- 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()
core.register_on_mods_loaded(function() core.register_on_joinplayer(update_builtin_statbars)
if not disable_health then end)
hud.register("health", health_bar_definition) core.register_on_leaveplayer(cleanup_builtin_statbars)
core.register_on_joinplayer(update_builtin_statbars) core.register_playerevent(player_event_handler)
end
end)
core.register_on_leaveplayer(cleanup_builtin_statbars)
core.register_playerevent(player_event_handler)
end