new metaserver
This commit is contained in:
parent
b6acaeb496
commit
8558d918ec
|
|
@ -1,2 +1,3 @@
|
|||
logs/
|
||||
build/
|
||||
mood/
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
color 0a
|
||||
D:/dev/love/love.exe "./client/"
|
||||
pause
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
D:/dev/love/love.exe "./metaserver/"
|
||||
pause
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
function love.conf(t)
|
||||
t.identity = "metaserver" -- The name of the save directory (string)
|
||||
t.appendidentity = false -- Search files in source directory before save directory (boolean)
|
||||
t.version = "11.4" -- The LÖVE version this game was made for (string)
|
||||
t.console = true -- Attach a console (boolean, Windows only)
|
||||
t.accelerometerjoystick = false -- Enable the accelerometer on iOS and Android by exposing it as a Joystick (boolean)
|
||||
t.externalstorage = false -- True to save files (and read from the save directory) in external storage on Android (boolean)
|
||||
t.gammacorrect = false -- Enable gamma-correct rendering, when supported by the system (boolean)
|
||||
|
||||
t.audio.mic = false -- Request and use microphone capabilities in Android (boolean)
|
||||
t.audio.mixwithsystem = true -- Keep background music playing when opening LOVE (boolean, iOS and Android only)
|
||||
|
||||
t.window.title = "metaserver" -- The window title (string)
|
||||
t.window.icon = false -- Filepath to an image to use as the window's icon (string)
|
||||
t.window.width = 800 -- The window width (number)
|
||||
t.window.height = 600 -- The window height (number)
|
||||
t.window.borderless = false -- Remove all border visuals from the window (boolean)
|
||||
t.window.resizable = true -- Let the window be user-resizable (boolean)
|
||||
t.window.minwidth = 400 -- Minimum window width if the window is resizable (number)
|
||||
t.window.minheight = 400 -- Minimum window height if the window is resizable (number)
|
||||
t.window.fullscreen = false -- Enable fullscreen (boolean)
|
||||
t.window.fullscreentype = "desktop" -- Choose between "desktop" fullscreen or "exclusive" fullscreen mode (string)
|
||||
t.window.vsync = 1 -- Vertical sync mode (number)
|
||||
t.window.msaa = 3 -- The number of samples to use with multi-sampled antialiasing (number)
|
||||
t.window.depth = nil -- The number of bits per sample in the depth buffer
|
||||
t.window.stencil = nil -- The number of bits per sample in the stencil buffer
|
||||
t.window.display = 1 -- Index of the monitor to show the window in (number)
|
||||
t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean)
|
||||
t.window.usedpiscale = true -- Enable automatic DPI scaling when highdpi is set to true as well (boolean)
|
||||
t.window.x = nil -- The x-coordinate of the window's position in the specified display (number)
|
||||
t.window.y = nil -- The y-coordinate of the window's position in the specified display (number)
|
||||
|
||||
t.modules.audio = false -- Enable the audio module (boolean)
|
||||
t.modules.data = true -- Enable the data module (boolean)
|
||||
t.modules.event = true -- Enable the event module (boolean)
|
||||
t.modules.font = false -- Enable the font module (boolean)
|
||||
t.modules.graphics = false -- Enable the graphics module (boolean)
|
||||
t.modules.image = false -- Enable the image module (boolean)
|
||||
t.modules.joystick = false -- Enable the joystick module (boolean)
|
||||
t.modules.keyboard = false -- Enable the keyboard module (boolean)
|
||||
t.modules.math = false -- Enable the math module (boolean)
|
||||
t.modules.mouse = false -- Enable the mouse module (boolean)
|
||||
t.modules.physics = false -- Enable the physics module (boolean)
|
||||
t.modules.sound = false -- Enable the sound module (boolean)
|
||||
t.modules.system = false -- Enable the system module (boolean)
|
||||
t.modules.thread = false -- Enable the thread module (boolean)
|
||||
t.modules.timer = true -- Enable the timer module (boolean), Disabling it will result 0 delta time in love.update
|
||||
t.modules.touch = false -- Enable the touch module (boolean)
|
||||
t.modules.video = false -- Enable the video module (boolean)
|
||||
t.modules.window = false -- Enable the window module (boolean)
|
||||
end
|
||||
|
|
@ -1 +0,0 @@
|
|||
assert( assert( require 'socket.http' ).request 'https://api.ipify.org' == '142.162.167.92')
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
--Note, this won't work unless you set up port forwarding!
|
||||
local SERVERTIMEOUT = 30
|
||||
local CLIENTTIMEOUT = 1
|
||||
|
||||
local shared = assert( require '../shared.shared' )
|
||||
local socket = assert( require 'socket' )
|
||||
local packet = assert( shared.packet )
|
||||
local udp = assert( socket.udp() )
|
||||
local msip = assert( require 'getip' )
|
||||
udp:settimeout(0)
|
||||
local localIP = socket.dns.toip(socket.dns.gethostname())
|
||||
print( "Metaserver local IP:", localIP )
|
||||
assert( udp:setsockname( localIP, 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 function serverID( ip, port )
|
||||
return ip..":"..port
|
||||
end
|
||||
|
||||
local handlers = setmetatable({
|
||||
|
||||
serverInfo = function( svInfo, ip, port )
|
||||
print( "Server:", ip, port )
|
||||
local id = serverID(ip, port)
|
||||
local t = socket.gettime()
|
||||
if not servers[id] then
|
||||
servers[id] = { ip = ip, port = port, info = svInfo }
|
||||
--NAT punch: the server doesn't know its own external IP
|
||||
--so it contacts a third party (the metaserver) to discover it.
|
||||
--This external IP gets advertised to prospective clients.
|
||||
svInfo.ip.ip = ip
|
||||
svInfo.port = port
|
||||
end
|
||||
servers[id].time = t
|
||||
packet.advertised{ time = t, ip = svInfo.ip, port = svInfo.port }
|
||||
return udp:sendto( packet.get(), ip, port )
|
||||
end,
|
||||
|
||||
default = function( s, ip, port )
|
||||
print( ip, port, "Malformed message: ", s )
|
||||
end,
|
||||
|
||||
metaServer = function()
|
||||
|
||||
end,
|
||||
|
||||
clientInfo = function( clientInfo, ip, port )
|
||||
--[[if ip ~= tostring( clientInfo.ip ) then
|
||||
return print( ip, port, "Client IP mismatch:", clientInfo.ip )
|
||||
end]]
|
||||
|
||||
print( "Server List:", ip, port )
|
||||
|
||||
clients[ip] = clients[ip] or {}
|
||||
|
||||
local t = socket.gettime()
|
||||
clients[ip].time = t
|
||||
|
||||
for svIP, server in pairs( servers ) do
|
||||
print( "", svIP, packet.getString( server.info.svname ))
|
||||
packet.serverInfo( server.info )
|
||||
end
|
||||
|
||||
return udp:sendto( packet.get(), ip, port )
|
||||
end
|
||||
},
|
||||
|
||||
{
|
||||
__index = function(t) return t.default end
|
||||
})
|
||||
|
||||
local function read(msg, ip, port)
|
||||
if not msg then return end
|
||||
local msgs, types = packet.deserialise( msg )
|
||||
if types[1] ~= "metaServer" then
|
||||
print( ip, port, "Dropped packet, no padding." )
|
||||
return read( udp:receivefrom() )
|
||||
end
|
||||
for i = 1, #msgs do
|
||||
handlers[ types[i] ]( msgs[i], ip, port )
|
||||
end
|
||||
return read( udp:receivefrom() )
|
||||
end
|
||||
|
||||
local function prune( t )
|
||||
for ip, server in pairs(servers) do
|
||||
if server.time < t - SERVERTIMEOUT then
|
||||
print( "Pruning server IP:", ip )
|
||||
servers[ip] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print( "Starting Metaserver", os.time(), udp:getsockname() )
|
||||
function love.update()
|
||||
read( udp:receivefrom() )
|
||||
prune( socket.gettime() )
|
||||
io.flush()
|
||||
tick = tick + 1
|
||||
end
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
local ffi = assert( require( "ffi" ) )
|
||||
|
||||
local metaServerFormats = setmetatable({}, {__index = {
|
||||
domain = "vision.wan-may.art",
|
||||
port = 10587,
|
||||
}})
|
||||
|
||||
local function instantiate( fmt, ... )
|
||||
return fmt.ct( fmt.header, ... )
|
||||
end
|
||||
|
||||
local formatMetatable = { __call = instantiate }
|
||||
local i = 1
|
||||
|
||||
local function addFormat( name, decl )
|
||||
local fmt = { name = name, header = i, ct = ffi.typeof(decl) }
|
||||
fmt.size = ffi.sizeof( fmt.ct )
|
||||
metaServerFormats[name] = fmt
|
||||
metaServerFormats[i] = fmt
|
||||
setmetatable( fmt, formatMetatable )
|
||||
print( "loading msv protocol", fmt.header, fmt.size, fmt.name )
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
ffi.cdef[[ typedef struct{
|
||||
uint8_t players;
|
||||
uint8_t capacity;
|
||||
uint16_t gameTime;
|
||||
uint32_t serverTime;
|
||||
char svName[32];
|
||||
char mapID[32];
|
||||
} gameInfo;]]
|
||||
|
||||
--sent by server
|
||||
addFormat("addServer", [[struct{
|
||||
uint8_t header;
|
||||
} ]])
|
||||
|
||||
--sent by metaserver
|
||||
addFormat("challenge", [[struct{
|
||||
uint8_t header;
|
||||
uint32_t challenge;
|
||||
} ]])
|
||||
|
||||
--sent by server
|
||||
addFormat("updateServer", [[struct{
|
||||
uint8_t header;
|
||||
uint32_t response;
|
||||
gameInfo info;
|
||||
} ]])
|
||||
|
||||
--sent by client to metaServer
|
||||
addFormat("getServerList", [[struct{
|
||||
uint8_t header;
|
||||
}]])
|
||||
|
||||
--sent by metaserver to client
|
||||
addFormat("serverListing", [[struct{
|
||||
uint8_t header;
|
||||
char ip[39];
|
||||
uint16_t port;
|
||||
gameInfo info;
|
||||
}]])
|
||||
|
||||
--sent by client to metaserver, then by metaserver to server
|
||||
addFormat("requestConnection", [[struct{
|
||||
uint8_t header;
|
||||
char ip[39];
|
||||
uint16_t port;
|
||||
}]])
|
||||
|
||||
return metaServerFormats
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
color 04
|
||||
D:/dev/love/love.exe "./server/"
|
||||
pause
|
||||
Loading…
Reference in New Issue