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()
Beispiel #2
0
    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()
Beispiel #3
0
    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()