diff --git a/src/client/udp.lua b/src/client/udp.lua index ab7b083..eb041b7 100644 --- a/src/client/udp.lua +++ b/src/client/udp.lua @@ -1,15 +1,31 @@ local socket = assert( require 'socket' ) +local ms = assert( require 'shared.metaserver' ) local udp = {} local packet = assert( require 'shared.packet' ) local cxn = assert( socket.udp() ) +local mscxn = assert( socket.udp() ) cxn:settimeout( 0 ) +mscxn:settimeout( 0 ) +assert(mscxn:setpeername( ms.ip, ms.port )) function udp.receive() return cxn:receive() end +function udp.receiveMeta() + return mscxn:receive() +end + +function udp.requestServerList() + print( "Requesting server list." ) + packet.get() + packet.metaServer() + packet.clientInfo() + return mscxn:send( packet.get() ) +end + function udp.isValid( ip, port ) local s, e = socket.udp() if s then s, e = s:setpeername( ip, port ) end diff --git a/src/client/ui/browser.lua b/src/client/ui/browser.lua index cb2aefb..13143f6 100644 --- a/src/client/ui/browser.lua +++ b/src/client/ui/browser.lua @@ -6,9 +6,10 @@ local packet = assert( require 'shared.packet' ) local menu = assert( require 'client.ui.menu' ) local strings = assert( require 'client.strings' ) local fonts = assert( require 'client.ui.fonts' ) +local metaserver = assert ( require 'client.udp' ) local utf8 = assert( require 'utf8' ) -local browser = {} +local browser = { latest = 0, } local test = assert( require 'client.test.browser' ) @@ -62,6 +63,7 @@ serverList.selected = false serverList.x = 25 serverList.y = 0 serverList.h = 36 +serverList.ips = {} local serverButtons = serverList.buttons local color = { 1, 0.6, 0.6, 0.1 } local ti = textInput.new{ @@ -77,7 +79,7 @@ function ti:callback() return self:enterText( browser.joinIPString ) end local headerButtons = { button{ - callback = function() return serverList.refresh( test.getTestServers() ) end, + callback = function() return serverList.requestServers() end, text = lg.newText( fonts.midFont, strings.refresh_button ) , color = color, x = cw * 32, @@ -110,49 +112,42 @@ for j, headerButton in ipairs( headerButtons ) do serverButtons[j] = headerButton end -function serverList.refresh( serverInfo ) - local n = #headerButtons + 1 +function serverList.requestServers() + for i = 1, 5 do metaserver.requestServerList() end +end - for i, server in ipairs( serverInfo ) do - local b = serverButtons[n] or button{} - b.space = 0 - b.x = cw - b.w = lg.getWidth() - b.y = 27 * i + 145 - b.h = 24 - b.color = { 0.3 + 0.1 * (n % 2), 0.3 + 0.1 * (n % 2), 0.8, 0.3 } - b.callback = joinServerCallback - b.serverInfo = server - b.ip = tostring( server.ip ) - b.port = server.port - b.text = serverInfoToText( server ) - b.active = ( b.y < lg.getHeight() ) - serverButtons[n] = b - n = n + 1 - end +function serverList.clear( ) + for i = #headerButtons + 1, #serverButtons do serverButtons[i] = nil end + for ip in pairs( serverList.ips ) do serverList.ips[ip] = nil end +end - for i = #headerButtons + #serverInfo + 1, #headerButtons + #serverButtons do serverButtons[i] = nil end - +function serverList.add( serverInfo ) + local y = 27 * ( #serverButtons - #headerButtons ) + 180 + local ip = tostring( serverInfo.ip ) + serverButtons[ #serverButtons + 1] = button{ + space = 0, + x = cw, + w = lg.getWidth(), + y = y, + h = 24, + color = { 0.3 + 0.1 * (#serverButtons % 2), 0.3 + 0.1 * (#serverButtons % 2), 0.8, 0.3 }, + callback = joinServerCallback, + serverInfo = serverInfo, + ip = ip, + port = serverInfo.port, + text = serverInfoToText( serverInfo ), + active = ( y < lg.getHeight() )} + serverList.ips[ ip ] = true return serverList:paint() end - -do - local rs = serverList.resize - serverList.resize = function( x, y ) - rs( x, y ) - for i, button in ipairs( serverButtons ) do - button.w = x - end - return serverList:paint() - end - - local ol = serverList.onLoad - function serverList:onLoad() - serverList.refresh( test.getTestServers() ) - return ol( serverList ) - end -end +local metaServerHandlers = setmetatable( + { + default = function() end, + heartbeat = serverList.clear, + serverInfo = serverList.add, + }, + {__index = function( t ) return t.default end }) function serverList.scroll( up ) local minY = 170 @@ -177,7 +172,11 @@ function browser.draw() end function browser.update( dt ) - + local p = metaserver.receiveMeta() + if not p then return end + print( "Receiving server list:", p ) + local msgs, types = packet.deserialise( p ) + for i = 1, #msgs do metaServerHandlers[types[i]]( msgs[i] ) end end function browser.onLoad( ) @@ -195,7 +194,12 @@ function browser.wheelmoved( x, y ) end function browser.resize( x, y ) - return serverList.resize( x, y ) + serverList.resize( x, y ) + + for i, button in ipairs( serverButtons ) do + button.w = x + end + return serverList:paint() end function browser.mousepressed(x, y, button, istouch, pressed) diff --git a/src/metaserver.lua b/src/metaserver.lua index 94aa93a..de863c3 100644 --- a/src/metaserver.lua +++ b/src/metaserver.lua @@ -5,16 +5,20 @@ local shared = assert( require 'shared' ) local socket = assert( require 'socket' ) local packet = assert( shared.packet ) local udp = assert( socket.udp() ) +udp:settimeout(0) +assert( udp:setsockname( shared.metaserver.ip, shared.metaserver.port ) ) --Servers broadcast their information here. --The metaserver builds a list of available servers. ( available meaning, "broadcasted in last ten heartbeats" ) --Clients ask the metaserver for this list ( maybe with some filter? ) local servers = {} local clients = {} +local tick = 0 local handlers = setmetatable({ serverInfo = function( svInfo, ip, port ) + print( "Received server info from:", ip, port ) if ip ~= tostring( svInfo.ip ) then return print("Server IP mismatch:", ip, svInfo.ip) end local t = socket.gettime() if not servers[ip] then servers[ip] = { ip = ip, port = port, info = svInfo } end @@ -34,16 +38,19 @@ local handlers = setmetatable({ end, clientInfo = function( clientInfo, ip, port ) - if ip ~= tostring( clientInfo.ip ) then + --[[if ip ~= tostring( clientInfo.ip ) then return print( ip, port, "Client IP mismatch:", clientInfo.ip ) - end + end]] - if clients[ip] then print( ip, port, "Client request timeout." ) end + print( "Client requested server list: ", ip, port ) + + clients[ip] = clients[ip] or {} local t = socket.gettime() clients[ip].time = t - for i, server in ipairs( servers ) do + packet.heartbeat{ tick = tick } + for ip, server in pairs( servers ) do packet.serverInfo( server.info ) end @@ -70,9 +77,9 @@ local function read(msg, ip, port) end local function prune( t ) - print( "Pruning", socket.gettime() ) for ip, server in pairs(servers) do if server.time < t - SERVERTIMEOUT then + print( "Pruning server IP:", ip ) servers[ip] = nil end end @@ -83,4 +90,5 @@ repeat read( udp:receivefrom() ) prune( socket.gettime() ) io.flush() + tick = tick + 1 until socket.sleep( 2.0 ) \ No newline at end of file diff --git a/src/server.lua b/src/server.lua index ab4738e..03f1d17 100644 --- a/src/server.lua +++ b/src/server.lua @@ -1,6 +1,7 @@ local shared = assert( require 'shared' ) local packet = shared.packet local socket = assert( require 'socket' ) +local ms = shared.metaserver local udp local io = assert( io ) @@ -17,8 +18,6 @@ local server = { tick = 0, } -local msIP, msPort = socket.dns.toip(socket.dns.gethostname()), 42069 - local clients = {} --Developer convenience function: start the local client program. @@ -30,7 +29,7 @@ function server.Advertise() print( "Advertise." ) packet.metaServer() packet.serverInfo( svInfo ) - udp:sendto( packet.get() , msIP, msPort ) + udp:sendto( packet.get() , ms.ip, ms.port ) end function server.serverInfo( serverInfo ) diff --git a/src/shared.lua b/src/shared.lua index 9bc8e32..6835c4c 100644 --- a/src/shared.lua +++ b/src/shared.lua @@ -5,6 +5,7 @@ local shared = {} shared.ip = assert( require 'shared.ipstring' ) shared.packet = assert( require 'shared.packet' ) shared.print = assert( require 'shared.print' ) +shared.metaserver = assert( require 'shared.metaserver' ) --Turn on logging? print = shared.print diff --git a/src/shared/metaserver.lua b/src/shared/metaserver.lua new file mode 100644 index 0000000..779a2fb --- /dev/null +++ b/src/shared/metaserver.lua @@ -0,0 +1,2 @@ +local socket = assert( require 'socket' ) +return { ip = socket.dns.toip(socket.dns.gethostname()), port = 42069 } \ No newline at end of file