diff options
| author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-06-03 22:31:42 +0200 |
|---|---|---|
| committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-06-03 23:30:17 +0200 |
| commit | 341af788ffb60b1066f7735c10a2ef8480ec0aa9 (patch) | |
| tree | b1acbfe48184a263098e6146922730dd7ece8808 /server.lua | |
| parent | a42c94e103ecf7cb365a8888c3f5afc785def284 (diff) | |
| download | r6p-main.tar.xz | |
Diffstat (limited to 'server.lua')
| -rw-r--r-- | server.lua | 150 |
1 files changed, 144 insertions, 6 deletions
@@ -2,19 +2,108 @@ local enet = require("enet") local socket = require("socket") local util = require("util") local common = require("common") +local save_file = require("save_file") local server = {} -function server.create(match_addr) +local function migrate_save(save) + save.players = save.players or {} +end + +local function save_data(srv) + -- TODO: handle failure + save_file.write(srv.save_file, srv.data) +end + +local function get_player(srv, name) + for _, player in ipairs(srv.data.players) do + if player.name == name then + return player + end + end +end + +local function get_players(srv) + local players = {} + for _, player in ipairs(srv.data.players) do + table.insert(players, { + name = player.name, + active = srv.players[player.name] ~= nil, + }) + end + return players +end + +local function get_info_pkt(srv) + return util.json_enc({ + type = "client_info", + players = get_players(srv), + }) +end + +local function broadcast_info(srv) + local pkt = get_info_pkt(srv) + for _, clt in pairs(srv.clients) do + clt.peer:send(pkt) + end +end + +local function create_player(srv, name) + local player = { name = name } + table.insert(srv.data.players, player) + print("[server] created player " .. name) + save_data(srv) + return player +end + +local function disconnect(srv, clt) + srv.clients[clt.peer] = nil + if clt.player then + srv.players[clt.player.name] = nil + end + broadcast_info(srv) +end + +local function select_player(srv, clt, pkt) + if #pkt.name > 128 then + return "name_too_long" + end + if srv.players[pkt.name] then + return nil, "already_active" + end + local player = get_player(srv, pkt.name) + if pkt.create and player then + return nil, "already_exists" + end + if not pkt.create and not player then + return nil, "not_exists" + end + + if pkt.create then + player = create_player(srv, pkt.name) + end + return player +end + +function server.create(filename, match_addr) local srv = {} srv.host = enet.host_create() srv.secret = util.rand_string(common.secret_len) srv.clients = {} + srv.players = {} srv.match = srv.host:connect(match_addr or common.default_match_addr) srv.match_req = socket.gettime() + local save, err = save_file.read(filename) + if err then + return nil, err + end + srv.save_file = filename + srv.data = save + migrate_save(save) + return srv end @@ -57,14 +146,54 @@ local function handle_client(srv, peer, pkt) if secret == srv.secret then print("[server] auth success " .. tostring(peer)) - srv.clients[peer] = { peer = peer } - peer:send(util.json_enc({ type = "client_hi" })) + local clt = { peer = peer } + srv.clients[peer] = clt + util.send(peer, { + type = "client_hi", + }) + peer:send(get_info_pkt(srv)) else print("[server] auth failure " .. tostring(peer)) - peer:send(util.json_enc({ type = "client_reject" })) + util.send(peer, { type = "client_reject" }) peer:disconnect_later() end end + + local clt = srv.clients[peer] + if not clt then + print("[server] dropping unauthenicated packet from " .. tostring(peer)) + return + end + + if pkt.type == "server_player" then + if clt.player then + print("[server] dropping server_player from already authenticated player") + return + end + + if type(pkt.name) ~= "string" or type(pkt.create) ~= "boolean" then + print("[server] server_player: invalid packet") + return + end + + local player, err = select_player(srv, clt, pkt) + if err then + print("[server] failed to select player " .. tostring(clt.peer)) + util.send(clt.peer, { + type = "client_player_fail", + error = err, + }) + else + print("[server] select player " .. tostring(clt.peer) .. ": " .. player.name) + srv.players[player.name] = clt + clt.player = player + util.send(clt.peer, { + type = "client_player", + name = player.name, + }) + broadcast_info(srv) + end + end end function server.update(srv) @@ -81,7 +210,7 @@ function server.update(srv) end elseif event.type == "connect" then if event.peer == srv.match then - srv.match:send(util.json_enc({ type = "match_register" })) + util.send(srv.match, { type = "match_register" }) end print("[server] connect " .. tostring(event.peer)) elseif event.type == "disconnect" then @@ -89,7 +218,10 @@ function server.update(srv) if event.peer == srv.match then -- TODO else - srv.clients[event.peer] = nil + local clt = srv.clients[event.peer] + if clt then + disconnect(srv, clt) + end end end event = srv.host:service() @@ -107,6 +239,12 @@ function server.match_status(srv) end function server.close(srv) + save_data(srv) + local peers = srv.host:peer_count() + for i = 1, peers do + srv.host:get_peer(i):disconnect() + end + srv.host:flush() srv.host:destroy() end |
