From 1490cf19a950d99b045fe68d7151a6cd54c57e27 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jun 2023 03:31:03 +0100 Subject: add handshaking system, and refactor server a bit --- client/game.lua | 8 ++- server/player.lua | 6 ++- server/server.lua | 152 +++++++++++++++++++++++++++++++++++------------------- 3 files changed, 109 insertions(+), 57 deletions(-) diff --git a/client/game.lua b/client/game.lua index 50b74f9..31e02b8 100644 --- a/client/game.lua +++ b/client/game.lua @@ -342,12 +342,16 @@ local function draw() end local connected = false +local sent_hshake = false function SCENE.update(dt) if connected then return update(dt) else handle_net() - if peer:state() == "connected" and local_player then + if peer:state() == "connected" and not sent_hshake then + peer:send(json.encode{t='handshake',username=username}) + sent_hshake = true + elseif peer:state() == "connected" and local_player then connected = true msgbox.add("connected to "..SERVER_HOSTNAME..":8473") msgbox.add("press F1 for controls help") @@ -363,7 +367,7 @@ function SCENE.draw() end end -function SCENE.load() +function SCENE.load(username) love.keyboard.setKeyRepeat(true) -- require"profile".start(10,io.open("./trace","w")) host = enet.host_create() diff --git a/server/player.lua b/server/player.lua index 365eadc..bd7b52a 100644 --- a/server/player.lua +++ b/server/player.lua @@ -8,23 +8,25 @@ local function random_color() end local Player = class() -function Player.make(cls,peer) +function Player.make(cls,peer,username) local self = { pos = Pos:make(0,0), color = random_color(), peer = peer, id = nextid, + username = username, } nextid = nextid + 1 return setmetatable(self,cls) end function Player.info_part(self) - -- eh + -- eh return { id=self.id, x=self.pos.x, y=self.pos.y, color=self.color, + username=self.username, } end diff --git a/server/server.lua b/server/server.lua index 701551d..5d17e5f 100644 --- a/server/server.lua +++ b/server/server.lua @@ -55,10 +55,18 @@ local map = MapS:make() -local function on_player_connect(ev) - local player = Player:make(ev.peer) + + +-- set of peers currently within handshake procedure +local connecting_peers = {} + +local function create_player(...) + -- advances connecting peer to player + local player = Player:make(...) table.insert(playerlist, player) + connecting_peers[player.peer] = nil + player.peer:send(player_you_packet(player)) for i,otherplayer in ipairs(playerlist) do @@ -71,64 +79,102 @@ local function on_player_connect(ev) print("connect",player.id,player.peer) end -local function on_player_disconnect(ev) - local player,idx = player_by_peer(ev.peer) - if not player then error("sneeze"..ev.peer) end - table.remove(playerlist,idx) - - for i,otherplayer in ipairs(playerlist) do - otherplayer.peer:send(player_leave_packet(player)) +local function connecting_peer_ev() + local ev = coroutine.yield() + print("hello") + local j = json.decode(ev.data) + local op = j.t + if op == "handshake" then + print(ev,'handshake; username',j.username) + create_player(ev.peer,j.username) + else + error("weird handshake: "..op) end +end + - print("disconnect", player.id, player.peer) +local function on_peer_connect(peer) + print("peer connect: ",peer) + local co = coroutine.create(connecting_peer_ev) + assert(coroutine.resume(co)) + connecting_peers[peer] = co end - - -local function handle_ev(ev) - -- handle network event - if ev.type == "connect" then - on_player_connect(ev) - elseif ev.type == "disconnect" then - on_player_disconnect(ev) - elseif ev.type == "receive" then - local player = player_by_peer(ev.peer) - if not player then error("sneezey "..ev.peer) end - local j = json.decode(ev.data) - -- print(ev.channel,ev.data) - local op = j.t - if op == "ppos" then - local x,y = j.x,j.y - player.pos = coords.Pos:make(x,y) - -- print(player.id,"-->",player.pos[1],player.pos[2]) - for i,otherplayer in ipairs(playerlist) do - if otherplayer ~= player then - otherplayer.peer:send(player_move_packet(player,x,y),1) - end + +local function on_peer_disconnect(peer) + print("peer disconnect: ",peer) + connecting_peers[peer] = nil + local player,idx = player_by_peer(peer) + if player then + table.remove(playerlist, idx) + for i,otherplayer in ipairs(playerlist) do + otherplayer.peer:send(player_leave_packet(player)) + end + print("disconnect", player.id, player.peer) + end +end + +local function handle_player_packet(player,ev) + print('player packet ',player,ev.data) + local j = json.decode(ev.data) + -- print(ev.channel,ev.data) + local op = j.t + if op == "ppos" then + local x,y = j.x,j.y + player.pos = coords.Pos:make(x,y) + -- print(player.id,"-->",player.pos[1],player.pos[2]) + for i,otherplayer in ipairs(playerlist) do + if otherplayer ~= player then + otherplayer.peer:send(player_move_packet(player,x,y),1) end - elseif op == "settile" then - local h = coords.Hex:make(j.q,j.r) - map:set_at(h,j.tile) - -- print(player.id,"settile",h,j.tile) - for i,otherplayer in ipairs(playerlist) do - if otherplayer ~= player then - -- same packet structure s2c as c2s - -- when multiple chunks exist and players only get info - -- about stuff near to them, that won't be the case any more - otherplayer.peer:send(ev.data) - end + end + elseif op == "settile" then + local h = coords.Hex:make(j.q,j.r) + map:set_at(h,j.tile) + -- print(player.id,"settile",h,j.tile) + for i,otherplayer in ipairs(playerlist) do + if otherplayer ~= player then + -- same packet structure s2c as c2s + -- when multiple chunks exist and players only get info + -- about stuff near to them, that won't be the case any more + otherplayer.peer:send(ev.data) end - elseif op == "reqchunk" then - -- i am not certain this is the best way for this to work - -- i might change it later - local cp = coords.ChunkPos:make(j.u,j.v) - local ch = map:obtain(cp) - player.peer:send(ch:data_packet()) - elseif op == "chat" then - print("chat ["..player.id.."] "..j.msg) - for i,otherplayer in ipairs(playerlist) do - otherplayer.peer:send(chat_packet(player,j.msg)) + end + elseif op == "reqchunk" then + -- i am not certain this is the best way for this to work + -- i might change it later + local cp = coords.ChunkPos:make(j.u,j.v) + local ch = map:obtain(cp) + player.peer:send(ch:data_packet()) + elseif op == "chat" then + print("chat ["..player.id.."] "..j.msg) + for i,otherplayer in ipairs(playerlist) do + otherplayer.peer:send(chat_packet(player,j.msg)) + end + end +end + +local function handle_ev(ev) + if ev.type == 'connect' then + on_peer_connect(ev.peer) + elseif ev.type == 'disconnect' then + on_peer_disconnect(ev.peer) + elseif ev.type == 'receive' then + print("recv:",ev.peer,ev.data) + if connecting_peers[ev.peer] then + local co = connecting_peers[ev.peer] + print("\t-> hshake",co,coroutine.status(co)) + local ok,err = coroutine.resume(co, ev) + if not ok then + print("hshake error: ",ev.peer,err) + connecting_peers[ev.peer] = nil + ev.peer:disconnect_now() end + else + local player = player_by_peer(ev.peer) + if not player then error("packet from unknown peer ",ev.peer) end + print("\t-> player",player) + handle_player_packet(player, ev) end end end -- cgit v1.2.3