-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlobby.lua
101 lines (88 loc) · 2.59 KB
/
lobby.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
-- Lobby Matchmaking Class
-- @author Abelidze
-- @copyright Atom-TM 2020
local next = _G.next
local print = _G.print
local pairs = _G.pairs
local tostring = _G.tostring
local random = math.random
local strjoin = table.concat
local strchar = string.char
local strbyte = string.byte
local strmatch = string.match
local strformat = string.format
-- Master message codes
local FLUSH = 1
local LIST = 2
local LINK = 3
local RELAY = 4
local LOBBY = 6
local SEP = 29
local lobbies = { }
local Lobby = { }
local A, Z = strbyte('a'), strbyte('z')
local function randomtext(min, max)
local result = { }
for i = 1, random(min, max) do
result[i] = strchar(random(A, Z))
end
return strjoin(result)
end
local function genid()
local id
repeat
id = strformat('%s#%03d', randomtext(3, 5), random(0, 999))
until not lobbies[id]
return id
end
function Lobby:all()
return next, lobbies
end
function Lobby:new()
local lobby = setmetatable({ id = genid(), players = { }, size = 0 }, self)
self.__index = self
self.__call = function (cls, ...) return cls:new(...) end
lobbies[lobby.id] = lobby
return lobby
end
function Lobby:get(id)
return lobbies[id]
end
function Lobby:add(id, player)
if self.players[id] then return end
if player.lobby then
print('MOVE', player.lobby.id, '->', self.id, player.name or player.id)
player.lobby:remove(id)
player.peer:send( strchar(FLUSH) )
end
player.lobby = self
player.peer:send( strformat('%c%s', LOBBY, self.id) )
local ip1, port1, ip2, port2
for i, other in pairs(self.players) do
ip1, port1 = strmatch(tostring(player.peer), '^(%S*):(%S*)')
ip2, port2 = strmatch(tostring(other.peer), '^(%S*):(%S*)')
print('LINK', strformat('%s:%s[%s] <-> %s:%s[%s]', ip1, port1, player.name or player.id, ip2, port2, other.name or other.id))
player.peer:send( strformat('%c%s%c%s%c%s%c%s%c%s%c%s', LINK, ip1, SEP, other.id, SEP, other.name, SEP, other.ip, SEP, ip2, SEP, port2) )
other.peer:send( strformat('%c%s%c%s%c%s%c%s%c%s%c%s', LINK, ip2, SEP, player.id, SEP, player.name, SEP, player.ip, SEP, ip1, SEP, port1) )
end
self.players[id] = player
self.size = self.size + 1
return true
end
function Lobby:remove(id)
local player = self.players[id]
if not player then return end
print('LEAVE', self.id, player.name or player.id)
player.lobby = nil
self.players[id] = nil
self.size = self.size - 1
if self.size > 0 then return end
print('DESTROY', self.id)
self.players = { }
lobbies[self.id] = nil
return true
end
return setmetatable(Lobby, {
__index = Lobby,
__call = function (cls, ...) return cls:new(...) end
})