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()
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())