diff --git a/DOCS.md b/DOCS.md index 6594768..2d2cf02 100644 --- a/DOCS.md +++ b/DOCS.md @@ -63,7 +63,7 @@ The second field, on the contrary, is a table of optional parameters: they defin * `selected_image =`: (string) the image to show when a slot is selected If a field is not declared, it'll keep the server defaults * `join_while_in_progress`: (bool) whether the minigame allows to join an ongoing match. Default is `false` -* `keep_inventory`: (bool) whether to keep players inventories when joining an arena. Default is `false` +* `keep_inventory`: (bool) whether to keep players inventories when joining an arena. Default is `false`. Check out also `STORE_INVENTORY_MODE` in `SETTINGS.lua`, to choose whether and how to store players' inventory * `show_nametags`: (bool) whether to show the players nametags while in game. Default is `false` * `show_minimap`: (bool) whether to allow players to use the builtin minimap function. Default is `false` * `time_mode`: (int) whether arenas will keep track of the time or not. diff --git a/SETTINGS.lua b/SETTINGS.lua index d0a4694..175a0d5 100644 --- a/SETTINGS.lua +++ b/SETTINGS.lua @@ -11,3 +11,12 @@ arena_lib.SERVER_PHYSICS = { sneak_glitch = false, new_move = true } + +-- for mods where `keep_inventory = false`. +-- It determines whether the inventory before entering an arena should be stored +-- and where. When stored, players will get it back either when the match ends or, +-- if they disconnect/the server crashes, next time they log in. +-- "none" = don't store +-- "mod_db" = store in the arena_lib mod database +-- "external_db" = store in an external database -TODO: NOT YET IMPLEMENTED +arena_lib.STORE_INVENTORY_MODE = "mod_db" diff --git a/api.lua b/api.lua index fd7e40c..aaabf9a 100755 --- a/api.lua +++ b/api.lua @@ -1106,8 +1106,6 @@ end -- winner_name può essere stringa (no team) o tabella di nomi (team) function arena_lib.load_celebration(mod, arena, winner_name) - local mod_ref = arena_lib.mods[mod] - arena.in_celebration = true arena_lib.update_sign(arena) @@ -1128,6 +1126,8 @@ function arena_lib.load_celebration(mod, arena, winner_name) winning_message = S("Team @1 wins the game", arena.teams[winner_team_ID].name) end + local mod_ref = arena_lib.mods[mod] + arena_lib.HUD_send_msg_all("title", arena, winning_message, mod_ref.celebration_time) -- eventuale codice aggiuntivo @@ -1241,7 +1241,6 @@ function arena_lib.is_player_in_arena(p_name, mod) end return true - end end @@ -1261,7 +1260,6 @@ function arena_lib.is_player_in_queue(p_name, mod) end return true - end end @@ -1497,6 +1495,44 @@ end +--WARNING: internal use only +function arena_lib.restore_inventory(p_name) + + if arena_lib.STORE_INVENTORY_MODE == "mod_db" and storage:get_string(p_name .. ".INVENTORY") ~= "" then + + local stored_inv = minetest.deserialize(storage:get_string(p_name .. ".INVENTORY")) + local current_inv = minetest.get_player_by_name(p_name):get_inventory() + + -- ripristino l'inventario + for listname, content in pairs(stored_inv) do + -- se una lista non esiste più (es. son cambiate le mod), la rimuovo + if not current_inv:get_list(listname) then + stored_inv[listname] = nil + else + for i_name, i_def in pairs(content) do + stored_inv[listname][i_name] = ItemStack(i_def) + end + end + end + + -- quando una lista viene salvata, la sua grandezza equivarrà all'ultimo slot contenente + -- un oggetto. Per evitare quindi che reimpostando la lista, l'inventario si rimpicciolisca, + -- salvo prima la grandezza dell'inventario immacolato, applico la lista e poi reimposto la grandezza. + -- Questo mi evita di dover salvare nel database la grandezza di ogni lista. + for listname, _ in pairs (current_inv:get_lists()) do + local list_size = current_inv:get_size(listname) + current_inv:set_list(listname, stored_inv[listname]) + current_inv:set_size(listname, list_size) + end + + storage:set_string(p_name .. ".INVENTORY", "") + -- TODO: storaggio database esterno + --elseif arena_lib.STORE_INVENTORY_MODE == "external_db" then + end +end + + + function arena_lib.send_message_players_in_arena(arena, msg, teamID, except_teamID) if teamID then @@ -2081,8 +2117,28 @@ function operations_before_entering_arena(mod_ref, mod, arena, arena_ID, p_name) -- chiudo eventuali formspec minetest.close_formspec(p_name, "") - -- svuoto eventualmente l'inventario + -- svuoto eventualmente l'inventario, decidendo se e come salvarlo if not mod_ref.keep_inventory then + if arena_lib.STORE_INVENTORY_MODE == "mod_db" then + + local p_inv = player:get_inventory() + local stored_inv = {} + + -- itero ogni lista non vuota per convertire tutti gli itemstack in tabelle (sennò non li serializza) + for listname, content in pairs(p_inv:get_lists()) do + if not p_inv:is_empty(listname) then + stored_inv[listname] = {} + for i_name, i_def in pairs(content) do + stored_inv[listname][i_name] = i_def:to_table() + end + end + end + + storage:set_string(p_name .. ".INVENTORY", minetest.serialize(stored_inv)) + -- TODO: storaggio database esterno + --elseif arena_lib.STORE_INVENTORY_MODE == "external_db" then + end + player:get_inventory():set_list("main",{}) player:get_inventory():set_list("craft",{}) end @@ -2101,10 +2157,14 @@ function operations_before_leaving_arena(mod_ref, arena, p_name) local player = minetest.get_player_by_name(p_name) - -- svuoto eventualmente l'inventario + -- svuoto eventualmente l'inventario e ripristino gli oggetti if not mod_ref.keep_inventory then player:get_inventory():set_list("main", {}) player:get_inventory():set_list("craft",{}) + + if arena_lib.STORE_INVENTORY_MODE ~= "none" then + arena_lib.restore_inventory(p_name) + end end -- resetto eventuali texture diff --git a/player_manager.lua b/player_manager.lua index 55a2655..94f4882 100755 --- a/player_manager.lua +++ b/player_manager.lua @@ -2,6 +2,10 @@ minetest.register_on_joinplayer(function(player) arena_lib.HUD_add(player) + if arena_lib.STORE_INVENTORY_MODE ~= "none" then + arena_lib.restore_inventory(player:get_player_name()) + end + -- nel caso qualcuno si fosse disconnesso da dentro all'editor o fosse crashato il server con qualcuno nell'editor if player:get_inventory():contains_item("main", "arena_lib:editor_quit") then