Add arena status HUD + get_players_in_hub() util

master
Zughy 2022-06-26 18:14:32 +00:00
parent 1206232e98
commit 7f2e288f05
9 changed files with 375 additions and 3 deletions

View File

@ -23,3 +23,5 @@ hub_manager.settings.physics = {
sneak_glitch=false,
new_move=true
}
hub_manager.settings.MAX_ARENAS_IN_STATUS = 4

View File

@ -11,5 +11,7 @@ dofile(srcpath .. "/chatcmdbuilder.lua")
dofile(srcpath .. "/commands.lua")
dofile(srcpath .. "/items.lua")
dofile(srcpath .. "/player_manager.lua")
dofile(srcpath .. "/deps/arena_lib.lua")
dofile(srcpath .. "/HUD/hud_arenastatus.lua")
minetest.log("action", "[HUB_MANAGER] Mod initialised, running version " .. version)

262
src/HUD/hud_arenastatus.lua Normal file
View File

@ -0,0 +1,262 @@
local function trim_name() end
local arenas = {} -- KEY: sorting ID, VALUE: {mod = mod, mg = mg_name, name = a_name, icon = mg_icon, y_off, bg = {...}, amount = {...}}
local hidden_panels = {} -- KEY: p_name, VALUE: true
local MAX_ARENAS_IN_STATUS = hub_manager.settings.MAX_ARENAS_IN_STATUS
local SLOT_DISTANCE = 52
-- I pannelli si dividono nelle tabelle contenenti le informazioni da mostrare (`arenas`)
-- e nella loro resa grafica vera e propria (panel_lib). Ogni volta che un pannello
-- viene aggiornato, pesca i dati da `arenas`.
-- I pannelli sono gestiti in modo tale che le loro posizioni non si intersechino mai:
-- il pannello più in alto sarà sempre il n°1, quello seguente il n°2 ecc. Se l'arena
-- associata al primo pannello scompare, le informazioni del pannello n°2 passeranno
-- a quest'ultimo e via dicendo, nascondendo quello visibile più in fondo (a meno che
-- il numero di `arenas` non superi il numero di pannelli visibili: in quel caso
-- otterrà le informazioni dal primo non visibile)
function hub_manager.HUD_arstatus_create(p_name)
for i = 1, MAX_ARENAS_IN_STATUS do
local a_data = arenas[i]
local y_off = a_data and a_data.y_off or 0
local bg = a_data and a_data.bg.bg or "blank.png"
local icon = a_data and a_data.icon or "blank.png"
local a_name = a_data and trim_name(a_data.name) or ""
local amount = a_data and a_data.amount.p_amount.text or ""
Panel:new("hubman_arenastatus_" .. i, {
player = p_name,
position = {x = 1, y = 0.5},
offset = {x = 0, y = y_off},
bg = bg,
bg_scale = {x = 3, y = 3},
title = "",
sub_img_elems = {
icon = {
text = icon,
offset = {x = -180}
}
},
sub_txt_elems = {
arena_name = {
text = a_name,
alignment = {x = 1},
offset = {x = -175}
},
p_amount = {
text = amount,
alignment = {x = -1},
offset = {x = -5}
}
}
})
end
end
function hub_manager.HUD_arstatus_add(mod, arena)
local arenas_amnt = #arenas
local y_off
-- calcolo lo scostamento che avrà il pannello. Se sono già visualizzati i pannelli massimi,
-- lo accoderò in basso di un'unità. Al contrario, se questo sarà visibile,
-- sposterò tutti quelli visibili di mezza unità verso l'alto, accodando quello
-- nuovo sempre di mezza unità
if arenas_amnt == 0 then
y_off = 0
else
if arenas_amnt >= MAX_ARENAS_IN_STATUS then
y_off = arenas[arenas_amnt].y_off + SLOT_DISTANCE
else
y_off = arenas[arenas_amnt].y_off + SLOT_DISTANCE / 2
for _, slot in ipairs(arenas) do
slot.y_off = slot.y_off - SLOT_DISTANCE / 2
end
end
end
-- aggiungo l'arena nella tabella
local bg_img = arena.players_amount < arena.max_players and "hubmanager_arenastatus_join.png" or "hubmanager_arenastatus_nojoin.png"
local mg = arena_lib.mods[mod]
local a_info = {
mod = mod,
mg = mg.name,
name = arena.name,
icon = mg.icon or "hubmanager_mg_missing_icon.png",
y_off = y_off,
bg = {bg = bg_img},
amount = { p_amount = { text = arena.players_amount .. "/" .. arena.max_players }}
}
table.insert(arenas, a_info)
-- se supera il numero massimo di slot visibili, la grafica non verrebbe aggiornata ugualmente
if #arenas > MAX_ARENAS_IN_STATUS then return end
for i = 1, #arenas do
hub_manager.HUD_arstatus_update(i)
end
end
function hub_manager.HUD_arstatus_remove(mg_name, arena_name)
-- trovo l'ID dell'arena nell'HUD
local HUD_ID = hub_manager.get_arenastatus_slot(mg_name, arena_name)
table.remove(arenas, HUD_ID)
local arenas_amnt = #arenas
-- scalo la posizione dei pannelli che venivano dopo quello rimosso. Li muovo
-- di mezza unità verso l'alto se quelli visibili cambieranno di numero, o di
-- una intera se erano già al completo (ovvero uguali o maggiori di MAX_ARENAS_IN_STATUS)
local mov_divisor = arenas_amnt < MAX_ARENAS_IN_STATUS and 2 or 1
for i = HUD_ID, arenas_amnt do
arenas[i].y_off = arenas[i].y_off - SLOT_DISTANCE / mov_divisor
end
-- se ora ci sono meno slot di quelli massimi..
if arenas_amnt < MAX_ARENAS_IN_STATUS then
-- aggiorno la posizione degli slot che venivano prima
for i = 1, HUD_ID -1 do
arenas[i].y_off = arenas[i].y_off + SLOT_DISTANCE / 2
end
-- e faccio sparire l'ultimo
for pl_name in pairs(hub_manager.get_players_in_hub()) do
local panel = panel_lib.get_panel(pl_name, "hubman_arenastatus_" .. arenas_amnt + 1)
if panel.visible then
panel:hide()
end
end
end
-- se l'HUD già non appariva o se era l'unica rimasta, fermati qua
if HUD_ID > MAX_ARENAS_IN_STATUS or arenas_amnt == 0 then return end
-- se lo slot rimosso era visibile, aggiorno la posizione di tutti quelli visibili
for i = 1, arenas_amnt do
hub_manager.HUD_arstatus_update(i)
end
end
function hub_manager.HUD_arstatus_update(slot_ID, skip_mgarena, skip_pos, skip_status, skip_amount)
local slot = arenas[slot_ID]
local elem = {}
local subtxt_elems = {}
local icon = nil
local status = nil
if not skip_mgarena then
icon = { icon = { text = slot.icon }}
subtxt_elems.arena_name = { text = trim_name(slot.name) }
end
if not skip_pos then
elem.offset = { x = 0, y = slot.y_off }
end
local _, arena = arena_lib.get_arena_by_name(slot.mod, slot.name)
if not skip_status then
local bg_img = ""
if not arena.in_loading and not arena.in_celebration and
arena.players_amount < arena.max_players and
(arena.in_queue or (arena.in_game and arena_lib.mods[slot.mod].join_while_in_progress)) then
bg_img = "hubmanager_arenastatus_join.png"
else
bg_img = "hubmanager_arenastatus_nojoin.png"
end
elem.bg = bg_img
end
if not skip_amount then
subtxt_elems.p_amount = { text = arena.players_amount .. "/" .. arena.max_players }
end
-- se non c'è nessun elemento/sottoelemento da aggiornare, faccio sparire
if not next(elem) then
elem = nil
end
if not next(subtxt_elems) then
subtxt_elems = nil
end
for pl_name in pairs(hub_manager.get_players_in_hub()) do
local panel = panel_lib.get_panel(pl_name, "hubman_arenastatus_" .. slot_ID)
panel:update(elem, icon, subtxt_elems)
-- se non era visibile e l'opzione per non vederlo non era abilitata, mostralo
if not panel:is_visible() and not hidden_panels[p_name] then
panel:show()
end
end
end
function hub_manager.HUD_arstatus_show(p_name)
if not hidden_panels[p_name] then return end
for i = 1, MAX_ARENAS_IN_STATUS do
local panel = panel_lib.get_panel(p_name, "hubman_arenastatus_" .. i)
panel:show()
end
hidden_panels[p_name] = nil
end
function hub_manager.HUD_arstatus_hide(p_name)
if hidden_panels[p_name] then return end
for i = 1, MAX_ARENAS_IN_STATUS do
local panel = panel_lib.get_panel(p_name, "hubman_arenastatus_" .. i)
panel:hide()
end
hidden_panels[p_name] = true
end
function hub_manager.get_arenastatus_slot(mg_name, arena_name)
for i = 1, #arenas do
if arenas[i].name == arena_name and arenas[i].mg == mg_name then
return i
end
end
end
----------------------------------------------
---------------FUNZIONI LOCALI----------------
----------------------------------------------
function trim_name(name)
if name:len() > 15 then
return name:sub(1, 13) .. "..."
else
return name
end
end

