From ec5e46c0e2e4c9efc91c77ff7993ce764face54a Mon Sep 17 00:00:00 2001 From: Zughy <4279489-marco_a@users.noreply.gitlab.com> Date: Sun, 5 Jun 2022 12:20:28 +0000 Subject: [PATCH] Separate queuing system from signs (check description) * adds `arena_lib.join_queue(mod, arena, p_name)` * adds `arena_lib.get_players_amount_left_to_start_queue(arena)` * `arena_lib.remove_player_from_queue(p_name)` now returns `true` if successful --- DOCS.md | 4 +- init.lua | 1 + locale/arena_lib.it.tr | 13 +- locale/template.txt | 13 +- src/api/in_game.lua | 108 +--------- src/api/in_queue.lua | 434 +++++++++++++++++++++++++++++++++++++++++ src/signs.lua | 310 ++--------------------------- 7 files changed, 481 insertions(+), 402 deletions(-) create mode 100644 src/api/in_queue.lua diff --git a/DOCS.md b/DOCS.md index 38f79ff..cc3ffdd 100644 --- a/DOCS.md +++ b/DOCS.md @@ -229,7 +229,8 @@ There are also some other functions which might turn useful. They are: * `arena_lib.is_player_in_same_team(arena, p_name, t_name)`: compares two players teams by the players names. Returns true if on the same team, false if not * `arena_lib.is_team_declared(mod_ref, team_name)`: returns true if there is a team called `team_name`. Otherwise it returns false * `arena_lib.force_arena_ending(mod, arena, )`: forcibly ends an ongoing game. It's usually called by `/forceend`, but it can be used, for instance, to annul a game. `sender` will inform players about who called the function. It returns `true` if successfully executed -* `arena_lib.remove_player_from_queue(p_name)`: removes the player from the queue is in, if any +* `arena_lib.join_queue(mod, arena, p_name)`: adds `p_name` to the queue of `arena`. Returns `true` if successful. If the player is already in a different queue, they'll be removed from the one they're currently in and automatically added to the new one +* `arena_lib.remove_player_from_queue(p_name)`: removes the player from the queue is in, if any. Returns `true` if successful * `arena_lib.remove_player_from_arena(p_name, reason, )`: removes the player from the arena and it brings back the player to the lobby if still online. Reason is an int, and it equals to... * `0`: player disconnected. Calls `on_disconnect` * `1`: player eliminated. Calls `on_eliminate` if declared. Otherwise calls `on_quit` @@ -257,6 +258,7 @@ Executioner can be passed to tell who removed the player. By default, this happe * `arena_lib.get_queueID_by_player(p_name)`: returns the ID of the arena the player's queueing for * `arena_lib.get_arena_spawners_count(arena, )`: returns the total amount of spawners declared in the specified arena. If team_ID is specified, it only counts the ones belonging to that team * `arena_lib.get_random_spawner(arena, )`: returns a random spawner declared in the specified arena. If team_ID is specified, it only considers the ones belonging to that team +* `arena_lib.get_players_amount_left_to_start_queue(arena)`: returns the amount of player still needed to make a queue start, or `nil` if the arena is already in game * `arena_lib.get_players_in_game()`: returns all the players playing in whatever arena of whatever minigame * `arena_lib.get_players_in_minigame(mod, )`: returns a table containing as index either the names of all the players inside the specified minigame (`mod`) or, if `to_player` is `true`, the players themselves * `arena_lib.get_players_in_team(arena, team_ID, )`: returns a table containing as index either the names of the players inside the specified team or, if `to_player` is `true`, the players themselves diff --git a/init.lua b/init.lua index 4d0f9d4..066d5c1 100755 --- a/init.lua +++ b/init.lua @@ -4,6 +4,7 @@ local srcpath = modpath .. "/src" dofile(srcpath .. "/api/core.lua") dofile(srcpath .. "/api/in_game.lua") +dofile(srcpath .. "/api/in_queue.lua") dofile(srcpath .. "/api/misc.lua") dofile(srcpath .. "/api/teams.lua") dofile(srcpath .. "/callbacks.lua") diff --git a/locale/arena_lib.it.tr b/locale/arena_lib.it.tr index 6f7b24c..482a7db 100755 --- a/locale/arena_lib.it.tr +++ b/locale/arena_lib.it.tr @@ -138,8 +138,14 @@ Overwrite=Sovrascrivi # signs.lua Arena sign=Cartello dell'arena -[!] You must leave the editor first!=[!] Devi prima uscire dall'editor! [!] Uh-oh, it looks like this sign has been misplaced: well, fixed, hit it again!==[!]Oh oh, sembra che questo cartello sia fuori posto: beh, sistemato, colpiscilo di nuovo! + +# utils.lua +[!] You must disable the arena first!=[!] Devi prima disabilitare l'arena! +[!] There must be no one inside the editor of the arena to perform this command! (now inside: @1)=[!] Non deve esserci nessuno nell'editor dell'arena per poter eseguire questo comando! (attualmente dentro: @1) + +# api/in_queue.lua +[!] You must leave the editor first!=[!] Devi prima uscire dall'editor! [!] Only the party leader can enter the queue!=[!] Solo il capo gruppo può entrare nella coda! [!] You must wait for all your party members to finish their ongoing games before entering a new one!=[!] Devi aspettare che i membri della tua squadra terminino le loro partite in corso prima di iniziarne una nuova! [!] Can't enter a game if some of your party members are attached to something! (e.g. boats, horses etc.)=[!] Non puoi entrare in partita se alcuni membri del gruppo sono attaccati a qualcosa! (es. navi, cavalli ecc.) @@ -151,6 +157,7 @@ Arena sign=Cartello dell'arena [!] The arena is already full!=[!] L'arena è già piena! [!] The arena is loading, try again in a few seconds!=[!] L'arena è in caricamento, riprova tra qualche secondo! [!] This minigame doesn't allow to join while in progress!=[!] Questo minigioco non permette di entrare a partita iniziata! +[!] You're already queuing for this arena!=[!] Sei già in coda per quest'arena! Waiting for more players...=In attesa di più giocatori... The queue has been cancelled due to not enough players=La coda è stata annullata per troppi pochi giocatori @1 seconds for the match to start=@1 secondi all'inizio @@ -158,10 +165,6 @@ You've joined team @1=Ti sei unito alla squadra @1 Game begins in @1!=La partita inizierà tra @1! Get ready!=Preparati! -# utils.lua -[!] You must disable the arena first!=[!] Devi prima disabilitare l'arena! -[!] There must be no one inside the editor of the arena to perform this command! (now inside: @1)=[!] Non deve esserci nessuno nell'editor dell'arena per poter eseguire questo comando! (attualmente dentro: @1) - # dependencies/parties.lua [!] You can't perform this action while in queue!=[!] Non puoi eseguire quest'azione mentre sei in coda! [!] You can't perform this action while in game!=[!] Non puoi eseguire quest'azione mentre sei in partita! diff --git a/locale/template.txt b/locale/template.txt index a45228b..e604e27 100755 --- a/locale/template.txt +++ b/locale/template.txt @@ -138,8 +138,14 @@ Overwrite= # signs.lua Arena sign= -[!] You must leave the editor first!= [!] Uh-oh, it looks like this sign has been misplaced: well, fixed, hit it again!= + +# utils.lua +[!] You must disable the arena first!= +[!] There must be no one inside the editor of the arena to perform this command! (now inside: @1)= + +# api/in_queue.lua +[!] You must leave the editor first!= [!] Only the party leader can enter the queue!= [!] You must wait for all your party members to finish their ongoing games before entering a new one!= [!] Can't enter a game if some of your party members are attached to something! (e.g. boats, horses etc.)= @@ -151,6 +157,7 @@ Arena sign= [!] The arena is already full!= [!] The arena is loading, try again in a few seconds!= [!] This minigame doesn't allow to join while in progress!= +[!] You're already queuing for this arena!= Waiting for more players...= The queue has been cancelled due to not enough players= @1 seconds for the match to start= @@ -158,10 +165,6 @@ You've joined team @1= Game begins in @1!= Get ready!= -# utils.lua -[!] You must disable the arena first!= -[!] There must be no one inside the editor of the arena to perform this command! (now inside: @1)= - # dependencies/parties.lua [!] You can't perform this action while in queue!= [!] You can't perform this action while in game!= diff --git a/src/api/in_game.lua b/src/api/in_game.lua index 0e6b22d..73a80db 100755 --- a/src/api/in_game.lua +++ b/src/api/in_game.lua @@ -11,7 +11,6 @@ local function time_start() end local function deprecated_winning_team_celebration() end local players_in_game = {} -- KEY: player name, VALUE: {(string) minigame, (int) arenaID} -local players_in_queue = {} -- KEY: player name, VALUE: {(string) minigame, (int) arenaID} local players_temp_storage = {} -- KEY: player_name, VALUE: {(int) hotbar_slots, (string) hotbar_background_image, (string) hotbar_selected_image, -- (int) bgm_handle, (int) fov, (table) camera_offset, (table) armor_groups} @@ -335,23 +334,6 @@ end --------------------UTILS--------------------- ---------------------------------------------- -function arena_lib.is_player_in_queue(p_name, mod) - - if not players_in_queue[p_name] then - return false - else - - -- se il campo mod è specificato, controllo che sia lo stesso - if mod then - if players_in_queue[p_name].minigame == mod then return true - else return false - end - end - - return true - end -end - -- mod è opzionale function arena_lib.is_player_in_arena(p_name, mod) @@ -372,65 +354,6 @@ end -function arena_lib.add_to_queue(p_name, mod, arena_ID) - local arena = arena_lib.mods[mod].arenas[arena_ID] - arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#c8d692", arena.name .. " > " .. p_name)) - - players_in_queue[p_name] = {minigame = mod, arenaID = arena_ID} -end - - - -function arena_lib.remove_player_from_queue(p_name) - - local mod_ref = arena_lib.mods[arena_lib.get_mod_by_player(p_name)] - local arena = arena_lib.get_arena_by_player(p_name) - - if not arena then return end - - arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#d69298", arena.name .. " < " .. p_name)) - - players_in_queue[p_name] = nil - arena.players_amount = arena.players_amount - 1 - if arena.teams_enabled then - local p_team_ID = arena.players[p_name].teamID - arena.players_amount_per_team[p_team_ID] = arena.players_amount_per_team[p_team_ID] - 1 - end - arena.players[p_name] = nil - arena.players_and_spectators[p_name] = nil - - arena_lib.HUD_hide("all", p_name) - - local players_required = arena_lib.get_players_to_start_queue(arena) - - -- se l'arena era in coda e ora ci son troppi pochi giocatori, annullo la coda - if arena.in_queue and players_required > 0 then - - local arena_max_players = arena.max_players * #arena.teams - local timer = minetest.get_node_timer(arena.sign) - - timer:stop() - arena.in_queue = false - - arena_lib.HUD_hide("broadcast", arena) - arena_lib.HUD_send_msg_all("hotbar", arena, arena_lib.queue_format(arena, S("Waiting for more players...")) .. " (" .. players_required .. ")") - arena_lib.send_message_in_arena(arena, "both", mod_ref.prefix .. S("The queue has been cancelled due to not enough players")) - - -- se già non era in coda, aggiorno HUD - elseif players_required > 0 then - arena_lib.HUD_send_msg_all("hotbar", arena, arena_lib.queue_format(arena, S("Waiting for more players...")) .. " (" .. players_required .. ")") - - -- idem se è rimasta in coda - else - local seconds = math.floor(minetest.get_node_timer(arena.sign):get_timeout() + 0.5) - arena_lib.HUD_send_msg_all("hotbar", arena, arena_lib.queue_format(arena, S("@1 seconds for the match to start", seconds))) - end - - arena_lib.update_sign(arena) -end - - - function arena_lib.remove_player_from_arena(p_name, reason, executioner) -- reason 0 = has disconnected -- reason 1 = has been eliminated @@ -581,27 +504,21 @@ function arena_lib.get_mod_by_player(p_name) if arena_lib.is_player_in_arena(p_name) then return players_in_game[p_name].minigame elseif arena_lib.is_player_in_queue(p_name) then - return players_in_queue[p_name].minigame - else - return end + return arena_lib.get_mod_by_queuing_player(p_name) + end end function arena_lib.get_arena_by_player(p_name) - - local mod, arenaID - if arena_lib.is_player_in_arena(p_name) then -- è in partita - mod = players_in_game[p_name].minigame - arenaID = players_in_game[p_name].arenaID - elseif arena_lib.is_player_in_queue(p_name) then -- è in coda - mod = players_in_queue[p_name].minigame - arenaID = players_in_queue[p_name].arenaID - else - return end + local mod = players_in_game[p_name].minigame + local arenaID = players_in_game[p_name].arenaID - return arena_lib.mods[mod].arenas[arenaID] + return arena_lib.mods[mod].arenas[arenaID] + elseif arena_lib.is_player_in_queue(p_name) then -- è in coda + return arena_lib.get_arena_by_queuing_player(p_name) + end end @@ -614,14 +531,6 @@ end -function arena_lib.get_queueID_by_player(p_name) - if players_in_queue[p_name] then - return players_in_queue[p_name].arenaID - end -end - - - function arena_lib.get_players_in_game() return players_in_game end @@ -758,7 +667,6 @@ function operations_before_entering_arena(mod_ref, mod, arena, arena_ID, p_name) end -- registro giocatori nella tabella apposita - players_in_queue[p_name] = nil players_in_game[p_name] = {minigame = mod, arenaID = arena_ID} end diff --git a/src/api/in_queue.lua b/src/api/in_queue.lua new file mode 100644 index 0000000..9025e43 --- /dev/null +++ b/src/api/in_queue.lua @@ -0,0 +1,434 @@ +local S = minetest.get_translator("arena_lib") + +local function initialise_queue_container() end +local function assign_team() end +local function countdown() end +local function go_to_arena() end +local function queue_format() end + +local players_in_queue = {} -- KEY: player name, VALUE: {(string) minigame, (int) arenaID} +local active_queues = {} -- KEY: [mod] arena_name, VALUE: (int) current timer + +-- inizializzo il contenitore delle code una volta che tutti i minigiochi sono stati caricati +minetest.after(0.1, function() + initialise_queue_container() +end) + +---------------------------------------- + + +function arena_lib.join_queue(mod, arena, p_name) + -- se si è nell'editor + if arena_lib.is_player_in_edit_mode(p_name) then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] You must leave the editor first!"))) + return end + + local arena_name = arena.name + local arenaID = arena_lib.get_arena_by_name(mod, arena_name) + + -- se c'è `parties` e si è in gruppo... + if minetest.get_modpath("parties") and parties.is_player_in_party(p_name) and arena_lib.get_queueID_by_player(p_name) ~= arenaID then + + -- se non si è il capo gruppo + if not parties.is_player_party_leader(p_name) then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] Only the party leader can enter the queue!"))) + return end + + local party_members = parties.get_party_members(p_name) + + -- per tutti i membri... + for _, pl_name in pairs(party_members) do + -- se uno è in partita + if arena_lib.is_player_in_arena(pl_name) then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] You must wait for all your party members to finish their ongoing games before entering a new one!"))) + return end + + -- se uno è attaccato a qualcosa + if minetest.get_player_by_name(pl_name):get_attach() then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] Can't enter a game if some of your party members are attached to something! (e.g. boats, horses etc.)"))) + return end + end + + --se non c'è spazio (no gruppo) + if not arena.teams_enabled then + if #party_members > arena.max_players - arena.players_amount then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] There is not enough space for the whole party!"))) + return end + -- se non c'è spazio (gruppo) + else + + local free_space = false + for _, amount in pairs(arena.players_amount_per_team) do + if #party_members <= arena.max_players - amount then + free_space = true + break + end + end + + if not free_space then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] There is no team with enough space for the whole party!"))) + return end + end + end + + local player = minetest.get_player_by_name(p_name) + + -- se si è attaccati a qualcosa + if player:get_attach() then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] You must detach yourself from the entity you're attached to before entering!"))) + return end + + -- se non è abilitata + if not arena.enabled then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] The arena is not enabled!"))) + return end + + -- se l'arena è piena + if arena.players_amount == arena.max_players * #arena.teams and arena_lib.get_queueID_by_player(p_name) ~= arenaID then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] The arena is already full!"))) + return end + + -- se sta caricando o sta finendo + if arena.in_loading or arena.in_celebration then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] The arena is loading, try again in a few seconds!"))) + return end + + local mod_ref = arena_lib.mods[mod] + + -- se è in corso e non permette l'entrata + if arena.in_game and mod_ref.join_while_in_progress == false then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] This minigame doesn't allow to join while in progress!"))) + return end + + -- se il giocatore è già in coda + if arena_lib.is_player_in_queue(p_name) then + local queued_mod = arena_lib.get_mod_by_player(p_name) + local queued_ID = arena_lib.get_queueID_by_player(p_name) + + -- se era in coda per la stessa arena, interrompo qua, sennò procedo per aggiungerlo nella nuova + if queued_mod == mod and queued_ID == arenaID then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] You're already queuing for this arena!"))) + return + else + arena_lib.remove_player_from_queue(p_name) + end + end + + local p_team_ID + + -- determino eventuale squadra giocatore + if arena.teams_enabled then + p_team_ID = assign_team(mod_ref, arena, p_name) + end + + local players_to_add = {} + + -- potrei avere o un giocatore o un intero gruppo da aggiungere. Quindi per evitare mille if, metto a prescindere il/i giocatore/i in una tabella per iterare in alcune operazioni successive + if minetest.get_modpath("parties") and parties.is_player_in_party(p_name) then + for k, v in pairs(parties.get_party_members(p_name)) do + players_to_add[k] = v + end + else + table.insert(players_to_add, p_name) + end + + -- aggiungo il giocatore + for _, pl_name in pairs(players_to_add) do + arena.players[pl_name] = {kills = 0, deaths = 0, teamID = p_team_ID} + arena.players_and_spectators[pl_name] = true + end + + -- aumento il conteggio di giocatori in partita + arena.players_amount = arena.players_amount + #players_to_add + if arena.teams_enabled then + arena.players_amount_per_team[p_team_ID] = arena.players_amount_per_team[p_team_ID] + #players_to_add + end + + -- notifico i vari giocatori del nuovo giocatore + if arena.in_game then + for _, pl_name in pairs(players_to_add) do + arena_lib.join_arena(mod, pl_name, arenaID) + arena_lib.update_sign(arena) + end + return + else + for _, pl_name in pairs(players_to_add) do + arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#c8d692", arena_name .. " > " .. p_name)) + players_in_queue[p_name] = {minigame = mod, arenaID = arenaID} + end + end + + local arena_max_players = arena.max_players * #arena.teams + + -- se la coda non è partita... + if not arena.in_queue and not arena.in_game then + + local players_required = arena_lib.get_players_amount_left_to_start_queue(arena) + + -- ...e ci sono abbastanza giocatori, parte il timer d'attesa + if players_required <= 0 then + local timer = mod_ref.settings.queue_waiting_time + + arena.in_queue = true + active_queues[mod][arena_name] = timer + countdown(mod, arena) + + -- sennò aggiorno semplicemente la HUD + else + arena_lib.HUD_send_msg_all("hotbar", arena, queue_format(arena, S("Waiting for more players...")) .. + " (" .. players_required .. ")") + end + end + + -- se raggiungo i giocatori massimi e la partita non è iniziata, accorcio eventualmente la durata + if arena.players_amount == arena_max_players and arena.in_queue then + if active_queues[mod][arena_name] > 5 then + active_queues[mod][arena_name] = 5 + end + end + + arena_lib.update_sign(arena) + return true +end + + + +function arena_lib.remove_player_from_queue(p_name) + + local mod = arena_lib.get_mod_by_player(p_name) + local mod_ref = arena_lib.mods[mod] + local arena = arena_lib.get_arena_by_player(p_name) + + if not arena then return end + + -- creo una tabella che andrò poi ad iterare, perché se parliamo di un gruppo, dovrò + -- eseguire la rimozione per ogni singolo membro + local players_to_remove = {} + + -- se è un gruppo + if minetest.get_modpath("parties") and parties.is_player_in_party(p_name) then + + -- (se non è il capogruppo, annullo) + if not parties.is_player_party_leader(p_name) then + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] Only the party leader can leave the queue!"))) + return end + + local party_members = parties.get_party_members(p_name) + + for _, pl_name in pairs(party_members) do + players_to_remove[pl_name] = true + end + + -- sennò singolo utente + else + players_to_remove[p_name] = true + end + + for pl_name, _ in pairs(players_to_remove) do + players_in_queue[pl_name] = nil + arena.players_amount = arena.players_amount - 1 + if arena.teams_enabled then + local p_team_ID = arena.players[pl_name].teamID + arena.players_amount_per_team[p_team_ID] = arena.players_amount_per_team[p_team_ID] - 1 + end + arena.players[pl_name] = nil + arena.players_and_spectators[pl_name] = nil + + arena_lib.HUD_hide("all", pl_name) + arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#d69298", arena.name .. " < " .. pl_name)) + end + + local players_required = arena_lib.get_players_amount_left_to_start_queue(arena) + + -- se l'arena era in coda e ora ci son troppi pochi giocatori, annullo la coda + if arena.in_queue and players_required > 0 then + + local arena_max_players = arena.max_players * #arena.teams + + arena.in_queue = false + + arena_lib.HUD_hide("broadcast", arena) + arena_lib.HUD_send_msg_all("hotbar", arena, queue_format(arena, S("Waiting for more players...")) .. " (" .. players_required .. ")") + arena_lib.send_message_in_arena(arena, "both", mod_ref.prefix .. S("The queue has been cancelled due to not enough players")) + + -- se già non era in coda, aggiorno HUD + elseif players_required > 0 then + arena_lib.HUD_send_msg_all("hotbar", arena, queue_format(arena, S("Waiting for more players...")) .. " (" .. players_required .. ")") + + -- idem se è rimasta in coda + else + local seconds = active_queues[mod][arena.name] + arena_lib.HUD_send_msg_all("hotbar", arena, queue_format(arena, S("@1 seconds for the match to start", seconds))) + end + + arena_lib.update_sign(arena) + return true +end + + + + + +---------------------------------------------- +-----------------GETTERS---------------------- +---------------------------------------------- + +function arena_lib.get_players_amount_left_to_start_queue(arena) + + if not arena or arena.in_game then return end + + local arena_min_players = arena.min_players * #arena.teams + local players_required + + if arena.teams_enabled then + + players_required = 0 + + for _, amount in pairs(arena.players_amount_per_team) do + if arena.min_players - amount > 0 then + players_required = players_required + (arena.min_players - amount) + end + end + else + players_required = arena_min_players - arena.players_amount + end + + return math.max(0, players_required) +end + + + +function arena_lib.get_queueID_by_player(p_name) + if players_in_queue[p_name] then + return players_in_queue[p_name].arenaID + end +end + + + +-- internal use only, don't use it. It makes the API smoother for modders +function arena_lib.get_mod_by_queuing_player(p_name) + return players_in_queue[p_name].minigame +end + + + +-- internal use only, don't use it. It makes the API smoother for modders +function arena_lib.get_arena_by_queuing_player(p_name) + local mod = players_in_queue[p_name].minigame + local arenaID = players_in_queue[p_name].arenaID + + return arena_lib.mods[mod].arenas[arenaID] +end + + + +---------------------------------------------- +--------------------UTILS--------------------- +---------------------------------------------- + +function arena_lib.is_player_in_queue(p_name, mod) + + if not players_in_queue[p_name] then + return false + else + + -- se il campo mod è specificato, controllo che sia lo stesso + if mod then + if players_in_queue[p_name].minigame == mod then return true + else return false + end + end + + return true + end +end + + + + + +---------------------------------------------- +---------------FUNZIONI LOCALI---------------- +---------------------------------------------- + +function initialise_queue_container() + for mod, _ in pairs(arena_lib.mods) do + active_queues[mod] = {} + end +end + + + +function assign_team(mod_ref, arena, p_name) + + local assigned_team_ID = 1 + + for i = 1, #arena.teams do + if arena.players_amount_per_team[i] < arena.players_amount_per_team[assigned_team_ID] then + assigned_team_ID = i + end + end + + local p_team = arena.teams[assigned_team_ID].name + + if minetest.get_modpath("parties") and parties.is_player_in_party(p_name) then + for _, pl_name in pairs(parties.get_party_members(p_name)) do + minetest.chat_send_player(pl_name, mod_ref.prefix .. S("You've joined team @1", minetest.colorize("#eea160", p_team))) + end + else + minetest.chat_send_player(p_name, mod_ref.prefix .. S("You've joined team @1", minetest.colorize("#eea160", p_team))) + end + + return assigned_team_ID +end + + + +function countdown(mod, arena) + if not arena.in_queue or not active_queues[mod][arena.name] then return end + + local seconds = active_queues[mod][arena.name] + + -- dai 5 secondi in giù il messaggio è stampato su broadcast e genero le squadre + if seconds == 0 then + go_to_arena(mod, arena) + elseif seconds <= 5 then + arena_lib.HUD_send_msg_all("broadcast", arena, S("Game begins in @1!", seconds), nil, "arenalib_countdown") + arena_lib.HUD_send_msg_all("hotbar", arena, queue_format(arena, S("Get ready!"))) + else + arena_lib.HUD_send_msg_all("hotbar", arena, queue_format(arena, S("@1 seconds for the match to start", seconds))) + end + + minetest.after(1, function() + active_queues[mod][arena.name] = seconds -1 + countdown(mod, arena) + end) +end + + + +function go_to_arena(mod, arena) + + active_queues[mod][arena.name] = nil + arena.in_queue = false + arena.in_game = true + arena_lib.update_sign(arena) + + for pl_name, _ in pairs(arena.players) do + players_in_queue[pl_name] = nil + end + + local arena_ID = arena_lib.get_arena_by_name(mod, arena.name) + + arena_lib.HUD_hide("all", arena) + arena_lib.load_arena(mod, arena_ID) +end + + + +-- es. Foresta | 3/4 | Il match inizierà a breve +function queue_format(arena, msg) + local arena_max_players = arena.max_players * #arena.teams + return arena.name .. " | " .. arena.players_amount .. "/" .. arena_max_players .. " | " .. msg +end diff --git a/src/signs.lua b/src/signs.lua index c588911..27218d5 100755 --- a/src/signs.lua +++ b/src/signs.lua @@ -1,9 +1,7 @@ local S = minetest.get_translator("arena_lib") local FS = minetest.formspec_escape -local function assign_team() end local function in_game_txt(arena) end -local function HUD_countdown(arena, seconds) end local function get_infobox_formspec() end @@ -25,7 +23,7 @@ signs_lib.register_sign("arena_lib:sign", { vert_scaling = 1.38, number_of_lines = 5, - -- forza widefont + -- forza carattere espanso on_construct = function(pos) minetest.get_meta(pos):set_int("widefont", 1) end, @@ -54,222 +52,29 @@ signs_lib.register_sign("arena_lib:sign", { if arenaID == 0 then return end local mod = minetest.get_meta(pos):get_string("mod") - local mod_ref = arena_lib.mods[mod] - local sign_arena = mod_ref.arenas[arenaID] + local arena = arena_lib.mods[mod].arenas[arenaID] local p_name = puncher:get_player_name() - if not sign_arena then return end -- nel caso qualche cartello dovesse impallarsi, si può rompere senza far crashare + if not arena then return end -- nel caso qualche cartello dovesse impallarsi, si può rompere senza far crashare - -- se si è nell'editor - if arena_lib.is_player_in_edit_mode(p_name) then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] You must leave the editor first!"))) - return end + -- se il cartello è stato spostato tipo con WorldEdit, lo aggiorno alla nuova posizione (e se c'è una partita in corso, la interrompo) + if minetest.serialize(arena.sign) ~= minetest.serialize(pos) then + local arena_name = arena.name + arena_lib.force_arena_ending(mod, arena, "ARENA_LIB") + arena_lib.disable_arena("", mod, arena_name) + arena_lib.set_sign("", mod, arena_name, nil, true) + arena_lib.set_sign("", mod, arena_name, pos) + arena_lib.enable_arena("", mod, arena_name) + minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] Uh-oh, it looks like this sign has been misplaced: well, fixed, hit it again!"))) + return end - -- se il cartello è stato spostato tipo con WorldEdit, lo aggiorno alla nuova posizione (e se c'è una partita in corso, la interrompo) - if minetest.serialize(sign_arena.sign) ~= minetest.serialize(pos) then - local arena_name = sign_arena.name - arena_lib.force_arena_ending(mod, sign_arena, "ARENA_LIB") - arena_lib.disable_arena("", mod, arena_name) - arena_lib.set_sign("", mod, arena_name, nil, true) - arena_lib.set_sign("", mod, arena_name, pos) - arena_lib.enable_arena("", mod, arena_name) - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] Uh-oh, it looks like this sign has been misplaced: well, fixed, hit it again!"))) - return end - - -- se c'è parties e si è in gruppo... - if minetest.get_modpath("parties") and parties.is_player_in_party(p_name) and arena_lib.get_queueID_by_player(p_name) ~= arenaID then - - -- se non si è il capo gruppo - if not parties.is_player_party_leader(p_name) then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] Only the party leader can enter the queue!"))) - return end - - local party_members = parties.get_party_members(p_name) - - -- per tutti i membri... - for _, pl_name in pairs(party_members) do - -- se uno è in partita - if arena_lib.is_player_in_arena(pl_name) then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] You must wait for all your party members to finish their ongoing games before entering a new one!"))) - return end - - -- se uno è attaccato a qualcosa - if minetest.get_player_by_name(pl_name):get_attach() then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] Can't enter a game if some of your party members are attached to something! (e.g. boats, horses etc.)"))) - return end - end - - --se non c'è spazio (no team) - if not sign_arena.teams_enabled then - if #party_members > sign_arena.max_players - sign_arena.players_amount then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] There is not enough space for the whole party!"))) - return end - -- se non c'è spazio (team) - else - - local free_space = false - for _, amount in pairs(sign_arena.players_amount_per_team) do - if #party_members <= sign_arena.max_players - amount then - free_space = true - break - end - end - - if not free_space then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] There is no team with enough space for the whole party!"))) - return end - end - end - - -- se si è attaccati a qualcosa - if puncher:get_attach() then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] You must detach yourself from the entity you're attached to before entering!"))) - return end - - -- se non è abilitata - if not sign_arena.enabled then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] The arena is not enabled!"))) - return end - - -- se l'arena è piena - if sign_arena.players_amount == sign_arena.max_players * #sign_arena.teams and arena_lib.get_queueID_by_player(p_name) ~= arenaID then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] The arena is already full!"))) - return end - - -- se sta caricando o sta finendo - if sign_arena.in_loading or sign_arena.in_celebration then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] The arena is loading, try again in a few seconds!"))) - return end - - -- se è in corso e non permette l'entrata - if sign_arena.in_game and mod_ref.join_while_in_progress == false then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] This minigame doesn't allow to join while in progress!"))) - return end - - -- se è già in coda - if arena_lib.is_player_in_queue(p_name) then - - local queued_mod = arena_lib.get_mod_by_player(p_name) - local queued_ID = arena_lib.get_queueID_by_player(p_name) - - -- se è un party, rimuovo tutto il gruppo - if minetest.get_modpath("parties") and parties.is_player_in_party(p_name) then - - -- (se non è il capogruppo, annullo) - if not parties.is_player_party_leader(p_name) then - minetest.chat_send_player(p_name, minetest.colorize("#e6482e", S("[!] Only the party leader can leave the queue!"))) - return end - - local party_members = parties.get_party_members(p_name) - - for _, pl_name in pairs(party_members) do - arena_lib.remove_player_from_queue(pl_name) - end - - -- sennò rimuovo il singolo utente - else - arena_lib.remove_player_from_queue(p_name) - end - - -- se era in coda per la stessa arena, interrompo qua, sennò procedo per - -- aggiungerlo nella nuova - if queued_mod == mod and queued_ID == arenaID then return end + -- se si è già in coda nella stessa arena, esci, sennò prova ad aggiungere il giocatore + if arena_lib.is_player_in_queue(p_name, mod) and arena_lib.get_queueID_by_player(p_name) == arenaID then + arena_lib.remove_player_from_queue(p_name) + else + arena_lib.join_queue(mod, arena, p_name) end - - local p_team_ID - - -- determino eventuale team giocatore - if sign_arena.teams_enabled then - p_team_ID = assign_team(mod_ref, sign_arena, p_name) - end - - local players_to_add = {} - - -- potrei avere o un giocatore o un intero gruppo da aggiungere. Quindi per evitare mille if, metto a prescindere il/i giocatore/i in una tabella per iterare in alcune operazioni successive - if minetest.get_modpath("parties") and parties.is_player_in_party(p_name) then - for k, v in pairs(parties.get_party_members(p_name)) do - players_to_add[k] = v - end - else - table.insert(players_to_add, p_name) - end - - -- aggiungo il giocatore - for _, pl_name in pairs(players_to_add) do - sign_arena.players[pl_name] = {kills = 0, deaths = 0, teamID = p_team_ID} - sign_arena.players_and_spectators[pl_name] = true - end - - -- aumento il conteggio di giocatori in partita - sign_arena.players_amount = sign_arena.players_amount + #players_to_add - if sign_arena.teams_enabled then - sign_arena.players_amount_per_team[p_team_ID] = sign_arena.players_amount_per_team[p_team_ID] + #players_to_add - end - - -- notifico i vari giocatori del nuovo giocatore - if sign_arena.in_game then - for _, pl_name in pairs(players_to_add) do - arena_lib.join_arena(mod, pl_name, arenaID) - arena_lib.update_sign(sign_arena) - end - return - else - for _, pl_name in pairs(players_to_add) do - arena_lib.add_to_queue(pl_name, mod, arenaID) - end - end - - local timer = minetest.get_node_timer(pos) - local arena_max_players = sign_arena.max_players * #sign_arena.teams - - -- se la coda non è partita... - if not sign_arena.in_queue and not sign_arena.in_game then - - local players_required = arena_lib.get_players_to_start_queue(sign_arena) - - -- ...e ci sono abbastanza giocatori, parte il timer d'attesa - if players_required <= 0 then - sign_arena.in_queue = true - timer:start(mod_ref.settings.queue_waiting_time) - HUD_countdown(sign_arena, timer) - - -- sennò aggiorno semplicemente la HUD - else - arena_lib.HUD_send_msg_all("hotbar", sign_arena, arena_lib.queue_format(sign_arena, S("Waiting for more players...")) .. - " (" .. players_required .. ")") - end - end - - arena_lib.update_sign(sign_arena) - - -- se raggiungo i giocatori massimi e la partita non è iniziata, accorcio eventualmente la durata - if sign_arena.players_amount == arena_max_players and sign_arena.in_queue then - if timer:get_timeout() - timer:get_elapsed() > 5 then - timer:stop() - timer:start(5) - end - end - - end, - - - - -- quello che succede una volta che il timer raggiunge lo 0 - on_timer = function(pos) - - local mod = minetest.get_meta(pos):get_string("mod") - local arena_ID = minetest.get_meta(pos):get_int("arenaID") - local sign_arena = arena_lib.mods[mod].arenas[arena_ID] - - sign_arena.in_queue = false - sign_arena.in_game = true - arena_lib.update_sign(sign_arena) - - arena_lib.HUD_hide("all", sign_arena) - arena_lib.load_arena(mod, arena_ID) - - return false - end, + end }) @@ -295,89 +100,12 @@ end --- es. Foresta | 3/4 | Il match inizierà a breve -function arena_lib.queue_format(arena, msg) - local arena_max_players = arena.max_players * #arena.teams - return arena.name .. " | " .. arena.players_amount .. "/" .. arena_max_players .. " | " .. msg -end - - - -function arena_lib.get_players_to_start_queue(arena) - - local arena_min_players = arena.min_players * #arena.teams - local players_required - - if arena.teams_enabled then - - players_required = 0 - - for _, amount in pairs(arena.players_amount_per_team) do - if arena.min_players - amount > 0 then - players_required = players_required + (arena.min_players - amount) - end - end - else - players_required = arena_min_players - arena.players_amount - end - - return players_required -end - - - ---------------------------------------------- ---------------FUNZIONI LOCALI---------------- ---------------------------------------------- -function assign_team(mod_ref, arena, p_name) - - local assigned_team_ID = 1 - - for i = 1, #arena.teams do - if arena.players_amount_per_team[i] < arena.players_amount_per_team[assigned_team_ID] then - assigned_team_ID = i - end - end - - local p_team = arena.teams[assigned_team_ID].name - - if minetest.get_modpath("parties") and parties.is_player_in_party(p_name) then - for _, pl_name in pairs(parties.get_party_members(p_name)) do - minetest.chat_send_player(pl_name, mod_ref.prefix .. S("You've joined team @1", minetest.colorize("#eea160", p_team))) - end - else - minetest.chat_send_player(p_name, mod_ref.prefix .. S("You've joined team @1", minetest.colorize("#eea160", p_team))) - end - - return assigned_team_ID -end - - - -function HUD_countdown(arena, timer) - - if not arena.in_queue or not timer:is_started() then return end - - local seconds = math.floor(timer:get_timeout() - timer:get_elapsed() + 0.51) - - -- dai 5 secondi in giù il messaggio è stampato su broadcast e genero i team - if seconds <= 5 then - arena_lib.HUD_send_msg_all("broadcast", arena, S("Game begins in @1!", seconds), nil, "arenalib_countdown") - arena_lib.HUD_send_msg_all("hotbar", arena, arena_lib.queue_format(arena, S("Get ready!"))) - else - arena_lib.HUD_send_msg_all("hotbar", arena, arena_lib.queue_format(arena, S("@1 seconds for the match to start", seconds))) - end - - minetest.after(1, function() - HUD_countdown(arena, timer) - end) -end - - - function in_game_txt(arena) local txt