def __init__(self, name, log=True): gr = GarbageReport.GarbageReport("ObjectReport's GarbageReport: %s" % name, log=log) gr.destroy() del gr self._name = name self._pool = ObjectPool.ObjectPool(self._getObjectList()) if log: self.notify.info("===== ObjectReport: '%s' =====\n%s" % (self._name, self.typeFreqStr()))
def __init__(self, name, log=True): gr = GarbageReport.GarbageReport('ObjectReport\'s GarbageReport: %s' % name, log=log) gr.destroy() del gr self._name = name self._pool = ObjectPool.ObjectPool(self._getObjectList()) #ExclusiveObjectPool.addExclObjs(self, self._pool, self._name) if log: self.notify.info('===== ObjectReport: \'%s\' =====\n%s' % (self._name, self.typeFreqStr()))
def doMagicWord(self, word, av, zoneId, senderId): wordIs = self.getWordIs(word) if wordIs("~rename"): if (not self.supportRename): self.notify.warning( "Rename is not supported for %s, requested by %d" % (av.name, senderId)) else: name = string.strip(word[8:]) if name == "": response = "No name." else: av.d_setName(name) elif wordIs("~badname"): self.notify.warning( "Renaming inappropriately named toon %s (doId %d)." % (av.name, av.doId)) name = "toon%d" % (av.doId % 1000000) av.d_setName(name) elif wordIs("~chat"): if (not self.supportSuperchat) and (senderId != av.doId): self.notify.warning( "Super chat is not supported for %s, requested by %d" % (av.name, senderId)) else: av.d_setCommonChatFlags(OTPGlobals.CommonChat) self.notify.debug("Giving common chat permission to " + av.name) elif wordIs("~superchat"): if not self.supportSuperchat: self.notify.warning("Super chat is not supported for " + av.name) else: av.d_setCommonChatFlags(OTPGlobals.SuperChat) self.notify.debug("Giving super chat permission to " + av.name) elif wordIs("~nochat"): av.d_setCommonChatFlags(0) self.notify.debug("Removing special chat permissions for " + av.name) elif wordIs("~listen"): if (not self.supportSuperchat) and (senderId != av.doId): self.notify.warning( "Listen is not supported for %s, requested by %d" % (av.name, senderId)) else: # This is a client-side word. if (senderId != av.doId): self.sendUpdateToAvatarId(av.doId, 'setMagicWord', [word, av.doId, zoneId]) elif wordIs("~fix"): anyChanged = av.fixAvatar() if anyChanged: response = "avatar fixed." else: response = "avatar does not need fixing." self.down_setMagicWordResponse(senderId, response) self.down_setMagicWordResponse(senderId, response) elif wordIs("~who all"): str = '' for obj in list(self.air.doId2do.values()): if hasattr(obj, "accountName"): str += '%s %s\n' % (obj.accountName, obj.name) if not str: str = "No avatars." self.down_setMagicWordResponse(senderId, str) elif wordIs("~ouch"): if av.hp < 1: av.b_setHp(0) av.toonUp(1) else: av.b_setHp(1) self.notify.debug("Only 1 hp for " + av.name) elif wordIs("~sad"): av.b_setHp(0) self.notify.debug("Only 0 hp for " + av.name) elif wordIs("~dead"): av.takeDamage(av.hp) self.notify.debug(av.name + " is dead") elif wordIs("~waydead"): av.takeDamage(av.hp) av.b_setHp(-100) self.notify.debug(av.name + " is way dead") elif wordIs("~toonup"): av.toonUp(av.maxHp) self.notify.debug("Full heal for " + av.name) elif wordIs('~hp'): args = word.split() hp = int(args[1]) av.b_setHp(hp) self.notify.debug('Set hp to %s for %s' % (hp, av.name)) elif wordIs("~ainotify"): args = word.split() n = Notify.ptr().getCategory(args[1]) n.setSeverity({ 'error': NSError, 'warning': NSWarning, 'info': NSInfo, 'debug': NSDebug, 'spam': NSSpam, }[args[2]]) elif wordIs("~ghost"): # Toggle ghost mode. Ghost mode == 2 indicates a magic # word was the source. if av.ghostMode: av.b_setGhostMode(0) else: av.b_setGhostMode(2) elif wordIs('~immortal'): # ~immortal toggles immortal mode on and off # ~immortal 0/1 and ~immortal on/off sets the mode explicitly args = word.split() invalid = False if len(args) > 1 and args[1] in ('0', 'off'): immortal = False elif len(args) > 1 and args[1] in ('1', 'on'): immortal = True elif len(args) > 1: invalid = True else: immortal = not av.immortalMode if invalid: self.down_setMagicWordResponse(senderId, 'unknown argument %s' % args[1]) else: # immortality av.setImmortalMode(immortal) if av.immortalMode: response = 'immortality ON' else: response = 'immortality OFF' self.down_setMagicWordResponse(senderId, response) elif wordIs("~dna"): # Fiddle with your dna. self.doDna(word, av, zoneId, senderId) elif wordIs('~ai'): # Execute an arbitrary Python command on the AI. command = string.strip(word[3:]) self.notify.warning("Executing command '%s' from %s" % (command, senderId)) text = self.__execMessage( command)[:simbase.config.GetInt("ai-debug-length", 300)] self.down_setMagicWordResponse(senderId, text) elif wordIs('~ud'): # Execute an arbitrary Python command on the ud. print(word) channel, command = re.match("~ud ([0-9]+) (.+)", word).groups() channel = int(channel) if (simbase.air.doId2do.get(channel)): self.notify.warning("Passing command '%s' to %s from %s" % (command, channel, senderId)) try: simbase.air.doId2do[channel].sendUpdate( "execCommand", [command, self.doId, senderId, zoneId]) except: pass elif wordIs('~aiobjects'): args = word.split() from direct.showbase import ObjectReport report = ObjectReport.ObjectReport('AI ~objects') if 'all' in args: self.notify.info('printing full object set...') report.getObjectPool().printObjsByType( printReferrers='ref' in args) if hasattr(self, 'baselineObjReport'): self.notify.info( 'calculating diff from baseline ObjectReport...') self.lastDiff = self.baselineObjReport.diff(report) self.lastDiff.printOut(full=('diff' in args or 'dif' in args)) if 'baseline' in args or not hasattr(self, 'baselineObjReport'): self.notify.info('recording baseline ObjectReport...') if hasattr(self, 'baselineObjReport'): self.baselineObjReport.destroy() self.baselineObjReport = report self.down_setMagicWordResponse(senderId, 'objects logged') elif wordIs('~aiobjecthg'): import gc objs = gc.get_objects() type2count = {} for obj in objs: tn = safeTypeName(obj) type2count.setdefault(tn, 0) type2count[tn] += 1 count2type = invertDictLossless(type2count) counts = list(count2type.keys()) counts.sort() counts.reverse() for count in counts: print('%s: %s' % (count, count2type[count])) self.down_setMagicWordResponse(senderId, '~aiobjecthg complete') elif wordIs('~aicrash'): # TODO: require a typed explanation in production # if we call notify.error directly, the magic word mgr will catch it # self.notify.error doesn't seem to work either DelayedCall( Functor(simbase.air.notify.error, '~aicrash: simulating an AI crash')) elif wordIs('~aicontainers'): args = word.split() limit = 30 if 'full' in args: limit = None ContainerReport.ContainerReport('~aicontainers', log=True, limit=limit, threaded=True) elif wordIs('~aigarbage'): args = word.split() # it can take a LOOONG time to print out the garbage referrers and referents # by reference (as opposed to by number) full = ('full' in args) safeMode = ('safe' in args) verbose = ('verbose' in args) delOnly = ('delonly' in args) def handleGarbageDone(senderId, garbageReport): self.down_setMagicWordResponse( senderId, 'garbage logged, %s AI cycles' % garbageReport.getNumCycles()) # This does a garbage collection and dumps the list of leaked (uncollectable) objects to the AI log. GarbageReport.GarbageReport('~aigarbage', fullReport=full, verbose=verbose, log=True, threaded=True, doneCallback=Functor( handleGarbageDone, senderId), safeMode=safeMode, delOnly=delOnly) elif wordIs("~creategarbage"): args = word.split() num = 1 if len(args) > 1: num = int(args[1]) GarbageReport._createGarbage(num) self.down_setMagicWordResponse(senderId, 'leaked garbage created') elif wordIs('~leaktask'): def leakTask(task): return task.cont taskMgr.add(leakTask, uniqueName('leakedTask')) leakTask = None self.down_setMagicWordResponse(senderId, 'leaked task created') elif wordIs('~aileakmessage'): MessengerLeakDetector._leakMessengerObject() self.down_setMagicWordResponse(senderId, 'messenger leak object created') elif wordIs('~leakContainer'): ContainerLeakDetector._createContainerLeak() self.down_setMagicWordResponse(senderId, 'leak container task created') elif wordIs('~aipstats'): args = word.split() hostname = None port = None if len(args) > 1: hostname = args[1] if len(args) > 2: port = int(args[2]) # make sure pstats is enabled simbase.wantStats = 1 Task.TaskManager.pStatsTasks = 1 result = simbase.createStats(hostname, port) connectionName = '%s' % hostname if port is not None: connectionName += ':%s' % port if result: response = 'connected AI pstats to %s' % connectionName else: response = 'could not connect AI pstats to %s' % connectionName self.down_setMagicWordResponse(senderId, response) elif wordIs('~aiprofile'): args = word.split() if len(args) > 1: num = int(args[1]) else: num = 5 session = taskMgr.getProfileSession('~aiprofile') session.setLogAfterProfile(True) taskMgr.profileFrames(num, session) self.down_setMagicWordResponse(senderId, 'profiling %s AI frames...' % num) elif wordIs('~aiframeprofile'): args = word.split() wasOn = bool(taskMgr.getProfileFrames()) if len(args) > 1: setting = bool(int(args[1])) else: setting = not wasOn taskMgr.setProfileFrames(setting) self.down_setMagicWordResponse( senderId, 'AI frame profiling %s%s' % (choice(setting, 'ON', 'OFF'), choice(wasOn == setting, ' already', ''))) elif wordIs('~aitaskprofile'): args = word.split() wasOn = bool(taskMgr.getProfileTasks()) if len(args) > 1: setting = bool(int(args[1])) else: setting = not wasOn taskMgr.setProfileTasks(setting) self.down_setMagicWordResponse( senderId, 'AI task profiling %s%s' % (choice(setting, 'ON', 'OFF'), choice(wasOn == setting, ' already', ''))) elif wordIs('~aitaskspikethreshold'): from direct.task.TaskProfiler import TaskProfiler args = word.split() if len(args) > 1: threshold = float(args[1]) response = 'AI task spike threshold set to %ss' % threshold else: threshold = TaskProfiler.GetDefaultSpikeThreshold() response = 'AI task spike threshold reset to %ss' % threshold TaskProfiler.SetSpikeThreshold(threshold) self.down_setMagicWordResponse(senderId, response) elif wordIs('~ailogtaskprofiles'): args = word.split() if len(args) > 1: name = args[1] else: name = None taskMgr.logTaskProfiles(name) response = 'logged AI task profiles%s' % choice( name, ' for %s' % name, '') self.down_setMagicWordResponse(senderId, response) elif wordIs('~aitaskprofileflush'): args = word.split() if len(args) > 1: name = args[1] else: name = None taskMgr.flushTaskProfiles(name) response = 'flushed AI task profiles%s' % choice( name, ' for %s' % name, '') self.down_setMagicWordResponse(senderId, response) elif wordIs('~aiobjectcount'): simbase.air.printObjectCount() self.down_setMagicWordResponse( senderId, 'logging AI distributed object count...') elif wordIs('~aitaskmgr'): print(taskMgr) self.down_setMagicWordResponse(senderId, 'logging AI taskMgr...') elif wordIs('~aijobmgr'): print(jobMgr) self.down_setMagicWordResponse(senderId, 'logging AI jobMgr...') elif wordIs('~aijobtime'): args = word.split() if len(args) > 1: time = float(args[1]) else: time = None response = '' if time is None: time = jobMgr.getDefaultTimeslice() time = time * 1000. response = 'reset AI jobMgr timeslice to %s ms' % time else: response = 'set AI jobMgr timeslice to %s ms' % time time = time / 1000. jobMgr.setTimeslice(time) self.down_setMagicWordResponse(senderId, response) elif wordIs('~aidetectleaks'): started = self.air.startLeakDetector() self.down_setMagicWordResponse( senderId, choice( started, 'AI leak detector started', 'AI leak detector already started', )) elif wordIs('~aitaskthreshold'): args = word.split() if len(args) > 1.: threshold = float(args[1]) else: threshold = None response = '' if threshold is None: threshold = taskMgr.DefTaskDurationWarningThreshold response = 'reset AI task duration warning threshold to %s' % threshold else: response = 'set AI task duration warning threshold to %s' % threshold taskMgr.setTaskDurationWarningThreshold(threshold) self.down_setMagicWordResponse(senderId, response) elif wordIs('~aimessenger'): print(messenger) self.down_setMagicWordResponse(senderId, 'logging AI messenger...') elif wordIs('~requestdeleted'): requestDeletedDOs = self.air.getRequestDeletedDOs() response = '%s requestDeleted AI objects%s' % ( len(requestDeletedDOs), choice(len(requestDeletedDOs), ', logging...', '')) s = '~requestDeleted: [' for do, age in requestDeletedDOs: s += '[%s, %s]' % (do.__class__.__name__, age) s += ']' self.notify.info(s) if len(requestDeletedDOs): response += '\noldest: %s, %s' % ( requestDeletedDOs[0][0].__class__.__name__, formatTimeCompact(requestDeletedDOs[0][1])) self.down_setMagicWordResponse(senderId, response) elif wordIs('~aigptc'): args = word.split() if len(args) > 1. and hasattr(self.cr, 'leakDetector'): gptcJob = self.cr.leakDetector.getPathsToContainers( '~aigptc', args[1], Functor(self._handleGPTCfinished, senderId, args[1])) else: self.down_setMagicWordResponse(senderId, 'error') elif wordIs('~aigptcn'): args = word.split() if len(args) > 1. and hasattr(self.cr, 'leakDetector'): gptcnJob = self.cr.leakDetector.getPathsToContainersNamed( '~aigptcn', args[1], Functor(self._handleGPTCNfinished, senderId, args[1])) else: self.down_setMagicWordResponse(senderId, 'error') else: # The word is not an AI-side magic word. If the sender is # different than the target avatar, then pass the magic # word down to the target client-side MagicWordManager to # execute a client-side magic word. # MPG this gets done in child class #if (senderId != av.doId): # self.sendUpdateToAvatarId(av.doId, 'setMagicWord', [word, av.doId, zoneId]) return 0 return 1