local enet = require("enet") local json = require("json") local socket = require("socket") local base64 = require("base64") local common = require("common") local client = {} local function create_client(secret) local clt = {} clt.host = enet.host_create() -- enet.host_create("10.75.98.51:58901") clt.secret = secret return clt end local function connect(clt, addr) clt.server = clt.host:connect(addr) clt.server_req = socket.gettime() clt.status = "wait_server" end function client.join(invite, match_addr) local invite_dec = base64.decode(invite) local game_id = invite_dec:sub(1, common.gameid_len) local secret = invite_dec:sub(common.gameid_len+1) local clt = create_client(secret) clt.match = clt.host:connect(match_addr or common.default_match_addr) clt.match:send(json.encode({ type = "match_join", game_id = game_id })) clt.match_req = socket.gettime() clt.game_id = game_id clt.status = "wait_match" return clt end function client.connect(addr, secret) local clt = create_client(secret) connect(clt, addr) return clt end local function handle_match(clt, pkt) if pkt.type == "client_join" then if type(pkt.peer_addr) ~= "string" then print("[client] client_join: invalid peer_addr") return end connect(clt, pkt.peer_addr) elseif pkt.type == "client_join_fail" then clt.status = "fail_match" end end local function handle_server(clt, pkt) if pkt.type == "client_hi" then clt.status = "active" elseif pkt.type == "client_reject" then clt.status = "fail_server" end end function client.update(clt) local event = clt.host:service(20) while event do if event.type == "receive" then local pkt = json.decode(event.data) if event.peer == clt.match and clt.status == "wait_match" then handle_match(clt, pkt) clt.match:disconnect() clt.match = nil elseif event.peer == clt.server then handle_server(clt, pkt) end elseif event.type == "connect" then if event.peer == clt.match and clt.status == "wait_match" then clt.match:send(json.encode({ type = "match_join", game_id = clt.game_id })) elseif event.peer == clt.server and clt.status == "wait_server" then clt.server:send(json.encode({ type = "server_hi", secret = clt.secret })) else event.peer:disconnect_now() end print("[client] connect " .. tostring(event.peer)) elseif event.type == "disconnect" then print("[client] disconnect " .. tostring(event.peer)) if event.peer == clt.server and clt.status == "active" then clt.status = "disco" end end event = clt.host:service() end end function client.status(clt) if clt.status == "wait_match" and clt.match_req+3 < socket.gettime() then clt.status = "timeout_match" elseif clt.status == "wait_server" and clt.match_req+5 < socket.gettime() then clt.status = "timeout_server" end return clt.status -- wait_match -- wait_server -- timeout_match -- fail_match -- timeout_server -- fail_server -- active -- disco end function client.close(clt) clt.host:destroy() end return client