class MsgServer(Factory):
    '''
    Base class for servers which receive packed NetworkMessage objects from the
    network.
    '''
    protocol = MsgServerProtocol
    messages = netmsg.MessageCollection()

    def checkGreeting(self, greeting):
        '''
        Must check whether the given greeting string is allowed for this
        server, and return true or false accordingly.
        '''
        return False

    def connectionEstablished(self, protocol):
        '''
        Called after a client has connected and sent an appropriate greeting
        string.
        '''
        pass

    def connectionLost(self, protocol, reason):
        pass

    def gotBadString(self, protocol, string):
        '''
        Called when a client has sent a string that cannot be decoded by our
        known message types.
        '''
        log.warning('Client sent bad message string')
        protocol.transport.abortConnection()
Exemple #2
0
clientMsgs = netmsg.MessageCollection(
    PlayerHasElephantMsg,
    PlayerHasTrosballMsg,
    InitClientMsg,
    CannotJoinMsg,
    TaggingZoneMsg,
    PlayerCoinsSpentMsg,
    PlayerHasUpgradeMsg,
    ShotFiredMsg,
    AddPlayerMsg,
    SetPlayerTeamMsg,
    RespawnMsg,
    UpdatePlayerStateMsg,
    AimPlayerAtMsg,
    SetTeamNameMsg,
    SetGameModeMsg,
    SetGameSpeedMsg,
    SetAgentPlayerMsg,
    RemovePlayerMsg,
    PlayerUpdateMsg,
    ResyncPlayerMsg,
    ResyncAcknowledgedMsg,
    CannotBuyUpgradeMsg,
    UpgradeApprovedMsg,
    ChatMsg,
    ZoneStateMsg,
    AchievementUnlockedMsg,
    WorldResetMsg,
    PlayerIsReadyMsg,
    SetPreferredDurationMsg,
    PreferredTeamSelectedMsg,
    SetPreferredSizeMsg,
    CreateCollectableCoinMsg,
    RemoveCollectableCoinMsg,
    ChangeNicknameMsg,
    FireShoxwaveMsg,
    UpgradeChangedMsg,
    TrosballPositionMsg,
    PlayerNoticedZombieHitMsg,
    AwardPlayerCoinMsg,
    SetPlayerCoinsMsg,
    ChatFromServerMsg,
    DelayUpdatedMsg,
    ShotHitPlayerMsg,
    WorldLoadingMsg,
    UpdateClockStateMsg,
    PlaySoundMsg,
    UpdateGameInfoMsg,
    UpdateScoreBoardModeMsg,
    SetTeamScoreMsg,
    SetPlayerScoreMsg,
    SetUIOptionsMsg,
    SetWorldAbilitiesMsg,
    TickMsg,
)
log = logging.getLogger(__name__)

# The set of messages that the server expects to receive.
serverMsgs = netmsg.MessageCollection(
    ShootMsg,
    UpdatePlayerStateMsg,
    AimPlayerAtMsg,
    BuyUpgradeMsg,
    GrapplingHookMsg,
    ThrowTrosballMsg,
    RespawnRequestMsg,
    JoinRequestMsg,
    ChatMsg,
    PlayerIsReadyMsg,
    SetPreferredDurationMsg,
    SetPreferredTeamMsg,
    SetPreferredSizeMsg,
    SetPreferredLevelMsg,
    RemovePlayerMsg,
    ChangeNicknameMsg,
    ChangeHeadMsg,
    PlayerHasUpgradeMsg,
    CheckSyncMsg,
    ResyncAcknowledgedMsg,
    PlayerAllDeadMsg,
    EmoteRequestMsg,
    PingMsg,
)


class TrosnothServerFactory(MsgServer):
class MsgClientProtocol(Int32StringReceiver, Hub):
    messages = netmsg.MessageCollection()
    greeting = None     # Override this in subclasses

    def connectionMade(self):
        self.agentRequests = {}
        self.nextAgentRequestId = 0
        self.sendString(self.greeting)
        self.agentIds = set()

    def connectionLost(self, reason=None):
        if self.node:
            while self.agentIds:
                agentId = self.agentIds.pop()
                self.node.agentDisconnected(agentId)
        else:
            self.agentIds.clear()

    def stringReceived(self, string):
        kind, body = string[:1], string[1:]
        try:
            if kind == SERVER_GENERAL_MESSAGE:
                self.receivedGeneralMessageString(body)
            elif kind == SERVER_TARGETED_MESSAGE:
                self.receivedTargetedMessageString(body)
            elif kind == SERVER_CONNECTED_AGENT:
                self.receivedAgentConnectedString(body)
            elif kind == SERVER_DISCONNECTED_AGENT:
                self.receivedAgentDisconnectedString(body)
            else:
                self.receivedBadString(string)
        except Exception:
            log.exception('Error responding to received message')

    def receivedBadString(self, string):
        log.warning(
            'Got unexpected string from remote end, dropping connection.')
        self.transport.abortConnection()

    def receivedGeneralMessageString(self, string):
        msg = self.buildMessage(string)
        if msg:
            msg.tracePoint(self, 'receivedGeneralMessageString')
            self.gotGeneralMsg(msg)
        else:
            self.receivedBadString(string)

    def gotGeneralMsg(self, msg):
        if self.node:
            self.node.gotServerCommand(msg)

    def receivedTargetedMessageString(self, string):
        agentId, body = string[:2], string[2:]

        msg = self.buildMessage(body)
        if not msg:
            self.receivedBadString(string)
        elif self.node:
            msg.tracePoint(self, 'receivedTargetedMessageString')
            self.node.gotMessageToAgent(agentId, msg)

    def buildMessage(self, string):
        try:
            return self.messages.buildMessage(string)
        except netmsg.NetworkMessageError:
            return None

    def receivedAgentConnectedString(self, string):
        reqId, agentId = string[:2], string[2:]
        try:
            d = self.agentRequests.pop(reqId)
        except KeyError:
            return
        self.agentIds.add(agentId)
        d.callback(agentId)

    def receivedAgentDisconnectedString(self, agentId):
        self.agentIds.discard(agentId)
        if self.node:
            self.node.agentDisconnected(agentId)

    def connectNewAgent(self, authTag=0):
        if len(self.agentRequests) >= AGENT_REQUEST_ID_LIMIT:
            raise OverflowError('Too many concurrent requests for new agents')
        while True:
            reqId = struct.pack('!H', self.nextAgentRequestId)
            self.nextAgentRequestId += 1
            self.nextAgentRequestId %= AGENT_REQUEST_ID_LIMIT
            if reqId not in self.agentRequests:
                break
        authTagStr = struct.pack('!Q', authTag)
        d = defer.Deferred()
        self.agentRequests[reqId] = d
        self.sendString(CLIENT_CONNECT_AGENT + reqId + authTagStr)

        return d

    def disconnectAgent(self, agentId):
        self.sendString(CLIENT_DISCONNECT_AGENT + agentId)

    def sendRequestToGame(self, agentId, msg):
        msg.tracePoint(self, 'sendRequestToGame')
        self.sendString(CLIENT_REQUEST + agentId + msg.pack())