-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlobbyServer.py
121 lines (102 loc) · 3.94 KB
/
lobbyServer.py
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"""
Use this if you want to run multiple matches at once
This is the way you should usually run the server
"""
import os
import copy
import random
import time
import ul_core.net.network as network
from ul_core.net.network_manager import ConnectionClosed
from ul_core.net.network import ServerNetworkManager
from gameServer import GameServer
class LobbyServer:
def __init__(self, verbose):
self.network_manager = ServerNetworkManager(self)
self.ready_players = []
self.game_server_procs = {}
self.verbose = self.network_manager.verbose = verbose
#
# Network functions
# These must be named in camelCase for compatibility reasons
#
def onClientConnected(self, conn):
for conn in self.network_manager.connections:
conn.updateNumPlayers(len(self.network_manager.connections))
if self.verbose:
print("Client connected from " + str(conn.addr))
def requestNumPlayers(self, addr):
for conn in self.network_manager.connections:
try:
conn.updateNumPlayers(len(self.network_manager.connections))
except (ConnectionResetError, BrokenPipeError):
print("connection reset")
pass # If they dc'd, don't worry about it
def addPlayer(self, addr):
conn = next(
conn for conn in self.network_manager.connections
if conn.addr == addr)
if conn not in self.ready_players:
self.ready_players.append(conn)
#
# End of network functions
#
def update_num_players(self):
self.requestNumPlayers(None)
def accept_connections(self):
try:
self.network_manager.accept()
self.network_manager.recv()
except network.OpcodeError as e:
print(e)
except ConnectionClosed as c:
self.network_manager.connections.remove(c.conn)
try:
self.ready_players.remove(c.conn)
except ValueError:
pass
self.update_num_players() # Tell everyone they DC'd
except AttributeError as e:
print("Client probably sending stuff it shouldn't: " + str(e))
# Get the first 2 ready players
ready_players = self.ready_players[:2]
if len(ready_players) == 2:
if self.verbose:
print("Game time started. Forking subprocess.")
f = os.fork()
if f == 0:
random.seed() # Regenerate the random seed for this game
netman = copy.copy(self.network_manager)
# We need only the players for the game we're currently serving
netman.connections = self.ready_players
GameServer(netman).run()
else:
self.network_manager.connections = [
c for c in self.network_manager.connections
if c not in ready_players]
self.game_server_procs[f] = ready_players
# Remove the 2 players from the list of ready players
self.ready_players = self.ready_players[2:]
while len(self.game_server_procs) > 0:
# Clean up when the game server finishes
pid = os.waitpid(-1, os.WNOHANG)[0]
if pid != 0:
self.on_game_server_finished(pid)
else:
break
def on_game_server_finished(self, procid):
"""
Send the player back to the lobby when the child proc finishes
"""
for pl in self.game_server_procs[procid]:
self.network_manager.connections.append(pl)
self.game_server_procs.pop(procid)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='store_true')
args = parser.parse_args()
lobby = LobbyServer(verbose=args.verbose)
while 1:
lobby.accept_connections()
time.sleep(0.01)