class DistributedPlayer(DistributedAvatar.DistributedAvatar, PlayerBase.PlayerBase, TelemetryLimited): __module__ = __name__ TeleportFailureTimeout = 60.0 chatGarbler = ChatGarbler.ChatGarbler() def __init__(self, cr): try: self.DistributedPlayer_initialized except: self.DistributedPlayer_initialized = 1 DistributedAvatar.DistributedAvatar.__init__(self, cr) PlayerBase.PlayerBase.__init__(self) TelemetryLimited.__init__(self) self.__teleportAvailable = 0 self.inventory = None self.experience = None self.friendsList = [] self.oldFriendsList = None self.timeFriendsListChanged = None self.ignoreList = [] self.lastFailedTeleportMessage = {} self._districtWeAreGeneratedOn = None self.DISLname = '' self.DISLid = 0 self.autoRun = 0 self.whiteListEnabled = base.config.GetBool( 'whitelist-chat-enabled', 1) return @staticmethod def GetPlayerGenerateEvent(): return 'DistributedPlayerGenerateEvent' @staticmethod def GetPlayerNetworkDeleteEvent(): return 'DistributedPlayerNetworkDeleteEvent' @staticmethod def GetPlayerDeleteEvent(): return 'DistributedPlayerDeleteEvent' def networkDelete(self): DistributedAvatar.DistributedAvatar.networkDelete(self) messenger.send(self.GetPlayerNetworkDeleteEvent(), [self]) def disable(self): DistributedAvatar.DistributedAvatar.disable(self) messenger.send(self.GetPlayerDeleteEvent(), [self]) def delete(self): try: self.DistributedPlayer_deleted except: self.DistributedPlayer_deleted = 1 del self.experience if self.inventory: self.inventory.unload() del self.inventory DistributedAvatar.DistributedAvatar.delete(self) def generate(self): DistributedAvatar.DistributedAvatar.generate(self) def announceGenerate(self): DistributedAvatar.DistributedAvatar.announceGenerate(self) messenger.send(self.GetPlayerGenerateEvent(), [self]) def setLocation(self, parentId, zoneId): DistributedAvatar.DistributedAvatar.setLocation(self, parentId, zoneId) if parentId in (0, None): if not zoneId in (0, None): self.cr._isValidPlayerLocation( parentId, zoneId) or self.cr.disableDoId(self.doId) self.cr.deleteObject(self.doId) return None def isGeneratedOnDistrict(self, districtId=None): if districtId is None: return self._districtWeAreGeneratedOn is not None else: return self._districtWeAreGeneratedOn == districtId return def getArrivedOnDistrictEvent(self, districtId=None): if districtId is None: return 'arrivedOnDistrict' else: return 'arrivedOnDistrict-%s' % districtId return def arrivedOnDistrict(self, districtId): curFrameTime = globalClock.getFrameTime() if hasattr(self, 'frameTimeWeArrivedOnDistrict' ) and curFrameTime == self.frameTimeWeArrivedOnDistrict: if districtId == 0 and self._districtWeAreGeneratedOn: self.notify.warning( 'ignoring arrivedOnDistrict 0, since arrivedOnDistrict %d occured on the same frame' % self._districtWeAreGeneratedOn) return self._districtWeAreGeneratedOn = districtId self.frameTimeWeArrivedOnDistrict = globalClock.getFrameTime() messenger.send(self.getArrivedOnDistrictEvent(districtId)) messenger.send(self.getArrivedOnDistrictEvent()) def setLeftDistrict(self): self._districtWeAreGeneratedOn = None return def hasParentingRules(self): if self is localAvatar: return True def setAccountName(self, accountName): self.accountName = accountName def setSystemMessage(self, aboutId, chatString, whisperType=WhisperPopup.WTSystem): self.displayWhisper(aboutId, chatString, whisperType) def displayWhisper(self, fromId, chatString, whisperType): print 'Whisper type %s from %s: %s' % (whisperType, fromId, chatString) def displayWhisperPlayer(self, playerId, chatString, whisperType): print 'WhisperPlayer type %s from %s: %s' % (whisperType, playerId, chatString) def whisperSCTo(self, msgIndex, sendToId, toPlayer): if toPlayer: base.cr.playerFriendsManager.sendSCWhisper(sendToId, msgIndex) else: messenger.send('wakeup') self.sendUpdate('setWhisperSCFrom', [self.doId, msgIndex], sendToId) def setWhisperSCFrom(self, fromId, msgIndex): handle = base.cr.identifyAvatar(fromId) if handle == None: return if base.cr.avatarFriendsManager.checkIgnored(fromId): self.d_setWhisperIgnored(fromId) return if fromId in self.ignoreList: self.d_setWhisperIgnored(fromId) return chatString = SCDecoders.decodeSCStaticTextMsg(msgIndex) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTQuickTalker) base.talkAssistant.receiveAvatarWhisperSpeedChat( TalkAssistant.SPEEDCHAT_NORMAL, msgIndex, fromId) return def whisperSCCustomTo(self, msgIndex, sendToId, toPlayer): if toPlayer: base.cr.playerFriendsManager.sendSCCustomWhisper( sendToId, msgIndex) return messenger.send('wakeup') self.sendUpdate('setWhisperSCCustomFrom', [self.doId, msgIndex], sendToId) def _isValidWhisperSource(self, source): return True def setWhisperSCCustomFrom(self, fromId, msgIndex): handle = base.cr.identifyAvatar(fromId) if handle == None: return if not self._isValidWhisperSource(handle): self.notify.warning('displayWhisper from non-toon %s' % fromId) return if base.cr.avatarFriendsManager.checkIgnored(fromId): self.d_setWhisperIgnored(fromId) return if fromId in self.ignoreList: self.d_setWhisperIgnored(fromId) return chatString = SCDecoders.decodeSCCustomMsg(msgIndex) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTQuickTalker) base.talkAssistant.receiveAvatarWhisperSpeedChat( TalkAssistant.SPEEDCHAT_CUSTOM, msgIndex, fromId) return def whisperSCEmoteTo(self, emoteId, sendToId, toPlayer): print 'whisperSCEmoteTo %s %s %s' % (emoteId, sendToId, toPlayer) if toPlayer: base.cr.playerFriendsManager.sendSCEmoteWhisper(sendToId, emoteId) return messenger.send('wakeup') self.sendUpdate('setWhisperSCEmoteFrom', [self.doId, emoteId], sendToId) def setWhisperSCEmoteFrom(self, fromId, emoteId): handle = base.cr.identifyAvatar(fromId) if handle == None: return if base.cr.avatarFriendsManager.checkIgnored(fromId): self.d_setWhisperIgnored(fromId) return chatString = SCDecoders.decodeSCEmoteWhisperMsg( emoteId, handle.getName()) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTEmote) base.talkAssistant.receiveAvatarWhisperSpeedChat( TalkAssistant.SPEEDCHAT_EMOTE, emoteId, fromId) return def d_setWhisperIgnored(self, sendToId): pass def setChatAbsolute(self, chatString, chatFlags, dialogue=None, interrupt=1, quiet=0): DistributedAvatar.DistributedAvatar.setChatAbsolute( self, chatString, chatFlags, dialogue, interrupt) if not quiet: pass def b_setChat(self, chatString, chatFlags): if self.cr.wantMagicWords and len( chatString) > 0 and chatString[0] == '~': messenger.send('magicWord', [chatString]) else: if base.config.GetBool('want-chatfilter-hacks', 0): if base.config.GetBool('want-chatfilter-drop-offending', 0): if badwordpy.test(chatString): return else: chatString = badwordpy.scrub(chatString) messenger.send('wakeup') self.setChatAbsolute(chatString, chatFlags) self.d_setChat(chatString, chatFlags) def d_setChat(self, chatString, chatFlags): self.sendUpdate('setChat', [chatString, chatFlags, 0]) def setTalk(self, fromAV, fromAC, avatarName, chat, mods, flags): newText, scrubbed = self.scrubTalk(chat, mods) self.displayTalk(newText) if base.talkAssistant.isThought(newText): newText = base.talkAssistant.removeThoughtPrefix(newText) base.talkAssistant.receiveThought(fromAV, avatarName, fromAC, None, newText, scrubbed) else: base.talkAssistant.receiveOpenTalk(fromAV, avatarName, fromAC, None, newText, scrubbed) return def setTalkWhisper(self, fromAV, fromAC, avatarName, chat, mods, flags): newText, scrubbed = self.scrubTalk(chat, mods) self.displayTalkWhisper(fromAV, avatarName, chat, mods) base.talkAssistant.receiveWhisperTalk(fromAV, avatarName, fromAC, None, self.doId, self.getName(), newText, scrubbed) return def displayTalkWhisper(self, fromId, avatarName, chatString, mods): print 'TalkWhisper from %s: %s' % (fromId, chatString) def scrubTalk(self, chat, mods): return chat def setChat(self, chatString, chatFlags, DISLid): self.notify.error('Should call setTalk') chatString = base.talkAssistant.whiteListFilterMessage(chatString) if base.cr.avatarFriendsManager.checkIgnored(self.doId): return if base.localAvatar.garbleChat and not self.isUnderstandable(): chatString = self.chatGarbler.garble(self, chatString) chatFlags &= ~(CFQuicktalker | CFPageButton | CFQuitButton) if chatFlags & CFThought: chatFlags &= ~(CFSpeech | CFTimeout) else: chatFlags |= CFSpeech | CFTimeout self.setChatAbsolute(chatString, chatFlags) def b_setSC(self, msgIndex): self.setSC(msgIndex) self.d_setSC(msgIndex) def d_setSC(self, msgIndex): messenger.send('wakeup') self.sendUpdate('setSC', [msgIndex]) def setSC(self, msgIndex): if base.cr.avatarFriendsManager.checkIgnored(self.doId): return if self.doId in base.localAvatar.ignoreList: return chatString = SCDecoders.decodeSCStaticTextMsg(msgIndex) if chatString: self.setChatAbsolute(chatString, CFSpeech | CFQuicktalker | CFTimeout, quiet=1) base.talkAssistant.receiveOpenSpeedChat(TalkAssistant.SPEEDCHAT_NORMAL, msgIndex, self.doId) def b_setSCCustom(self, msgIndex): self.setSCCustom(msgIndex) self.d_setSCCustom(msgIndex) def d_setSCCustom(self, msgIndex): messenger.send('wakeup') self.sendUpdate('setSCCustom', [msgIndex]) def setSCCustom(self, msgIndex): if base.cr.avatarFriendsManager.checkIgnored(self.doId): return if self.doId in base.localAvatar.ignoreList: return chatString = SCDecoders.decodeSCCustomMsg(msgIndex) if chatString: self.setChatAbsolute(chatString, CFSpeech | CFQuicktalker | CFTimeout) base.talkAssistant.receiveOpenSpeedChat(TalkAssistant.SPEEDCHAT_CUSTOM, msgIndex, self.doId) def b_setSCEmote(self, emoteId): self.b_setEmoteState(emoteId, animMultiplier=self.animMultiplier) def d_friendsNotify(self, avId, status): self.sendUpdate('friendsNotify', [avId, status]) def friendsNotify(self, avId, status): avatar = base.cr.identifyFriend(avId) if avatar != None: if status == 1: self.setSystemMessage( avId, OTPLocalizer.WhisperNoLongerFriend % avatar.getName()) elif status == 2: self.setSystemMessage( avId, OTPLocalizer.WhisperNowSpecialFriend % avatar.getName()) return def d_teleportQuery(self, requesterId, sendToId=None): teleportNotify.debug('sending teleportQuery%s' % ((requesterId, sendToId), )) self.sendUpdate('teleportQuery', [requesterId], sendToId) def teleportQuery(self, requesterId): teleportNotify.debug('receieved teleportQuery(%s)' % requesterId) avatar = base.cr.playerFriendsManager.identifyFriend(requesterId) if avatar != None: teleportNotify.debug('avatar is not None') if base.cr.avatarFriendsManager.checkIgnored(requesterId): teleportNotify.debug('avatar ignored via avatarFriendsManager') self.d_teleportResponse(self.doId, 2, 0, 0, 0, sendToId=requesterId) return if requesterId in self.ignoreList: teleportNotify.debug('avatar ignored via ignoreList') self.d_teleportResponse(self.doId, 2, 0, 0, 0, sendToId=requesterId) return if hasattr(base, 'distributedParty'): if base.distributedParty.partyInfo.isPrivate: if requesterId not in base.distributedParty.inviteeIds: teleportNotify.debug('avatar not in inviteeIds') self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId=requesterId) return if base.distributedParty.isPartyEnding: teleportNotify.debug('party is ending') self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId=requesterId) return if self.__teleportAvailable and not self.ghostMode and base.config.GetBool( 'can-be-teleported-to', 1): teleportNotify.debug('teleport initiation successful') self.setSystemMessage( requesterId, OTPLocalizer.WhisperComingToVisit % avatar.getName()) messenger.send('teleportQuery', [avatar, self]) return teleportNotify.debug('teleport initiation failed') if self.failedTeleportMessageOk(requesterId): self.setSystemMessage( requesterId, OTPLocalizer.WhisperFailedVisit % avatar.getName()) teleportNotify.debug('sending try-again-later message') self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId=requesterId) return def failedTeleportMessageOk(self, fromId): now = globalClock.getFrameTime() lastTime = self.lastFailedTeleportMessage.get(fromId, None) if lastTime != None: elapsed = now - lastTime if elapsed < self.TeleportFailureTimeout: return 0 self.lastFailedTeleportMessage[fromId] = now return 1 def d_teleportResponse(self, avId, available, shardId, hoodId, zoneId, sendToId=None): teleportNotify.debug( 'sending teleportResponse%s' % ((avId, available, shardId, hoodId, zoneId, sendToId), )) self.sendUpdate('teleportResponse', [avId, available, shardId, hoodId, zoneId], sendToId) def teleportResponse(self, avId, available, shardId, hoodId, zoneId): teleportNotify.debug('received teleportResponse%s' % ((avId, available, shardId, hoodId, zoneId), )) messenger.send('teleportResponse', [avId, available, shardId, hoodId, zoneId]) def d_teleportGiveup(self, requesterId, sendToId=None): teleportNotify.debug('sending teleportGiveup(%s) to %s' % (requesterId, sendToId)) self.sendUpdate('teleportGiveup', [requesterId], sendToId) def teleportGiveup(self, requesterId): teleportNotify.debug('received teleportGiveup(%s)' % (requesterId, )) avatar = base.cr.identifyAvatar(requesterId) if not self._isValidWhisperSource(avatar): self.notify.warning('teleportGiveup from non-toon %s' % requesterId) return if avatar != None: self.setSystemMessage( requesterId, OTPLocalizer.WhisperGiveupVisit % avatar.getName()) return def b_teleportGreeting(self, avId): self.d_teleportGreeting(avId) self.teleportGreeting(avId) def d_teleportGreeting(self, avId): self.sendUpdate('teleportGreeting', [avId]) def teleportGreeting(self, avId): avatar = base.cr.getDo(avId) if isinstance(avatar, Avatar.Avatar): self.setChatAbsolute( OTPLocalizer.TeleportGreeting % avatar.getName(), CFSpeech | CFTimeout) elif avatar is not None: self.notify.warning( 'got teleportGreeting from %s referencing non-toon %s' % (self.doId, avId)) return def setTeleportAvailable(self, available): self.__teleportAvailable = available def getTeleportAvailable(self): return self.__teleportAvailable def getFriendsList(self): return self.friendsList def setFriendsList(self, friendsList): self.oldFriendsList = self.friendsList self.friendsList = friendsList self.timeFriendsListChanged = globalClock.getFrameTime() messenger.send('friendsListChanged') Avatar.reconsiderAllUnderstandable() def setDISLname(self, name): self.DISLname = name def setDISLid(self, id): self.DISLid = id def setAutoRun(self, value): self.autoRun = value def getAutoRun(self): return self.autoRun
class DistributedPlayer(DistributedAvatar.DistributedAvatar, PlayerBase.PlayerBase): """Distributed Player class:""" # This is the length of time that should elapse before we allow # another failed-teleport message to be displayed from the same # avatar. TeleportFailureTimeout = 60.0 # Create a default chat garbler (can be overridden by child class) chatGarbler = ChatGarbler.ChatGarbler() def __init__(self, cr): """ Handle distributed updates """ try: self.DistributedPlayer_initialized except: self.DistributedPlayer_initialized = 1 DistributedAvatar.DistributedAvatar.__init__(self, cr) PlayerBase.PlayerBase.__init__(self) self.__teleportAvailable = 0 self.inventory = None self.experience = None self.friendsList = [] self.oldFriendsList = None self.timeFriendsListChanged = None self.ignoreList = [] self.lastFailedTeleportMessage = {} self._districtWeAreGeneratedOn = None self.DISLname = "" self.DISLid = 0 self.autoRun = 0 self.whiteListEnabled = base.config.GetBool('whitelist-chat-enabled', 1) ### managing ActiveAvatars ### def disable(self): """ This method is called when the DistributedObject is removed from active duty and stored in a cache. """ DistributedAvatar.DistributedAvatar.disable(self) def delete(self): """ This method is called when the DistributedObject is permanently removed from the world and deleted from the cache. """ try: self.DistributedPlayer_deleted except: self.DistributedPlayer_deleted = 1 del self.experience if self.inventory: self.inventory.unload() del self.inventory DistributedAvatar.DistributedAvatar.delete(self) def generate(self): """ This method is called when the DistributedObject is reintroduced to the world, either for the first time or from the cache. """ DistributedAvatar.DistributedAvatar.generate(self) def setLocation(self, parentId, zoneId, teleport=0): DistributedAvatar.DistributedAvatar.setLocation(self, parentId, zoneId, teleport) # if the avatar just got put somewhere it shouldn't be, delete it # this is to prevent hackers from sidling over into an 'uber' zone, thereby # keeping themselves on your client even after the client no longer has interest in the # original, legitimate zone from which the hacker toon was generated if not (parentId in (0, None) and zoneId in (0, None)): if not self.cr._isValidPlayerLocation(parentId, zoneId): self.cr.disableDoId(self.doId) self.cr.deleteObject(self.doId) def isGeneratedOnDistrict(self, districtId=None): if districtId is None: return self._districtWeAreGeneratedOn is not None else: return self._districtWeAreGeneratedOn == districtId def getArrivedOnDistrictEvent(self, districtId=None): if districtId is None: return 'arrivedOnDistrict' else: return 'arrivedOnDistrict-%s' % districtId def arrivedOnDistrict(self, districtId): # we have been generated on this district curFrameTime = globalClock.getFrameTime() if hasattr(self,"frameTimeWeArrivedOnDistrict") and \ curFrameTime == self.frameTimeWeArrivedOnDistrict: # rare case check if we get the zero from the shard we're leaving # AFTER we get the district id of the shard we were going to if districtId == 0 and self._districtWeAreGeneratedOn: self.notify.warning("ignoring arrivedOnDistrict 0, since arrivedOnDistrict %d occured on the same frame" % self._districtWeAreGeneratedOn) return self._districtWeAreGeneratedOn = districtId self.frameTimeWeArrivedOnDistrict = globalClock.getFrameTime() messenger.send(self.getArrivedOnDistrictEvent(districtId)) messenger.send(self.getArrivedOnDistrictEvent()) def setLeftDistrict(self): self._districtWeAreGeneratedOn = None def hasParentingRules(self): # we can't define setParentingRules for the localAvatar in the DC because # that would define parenting rules for other players' avatars. Just # override this and always return True for the sake of the DoInterestManager if self is localAvatar: return True ### setAccountName ### def setAccountName(self, accountName): self.accountName = accountName ### setWhisper ### def setSystemMessage(self, aboutId, chatString, whisperType = WhisperPopup.WTSystem): """setSystemMessage(self, int aboutId, string chatString) A message generated from the system (or the AI, or something like that). If this involves another avatar (e.g. Flippy is now online), the aboutId is filled in; otherwise, aboutId is zero. """ self.displayWhisper(aboutId, chatString, whisperType) def displayWhisper(self, fromId, chatString, whisperType): """displayWhisper(self, int fromId, string chatString, int whisperType) Displays the whisper message in whatever capacity makes sense. This is separate from setWhisper so we can safely call it by name from within setWhisper and expect the derived function to override it. """ print "Whisper type %s from %s: %s" % (whisperType, fromId, chatString) def displayWhisperPlayer(self, playerId, chatString, whisperType): """ Displays the whisper message in whatever capacity makes sense. This is separate from setWhisper so we can safely call it by name from within setWhisper and expect the derived function to override it. """ print "WhisperPlayer type %s from %s: %s" % (whisperType, playerId, chatString) ### setWhisperSC ### def whisperSCTo(self, msgIndex, sendToId, toPlayer): """ Sends a speedchat whisper message to the indicated avatar/player. """ if toPlayer: base.cr.playerFriendsManager.sendSCWhisper(sendToId, msgIndex) else: messenger.send("wakeup") self.sendUpdate("setWhisperSCFrom", [self.doId, msgIndex], sendToId) def setWhisperSCFrom(self, fromId, msgIndex): """ Receive and decode the SpeedChat message. """ handle = base.cr.identifyAvatar(fromId) if handle == None: return if base.cr.avatarFriendsManager.checkIgnored(fromId): # We're ignoring this jerk. self.d_setWhisperIgnored(fromId) return if fromId in self.ignoreList: # We're ignoring this jerk. self.d_setWhisperIgnored(fromId) return chatString = SCDecoders.decodeSCStaticTextMsg(msgIndex) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTQuickTalker) base.talkAssistant.receiveAvatarWhisperSpeedChat(TalkAssistant.SPEEDCHAT_NORMAL, msgIndex, fromId) ### setWhisperSCCustom ### def whisperSCCustomTo(self, msgIndex, sendToId, toPlayer): """ Sends a speedchat whisper message to the indicated toon, prefixed with our own name. """ if toPlayer: base.cr.playerFriendsManager.sendSCCustomWhisper(sendToId, msgIndex) return messenger.send("wakeup") self.sendUpdate("setWhisperSCCustomFrom", [self.doId, msgIndex], sendToId) def _isValidWhisperSource(self, source): return True def setWhisperSCCustomFrom(self, fromId, msgIndex): """ Receive and decode the SC message. """ handle = base.cr.identifyAvatar(fromId) if handle == None: return if not self._isValidWhisperSource(handle): self.notify.warning('displayWhisper from non-toon %s' % fromId) return # new ignore list is handled by the Friends manager's, there are now two types, avatar and player. if base.cr.avatarFriendsManager.checkIgnored(fromId): # We're ignoring this jerk. self.d_setWhisperIgnored(fromId) return if fromId in self.ignoreList: # We're ignoring this jerk. self.d_setWhisperIgnored(fromId) return chatString = SCDecoders.decodeSCCustomMsg(msgIndex) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTQuickTalker) base.talkAssistant.receiveAvatarWhisperSpeedChat(TalkAssistant.SPEEDCHAT_CUSTOM, msgIndex, fromId) ### setWhisperSCEmote ### def whisperSCEmoteTo(self, emoteId, sendToId, toPlayer): """ Sends a speedchat whisper message to the indicated toon, prefixed with our own name. """ print("whisperSCEmoteTo %s %s %s" % (emoteId, sendToId, toPlayer)) if toPlayer: base.cr.playerFriendsManager.sendSCEmoteWhisper(sendToId, emoteId) return messenger.send("wakeup") self.sendUpdate("setWhisperSCEmoteFrom", [self.doId, emoteId], sendToId) def setWhisperSCEmoteFrom(self, fromId, emoteId): """ Receive and decode the SC message. """ handle = base.cr.identifyAvatar(fromId) if handle == None: return if base.cr.avatarFriendsManager.checkIgnored(fromId): # We're ignoring this jerk. self.d_setWhisperIgnored(fromId) return chatString = SCDecoders.decodeSCEmoteWhisperMsg(emoteId, handle.getName()) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTEmote) base.talkAssistant.receiveAvatarWhisperSpeedChat(TalkAssistant.SPEEDCHAT_EMOTE, emoteId, fromId) def d_setWhisperIgnored(self, sendToId): # Don't send this message for the time being. # I haven't removed it completely since we may # want to send it in the future. # self.sendUpdate("setWhisperIgnored", [self.doId], sendToId) pass ### setChat ### def setChatAbsolute(self, chatString, chatFlags, dialogue = None, interrupt = 1, quiet = 0): DistributedAvatar.DistributedAvatar.setChatAbsolute(self, chatString, chatFlags, dialogue, interrupt) if not quiet: pass def b_setChat(self, chatString, chatFlags): # Is this a magic word? All magic words begin with a ~ if (self.cr.wantMagicWords and (len(chatString) > 0) and (chatString[0] == "~")): # Tell the magic word manager we just said a magic word messenger.send("magicWord", [chatString]) else: # HACK for demo - Outgoing dirty word check. NEVER RELY ON THIS. if base.config.GetBool('want-chatfilter-hacks',0): if base.config.GetBool('want-chatfilter-drop-offending',0): if badwordpy.test(chatString): return else: chatString = badwordpy.scrub(chatString) # Local # avoid having to check if this is the local toon messenger.send("wakeup") self.setChatAbsolute(chatString, chatFlags) # Distributed self.d_setChat(chatString, chatFlags) def d_setChat(self, chatString, chatFlags): self.sendUpdate("setChat", [chatString, chatFlags, 0]) #self.sendUpdate("setTalk", [0, 0, chatString, []]) def setTalk(self, fromAV, fromAC, avatarName, chat, mods, flags): newText, scrubbed = self.scrubTalk(chat, mods) self.displayTalk(newText) if base.talkAssistant.isThought(newText): newText = base.talkAssistant.removeThoughtPrefix(newText) base.talkAssistant.receiveThought(fromAV, avatarName, fromAC, None, newText, scrubbed) else: base.talkAssistant.receiveOpenTalk(fromAV, avatarName, fromAC, None, newText, scrubbed) def setTalkWhisper(self, fromAV, fromAC, avatarName, chat, mods, flags): newText, scrubbed = self.scrubTalk(chat, mods) #self.displayTalk(newText) self.displayTalkWhisper(fromAV, avatarName, chat, mods) base.talkAssistant.receiveWhisperTalk(fromAV, avatarName, fromAC, None, self.doId, self.getName(), newText, scrubbed) def displayTalkWhisper(self, fromId, avatarName, chatString, mods): """displayTalkWhisper(self, int fromId, string chatString) Displays the whisper message in whatever capacity makes sense. This is separate from setWhisper so we can safely call it by name from within setWhisper and expect the derived function to override it. """ print "TalkWhisper from %s: %s" % (fromId, chatString) def scrubTalk(self, chat, mods): """ returns chat where the mods have been replaced with appropreiate words this is not in chat assistant because the replacement needs to be done by the object that speeaks them. A pirate says "arr", a duck says "quack", etc.. """ return chat def setChat(self, chatString, chatFlags, DISLid): """setChat(self, string) Garble the message if needed, then pass message to setChatAbsolute """ self.notify.error("Should call setTalk") chatString = base.talkAssistant.whiteListFilterMessage(chatString) if base.cr.avatarFriendsManager.checkIgnored(self.doId): # We're ignoring this jerk. return # if we don't have chat permission, garble the chat message if base.localAvatar.garbleChat and (not self.isUnderstandable()): chatString = self.chatGarbler.garble(self, chatString) # Clear any buttons or speedchat state from the chat flags; # both of these go through a different interface. chatFlags &= ~(CFQuicktalker | CFPageButton | CFQuitButton) # Also, enforce that either the speech or thought bit is set, # and the timeout is set iff speech is set. if (chatFlags & CFThought): chatFlags &= ~(CFSpeech | CFTimeout) else: chatFlags |= (CFSpeech | CFTimeout) self.setChatAbsolute(chatString, chatFlags) ### setSC ### def b_setSC(self, msgIndex): # Local self.setSC(msgIndex) # Distributed self.d_setSC(msgIndex) def d_setSC(self, msgIndex): messenger.send("wakeup") self.sendUpdate("setSC", [msgIndex]) def setSC(self, msgIndex): """ Receive and decode the SC message """ if base.cr.avatarFriendsManager.checkIgnored(self.doId): # We're ignoring this jerk. return if self.doId in base.localAvatar.ignoreList: # We're ignoring this jerk. return chatString = SCDecoders.decodeSCStaticTextMsg(msgIndex) if chatString: self.setChatAbsolute(chatString, CFSpeech | CFQuicktalker | CFTimeout, quiet = 1) base.talkAssistant.receiveOpenSpeedChat(TalkAssistant.SPEEDCHAT_NORMAL, msgIndex, self.doId) ### setSCCustom ### def b_setSCCustom(self, msgIndex): # Local self.setSCCustom(msgIndex) # Distributed self.d_setSCCustom(msgIndex) def d_setSCCustom(self, msgIndex): messenger.send("wakeup") self.sendUpdate("setSCCustom", [msgIndex]) def setSCCustom(self, msgIndex): """ Receive and decode the SC message """ # new ignore list is handled by the Friends manager's, there are now two types, avatar and player. if base.cr.avatarFriendsManager.checkIgnored(self.doId): # We're ignoring this jerk. return if self.doId in base.localAvatar.ignoreList: # We're ignoring this jerk. return chatString = SCDecoders.decodeSCCustomMsg(msgIndex) if chatString: self.setChatAbsolute(chatString, CFSpeech | CFQuicktalker | CFTimeout) base.talkAssistant.receiveOpenSpeedChat(TalkAssistant.SPEEDCHAT_CUSTOM, msgIndex, self.doId) ### setSCEmote ### def b_setSCEmote(self, emoteId): self.b_setEmoteState(emoteId, animMultiplier=self.animMultiplier) def d_friendsNotify(self, avId, status): self.sendUpdate("friendsNotify", [avId, status]) def friendsNotify(self, avId, status): """friendsNotify(self, int32 avId, int8 status) This message is sent by the AI to notify the client when friends are added or removed without the client's participation, if the client happens to be logged in. status is one of: 1 - The indicated avatar is no longer your friend. 2 - The indicated avatar is now your "special" friend. Other changes don't require notification, because the client was presumably in direct control. """ avatar = base.cr.identifyFriend(avId) if (avatar != None): if (status == 1): self.setSystemMessage(avId, OTPLocalizer.WhisperNoLongerFriend % avatar.getName()) elif (status == 2): self.setSystemMessage(avId, OTPLocalizer.WhisperNowSpecialFriend % avatar.getName()) ### teleportQuery ### def d_teleportQuery(self, requesterId, sendToId = None): self.sendUpdate("teleportQuery", [requesterId], sendToId) #print("sending teleportQuery %s %s" % (requesterId, sendToId)) def teleportQuery(self, requesterId): """teleportQuery(self, int requesterId) This distributed message is sent peer-to-peer from one client who is considering teleporting to another client. When it is received, the receiving client should send back a teleportResponse indicating whether she is available to be teleported to (e.g. not on a trolley or something), and if so, where she is. """ # Only consider teleport requests from toons who are on our # friends list, or who are somewhere nearby. #print("received teleportQuery %s" % (requesterId)) #avatar = base.cr.identifyAvatar(requesterId) avatar = base.cr.playerFriendsManager.identifyFriend(requesterId) if avatar != None: # new ignore list is handled by the Friends manager's, there are now two types, avatar and player. if base.cr.avatarFriendsManager.checkIgnored(requesterId): self.d_teleportResponse(self.doId, 2, 0, 0, 0, sendToId = requesterId) return # We're ignoring this jerk. Send back a suitable response. if requesterId in self.ignoreList: self.d_teleportResponse(self.doId, 2, 0, 0, 0, sendToId = requesterId) return # If we're in a private party and the requester isn't invited, tell # them we're busy (ie: let them down easy, don't rub it in their face) if hasattr(base, "distributedParty"): if base.distributedParty.partyInfo.isPrivate: # We need to check the guest list of this party and see if # requesterId is on the list if requesterId not in base.distributedParty.inviteeIds: # Sorry, not on the list, send a try-again-later message self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId = requesterId) return if base.distributedParty.isPartyEnding: self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId = requesterId) return #print("teleport Available %s Ghost %s" % (self.__teleportAvailable, self.ghostMode)) if self.__teleportAvailable and not self.ghostMode: # Generate a whisper message that so-and-so is teleporting # to us. self.setSystemMessage(requesterId, OTPLocalizer.WhisperComingToVisit % (avatar.getName())) # We don't know where we are, so send a teleportQuery # to someone who does. Whoever hangs a hook on this # event will call the appropriate teleportResponse. messenger.send('teleportQuery', [avatar, self]) return # Generate a whisper message that so-and-so wants to # teleport to us, but can't because we're busy. But don't # generate more than one of these per minute or so. if self.failedTeleportMessageOk(requesterId): self.setSystemMessage(requesterId, OTPLocalizer.WhisperFailedVisit % (avatar.getName())) # Send back a try-again-later message. self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId = requesterId) def failedTeleportMessageOk(self, fromId): """failedTeleportMessageOk(self, int fromId) Registers a failure-to-teleport attempt from the indicated avatar. Returns true if it is ok to display this message, or false if the message should be suppressed (because we just recently displayed one). """ now = globalClock.getFrameTime() lastTime = self.lastFailedTeleportMessage.get(fromId, None) if lastTime != None: elapsed = now - lastTime if elapsed < self.TeleportFailureTimeout: return 0 self.lastFailedTeleportMessage[fromId] = now return 1 ### teleportResponse ### def d_teleportResponse(self, avId, available, shardId, hoodId, zoneId, sendToId = None): self.sendUpdate("teleportResponse", [avId, available, shardId, hoodId, zoneId], sendToId) def teleportResponse(self, avId, available, shardId, hoodId, zoneId): messenger.send('teleportResponse', [avId, available, shardId, hoodId, zoneId]) ### teleportGiveup ### def d_teleportGiveup(self, requesterId, sendToId = None): self.sendUpdate("teleportGiveup", [requesterId], sendToId) def teleportGiveup(self, requesterId): """teleportGiveup(self, int requesterId) This message is sent after a client has failed to teleport successfully to another client, probably because the target client didn't stay put. It just pops up a whisper message to that effect. """ avatar = base.cr.identifyAvatar(requesterId) if not self._isValidWhisperSource(avatar): self.notify.warning('teleportGiveup from non-toon %s' % requesterId) return if avatar != None: self.setSystemMessage(requesterId, OTPLocalizer.WhisperGiveupVisit % (avatar.getName())) ### teleportGreeting ### # This message is sent on completion of teleport, to set up the # automatic "Hi, so-and-so" chat balloon. We can't use setChat # because that gets garbled for speedchat-only clients. def b_teleportGreeting(self, avId): self.d_teleportGreeting(avId) self.teleportGreeting(avId) def d_teleportGreeting(self, avId): self.sendUpdate("teleportGreeting", [avId]) def teleportGreeting(self, avId): # Normally, the greeting will be issued to someone who we have # just teleported to, and is therefore in the same zone with # us. If this is so, it is easy to determine what the greeted # toon's actual name is; otherwise, something went wrong # (maybe our greeted toon just left!) and we can simply ignore # the message. avatar = base.cr.getDo(avId) if isinstance(avatar, Avatar.Avatar): self.setChatAbsolute(OTPLocalizer.TeleportGreeting % ( avatar.getName()), CFSpeech | CFTimeout) elif avatar is not None: self.notify.warning( 'got teleportGreeting from %s referencing non-toon %s' % ( self.doId, avId)) ### Teleport support functions ### def setTeleportAvailable(self, available): """setTeleportAvailable(self, bool available) Sets the 'teleportAvailable' flag. When this is true, the client is deemed to be available to be teleported to, and someone should be listening to teleportQuery messages from the messenger. When it is false, teleport queries from nearby toons will automatically be returned with a false response without generating a teleportQuery message. """ self.__teleportAvailable = available def getTeleportAvailable(self): return self.__teleportAvailable def getFriendsList(self): return self.friendsList def setFriendsList(self, friendsList): self.oldFriendsList = self.friendsList self.friendsList = friendsList self.timeFriendsListChanged = globalClock.getFrameTime() assert self.notify.debug("setting friends list to %s" % self.friendsList) # We want to throw a special event whenever the LocalToon's # friends list changes, although not when just any # DistributedToon's friends list changes. It would be cleaner # to define this special behavior in LocalToon.py, but as it # happens, it won't get called there because of the way # ClientDistUpdate.py works. # Fortunately, this method will *only* get called for # LocalToon, and not for any of the other DistributedToons. # So we can get away with putting this here. messenger.send('friendsListChanged') # When our friends list changes, the set of other avatars we # can understand might also change. Avatar.reconsiderAllUnderstandable() def setDISLname(self, name): self.DISLname = name def setDISLid(self, id): self.DISLid = id def setAutoRun(self, value): self.autoRun = value def getAutoRun(self): return self.autoRun
class DistributedPlayer(DistributedAvatar.DistributedAvatar, PlayerBase.PlayerBase, TelemetryLimited): chatGarbler = ChatGarbler.ChatGarbler( {'default': OTPLocalizer.ChatGarblerDefault}) def __init__(self, cr): try: self.DistributedPlayer_initialized except: self.DistributedPlayer_initialized = 1 DistributedAvatar.DistributedAvatar.__init__(self, cr) PlayerBase.PlayerBase.__init__(self) TelemetryLimited.__init__(self) self.__teleportAvailable = 0 self.inventory = None self.experience = None self.friendsList = [] self._districtWeAreGeneratedOn = None self.DISLid = 0 self.adminAccess = 0 self.autoRun = 0 self.lastTeleportQuery = time.time() @staticmethod def GetPlayerGenerateEvent(): return 'DistributedPlayerGenerateEvent' @staticmethod def GetPlayerNetworkDeleteEvent(): return 'DistributedPlayerNetworkDeleteEvent' @staticmethod def GetPlayerDeleteEvent(): return 'DistributedPlayerDeleteEvent' def networkDelete(self): DistributedAvatar.DistributedAvatar.networkDelete(self) messenger.send(self.GetPlayerNetworkDeleteEvent(), [self]) def disable(self): DistributedAvatar.DistributedAvatar.disable(self) messenger.send(self.GetPlayerDeleteEvent(), [self]) def delete(self): try: self.DistributedPlayer_deleted except: self.DistributedPlayer_deleted = 1 del self.experience if self.inventory: self.inventory.unload() del self.inventory DistributedAvatar.DistributedAvatar.delete(self) def generate(self): DistributedAvatar.DistributedAvatar.generate(self) def announceGenerate(self): DistributedAvatar.DistributedAvatar.announceGenerate(self) messenger.send(self.GetPlayerGenerateEvent(), [self]) def setLocation(self, parentId, zoneId): DistributedAvatar.DistributedAvatar.setLocation(self, parentId, zoneId) if not (parentId in (0, None) and zoneId in (0, None)): if not self.cr._isValidPlayerLocation(parentId, zoneId): self.cr.disableDoId(self.doId) self.cr.deleteObject(self.doId) return None def isGeneratedOnDistrict(self, districtId=None): return True # fix for the task button if districtId is None: return self._districtWeAreGeneratedOn is not None else: return self._districtWeAreGeneratedOn == districtId return def getArrivedOnDistrictEvent(self, districtId=None): if districtId is None: return 'arrivedOnDistrict' else: return 'arrivedOnDistrict-%s' % districtId return def arrivedOnDistrict(self, districtId): curFrameTime = globalClock.getFrameTime() if hasattr(self, 'frameTimeWeArrivedOnDistrict' ) and curFrameTime == self.frameTimeWeArrivedOnDistrict: if districtId == 0 and self._districtWeAreGeneratedOn: self.notify.warning( 'ignoring arrivedOnDistrict 0, since arrivedOnDistrict %d occured on the same frame' % self._districtWeAreGeneratedOn) return self._districtWeAreGeneratedOn = districtId self.frameTimeWeArrivedOnDistrict = globalClock.getFrameTime() messenger.send(self.getArrivedOnDistrictEvent(districtId)) messenger.send(self.getArrivedOnDistrictEvent()) def setLeftDistrict(self): self._districtWeAreGeneratedOn = None return def hasParentingRules(self): if self is localAvatar: return True def setSystemMessage(self, aboutId, chatString, whisperType=WhisperPopup.WTSystem): self.displayWhisper(aboutId, chatString, whisperType) def displayWhisper(self, fromId, chatString, whisperType): print 'Whisper type %s from %s: %s' % (whisperType, fromId, chatString) def whisperSCTo(self, msgIndex, sendToId): messenger.send('wakeup') base.cr.TTEFriendsManager.d_whisperSCTo(sendToId, msgIndex) def setWhisperSCFrom(self, fromId, msgIndex): handle = base.cr.identifyAvatar(fromId) if handle == None or base.localAvatar.isIgnored(fromId): return chatString = SCDecoders.decodeSCStaticTextMsg(msgIndex) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTNormal) return def whisperSCCustomTo(self, msgIndex, sendToId): messenger.send('wakeup') base.cr.TTEFriendsManager.d_whisperSCCustomTo(sendToId, msgIndex) def _isValidWhisperSource(self, source): return True def setWhisperSCCustomFrom(self, fromId, msgIndex): handle = base.cr.identifyAvatar(fromId) if handle == None: return if not self._isValidWhisperSource(handle): self.notify.warning('displayWhisper from non-toon %s' % fromId) return if base.localAvatar.isIgnored(fromId): return chatString = SCDecoders.decodeSCCustomMsg(msgIndex) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTNormal) def whisperSCEmoteTo(self, emoteId, sendToId): messenger.send('wakeup') base.cr.TTEFriendsManager.d_whisperSCEmoteTo(sendToId, emoteId) def setWhisperSCEmoteFrom(self, fromId, emoteId): handle = base.cr.identifyAvatar(fromId) if handle == None or base.localAvatar.isIgnored(fromId): return chatString = SCDecoders.decodeSCEmoteWhisperMsg( emoteId, handle.getName()) if chatString: self.displayWhisper(fromId, chatString, WhisperPopup.WTEmote) return def setChatAbsolute(self, chatString, chatFlags, dialogue=None, interrupt=1, quiet=0): DistributedAvatar.DistributedAvatar.setChatAbsolute( self, chatString, chatFlags, dialogue, interrupt) if not quiet: pass def setTalk(self, chat): if not base.cr.chatAgent.verifyMessage(chat): return if base.localAvatar.isIgnored(self.doId): return if not self.understandable: chat = self.chatGarbler.garble(self, len(chat.split(' '))) elif base.whiteList and self.understandable < 2: chat = base.whiteList.processThroughAll(chat, self, self.chatGarbler) self.displayTalk(chat) def setTalkWhisper(self, avId, chat): if not base.cr.chatAgent.verifyMessage(chat): return if base.localAvatar.isIgnored(avId): return if not self.understandable: chat = self.chatGarbler.garble(self, len(chat.split(' '))) elif base.whiteList and self.understandable < 2: chat = base.whiteList.processThroughAll(chat, self.chatGarbler) self.displayTalkWhisper(avId, chat) def displayTalk(self, chat): print 'Talk: %s' % chat def displayTalkWhisper(self, avId, chat): print 'TalkWhisper from %s: %s' % (avId, chat) def b_setSC(self, msgIndex): self.setSC(msgIndex) self.d_setSC(msgIndex) def d_setSC(self, msgIndex): messenger.send('wakeup') self.sendUpdate('setSC', [msgIndex]) def setSC(self, msgIndex): if base.localAvatar.isIgnored(self.doId): return chatString = SCDecoders.decodeSCStaticTextMsg(msgIndex) if chatString: self.setChatAbsolute(chatString, CFSpeech | CFQuicktalker | CFTimeout, quiet=1) def b_setSCCustom(self, msgIndex): self.setSCCustom(msgIndex) self.d_setSCCustom(msgIndex) def d_setSCCustom(self, msgIndex): messenger.send('wakeup') self.sendUpdate('setSCCustom', [msgIndex]) def setSCCustom(self, msgIndex): if base.localAvatar.isIgnored(self.doId): return chatString = SCDecoders.decodeSCCustomMsg(msgIndex) if chatString: self.setChatAbsolute(chatString, CFSpeech | CFQuicktalker | CFTimeout) def b_setSCEmote(self, emoteId): self.b_setEmoteState(emoteId, animMultiplier=self.animMultiplier) def d_friendsNotify(self, avId, status): self.sendUpdate('friendsNotify', [avId, status]) def friendsNotify(self, avId, status): avatar = base.cr.identifyFriend(avId) if avatar != None: if status == 1: self.setSystemMessage( avId, OTPLocalizer.WhisperNoLongerFriend % avatar.getName()) elif status == 2: self.setSystemMessage( avId, OTPLocalizer.WhisperNowSpecialFriend % avatar.getName()) return def d_teleportQuery(self, requesterId, sendToId=None): lastQuery = self.lastTeleportQuery currentQuery = time.time() if currentQuery - lastQuery < 0.1: # Oh boy! We found a skid! self.cr.stopReaderPollTask() self.cr.lostConnection() self.lastTeleportQuery = time.time() base.cr.TTEFriendsManager.d_teleportQuery(sendToId) def teleportQuery(self, requesterId): avatar = base.cr.identifyFriend(requesterId) if avatar is None: self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId=requesterId) elif base.localAvatar.isIgnored(requesterId): self.d_teleportResponse(self.doId, 2, 0, 0, 0, sendToId=requesterId) elif hasattr(base, 'distributedParty') and ( (base.distributedParty.partyInfo.isPrivate and requesterId not in base.distributedParty.inviteeIds) or base.distributedParty.isPartyEnding): self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId=requesterId) elif self.__teleportAvailable and not self.ghostMode: self.setSystemMessage( requesterId, OTPLocalizer.WhisperComingToVisit % avatar.getName()) messenger.send('teleportQuery', [avatar, self]) else: self.setSystemMessage( requesterId, OTPLocalizer.WhisperFailedVisit % avatar.getName()) self.d_teleportResponse(self.doId, 0, 0, 0, 0, sendToId=requesterId) def d_teleportResponse(self, avId, available, shardId, hoodId, zoneId, sendToId): teleportNotify.debug( 'sending teleportResponse%s' % ((avId, available, shardId, hoodId, zoneId, sendToId), )) base.cr.TTEFriendsManager.d_teleportResponse(sendToId, available, shardId, hoodId, zoneId) def teleportResponse(self, avId, available, shardId, hoodId, zoneId): teleportNotify.debug('received teleportResponse%s' % ((avId, available, shardId, hoodId, zoneId), )) messenger.send('teleportResponse', [avId, available, shardId, hoodId, zoneId]) def d_teleportGiveup(self, requesterId, sendToId): teleportNotify.debug('sending teleportGiveup(%s) to %s' % (requesterId, sendToId)) base.cr.TTEFriendsManager.d_teleportGiveup(sendToId) def teleportGiveup(self, requesterId): teleportNotify.debug('received teleportGiveup(%s)' % (requesterId, )) avatar = base.cr.identifyAvatar(requesterId) if not self._isValidWhisperSource(avatar): self.notify.warning('teleportGiveup from non-toon %s' % requesterId) return if avatar is not None: self.setSystemMessage( requesterId, OTPLocalizer.WhisperGiveupVisit % avatar.getName()) def b_teleportGreeting(self, avId): if hasattr(self, 'ghostMode') and self.ghostMode: return self.d_teleportGreeting(avId) self.teleportGreeting(avId) def d_teleportGreeting(self, avId): self.sendUpdate('teleportGreeting', [avId]) def teleportGreeting(self, avId): avatar = base.cr.getDo(avId) if isinstance(avatar, Avatar.Avatar): self.setChatAbsolute( OTPLocalizer.TeleportGreeting % avatar.getName(), CFSpeech | CFTimeout) elif avatar is not None: self.notify.warning( 'got teleportGreeting from %s referencing non-toon %s' % (self.doId, avId)) return def setTeleportAvailable(self, available): self.__teleportAvailable = available def getTeleportAvailable(self): return self.__teleportAvailable def getFriendsList(self): return self.friendsList def setFriendsList(self, friendsList): self.friendsList = friendsList messenger.send('friendsListChanged') Avatar.reconsiderAllUnderstandable() def setDISLid(self, id): self.DISLid = id def setAdminAccess(self, access): self.adminAccess = access self.considerUnderstandable() def getAdminAccess(self): return self.adminAccess def isAdmin(self): return self.adminAccess >= MINIMUM_MAGICWORD_ACCESS def setAutoRun(self, value): self.autoRun = value def getAutoRun(self): return self.autoRun