from pandac.PandaModules import * from direct.showbase.PythonUtil import Functor, PriorityCallbacks from direct.task import Task from toontown.distributed.ToontownMsgTypes import * from otp.otpbase import OTPGlobals from direct.directnotify import DirectNotifyGlobal from direct.fsm import StateData from direct.fsm import ClassicFSM, State from direct.fsm import State import ZoneUtil class QuietZoneState(StateData.StateData): notify = DirectNotifyGlobal.directNotify.newCategory('QuietZoneState') Disable = False Queue = [] def __init__(self, doneEvent): StateData.StateData.__init__(self, doneEvent) self.fsm = ClassicFSM.ClassicFSM('QuietZoneState', [State.State('off', self.enterOff, self.exitOff, ['waitForQuietZoneResponse']), State.State('waitForQuietZoneResponse', self.enterWaitForQuietZoneResponse, self.exitWaitForQuietZoneResponse, ['waitForZoneRedirect']), State.State('waitForZoneRedirect', self.enterWaitForZoneRedirect, self.exitWaitForZoneRedirect, ['waitForSetZoneResponse']), State.State('waitForSetZoneResponse', self.enterWaitForSetZoneResponse, self.exitWaitForSetZoneResponse, ['waitForSetZoneComplete']), State.State('waitForSetZoneComplete', self.enterWaitForSetZoneComplete, self.exitWaitForSetZoneComplete, ['waitForLocalAvatarOnShard']), State.State('waitForLocalAvatarOnShard', self.enterWaitForLocalAvatarOnShard, self.exitWaitForLocalAvatarOnShard, ['off'])], 'off', 'off') self._enqueueCount = 0 self.fsm.enterInitialState() def load(self): self.notify.debug('load()') def unload(self): self._dequeue() self.notify.debug('unload()') del self.fsm @classmethod def enqueueState(cls, state, requestStatus): cls.Queue = [(state, requestStatus)] + cls.Queue state._enqueueCount += 1 if len(cls.Queue) == 1: cls.startNextQueuedState() @classmethod def dequeueState(cls, state): s, requestStatus = cls.Queue.pop() s._enqueueCount -= 1 if len(cls.Queue) > 0: cls.startNextQueuedState() @classmethod def startNextQueuedState(cls): state, requestStatus = cls.Queue[-1] state._start(requestStatus) def _dequeue(self): newQ = [] for item in self.__class__.Queue: state, requestStatus = item if state is not self: newQ.append(item) self.__class__.Queue = newQ def getEnterWaitForSetZoneResponseMsg(self): return 'enterWaitForSetZoneResponse-%s' % (id(self),) def getQuietZoneLeftEvent(self): return '%s-%s' % (base.cr.getQuietZoneLeftEvent(), id(self)) def getSetZoneCompleteEvent(self): return 'setZoneComplete-%s' % (id(self),) def enter(self, requestStatus): self.notify.debug('enter(requestStatus=' + str(requestStatus) + ')') self._requestStatus = requestStatus self._leftQuietZoneCallbacks = None self._setZoneCompleteCallbacks = None self._leftQuietZoneLocalCallbacks = {} self._setZoneCompleteLocalCallbacks = {} self.enqueueState(self, requestStatus) return def _start(self, requestStatus): base.transitions.fadeScreen(1.0) self.fsm.request('waitForQuietZoneResponse') def getRequestStatus(self): return self._requestStatus def exit(self): self.notify.debug('exit()') del self._requestStatus base.transitions.noTransitions() self.fsm.request('off') self._dequeue() def waitForDatabase(self, description): if base.endlessQuietZone: return base.cr.waitForDatabaseTimeout(requestName='quietZoneState-%s' % description) def clearWaitForDatabase(self): base.cr.cleanupWaitingForDatabase() def addLeftQuietZoneCallback(self, callback, priority = None): if self._leftQuietZoneCallbacks: return self._leftQuietZoneCallbacks.add(callback, priority) else: token = PriorityCallbacks.GetToken() fdc = SubframeCall(callback, taskMgr.getCurrentTask().getPriority() - 1) self._leftQuietZoneLocalCallbacks[token] = fdc return token def removeLeftQuietZoneCallback(self, token): if token is not None: lc = self._leftQuietZoneLocalCallbacks.pop(token, None) if lc: lc.cleanup() if self._leftQuietZoneCallbacks: self._leftQuietZoneCallbacks.remove(token) return def addSetZoneCompleteCallback(self, callback, priority = None): if self._setZoneCompleteCallbacks: return self._setZoneCompleteCallbacks.add(callback, priority) else: token = PriorityCallbacks.GetToken() fdc = SubframeCall(callback, taskMgr.getCurrentTask().getPriority() - 1) self._setZoneCompleteLocalCallbacks[token] = fdc return token def removeSetZoneCompleteCallback(self, token): if token is not None: lc = self._setZoneCompleteLocalCallbacks.pop(token, None) if lc: lc.cleanup() if self._setZoneCompleteCallbacks: self._setZoneCompleteCallbacks.remove(token) return def handleWaitForQuietZoneResponse(self, msgType, di): self.notify.debug('handleWaitForQuietZoneResponse(' + 'msgType=' + str(msgType) + ', di=' + str(di) + ')') if msgType == CLIENT_ENTER_OBJECT_REQUIRED: base.cr.handleQuietZoneGenerateWithRequired(di) elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER: base.cr.handleQuietZoneGenerateWithRequiredOther(di) elif msgType == CLIENT_OBJECT_SET_FIELD: base.cr.handleQuietZoneUpdateField(di) elif msgType in QUIET_ZONE_IGNORED_LIST: self.notify.debug('ignoring unwanted message from previous zone') else: base.cr.handlePlayGame(msgType, di) def handleWaitForZoneRedirect(self, msgType, di): self.notify.debug('handleWaitForZoneRedirect(' + 'msgType=' + str(msgType) + ', di=' + str(di) + ')') if msgType == CLIENT_ENTER_OBJECT_REQUIRED: base.cr.handleQuietZoneGenerateWithRequired(di) elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER: base.cr.handleQuietZoneGenerateWithRequiredOther(di) elif msgType == CLIENT_OBJECT_SET_FIELD: base.cr.handleQuietZoneUpdateField(di) else: base.cr.handlePlayGame(msgType, di) def enterOff(self): self.notify.debug('enterOff()') def exitOff(self): self.notify.debug('exitOff()') self._leftQuietZoneCallbacks = PriorityCallbacks() self._setZoneCompleteCallbacks = PriorityCallbacks() self._leftQuietZoneLocalCallbacks = {} self._setZoneCompleteLocalCallbacks = {} def enterWaitForQuietZoneResponse(self): self.notify.debug('enterWaitForQuietZoneResponse(doneStatus=' + str(self._requestStatus) + ')') if not self.Disable: base.cr.handler = self.handleWaitForQuietZoneResponse base.cr.handlerArgs = self._requestStatus base.cr.setInQuietZone(True) self.setZoneDoneEvent = base.cr.getNextSetZoneDoneEvent() self.acceptOnce(self.setZoneDoneEvent, self._handleQuietZoneComplete) self.waitForDatabase('WaitForQuietZoneResponse') if base.slowQuietZone: def sQZR(task): base.cr.sendQuietZoneRequest() return Task.done taskMgr.doMethodLater(base.slowQuietZoneDelay, sQZR, 'slowQuietZone-sendQuietZoneRequest') else: base.cr.sendQuietZoneRequest() def _handleQuietZoneComplete(self): self.fsm.request('waitForZoneRedirect') def exitWaitForQuietZoneResponse(self): self.notify.debug('exitWaitForQuietZoneResponse()') self.clearWaitForDatabase() base.cr.handler = base.cr.handlePlayGame base.cr.handlerArgs = None base.cr.setInQuietZone(False) self.ignore(self.setZoneDoneEvent) del self.setZoneDoneEvent return def enterWaitForZoneRedirect(self): self.notify.debug('enterWaitForZoneRedirect(requestStatus=' + str(self._requestStatus) + ')') if not self.Disable: base.cr.handler = self.handleWaitForZoneRedirect base.cr.handlerArgs = self._requestStatus base.cr.setInQuietZone(True) self.waitForDatabase('WaitForZoneRedirect') self.gotZoneRedirect(self._requestStatus['zoneId']) def gotZoneRedirect(self, zoneId): self.notify.info('Redirecting to zone %s.' % zoneId) base.cr.handlerArgs['zoneId'] = zoneId base.cr.handlerArgs['hoodId'] = ZoneUtil.getHoodId(zoneId) self.fsm.request('waitForSetZoneResponse') def exitWaitForZoneRedirect(self): self.notify.debug('exitWaitForZoneRedirect()') self.clearWaitForDatabase() base.cr.handler = base.cr.handlePlayGame base.cr.handlerArgs = None base.cr.setInQuietZone(False) return def enterWaitForSetZoneResponse(self): self.notify.debug('enterWaitForSetZoneResponse(requestStatus=' + str(self._requestStatus) + ')') if not self.Disable: messenger.send(self.getEnterWaitForSetZoneResponseMsg(), [self._requestStatus]) base.cr.handlerArgs = self._requestStatus zoneId = self._requestStatus['zoneId'] base.cr.dumpAllSubShardObjects() base.cr.resetDeletedSubShardDoIds() base.cr.sendSetZoneMsg(zoneId) self.waitForDatabase('WaitForSetZoneResponse') self.fsm.request('waitForSetZoneComplete') def exitWaitForSetZoneResponse(self): self.notify.debug('exitWaitForSetZoneResponse()') self.clearWaitForDatabase() base.cr.handler = base.cr.handlePlayGame base.cr.handlerArgs = None return def enterWaitForSetZoneComplete(self): self.notify.debug('enterWaitForSetZoneComplete(requestStatus=' + str(self._requestStatus) + ')') if not self.Disable: base.cr.handlerArgs = self._requestStatus if base.slowQuietZone: def delayFunc(self = self): def hSZC(task): self._handleSetZoneComplete() return Task.done taskMgr.doMethodLater(base.slowQuietZoneDelay, hSZC, 'slowQuietZone-sendSetZoneComplete') nextFunc = delayFunc else: nextFunc = self._handleSetZoneComplete self.waitForDatabase('WaitForSetZoneComplete') self.setZoneDoneEvent = base.cr.getLastSetZoneDoneEvent() self.acceptOnce(self.setZoneDoneEvent, nextFunc) if base.placeBeforeObjects: self._leftQuietZoneCallbacks() self._leftQuietZoneCallbacks = None fdcs = self._leftQuietZoneLocalCallbacks.values() self._leftQuietZoneLocalCallbacks = {} for fdc in fdcs: if not fdc.isFinished(): fdc.finish() messenger.send(self.getQuietZoneLeftEvent()) return def _handleSetZoneComplete(self): self.fsm.request('waitForLocalAvatarOnShard') def exitWaitForSetZoneComplete(self): self.notify.debug('exitWaitForSetZoneComplete()') self.clearWaitForDatabase() base.cr.handler = base.cr.handlePlayGame base.cr.handlerArgs = None self.ignore(self.setZoneDoneEvent) del self.setZoneDoneEvent return def enterWaitForLocalAvatarOnShard(self): self.notify.debug('enterWaitForLocalAvatarOnShard()') if not self.Disable: base.cr.handlerArgs = self._requestStatus self._onShardEvent = localAvatar.getArrivedOnDistrictEvent() self.waitForDatabase('WaitForLocalAvatarOnShard') if localAvatar.isGeneratedOnDistrict(localAvatar.defaultShard): self._announceDone() else: self.acceptOnce(self._onShardEvent, self._announceDone) def _announceDone(self): base.localAvatar.startChat() if base.endlessQuietZone: self._dequeue() return doneEvent = self.doneEvent requestStatus = self._requestStatus self._setZoneCompleteCallbacks() self._setZoneCompleteCallbacks = None fdcs = self._setZoneCompleteLocalCallbacks.values() self._setZoneCompleteLocalCallbacks = {} for fdc in fdcs: if not fdc.isFinished(): fdc.finish() messenger.send(self.getSetZoneCompleteEvent(), [requestStatus]) messenger.send(doneEvent) self._dequeue() return def exitWaitForLocalAvatarOnShard(self): self.notify.debug('exitWaitForLocalAvatarOnShard()') self.clearWaitForDatabase() self.ignore(self._onShardEvent) base.cr.handlerArgs = None del self._onShardEvent return