First commit

This commit is contained in:
Marco 2020-03-31 17:04:03 +02:00
parent 8fa35da49c
commit 4b48e11cde
5 changed files with 435 additions and 0 deletions

297
api.lua Normal file
View File

@ -0,0 +1,297 @@
local storage = minetest.get_mod_storage()
storage:set_string("arenas", nil) -- PER RESETTARE LO STORAGE
arena_lib = { arenas = {} }
if minetest.deserialize(storage:get_string("arenas")) ~= nil then
arena_lib.arenas = minetest.deserialize(storage:get_string("arenas"))
end
local function newArena() end
local function nextID() end
local function in_game_txt(arena) end
local arenasID
local players_in_game = {} --KEY: player name, INDEX: arenaID
local arena_default_max_players = 4
local arena_default_min_players = 2
local arena_default_kill_cap = 10
arena_lib.arena_default = {
name = "",
sign = {},
players = {}, --KEY: player name, INDEX: kills, deaths, killstreak
spawn_points = {},
max_players = arena_default_max_players,
min_players = arena_default_min_players,
kill_cap = arena_default_kill_cap,
kill_leader = "",
in_queue = false,
in_game = false,
in_celebration = false
}
function arena_lib.create_arena(sender, arena_name)
arenasID = nextID()
-- controllo che non ci siano duplicati
if arenasID > 1 and arena_lib.get_arena_by_name(arena_name) ~= nil then
minetest.chat_send_player(sender, minetest.colorize("#e6482e", "[!] Esiste già un'arena con quel nome!"))
return end
-- creo l'arena e la rinomino, aggiornando anche lo storage
arena_lib.arenas[arenasID] = newArena(arena_lib.arena_default)
arena_lib.arenas[arenasID].name = arena_name
arena_lib.update_storage()
minetest.chat_send_player(sender, "Arena " .. arena_name .. " creata con successo")
end
function arena_lib.remove_arena(sender, arena_name)
local id, arena = arena_lib.get_arena_by_name(arena_name)
if not arena then minetest.chat_send_player(sender, minetest.colorize("#e6482e", "[!] Non c'è nessun'arena chiamata " .. arena_name .. "!"))
return end
if arena.in_game then
minetest.chat_send_player(sender, minetest.colorize("#e6482e", "[!] Una partita è in corso nell'arena " .. arena_name .. ": impossibile rimuoverla"))
return end
--TODO: -chiedere conferma
-- rimozione cartello coi rispettivi metadati
if arena.sign ~= nil then minetest.set_node(arena.sign, {name = "air"}) end
arena_lib.send_message_players_in_arena(id, "[Quake] L'arena per la quale eri in coda è stata rimossa... :(")
-- rimozione arena e aggiornamento storage
arena_lib.arenas[id] = nil
arena_lib.update_storage()
minetest.chat_send_player(sender, "Arena " .. arena_name .. " rimossa con successo")
end
function arena_lib.is_player_in_arena(pl_name)
if players_in_game[pl_name] ~= nil then return true
else return false end
end
----------------------------------------------
---------------GESTIONE ARENA-----------------
----------------------------------------------
-- per tutti i giocatori quando finisce la coda
function arena_lib.load_arena(arena_ID)
local count = 1
local weapon = ItemStack("quake:railgun")
local arena = arena_lib.arenas[arena_ID]
-- teletrasporto giocatori e sostituisco l'inventario
for pl_name, stats in pairs(arena.players) do
local player = minetest.get_player_by_name(pl_name)
player:set_nametag_attributes({color = {a = 0, r = 255, g = 255, b = 255}})
player: set_physics_override({
speed = 1.7,
jump = 1.5,
gravity = 1.15,
})
player:set_pos(arena.spawn_points[count])
player:get_inventory():set_list("main",{})
player:get_inventory():add_item("main", weapon)
players_in_game[pl_name] = arena_ID -- registro giocatori nella tabella apposita
count = count +1
end
end
-- per il player singolo a match iniziato
function arena_lib.join_arena(arena_ID)
--TODO
end
--a partita finita
function arena_lib.load_celebration(arena_ID, winner_name)
local arena = arena_lib.arenas[arena_ID]
arena.in_celebration = true
arena_lib.update_sign(arena.sign, arena)
arena_lib.update_storage()
for pl_name, stats in pairs(arena.players) do
local inv = minetest.get_player_by_name(pl_name):get_inventory()
local weapon = inv:get_stack("main", 1)
local meta = weapon:get_meta():set_int("immune", 1)
inv:set_stack("main", 1, weapon)
minetest.get_player_by_name(pl_name):set_nametag_attributes({color = {a = 255, r = 255, g = 255, b = 255}})
minetest.chat_send_player(pl_name, "[Quake] " .. winner_name .. " ha vinto la partita")
end
-- momento celebrazione
minetest.after(3, arena_lib.end_arena(arena))
end
function arena_lib.end_arena(arena)
for pl_name, stats in pairs(arena.players) do
arena.players[pl_name] = nil
players_in_game[pl_name] = nil
arena.in_celebration = false
arena.in_game = false
arena_lib.update_sign(arena.sign, arena)
arena_lib.update_storage()
minetest.get_player_by_name(pl_name):set_physics_override({
speed = 1,
jump = 1,
gravity = 1,
})
--TODO: teleport lobby, metti variabile locale
end
end
----------------------------------------------
--------------------UTILS---------------------
----------------------------------------------
function arena_lib.remove_player_from_arena(p_name)
local arena_ID = players_in_game[p_name]
arena[arena_ID].players[p_name] = nil
players_in_game[p_name] = nil
arena_lib.send_message_players_in_arena(arena_ID, "[Quake] " .. p_name .. " ha abbandonato la partita")
--TODO: se in arena è rimasto solo un giocatore, ha vinto e end arena
end
function arena_lib.send_message_players_in_arena(arena_ID, msg)
for pl_name, stats in pairs(arena_lib.arenas[arena_ID].players) do
minetest.chat_send_player(pl_name, msg)
end
end
function arena_lib.calc_kill_leader(arena, killer)
if arena.players[killer].kills > arena.player[kill_leader].kills then
arena.kill_leader = killer
end
end
----------------------------------------------
-----------------GETTERS----------------------
----------------------------------------------
function arena_lib.get_arena_by_name(arena_name)
for id, arena in pairs(arena_lib.arenas) do
if arena.name == arena_name then
return id, arena end
end
end
function arena_lib.get_arenaID_by_player(p_name)
return players_in_game[p_name]
end
function arena_lib.get_arena_players_count(arena_ID)
local count = 0
local arena = arena_lib.arenas[arena_ID]
for id, spawn in pairs(arena.players) do
count = count+1
end
return count
end
function arena_lib.get_arena_spawners_count(arena_ID)
return table.maxn(arena_lib.arenas[arena_ID].spawn_points)
end
function arena_lib.get_random_spawner(arena_ID)
return arena_lib.arenas[arena_ID].spawn_points[math.random(1,arena_lib.get_arena_spawners_count(arena_ID))]
end
--[[
------------------------
Funzioni locali
------------------------
]]
--[[ Dato che in Lua non è possibile istanziare le tabelle copiandole, bisogna istanziare ogni campo in una nuova tabella.
Ricorsivo per le sottotabelle. Codice da => http://lua-users.org/wiki/CopyTable]]
function newArena(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[newArena(orig_key)] = newArena(orig_value)
end
setmetatable(copy, newArena(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
--[[ l'ID di base parte da 1 (n+1) per non generare errori, tipo "if arenaID == 0" al verificare se non esiste.
In una sequenza 0, 1, 2, 3 se si rimuove "2" e si aggiunge un nuovo ID perciò si avrà 0, 1, 3, 4]]
function nextID()
local n = 0
for id, arena in pairs(arena_lib.arenas) do
if id > n then n = id end
end
return n+1
end
function in_game_txt(arena)
local txt
if arena.in_celebration then txt = "Concludendo"
elseif arena.in_game then txt = "In partita"
else txt = "In attesa" end
return txt
end

1
depends.txt Normal file
View File

@ -0,0 +1 @@
signs_lib

2
init.lua Normal file
View File

@ -0,0 +1,2 @@
dofile(minetest.get_modpath("arena_lib") .. "/api.lua")
dofile(minetest.get_modpath("arena_lib") .. "/signs.lua")

1
mod.conf Normal file
View File

@ -0,0 +1 @@
name = arena_lib

134
signs.lua Normal file
View File

@ -0,0 +1,134 @@
minetest.override_item("default:sign_wall", {
on_punch = function(pos, node, puncher, pointed_thing)
local arenaID = minetest.get_meta(pos):get_int("arenaID")
if arenaID == 0 then return end
local sign_arena = arena_lib.arenas[arenaID]
local p_name = puncher:get_player_name()
if not sign_arena then return end -- nel caso qualche cartello dovesse buggarsi, si può rompere e non fa crashare
-- se è già in coda o viene fermato (cartello diverso) o si toglie dalla coda (cartello uguale)
if arena_lib.is_player_in_arena(p_name) then
if arena_lib.get_arenaID_by_player(p_name) ~= arenaID then
minetest.chat_send_player(p_name, "[Quake]" .. minetest.colorize("#e6482e", "Devi prima uscire dalla coda di " .. arena.name .. "!"))
else
sign_arena.players[p_name] = nil
arena_lib.update_sign(pos, sign_arena)
minetest.chat_send_player(p_name, "[Quake] Sei uscito dalla coda")
arena_lib.send_message_players_in_arena(arenaID, "[Quake] " .. p_name .. " ha abbandonato la coda")
-- se non ci sono più abbastanza giocatori, annullo la coda
if arena_lib.get_arena_players_count(arenaID) < sign_arena.min_players and sign_arena.in_queue then
timer:stop()
arena.send_message_players_in_arena(arenaID, "[Quake] La coda è stata annullata per troppi pochi giocatori")
end
end
return end
-- se l'arena è piena
if arena_lib.get_arena_players_count(arenaID) == sign_arena.max_players then
minetest.chat_send_player(p_name, minetest.colorize("#e6482e", "[!] L'arena è già piena!"))
return end
-- notifico i vari giocatori del nuovo player
if sign_arena.in_game then
--TODO: butta dentro alla partita in corso. Sì, si può entrare mentre è in corso -------- arena_lib.join_arena(arenaID)
arena_lib.send_message_players_in_arena(arenaID, "[Quake] " .. p_name .. " si è aggiunto alla partita")
minetest.chat_send_player(p_name, "[Quake] Sei entrato nell'arena " .. sign_arena.name)
else
arena_lib.send_message_players_in_arena(arenaID, "[Quake] " .. p_name .. " si è aggiunto alla coda")
minetest.chat_send_player(p_name, "[Quake] Ti sei aggiunto alla coda per " .. sign_arena.name)
end
-- aggiungo il giocatore e aggiorno il cartello
sign_arena.players[p_name] = {kills = 0, deaths = 0, killstreak = 0}
arena_lib.update_storage()
arena_lib.update_sign(pos, sign_arena)
local timer = minetest.get_node_timer(pos)
local waiting_time = 5
-- se ci sono abbastanza giocatori, parte il timer di attesa
if arena_lib.get_arena_players_count(arenaID) == sign_arena.min_players and not sign_arena.in_queue and not sign_arena.in_game then
arena_lib.send_message_players_in_arena(arenaID, "[Quake] La partita inizierà tra " .. waiting_time .. " secondi!")
sign_arena.in_queue = true
timer:start(waiting_time)
end
-- se raggiungo i giocatori massimi e la partita non è iniziata, parte subito
if arena_lib.get_arena_players_count(arenaID) == sign_arena.max_players and sign_arena.in_queue then
timer:stop()
timer:start(0.01)
end
--TODO: timer ciclico che avvisa i giocatori quanto tempo manca ogni N secondi
end,
-- quello che succede una volta che il timer raggiunge lo 0
on_timer = function(pos)
local arenaID = minetest.get_meta(pos):get_int("arenaID")
local sign_arena = arena_lib.arenas[arenaID]
sign_arena.in_queue = false
sign_arena.in_game = true
arena_lib.update_sign(pos, sign_arena)
arena_lib.load_arena(arenaID)
return false
end,
})
function arena_lib.set_sign(sender, arena_name)
local arena_ID, arena = arena_lib.get_arena_by_name(arena_name)
if arena == nil then minetest.chat_send_player(sender, minetest.colorize("#e6482e", "[!] Quest'arena non esiste!"))
return end
if arena_lib.get_arena_spawners_count(arena_ID) < arena.max_players then minetest.chat_send_player(sender, minetest.colorize("#e6482e", "[!] Gli spawner devono essere quanto i giocatori massimi prima di impostare il cartello!"))
return end
-- assegno item creazione arene con ID arena nei metadati da restituire al premere sul cartello
local stick = ItemStack("arena_lib:create_sign")
local meta = stick:get_meta()
meta:set_int("arenaID", arena_ID)
minetest.get_player_by_name(sender):set_wielded_item(stick)
minetest.chat_send_player(sender, "Click sinistro su un cartello per settare l'arena")
end
function arena_lib.update_storage()
storage:set_string("arenas", minetest.serialize(arena_lib.arenas))
end
function arena_lib.update_sign(pos, arena)
-- non uso il getter perché dovrei richiamare 2 funzioni (ID e count)
local p_count = 0
for pl, stats in pairs(arena.players) do
p_count = p_count +1
end
signs_lib.update_sign(pos, {text = [[
]] .. arena.name .. [[
]] .. p_count .. "/".. arena.max_players .. [[
]] .. in_game_txt(arena) .. [[
]]})
end