View File

@ -29,6 +29,23 @@ end
function hub_manager.get_players_in_hub()
local in_hub = {}
local in_game = arena_lib.get_players_in_game()
for _, pl in pairs(minetest.get_connected_players()) do
local pl_name = pl:get_player_name()
if not in_game[pl_name] then
in_hub[pl_name] = true
end
end
return in_hub
end
----------------------------------------------

91
src/deps/arena_lib.lua Normal file
View File

@ -0,0 +1,91 @@
arena_lib.register_on_join_queue(function(mg, arena, p_name, has_status_changed)
if has_status_changed then
local mod = arena_lib.get_mod_by_player(p_name)
hub_manager.HUD_arstatus_add(mod, arena)
elseif arena.in_queue then
local slot_ID = hub_manager.get_arenastatus_slot(mg.name, arena.name)
local skip_status = arena.players_amount == arena.max_players and true or false
hub_manager.HUD_arstatus_update(slot_ID, true, true, skip_status)
end
end)
arena_lib.register_on_leave_queue(function(mg, arena, p_name, has_status_changed)
if has_status_changed then
hub_manager.HUD_arstatus_remove(mg.name, arena.name)
elseif arena.in_queue then
local slot_ID = hub_manager.get_arenastatus_slot(mg.name, arena.name)
local skip_status = arena.players_amount < arena.max_players and true or false
hub_manager.HUD_arstatus_update(slot_ID, true, true, skip_status)
end
end)
arena_lib.register_on_load(function(mg, arena)
local mg_name = mg.name
local slot_ID = hub_manager.get_arenastatus_slot(mg_name, arena.name)
hub_manager.HUD_arstatus_update(slot_ID, true, true, false, true)
if slot_ID > hub_manager.settings.MAX_ARENAS_IN_STATUS then return end
for pl_name in pairs(arena.players) do
hub_manager.HUD_arstatus_hide(pl_name)
end
end)
arena_lib.register_on_start(function(mg, arena)
if not mg.join_while_in_progress or arena.players_amount == arena.max_players then return end
local slot_ID = hub_manager.get_arenastatus_slot(mg.name, arena.name)
hub_manager.HUD_arstatus_update(slot_ID, true, true, false, true)
end)
arena_lib.register_on_join(function(mg, arena, p_name, as_spectator)
local slot_ID = hub_manager.get_arenastatus_slot(mg.name, arena.name)
hub_manager.HUD_arstatus_hide(p_name)
hub_manager.HUD_arstatus_update(slot_ID)
end)
arena_lib.register_on_quit(function(mg, arena, p_name, is_spectator, reason)
local mg_name = mg.name
local slot_ID = hub_manager.get_arenastatus_slot(mg.name, arena.name)
-- se mostro e aggiorno al tempo stesso, non funziona. Da qui l'attesa di 0.1s
minetest.after(0.1, function()
hub_manager.HUD_arstatus_update(slot_ID)
end)
if reason == 0 then return end
hub_manager.HUD_arstatus_show(p_name)
end)
arena_lib.register_on_end(function(mg, arena, players, winners, spectators, is_forced)
for pl_name in pairs(players) do
hub_manager.HUD_arstatus_show(pl_name)
end
for sp_name in pairs(spectators) do
hub_manager.HUD_arstatus_show(sp_name)
end
-- se mostro E aggiorno al tempo stesso, non funziona. Da qui l'attesa di 0.1s
minetest.after(0.1, function()
hub_manager.HUD_arstatus_remove(mg.name, arena.name)
end)
end)

View File

@ -6,7 +6,7 @@ minetest.register_on_joinplayer(function(player)
hub_manager.set_items(player)
hub_manager.set_hub_physics(player)
hub_manager.HUD_arstatus_create(player:get_player_name())
end)
@ -21,7 +21,6 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason)
end
return hp_change
end, true)
@ -32,5 +31,4 @@ minetest.register_on_respawnplayer(function(player)
player:set_pos(hub_manager.get_hub_spawn_point())
return true
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B