diff --git a/SETTINGS.lua b/SETTINGS.lua index 7e8344b..a1e64cc 100644 --- a/SETTINGS.lua +++ b/SETTINGS.lua @@ -23,3 +23,5 @@ hub_manager.settings.physics = { sneak_glitch=false, new_move=true } + +hub_manager.settings.MAX_ARENAS_IN_STATUS = 4 diff --git a/init.lua b/init.lua index 48e39ec..d4bade1 100644 --- a/init.lua +++ b/init.lua @@ -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) diff --git a/src/HUD/hud_arenastatus.lua b/src/HUD/hud_arenastatus.lua new file mode 100644 index 0000000..956cdc7 --- /dev/null +++ b/src/HUD/hud_arenastatus.lua @@ -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 diff --git a/src/api.lua b/src/api.lua index 2596571..c89dd33 100644 --- a/src/api.lua +++ b/src/api.lua @@ -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 + + + ---------------------------------------------- diff --git a/src/deps/arena_lib.lua b/src/deps/arena_lib.lua new file mode 100644 index 0000000..bdf9051 --- /dev/null +++ b/src/deps/arena_lib.lua @@ -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) diff --git a/src/player_manager.lua b/src/player_manager.lua index dc47dc2..307fa6c 100644 --- a/src/player_manager.lua +++ b/src/player_manager.lua @@ -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) diff --git a/textures/hubmanager_arenastatus_join.png b/textures/hubmanager_arenastatus_join.png new file mode 100644 index 0000000..85d4a5f Binary files /dev/null and b/textures/hubmanager_arenastatus_join.png differ diff --git a/textures/hubmanager_arenastatus_nojoin.png b/textures/hubmanager_arenastatus_nojoin.png new file mode 100644 index 0000000..db64699 Binary files /dev/null and b/textures/hubmanager_arenastatus_nojoin.png differ diff --git a/textures/hubmanager_mg_missing_icon.png b/textures/hubmanager_mg_missing_icon.png new file mode 100644 index 0000000..bf398bf Binary files /dev/null and b/textures/hubmanager_mg_missing_icon.png differ