ToonTownRewritten/toontown/hood/QuietZoneState.py

352 lines
14 KiB
Python

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')
zoneId = self._requestStatus['zoneId']
avId = self._requestStatus.get('avId', -1)
allowRedirect = self._requestStatus.get('allowRedirect', 1)
if avId != -1:
allowRedirect = 0
if not base.cr.welcomeValleyManager:
newZoneId = ZoneUtil.getCanonicalZoneId(zoneId)
if newZoneId != zoneId:
self.gotZoneRedirect(newZoneId)
return
if allowRedirect and ZoneUtil.isWelcomeValley(zoneId):
self.notify.info('Requesting AI redirect from zone %s.' % zoneId)
if base.slowQuietZone:
def rZI(task, zoneId = zoneId, self = self):
base.cr.welcomeValleyManager.requestZoneId(zoneId, self.gotZoneRedirect)
return Task.done
taskMgr.doMethodLater(base.slowQuietZoneDelay, rZI, 'slowQuietZone-welcomeValleyRedirect')
else:
base.cr.welcomeValleyManager.requestZoneId(zoneId, self.gotZoneRedirect)
else:
self.fsm.request('waitForSetZoneResponse')
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