def startListenServer(self, halfMapWidth=3, mapHeight=2): if self.server is not None and self.server.running: return game = LocalGame(self.layoutDatabase, saveReplay=True, gamePrefix='LAN', level=StandardLobbyLevel((halfMapWidth, mapHeight), lobbySettings=None)) self.server = TrosnothServerFactory(game) self.server.onShutdown.addListener(self._serverShutdown) self.server.startListening()
def startServer( self, halfMapWidth=3, mapHeight=2, gameDuration=0, invisibleGame=False): if self.server is not None and self.server.running: return game = LocalGame( self.layoutDatabase, halfMapWidth, mapHeight, duration=gameDuration * 60, saveReplay=True, gamePrefix='LAN') self.server = TrosnothServerFactory(game) self.serverInvisible = invisibleGame self.server.onShutdown.addListener(self._serverShutdown) self.server.startListening()
def createGame(self): ''' Creates a new game and returns the game id. ''' gameId = self.nextId self.nextId += 1 authTagMan = self.authManager.newTagManager() game = LocalGame( layoutDatabase=self.layoutDatabase, maxPerTeam=self.settings.maxPerTeam, authTagManager=authTagMan, saveReplay=True, gamePrefix='Server', replayPath=REPLAY_SUB_PATH, level=StandardLobbyLevel(self.settings.lobbySize), ) server = TrosnothServerFactory(game, authTagMan) def onShutdown(): server.stopListening() del self.servers[gameId] del self.gameStats[game] game.world.onSwitchStats.removeListener(switchGameStats) if gameId == self.primaryGameId: self.primaryGameId = None self.onPrimaryGameChanged(None) server.onShutdown.addListener(onShutdown) server.startListening() self.gameStats[game] = None switchGameStats = partial(self.switchGameStats, game=game) game.world.onSwitchStats.addListener(switchGameStats) if murmur.state == 'initialised': game.world.onChangeVoiceChatRooms.addListener(murmur.setupRooms) log.info('Created game (id=%d)' % (gameId, )) self.servers[gameId] = server self.broadcast('a new game has been created') if self.primaryGameId is None: self.primaryGameId = gameId self.onPrimaryGameChanged(server) return gameId
def startServer(self, halfMapWidth=3, mapHeight=2, gameDuration=0): if self.server is not None and self.server.running: log.warning('Refusing to start local game: one is already running') return game = LocalGame(self.app.layoutDatabase, halfMapWidth, mapHeight, duration=gameDuration * 60, saveReplay=True, gamePrefix='LAN') self.server = TrosnothServerFactory(game) self.server.onShutdown.addListener(self._serverShutdown) self.server.startListening() # Start listening for game requests on the lan. self.multicaster = UDPMulticaster(self._getGames)
class Hoster(object): ''' If this Trosnoth instance is hosting any games, takes care of keeping the game running even if you leave the game but keep Trosnoth open. ''' def __init__(self, app): self.app = app self.server = None self.multicaster = None def startServer(self, halfMapWidth=3, mapHeight=2, gameDuration=0): if self.server is not None and self.server.running: log.warning('Refusing to start local game: one is already running') return game = LocalGame(self.app.layoutDatabase, halfMapWidth, mapHeight, duration=gameDuration * 60, saveReplay=True, gamePrefix='LAN') self.server = TrosnothServerFactory(game) self.server.onShutdown.addListener(self._serverShutdown) self.server.startListening() # Start listening for game requests on the lan. self.multicaster = UDPMulticaster(self._getGames) def stop(self): # Shut down the server if one's running. if self.server is not None: self.server.shutdown() if self.multicaster is not None: self.multicaster.stop() self.multicaster = None def getGameObject(self): if self.server is None: return None return self.server.game def _serverShutdown(self): self.server.stopListening() self.server = None def _getGames(self): ''' Called by multicast listener when a game request comes in. ''' if self.server: gameInfo = { 'version': serverVersion, 'port': self.server.getTCPPort(), } return [gameInfo] return []
async def startBot(self, aiName, fromLevel=False, nick='', team=None): if self.server is None: self.server = TrosnothServerFactory( self.game, noAuth=True, agentCallback=self.agentConnected) self.server.startListening(port=0, interface=LOCALHOST) await self.ensureProcessHasStarted() authTag = len(self.joiningAgents) agentHasJoined = defer.Deferred() self.joiningAgents.append((agentHasJoined, fromLevel)) await self.amp.callRemote( StartBot, name=aiName, fromLevel=fromLevel, nick=nick, teamId=team.id if team else NEUTRAL_TEAM_ID, authTag=authTag, ) agent = await agentHasJoined return agent
class Main(app.MultiWindowApplication): '''Instantiating the Main class will set up the game. Calling the run() method will run the reactor. This class handles the three steps of joining a game: (1) get list of clients; (2) connect to a server; (3) join the game.''' standardInterfaceFactory = interface.Interface singleInterfaceFactory = interface.SingleAuthInterface def __init__(self, serverDetails=None, showReplay=None): '''Initialise the game.''' pygame.init() self.serverDetails = serverDetails self.server = None self.displaySettings = DisplaySettings(self) self.soundSettings = SoundSettings(self) self.identitySettings = IdentitySettings(self) self.connectionSettings = ConnectionSettings(self) pygame.font.init() if self.serverDetails is not None: iface = self.singleInterfaceFactory else: iface = self.standardInterfaceFactory if showReplay: reactor.callWhenRunning(self.loadReplay, showReplay) super(Main, self).__init__(self.displaySettings.getSize(), self.displaySettings.fullScreen, GAME_TITLE, iface) # Set the master sound volume. self.soundSettings.apply() # Start listening for game requests on the lan. self.multicaster = UDPMulticaster(self.getGames) def __str__(self): return 'Trosnoth Main Object' def getConsoleLocals(self): result = { 'server': self.server, 'helper': LocalManholeHelper(lambda: getattr(self, 'interface', None).game), } try: result['game'] = self.interface.game except AttributeError: pass return result def stopping(self): # Shut down the server if one's running. if self.server is not None: self.server.shutdown() self.multicaster.stop() super(Main, self).stopping() def initialise(self): super(Main, self).initialise() # Loading the theme loads the fonts. self.theme = Theme(self) self.layoutDatabase = LayoutDatabase(pathGetter=self.theme.getPath) def loadReplay(self, filename): self.screenManager.interface.connectToReplay(filename) def getFontFilename(self, fontName): ''' Tells the UI framework where to find the given font. ''' return self.theme.getPath('fonts', fontName) def changeScreenSize(self, size, fullScreen): self.screenManager.setScreenProperties(size, fullScreen, GAME_TITLE) def startListenServer(self, halfMapWidth=3, mapHeight=2): if self.server is not None and self.server.running: return game = LocalGame(self.layoutDatabase, saveReplay=True, gamePrefix='LAN', level=StandardLobbyLevel((halfMapWidth, mapHeight), lobbySettings=None)) self.server = TrosnothServerFactory(game) self.server.onShutdown.addListener(self._serverShutdown) self.server.startListening() def getGames(self): ''' Called by multicast listener when a game request comes in. ''' if self.server: gameInfo = { 'version': serverVersion, 'port': self.server.getTCPPort(), } return [gameInfo] return [] def _serverShutdown(self): self.server.stopListening() self.server = None
class ServerSideBotProcessManager: def __init__(self, game, logPrefix): self.game = game self.logPrefix = logPrefix self.process = None self.starting = None self.token = None self.waitForAMPConnection = None self.waitForProcessStart = None self.amp = None self.server = None self.joiningAgents = [] def stop(self): if self.server: self.server.stopListening() self.server = None async def startBot(self, aiName, fromLevel=False, nick='', team=None): if self.server is None: self.server = TrosnothServerFactory( self.game, noAuth=True, agentCallback=self.agentConnected) self.server.startListening(port=0, interface=LOCALHOST) await self.ensureProcessHasStarted() authTag = len(self.joiningAgents) agentHasJoined = defer.Deferred() self.joiningAgents.append((agentHasJoined, fromLevel)) await self.amp.callRemote( StartBot, name=aiName, fromLevel=fromLevel, nick=nick, teamId=team.id if team else NEUTRAL_TEAM_ID, authTag=authTag, ) agent = await agentHasJoined return agent def agentConnected(self, agent, authTag): d, fromLevel = self.joiningAgents[authTag] self.joiningAgents[authTag] = None while self.joiningAgents and self.joiningAgents[-1] is None: self.joiningAgents.pop() agent.allowBotPlayer(fromLevel) d.callback(agent) async def ensureProcessHasStarted(self): if self.starting: await self.starting.waitOrRaise() return if self.process: return success = False self.starting = Event(['result']) try: await self._startProcess() success = True except Exception as e: self.starting.execute(e) raise else: self.starting.execute(None) finally: self.starting = None if not success: self.process = None self.amp = None async def _startProcess(self): assert self.process is None self.process = BotProcessProtocol(self) self.token = uuid.uuid4().hex.encode('ascii') self.waitForAMPConnection = defer.Deferred() ampFactory = Factory.forProtocol(ArenaSideAMPProtocol) ampFactory.manager = self ampEndpoint = TCP4ServerEndpoint(reactor, 0) listeningPort = await ampEndpoint.listen(ampFactory) try: ampPort = listeningPort.getHost().port cmd = self.getCommand() + [str(ampPort)] if self.logPrefix: cmd += [self.logPrefix] log.info('Running command %r', cmd) self.waitForProcessStart = defer.Deferred() transport = reactor.spawnProcess( self.process, cmd[0], cmd, env=None, childFDs=None if os.name == 'nt' else {0: 'w', 1: 1, 2: 2}) try: await self.waitForProcessStart finally: self.waitForProcessStart = None self.process.transport.write(self.token + b'\n') try: self.amp = await self.waitForAMPConnection finally: self.waitForAMPConnection = None await self.amp.callRemote( ConnectToServer, port=self.server.port.getHost().port) finally: listeningPort.stopListening() def getCommand(self): if getattr(sys, 'frozen', False): # Bundled by PyInstaller path = os.path.dirname(sys.executable) ext = '.exe' if os.name == 'nt' else '' return [os.path.join(path, 'support' + ext), 'bots'] return [sys.executable, __file__] def ampConnectionLost(self): if self.process: log.warning('Lost AMP connection to bot subprocess') self.process.killProcess()