1. Commands and saved settings
In this chapter the arena learns where its lobby and spawn points are, and players can join and leave a queue. Nothing fights yet, but the base everything else builds on is here.
Create config/ignis/arena.lua. With /ignis watch on each save reloads it.
Settings that survive restarts
Section titled “Settings that survive restarts”An admin sets the arena up once, so the positions have to survive a restart. mc.data is a table that
PxIgnis saves to config/ignis/storage/global.json by itself:
local ADMIN = "arena.admin"
-- Corners, spawn points and lobby, kept across restarts by mc.data.mc.data.arena = mc.data.arena or {}local config = mc.data.arenaconfig.spawns = config.spawns or {}mc.data.arena or {} means “the saved table, or a new empty one the first time”.
A position is stored as a plain table with the world name. Two helpers convert between it and a player:
-- Where a player stands, as a plain table that can be saved.local function here(player) local p = player.pos return { x = p.x, y = p.y, z = p.z, world = player.world.name }end
local function teleport(player, point) player:teleport(point.x, point.y, point.z, point.world)endAdmin commands
Section titled “Admin commands”register(syntax, handler, permission) adds a command. Words in the syntax are literal parts of the
command, so "arena setlobby" is /arena setlobby. The handler gets ctx, and ctx.player is the player
who ran it:
register("arena setlobby", function(ctx) config.lobby = here(ctx.player) ctx.player:sendMessage("Lobby set.")end, ADMIN)The third argument is a permission. Players without arena.admin do not see the command at all. Without a
permissions mod, operators (op level 4) have every script permission. Spawn points are a list, and a new one
goes after the last one:
register("arena addspawn", function(ctx) local spawns = config.spawns spawns[#spawns + 1] = here(ctx.player) ctx.player:sendMessage("Spawn point #" .. #spawns .. " added.")end, ADMIN)
register("arena clearspawns", function(ctx) config.spawns = {} ctx.player:sendMessage("All spawn points removed.")end, ADMIN)The game state
Section titled “The game state”Who is in the arena right now is not worth saving: after a restart nobody is. That state lives in an ordinary local table, keyed by the player’s UUID:
-- Game state. It lives only in memory: a reload starts from scratch.local game = { players = {}, -- uuid -> Player: everyone who joined}
local function tell(text) for _, player in pairs(game.players) do player:sendMessage(text) endendtell sends a message to everyone in the arena. count(t) (in the checkpoint) counts the keys of a table,
since # only works for lists.
Joining and leaving
Section titled “Joining and leaving”local function join(player) if not config.lobby then player:sendMessage("§cThe arena is not set up yet.") elseif game.players[player.uuid] then player:sendMessage("§eYou have already joined.") else game.players[player.uuid] = player teleport(player, config.lobby) tell("§a" .. player.name .. " §7joined the arena (" .. count(game.players) .. ")") endend
local function leave(player) local uuid = player.uuid if not game.players[uuid] then return end game.players[uuid] = nil player:sendMessage("§7You left the arena.")endA player who disconnects must leave the arena too, or a round could wait for them forever. The
player.leave event fires when a player leaves the server; handlers get an event table e with the
player in e.player:
mc.on("player.leave", function(e) leave(e.player)end)Finally the player commands. They have no permission, so everyone can use them:
register("arena join", function(ctx) join(ctx.player) end)register("arena leave", function(ctx) leave(ctx.player) end)Try it
Section titled “Try it”- Stand where the lobby should be and run
/arena setlobby. - Walk into your arena and run
/arena addspawnin two or more places. - Run
/ignis eval mc.data.arenato see what was saved. /arena jointeleports you to the lobby;/arena leavetakes you out of the queue.- Restart the server or run
/ignis reload: the settings are still there, the queue is empty.
Checkpoint
Section titled “Checkpoint”config/ignis/arena.lua after chapter 1
-- config/ignis/arena.lua: a last-player-standing PvP arena.
local ADMIN = "arena.admin"
-- Corners, spawn points and lobby, kept across restarts by mc.data.mc.data.arena = mc.data.arena or {}local config = mc.data.arenaconfig.spawns = config.spawns or {}
-- Where a player stands, as a plain table that can be saved.local function here(player) local p = player.pos return { x = p.x, y = p.y, z = p.z, world = player.world.name }end
local function teleport(player, point) player:teleport(point.x, point.y, point.z, point.world)end
local function count(t) local n = 0 for _ in pairs(t) do n = n + 1 end return nend
-- Game state. It lives only in memory: a reload starts from scratch.local game = { players = {}, -- uuid -> Player: everyone who joined}
local function tell(text) for _, player in pairs(game.players) do player:sendMessage(text) endend
-- ── Joining and leaving ────────────────────────────────────────────────────
local function join(player) if not config.lobby then player:sendMessage("§cThe arena is not set up yet.") elseif game.players[player.uuid] then player:sendMessage("§eYou have already joined.") else game.players[player.uuid] = player teleport(player, config.lobby) tell("§a" .. player.name .. " §7joined the arena (" .. count(game.players) .. ")") endend
local function leave(player) local uuid = player.uuid if not game.players[uuid] then return end game.players[uuid] = nil player:sendMessage("§7You left the arena.")end
mc.on("player.leave", function(e) leave(e.player)end)
-- ── Commands ───────────────────────────────────────────────────────────────
register("arena addspawn", function(ctx) local spawns = config.spawns spawns[#spawns + 1] = here(ctx.player) ctx.player:sendMessage("Spawn point #" .. #spawns .. " added.")end, ADMIN)
register("arena clearspawns", function(ctx) config.spawns = {} ctx.player:sendMessage("All spawn points removed.")end, ADMIN)
register("arena setlobby", function(ctx) config.lobby = here(ctx.player) ctx.player:sendMessage("Lobby set.")end, ADMIN)
register("arena join", function(ctx) join(ctx.player) end)register("arena leave", function(ctx) leave(ctx.player) end)Exercise: add /arena where, which tells the player how many spawn points are set and whether the lobby
is set.