1235 lines
52 KiB
Python
1235 lines
52 KiB
Python
import time
|
|
from pandac.PandaModules import *
|
|
from direct.distributed.ClockDelta import *
|
|
from direct.gui.DirectGui import *
|
|
from pandac.PandaModules import *
|
|
from direct.interval.IntervalGlobal import ivalMgr
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from direct.distributed import DistributedSmoothNode
|
|
from direct.distributed.PyDatagram import PyDatagram
|
|
from direct.distributed.PyDatagramIterator import PyDatagramIterator
|
|
from direct.task import Task
|
|
from direct.fsm import ClassicFSM
|
|
from direct.fsm import State
|
|
from direct.showbase.PythonUtil import Functor, ScratchPad
|
|
from direct.showbase.InputStateGlobal import inputState
|
|
from otp.avatar import Avatar
|
|
from otp.avatar import DistributedAvatar
|
|
from otp.friends import FriendManager
|
|
from otp.login import TTAccount
|
|
from otp.login import AccountServerConstants
|
|
from otp.login import LoginScreen
|
|
from otp.login import LoginGSAccount
|
|
from otp.login import LoginGoAccount
|
|
from otp.login import LoginWebPlayTokenAccount
|
|
from otp.login import LoginTTAccount
|
|
from otp.login import HTTPUtil
|
|
from otp.distributed import OTPClientRepository
|
|
from otp.distributed import PotentialAvatar
|
|
from otp.distributed import PotentialShard
|
|
from otp.distributed import DistributedDistrict
|
|
from otp.distributed.OtpDoGlobals import *
|
|
from otp.distributed import OtpDoGlobals
|
|
from otp.otpbase import OTPGlobals
|
|
from otp.otpbase import OTPLocalizer
|
|
from otp.otpbase import OTPLauncherGlobals
|
|
from otp.avatar.Avatar import teleportNotify
|
|
from toontown.toonbase.ToonBaseGlobal import *
|
|
from toontown.toonbase.ToontownGlobals import *
|
|
from toontown.launcher.DownloadForceAcknowledge import *
|
|
from toontown.distributed import DelayDelete
|
|
from toontown.friends import FriendHandle
|
|
from toontown.friends import FriendsListPanel
|
|
from toontown.friends import ToontownFriendSecret
|
|
from toontown.uberdog import TTSpeedchatRelay
|
|
from toontown.login import DateObject
|
|
from toontown.login import AccountServerDate
|
|
from toontown.login import AvatarChooser
|
|
from toontown.makeatoon import MakeAToon
|
|
from toontown.pets import DistributedPet, PetDetail, PetHandle
|
|
from toontown.toonbase import TTLocalizer
|
|
from toontown.toontowngui import TTDialog
|
|
from toontown.toon import LocalToon
|
|
from toontown.toon import ToonDNA
|
|
from toontown.distributed import ToontownDistrictStats
|
|
from toontown.makeatoon import TTPickANamePattern
|
|
from toontown.parties import ToontownTimeManager
|
|
from toontown.toon import Toon, DistributedToon
|
|
from .ToontownMsgTypes import *
|
|
from . import HoodMgr
|
|
from . import PlayGame
|
|
from toontown.toontowngui import ToontownLoadingBlocker
|
|
from toontown.hood import StreetSign
|
|
|
|
class ToontownClientRepository(OTPClientRepository.OTPClientRepository):
|
|
SupportTutorial = 1
|
|
GameGlobalsId = OTP_DO_ID_TOONTOWN
|
|
SetZoneDoneEvent = 'TCRSetZoneDone'
|
|
EmuSetZoneDoneEvent = 'TCREmuSetZoneDone'
|
|
SetInterest = 'Set'
|
|
ClearInterest = 'Clear'
|
|
ClearInterestDoneEvent = 'TCRClearInterestDone'
|
|
KeepSubShardObjects = False
|
|
|
|
def __init__(self, serverVersion, launcher = None):
|
|
OTPClientRepository.OTPClientRepository.__init__(self, serverVersion, launcher, playGame=PlayGame.PlayGame)
|
|
self._playerAvDclass = self.dclassesByName['DistributedToon']
|
|
setInterfaceFont(TTLocalizer.InterfaceFont)
|
|
setSignFont(TTLocalizer.SignFont)
|
|
setFancyFont(TTLocalizer.FancyFont)
|
|
nameTagFontIndex = 0
|
|
for font in TTLocalizer.NametagFonts:
|
|
setNametagFont(nameTagFontIndex, TTLocalizer.NametagFonts[nameTagFontIndex])
|
|
nameTagFontIndex += 1
|
|
|
|
self.toons = {}
|
|
if self.http.getVerifySsl() != HTTPClient.VSNoVerify:
|
|
self.http.setVerifySsl(HTTPClient.VSNoDateCheck)
|
|
#prepareAvatar(self.http)
|
|
self.__forbidCheesyEffects = 0
|
|
self.friendManager = None
|
|
self.speedchatRelay = None
|
|
self.trophyManager = None
|
|
self.bankManager = None
|
|
self.catalogManager = None
|
|
self.welcomeValleyManager = None
|
|
self.newsManager = None
|
|
self.streetSign = None
|
|
self.distributedDistrict = None
|
|
self.partyManager = None
|
|
self.inGameNewsMgr = None
|
|
self.whitelistMgr = None
|
|
self.toontownTimeManager = ToontownTimeManager.ToontownTimeManager()
|
|
self.avatarFriendsManager = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_AVATAR_FRIENDS_MANAGER, 'AvatarFriendsManager')
|
|
self.playerFriendsManager = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_PLAYER_FRIENDS_MANAGER, 'TTPlayerFriendsManager')
|
|
self.speedchatRelay = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_TOONTOWN_SPEEDCHAT_RELAY, 'TTSpeedchatRelay')
|
|
self.deliveryManager = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_TOONTOWN_DELIVERY_MANAGER, 'DistributedDeliveryManager')
|
|
if config.GetBool('want-code-redemption', 1):
|
|
self.codeRedemptionManager = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_TOONTOWN_CODE_REDEMPTION_MANAGER, 'TTCodeRedemptionMgr')
|
|
self.streetSign = None
|
|
self.furnitureManager = None
|
|
self.objectManager = None
|
|
self.friendsMap = {}
|
|
self.friendsOnline = {}
|
|
self.friendsMapPending = 0
|
|
self.friendsListError = 0
|
|
self.friendPendingChatSettings = {}
|
|
self.elderFriendsMap = {}
|
|
self.__queryAvatarMap = {}
|
|
self.dateObject = DateObject.DateObject()
|
|
self.accountServerDate = AccountServerDate.AccountServerDate()
|
|
self.hoodMgr = HoodMgr.HoodMgr(self)
|
|
self.setZonesEmulated = 0
|
|
self.old_setzone_interest_handle = None
|
|
self.setZoneQueue = Queue()
|
|
self.accept(ToontownClientRepository.SetZoneDoneEvent, self._handleEmuSetZoneDone)
|
|
self._deletedSubShardDoIds = set()
|
|
self.toonNameDict = {}
|
|
self.gameFSM.addState(State.State('skipTutorialRequest', self.enterSkipTutorialRequest, self.exitSkipTutorialRequest, ['playGame', 'gameOff', 'tutorialQuestion']))
|
|
state = self.gameFSM.getStateNamed('waitOnEnterResponses')
|
|
state.addTransition('skipTutorialRequest')
|
|
state = self.gameFSM.getStateNamed('playGame')
|
|
state.addTransition('skipTutorialRequest')
|
|
self.wantCogdominiums = base.config.GetBool('want-cogdominiums', 1)
|
|
self.wantEmblems = base.config.GetBool('want-emblems', 0)
|
|
if base.config.GetBool('tt-node-check', 0):
|
|
for species in ToonDNA.toonSpeciesTypes:
|
|
for head in ToonDNA.getHeadList(species):
|
|
for torso in ToonDNA.toonTorsoTypes:
|
|
for legs in ToonDNA.toonLegTypes:
|
|
for gender in ('m', 'f'):
|
|
print('species: %s, head: %s, torso: %s, legs: %s, gender: %s' % (species,
|
|
head,
|
|
torso,
|
|
legs,
|
|
gender))
|
|
dna = ToonDNA.ToonDNA()
|
|
dna.newToon((head,
|
|
torso,
|
|
legs,
|
|
gender))
|
|
toon = Toon.Toon()
|
|
try:
|
|
toon.setDNA(dna)
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
return
|
|
|
|
def congratulations(self, avatarChoice):
|
|
self.acceptedScreen = loader.loadModel('phase_3/models/gui/toon_council')
|
|
self.acceptedScreen.setScale(0.667)
|
|
self.acceptedScreen.reparentTo(aspect2d)
|
|
buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
|
|
self.acceptedBanner = DirectLabel(parent=self.acceptedScreen, relief=None, text=OTPLocalizer.CRNameCongratulations, text_scale=0.18, text_fg=Vec4(0.6, 0.1, 0.1, 1), text_pos=(0, 0.05), text_font=getMinnieFont())
|
|
newName = avatarChoice.approvedName
|
|
self.acceptedText = DirectLabel(parent=self.acceptedScreen, relief=None, text=OTPLocalizer.CRNameAccepted % newName, text_scale=0.125, text_fg=Vec4(0, 0, 0, 1), text_pos=(0, -0.15))
|
|
self.okButton = DirectButton(parent=self.acceptedScreen, image=(buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr')), relief=None, text='Ok', scale=1.5, text_scale=0.05, text_pos=(0.0, -0.1), pos=(0, 0, -1), command=self.__handleCongrats, extraArgs=[avatarChoice])
|
|
buttons.removeNode()
|
|
base.transitions.noFade()
|
|
return
|
|
|
|
def __handleCongrats(self, avatarChoice):
|
|
self.acceptedBanner.destroy()
|
|
self.acceptedText.destroy()
|
|
self.okButton.destroy()
|
|
self.acceptedScreen.removeNode()
|
|
del self.acceptedScreen
|
|
del self.okButton
|
|
del self.acceptedText
|
|
del self.acceptedBanner
|
|
if not self.astronSupport:
|
|
datagram = PyDatagram()
|
|
datagram.addUint16(CLIENT_SET_WISHNAME_CLEAR)
|
|
datagram.addUint32(avatarChoice.id)
|
|
datagram.addUint8(1)
|
|
self.send(datagram)
|
|
self.loginFSM.request('waitForSetAvatarResponse', [avatarChoice])
|
|
else:
|
|
self.astronLoginManager.sendAcknowledgeAvatarName(avatarChoice.id,
|
|
lambda: self.loginFSM.request('waitForSetAvatarResponse', [avatarChoice]))
|
|
|
|
def betterlucknexttime(self, avList, index):
|
|
self.rejectDoneEvent = 'rejectDone'
|
|
self.rejectDialog = TTDialog.TTGlobalDialog(doneEvent=self.rejectDoneEvent, message=TTLocalizer.NameShopNameRejected, style=TTDialog.Acknowledge)
|
|
self.rejectDialog.show()
|
|
self.acceptOnce(self.rejectDoneEvent, self.__handleReject, [avList, index])
|
|
base.transitions.noFade()
|
|
|
|
def __handleReject(self, avList, index):
|
|
self.rejectDialog.cleanup()
|
|
if not self.astronSupport:
|
|
datagram = PyDatagram()
|
|
datagram.addUint16(CLIENT_SET_WISHNAME_CLEAR)
|
|
avid = 0
|
|
for k in avList:
|
|
if k.position == index:
|
|
avid = k.id
|
|
|
|
if avid == 0:
|
|
self.notify.error('Avatar rejected not found in avList. Index is: ' + str(index))
|
|
if not self.astronSupport:
|
|
datagram.addUint32(avid)
|
|
datagram.addUint8(0)
|
|
self.send(datagram)
|
|
self.loginFSM.request('waitForAvatarList')
|
|
else:
|
|
self.astronLoginManager.sendAcknowledgeAvatarName(avId, lambda: self.loginFSM.request('waitForAvatarList'))
|
|
|
|
def enterChooseAvatar(self, avList):
|
|
ModelPool.garbageCollect()
|
|
TexturePool.garbageCollect()
|
|
self.sendSetAvatarIdMsg(0)
|
|
self.clearFriendState()
|
|
if self.music == None and base.musicManagerIsValid:
|
|
self.music = base.musicManager.getSound('phase_3/audio/bgm/tt_theme.ogg')
|
|
if self.music:
|
|
self.music.setLoop(1)
|
|
self.music.setVolume(0.9)
|
|
self.music.play()
|
|
base.playMusic(self.music, looping=1, volume=0.9, interrupt=None)
|
|
self.handler = self.handleMessageType
|
|
self.avChoiceDoneEvent = 'avatarChooserDone'
|
|
self.avChoice = AvatarChooser.AvatarChooser(avList, self.loginFSM, self.avChoiceDoneEvent)
|
|
self.avChoice.load(self.isPaid())
|
|
self.avChoice.enter()
|
|
self.accept(self.avChoiceDoneEvent, self.__handleAvatarChooserDone, [avList])
|
|
if config.GetBool('want-gib-loader', 1):
|
|
self.loadingBlocker = ToontownLoadingBlocker.ToontownLoadingBlocker(avList)
|
|
return
|
|
|
|
def __handleAvatarChooserDone(self, avList, doneStatus):
|
|
done = doneStatus['mode']
|
|
if done == 'exit':
|
|
if not launcher.isDummy() and launcher.VISTA:
|
|
if not self.isPaid():
|
|
self.loginFSM.request('shutdown', [OTPLauncherGlobals.ExitUpsell])
|
|
else:
|
|
self.loginFSM.request('shutdown')
|
|
else:
|
|
self.loginFSM.request('shutdown')
|
|
return
|
|
index = self.avChoice.getChoice()
|
|
for av in avList:
|
|
if av.position == index:
|
|
avatarChoice = av
|
|
self.notify.info('================')
|
|
self.notify.info('Chose avatar id: %s' % av.id)
|
|
self.notify.info('Chose avatar name: %s' % av.name)
|
|
dna = ToonDNA.ToonDNA()
|
|
dna.makeFromNetString(av.dna)
|
|
if base.logPrivateInfo:
|
|
self.notify.info('Chose avatar dna: %s' % (dna.asTuple(),))
|
|
self.notify.info('Chose avatar position: %s' % av.position)
|
|
self.notify.info('isPaid: %s' % self.isPaid())
|
|
self.notify.info('freeTimeLeft: %s' % self.freeTimeLeft())
|
|
self.notify.info('allowSecretChat: %s' % self.allowSecretChat())
|
|
self.notify.info('================')
|
|
|
|
if done == 'chose':
|
|
self.avChoice.exit()
|
|
if avatarChoice.approvedName != '':
|
|
self.congratulations(avatarChoice)
|
|
avatarChoice.approvedName = ''
|
|
elif avatarChoice.rejectedName != '':
|
|
avatarChoice.rejectedName = ''
|
|
self.betterlucknexttime(avList, index)
|
|
else:
|
|
self.loginFSM.request('waitForSetAvatarResponse', [avatarChoice])
|
|
elif done == 'nameIt':
|
|
self.accept('downloadAck-response', self.__handleDownloadAck, [avList, index])
|
|
self.downloadAck = DownloadForceAcknowledge('downloadAck-response')
|
|
self.downloadAck.enter(4)
|
|
elif done == 'create':
|
|
self.loginFSM.request('createAvatar', [avList, index])
|
|
elif done == 'delete':
|
|
self.loginFSM.request('waitForDeleteAvatarResponse', [avatarChoice])
|
|
|
|
def __handleDownloadAck(self, avList, index, doneStatus):
|
|
if doneStatus['mode'] == 'complete':
|
|
self.goToPickAName(avList, index)
|
|
else:
|
|
self.loginFSM.request('chooseAvatar', [avList])
|
|
self.downloadAck.exit()
|
|
self.downloadAck = None
|
|
self.ignore('downloadAck-response')
|
|
return
|
|
|
|
def exitChooseAvatar(self):
|
|
self.handler = None
|
|
self.avChoice.exit()
|
|
self.avChoice.unload()
|
|
self.avChoice = None
|
|
self.ignore(self.avChoiceDoneEvent)
|
|
return
|
|
|
|
def goToPickAName(self, avList, index):
|
|
self.avChoice.exit()
|
|
self.loginFSM.request('createAvatar', [avList, index])
|
|
|
|
def enterCreateAvatar(self, avList, index, newDNA = None):
|
|
if self.music:
|
|
self.music.stop()
|
|
self.music = None
|
|
if newDNA != None:
|
|
self.newPotAv = PotentialAvatar.PotentialAvatar('deleteMe', ['',
|
|
'',
|
|
'',
|
|
''], newDNA.makeNetString(), index, 1)
|
|
avList.append(self.newPotAv)
|
|
base.transitions.noFade()
|
|
self.avCreate = MakeAToon.MakeAToon(self.loginFSM, avList, 'makeAToonComplete', index, self.isPaid())
|
|
self.avCreate.load()
|
|
self.avCreate.enter()
|
|
if not self.astronSupport:
|
|
self.handler = self.handleCreateAvatar
|
|
self.accept('makeAToonComplete', self.__handleMakeAToon, [avList, index])
|
|
self.accept('nameShopCreateAvatar', self.sendCreateAvatarMsg)
|
|
self.accept('nameShopPost', self.relayMessage)
|
|
return
|
|
|
|
def relayMessage(self, dg):
|
|
self.send(dg)
|
|
|
|
def handleCreateAvatar(self, msgType, di):
|
|
if msgType == CLIENT_CREATE_AVATAR_RESP or msgType == CLIENT_SET_NAME_PATTERN_ANSWER or msgType == CLIENT_SET_WISHNAME_RESP:
|
|
self.avCreate.ns.nameShopHandler(msgType, di)
|
|
else:
|
|
self.handleMessageType(msgType, di)
|
|
|
|
def __handleMakeAToon(self, avList, avPosition):
|
|
done = self.avCreate.getDoneStatus()
|
|
if done == 'cancel':
|
|
if hasattr(self, 'newPotAv'):
|
|
if self.newPotAv in avList:
|
|
avList.remove(self.newPotAv)
|
|
self.avCreate.exit()
|
|
self.loginFSM.request('chooseAvatar', [avList])
|
|
elif done == 'created':
|
|
self.avCreate.exit()
|
|
if not base.launcher or base.launcher.getPhaseComplete(3.5):
|
|
for i in avList:
|
|
if i.position == avPosition:
|
|
newPotAv = i
|
|
|
|
self.loginFSM.request('waitForSetAvatarResponse', [newPotAv])
|
|
else:
|
|
self.loginFSM.request('chooseAvatar', [avList])
|
|
else:
|
|
self.notify.error('Invalid doneStatus from MakeAToon: ' + str(done))
|
|
|
|
def exitCreateAvatar(self):
|
|
self.ignore('makeAToonComplete')
|
|
self.ignore('nameShopPost')
|
|
self.ignore('nameShopCreateAvatar')
|
|
self.avCreate.unload()
|
|
self.avCreate = None
|
|
self.handler = None
|
|
if hasattr(self, 'newPotAv'):
|
|
del self.newPotAv
|
|
return
|
|
|
|
if not config.GetBool('astron-support', True):
|
|
def handleAvatarResponseMsg(self, di):
|
|
self.cleanupWaitingForDatabase()
|
|
avatarId = di.getUint32()
|
|
returnCode = di.getUint8()
|
|
if returnCode == 0:
|
|
dclass = self.dclassesByName['DistributedToon']
|
|
NametagGlobals.setMasterArrowsOn(0)
|
|
loader.beginBulkLoad('localAvatarPlayGame', OTPLocalizer.CREnteringToontown, 400, 1, TTLocalizer.TIP_GENERAL)
|
|
localAvatar = LocalToon.LocalToon(self)
|
|
localAvatar.dclass = dclass
|
|
base.localAvatar = localAvatar
|
|
__builtins__['localAvatar'] = base.localAvatar
|
|
NametagGlobals.setToon(base.localAvatar)
|
|
localAvatar.doId = avatarId
|
|
self.localAvatarDoId = avatarId
|
|
parentId = None
|
|
zoneId = None
|
|
localAvatar.setLocation(parentId, zoneId)
|
|
localAvatar.generateInit()
|
|
localAvatar.generate()
|
|
localAvatar.updateAllRequiredFields(dclass, di)
|
|
self.doId2do[avatarId] = localAvatar
|
|
localAvatar.initInterface()
|
|
self.sendGetFriendsListRequest()
|
|
self.loginFSM.request('playingGame')
|
|
else:
|
|
self.notify.error('Bad avatar: return code %d' % returnCode)
|
|
return
|
|
else:
|
|
def handleAvatarResponseMsg(self, avatarId, di):
|
|
self.cleanupWaitingForDatabase()
|
|
dclass = self.dclassesByName['DistributedToon']
|
|
NametagGlobals.setMasterArrowsOn(0)
|
|
loader.beginBulkLoad('localAvatarPlayGame', OTPLocalizer.CREnteringToontown, 400, 1, TTLocalizer.TIP_GENERAL)
|
|
localAvatar = LocalToon.LocalToon(self)
|
|
localAvatar.dclass = dclass
|
|
base.localAvatar = localAvatar
|
|
__builtins__['localAvatar'] = base.localAvatar
|
|
NametagGlobals.setToon(base.localAvatar)
|
|
localAvatar.doId = avatarId
|
|
self.localAvatarDoId = avatarId
|
|
parentId = None
|
|
zoneId = None
|
|
localAvatar.setLocation(parentId, zoneId)
|
|
localAvatar.generateInit()
|
|
localAvatar.generate()
|
|
dclass.receiveUpdateBroadcastRequiredOwner(localAvatar, di)
|
|
localAvatar.announceGenerate()
|
|
localAvatar.postGenerateMessage()
|
|
self.doId2do[avatarId] = localAvatar
|
|
localAvatar.initInterface()
|
|
self.sendGetFriendsListRequest()
|
|
self.loginFSM.request('playingGame')
|
|
|
|
def getAvatarDetails(self, avatar, func, *args):
|
|
pad = ScratchPad()
|
|
pad.func = func
|
|
pad.args = args
|
|
pad.avatar = avatar
|
|
pad.delayDelete = DelayDelete.DelayDelete(avatar, 'getAvatarDetails')
|
|
avId = avatar.doId
|
|
self.__queryAvatarMap[avId] = pad
|
|
self.__sendGetAvatarDetails(avId)
|
|
|
|
def cancelAvatarDetailsRequest(self, avatar):
|
|
avId = avatar.doId
|
|
if avId in self.__queryAvatarMap:
|
|
pad = self.__queryAvatarMap.pop(avId)
|
|
pad.delayDelete.destroy()
|
|
|
|
def __sendGetAvatarDetails(self, avId):
|
|
datagram = PyDatagram()
|
|
avatar = self.__queryAvatarMap[avId].avatar
|
|
datagram.addUint16(avatar.getRequestID())
|
|
datagram.addUint32(avId)
|
|
self.send(datagram)
|
|
|
|
def handleGetAvatarDetailsResp(self, di):
|
|
avId = di.getUint32()
|
|
returnCode = di.getUint8()
|
|
self.notify.info('Got query response for avatar %d, code = %d.' % (avId, returnCode))
|
|
try:
|
|
pad = self.__queryAvatarMap[avId]
|
|
except:
|
|
self.notify.warning('Received unexpected or outdated details for avatar %d.' % avId)
|
|
return
|
|
|
|
del self.__queryAvatarMap[avId]
|
|
gotData = 0
|
|
if returnCode != 0:
|
|
self.notify.warning('No information available for avatar %d.' % avId)
|
|
else:
|
|
dclassName = pad.args[0]
|
|
dclass = self.dclassesByName[dclassName]
|
|
pad.avatar.updateAllRequiredFields(dclass, di)
|
|
gotData = 1
|
|
if isinstance(pad.func, str):
|
|
messenger.send(pad.func, list((gotData, pad.avatar) + pad.args))
|
|
else:
|
|
pad.func(*(gotData, pad.avatar) + pad.args)
|
|
pad.delayDelete.destroy()
|
|
|
|
def enterPlayingGame(self, *args, **kArgs):
|
|
OTPClientRepository.OTPClientRepository.enterPlayingGame(self, *args, **kArgs)
|
|
self.gameFSM.request('waitOnEnterResponses', [None,
|
|
base.localAvatar.defaultZone,
|
|
base.localAvatar.defaultZone,
|
|
-1])
|
|
self._userLoggingOut = False
|
|
if not self.streetSign:
|
|
self.streetSign = StreetSign.StreetSign()
|
|
return
|
|
|
|
def exitPlayingGame(self):
|
|
ivalMgr.interrupt()
|
|
if self.objectManager != None:
|
|
self.objectManager.destroy()
|
|
self.objectManager = None
|
|
ToontownFriendSecret.unloadFriendSecret()
|
|
FriendsListPanel.unloadFriendsList()
|
|
messenger.send('cancelFriendInvitation')
|
|
base.removeGlitchMessage()
|
|
taskMgr.remove('avatarRequestQueueTask')
|
|
OTPClientRepository.OTPClientRepository.exitPlayingGame(self)
|
|
if hasattr(base, 'localAvatar'):
|
|
camera.reparentTo(render)
|
|
camera.setPos(0, 0, 0)
|
|
camera.setHpr(0, 0, 0)
|
|
del self.doId2do[base.localAvatar.getDoId()]
|
|
if base.localAvatar.getDelayDeleteCount() != 0:
|
|
self.notify.error('could not delete localAvatar, delayDeletes=%s' % (base.localAvatar.getDelayDeleteNames(),))
|
|
base.localAvatar.deleteOrDelay()
|
|
base.localAvatar.detectLeaks()
|
|
NametagGlobals.setToon(base.cam)
|
|
del base.localAvatar
|
|
del __builtins__['localAvatar']
|
|
loader.abortBulkLoad()
|
|
base.transitions.noTransitions()
|
|
if self._userLoggingOut:
|
|
self.detectLeaks(okTasks=[], okEvents=['destroy-ToontownLoadingScreenTitle', 'destroy-ToontownLoadingScreenTip', 'destroy-ToontownLoadingScreenWaitBar'])
|
|
return
|
|
|
|
def enterGameOff(self):
|
|
OTPClientRepository.OTPClientRepository.enterGameOff(self)
|
|
|
|
def enterWaitOnEnterResponses(self, shardId, hoodId, zoneId, avId):
|
|
self.resetDeletedSubShardDoIds()
|
|
OTPClientRepository.OTPClientRepository.enterWaitOnEnterResponses(self, shardId, hoodId, zoneId, avId)
|
|
|
|
def enterSkipTutorialRequest(self, hoodId, zoneId, avId):
|
|
self.handlerArgs = {'hoodId': hoodId,
|
|
'zoneId': zoneId,
|
|
'avId': avId}
|
|
if not self.astronSupport:
|
|
self.handler = self.handleTutorialQuestion
|
|
self.__requestSkipTutorial(hoodId, zoneId, avId)
|
|
|
|
def __requestSkipTutorial(self, hoodId, zoneId, avId):
|
|
self.notify.debug('requesting skip tutorial')
|
|
self.acceptOnce('skipTutorialAnswered', self.__handleSkipTutorialAnswered, [hoodId, zoneId, avId])
|
|
messenger.send('requestSkipTutorial')
|
|
self.waitForDatabaseTimeout(requestName='RequestSkipTutorial')
|
|
|
|
def __handleSkipTutorialAnswered(self, hoodId, zoneId, avId, allOk):
|
|
if allOk:
|
|
hoodId = self.handlerArgs['hoodId']
|
|
zoneId = self.handlerArgs['zoneId']
|
|
avId = self.handlerArgs['avId']
|
|
self.gameFSM.request('playGame', [hoodId, zoneId, avId])
|
|
else:
|
|
self.notify.warning('allOk is false on skip tutorial, forcing the tutorial.')
|
|
self.gameFSM.request('tutorialQuestion', [hoodId, zoneId, avId])
|
|
|
|
def exitSkipTutorialRequest(self):
|
|
self.cleanupWaitingForDatabase()
|
|
self.handler = None
|
|
self.handlerArgs = None
|
|
self.ignore('skipTutorialAnswered')
|
|
return
|
|
|
|
def enterTutorialQuestion(self, hoodId, zoneId, avId):
|
|
if not self.astronSupport:
|
|
self.handler = self.handleTutorialQuestion
|
|
self.__requestTutorial(hoodId, zoneId, avId)
|
|
|
|
def handleTutorialQuestion(self, msgType, di):
|
|
if msgType == CLIENT_CREATE_OBJECT_REQUIRED:
|
|
self.handleGenerateWithRequired(di)
|
|
elif msgType == CLIENT_CREATE_OBJECT_REQUIRED_OTHER:
|
|
self.handleGenerateWithRequiredOther(di)
|
|
elif msgType == CLIENT_OBJECT_UPDATE_FIELD:
|
|
self.handleUpdateField(di)
|
|
elif msgType == CLIENT_OBJECT_DISABLE_RESP:
|
|
self.handleDisable(di)
|
|
elif msgType == CLIENT_OBJECT_DELETE_RESP:
|
|
self.handleDelete(di)
|
|
elif msgType == CLIENT_GET_FRIEND_LIST_RESP:
|
|
self.handleGetFriendsList(di)
|
|
elif msgType == CLIENT_GET_FRIEND_LIST_EXTENDED_RESP:
|
|
self.handleGetFriendsListExtended(di)
|
|
elif msgType == CLIENT_FRIEND_ONLINE:
|
|
self.handleFriendOnline(di)
|
|
elif msgType == CLIENT_FRIEND_OFFLINE:
|
|
self.handleFriendOffline(di)
|
|
elif msgType == CLIENT_GET_AVATAR_DETAILS_RESP:
|
|
self.handleGetAvatarDetailsResp(di)
|
|
else:
|
|
self.handleMessageType(msgType, di)
|
|
|
|
def __requestTutorial(self, hoodId, zoneId, avId):
|
|
self.notify.debug('requesting tutorial')
|
|
self.acceptOnce('startTutorial', self.__handleStartTutorial, [avId])
|
|
messenger.send('requestTutorial')
|
|
self.waitForDatabaseTimeout(requestName='RequestTutorial')
|
|
|
|
def __handleStartTutorial(self, avId, zoneId):
|
|
self.gameFSM.request('playGame', [Tutorial, zoneId, avId])
|
|
|
|
def exitTutorialQuestion(self):
|
|
self.cleanupWaitingForDatabase()
|
|
self.handler = None
|
|
self.handlerArgs = None
|
|
self.ignore('startTutorial')
|
|
taskMgr.remove('waitingForTutorial')
|
|
return
|
|
|
|
def enterSwitchShards(self, shardId, hoodId, zoneId, avId):
|
|
OTPClientRepository.OTPClientRepository.enterSwitchShards(self, shardId, hoodId, zoneId, avId)
|
|
self.handler = self.handleCloseShard
|
|
|
|
def exitSwitchShards(self):
|
|
OTPClientRepository.OTPClientRepository.exitSwitchShards(self)
|
|
self.ignore(ToontownClientRepository.ClearInterestDoneEvent)
|
|
self.handler = None
|
|
return
|
|
|
|
def enterCloseShard(self, loginState = None):
|
|
OTPClientRepository.OTPClientRepository.enterCloseShard(self, loginState)
|
|
self.handler = self.handleCloseShard
|
|
self._removeLocalAvFromStateServer()
|
|
|
|
if not config.GetBool('astron-support', True):
|
|
def handleCloseShard(self, msgType, di):
|
|
if msgType == CLIENT_CREATE_OBJECT_REQUIRED:
|
|
di2 = PyDatagramIterator(di)
|
|
parentId = di2.getUint32()
|
|
if self._doIdIsOnCurrentShard(parentId):
|
|
return
|
|
elif msgType == CLIENT_CREATE_OBJECT_REQUIRED_OTHER:
|
|
di2 = PyDatagramIterator(di)
|
|
parentId = di2.getUint32()
|
|
if self._doIdIsOnCurrentShard(parentId):
|
|
return
|
|
elif msgType == CLIENT_OBJECT_UPDATE_FIELD:
|
|
di2 = PyDatagramIterator(di)
|
|
doId = di2.getUint32()
|
|
if self._doIdIsOnCurrentShard(doId):
|
|
return
|
|
self.handleMessageType(msgType, di)
|
|
else:
|
|
def handleCloseShard(self, msgType, di):
|
|
if msgType == CLIENT_ENTER_OBJECT_REQUIRED:
|
|
di2 = PyDatagramIterator(di)
|
|
parentId = di2.getUint32()
|
|
if self._doIdIsOnCurrentShard(parentId):
|
|
return
|
|
elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER:
|
|
di2 = PyDatagramIterator(di)
|
|
parentId = di2.getUint32()
|
|
if self._doIdIsOnCurrentShard(parentId):
|
|
return
|
|
elif msgType == CLIENT_OBJECT_SET_FIELD:
|
|
di2 = PyDatagramIterator(di)
|
|
doId = di2.getUint32()
|
|
if self._doIdIsOnCurrentShard(doId):
|
|
return
|
|
self.handleMessageType(msgType, di)
|
|
|
|
def _logFailedDisable(self, doId, ownerView):
|
|
if doId not in self.doId2do and doId in self._deletedSubShardDoIds:
|
|
return
|
|
OTPClientRepository.OTPClientRepository._logFailedDisable(self, doId, ownerView)
|
|
|
|
def exitCloseShard(self):
|
|
OTPClientRepository.OTPClientRepository.exitCloseShard(self)
|
|
self.ignore(ToontownClientRepository.ClearInterestDoneEvent)
|
|
self.handler = None
|
|
return
|
|
|
|
def isShardInterestOpen(self):
|
|
return self.old_setzone_interest_handle is not None or self.uberZoneInterest is not None
|
|
|
|
def resetDeletedSubShardDoIds(self):
|
|
self._deletedSubShardDoIds.clear()
|
|
|
|
def dumpAllSubShardObjects(self):
|
|
if self.KeepSubShardObjects:
|
|
return
|
|
isNotLive = not base.cr.isLive()
|
|
if isNotLive:
|
|
try:
|
|
localAvatar
|
|
except:
|
|
self.notify.info('dumpAllSubShardObjects')
|
|
else:
|
|
self.notify.info('dumpAllSubShardObjects: defaultShard is %s' % localAvatar.defaultShard)
|
|
|
|
ignoredClasses = ('MagicWordManager', 'TimeManager', 'DistributedDistrict', 'FriendManager', 'NewsManager', 'ToontownMagicWordManager', 'WelcomeValleyManager', 'DistributedTrophyMgr', 'CatalogManager', 'DistributedBankMgr', 'EstateManager', 'RaceManager', 'SafeZoneManager', 'DeleteManager', 'TutorialManager', 'ToontownDistrict', 'DistributedDeliveryManager', 'DistributedPartyManager', 'AvatarFriendsManager', 'InGameNewsMgr', 'WhitelistMgr', 'TTCodeRedemptionMgr')
|
|
messenger.send('clientCleanup')
|
|
for avId, pad in list(self.__queryAvatarMap.items()):
|
|
pad.delayDelete.destroy()
|
|
|
|
self.__queryAvatarMap = {}
|
|
delayDeleted = []
|
|
doIds = list(self.doId2do.keys())
|
|
for doId in doIds:
|
|
obj = self.doId2do[doId]
|
|
if isNotLive:
|
|
ignoredClass = obj.__class__.__name__ in ignoredClasses
|
|
if not ignoredClass and obj.parentId != localAvatar.defaultShard:
|
|
self.notify.info('dumpAllSubShardObjects: %s %s parent %s is not defaultShard' % (obj.__class__.__name__, obj.doId, obj.parentId))
|
|
if obj.parentId == localAvatar.defaultShard and obj is not localAvatar:
|
|
if obj.neverDisable:
|
|
if isNotLive:
|
|
if not ignoredClass:
|
|
self.notify.warning('dumpAllSubShardObjects: neverDisable set for %s %s' % (obj.__class__.__name__, obj.doId))
|
|
else:
|
|
self.deleteObject(doId)
|
|
self._deletedSubShardDoIds.add(doId)
|
|
if obj.getDelayDeleteCount() != 0:
|
|
delayDeleted.append(obj)
|
|
|
|
delayDeleteLeaks = []
|
|
for obj in delayDeleted:
|
|
if obj.getDelayDeleteCount() != 0:
|
|
delayDeleteLeaks.append(obj)
|
|
|
|
if len(delayDeleteLeaks):
|
|
s = 'dumpAllSubShardObjects:'
|
|
for obj in delayDeleteLeaks:
|
|
s += '\n could not delete %s (%s), delayDeletes=%s' % (safeRepr(obj), itype(obj), obj.getDelayDeleteNames())
|
|
|
|
self.notify.error(s)
|
|
if isNotLive:
|
|
self.notify.info('dumpAllSubShardObjects: doIds left: %s' % list(self.doId2do.keys()))
|
|
|
|
def _removeCurrentShardInterest(self, callback):
|
|
if self.old_setzone_interest_handle is None:
|
|
self.notify.warning('removeToontownShardInterest: no shard interest open')
|
|
callback()
|
|
return
|
|
self.acceptOnce(ToontownClientRepository.ClearInterestDoneEvent, Functor(self._tcrRemoveUberZoneInterest, callback))
|
|
self._removeEmulatedSetZone(ToontownClientRepository.ClearInterestDoneEvent)
|
|
return
|
|
|
|
def _tcrRemoveUberZoneInterest(self, callback):
|
|
self.acceptOnce(ToontownClientRepository.ClearInterestDoneEvent, Functor(self._tcrRemoveShardInterestDone, callback))
|
|
self.removeInterest(self.uberZoneInterest, ToontownClientRepository.ClearInterestDoneEvent)
|
|
|
|
def _tcrRemoveShardInterestDone(self, callback):
|
|
self.uberZoneInterest = None
|
|
callback()
|
|
return
|
|
|
|
def _doIdIsOnCurrentShard(self, doId):
|
|
if doId == base.localAvatar.defaultShard:
|
|
return True
|
|
do = self.getDo(doId)
|
|
if do:
|
|
if do.parentId == base.localAvatar.defaultShard:
|
|
return True
|
|
return False
|
|
|
|
def _wantShardListComplete(self):
|
|
print(self.activeDistrictMap)
|
|
if self._shardsAreReady():
|
|
self.acceptOnce(ToontownDistrictStats.EventName(), self.shardDetailStatsComplete)
|
|
ToontownDistrictStats.refresh()
|
|
else:
|
|
self.loginFSM.request('noShards')
|
|
|
|
def shardDetailStatsComplete(self):
|
|
self.loginFSM.request('waitForAvatarList')
|
|
|
|
def exitWaitForShardList(self):
|
|
self.ignore(ToontownDistrictStats.EventName())
|
|
OTPClientRepository.OTPClientRepository.exitWaitForShardList(self)
|
|
|
|
def fillUpFriendsMap(self):
|
|
if self.isFriendsMapComplete():
|
|
return 1
|
|
if not self.friendsMapPending and not self.friendsListError:
|
|
self.notify.warning('Friends list stale; fetching new list.')
|
|
self.sendGetFriendsListRequest()
|
|
return 0
|
|
|
|
def isFriend(self, doId):
|
|
for friendId, flags in base.localAvatar.friendsList:
|
|
if friendId == doId:
|
|
self.identifyFriend(doId)
|
|
return 1
|
|
|
|
return 0
|
|
|
|
def isAvatarFriend(self, doId):
|
|
for friendId, flags in base.localAvatar.friendsList:
|
|
if friendId == doId:
|
|
self.identifyFriend(doId)
|
|
return 1
|
|
|
|
return 0
|
|
|
|
def getFriendFlags(self, doId):
|
|
for friendId, flags in base.localAvatar.friendsList:
|
|
if friendId == doId:
|
|
return flags
|
|
|
|
return 0
|
|
|
|
def isFriendOnline(self, doId):
|
|
return doId in self.friendsOnline
|
|
|
|
def addAvatarToFriendsList(self, avatar):
|
|
self.friendsMap[avatar.doId] = avatar
|
|
|
|
def identifyFriend(self, doId, source = None):
|
|
if doId in self.friendsMap:
|
|
teleportNotify.debug('friend %s in friendsMap' % doId)
|
|
return self.friendsMap[doId]
|
|
avatar = None
|
|
if doId in self.doId2do:
|
|
teleportNotify.debug('found friend %s in doId2do' % doId)
|
|
avatar = self.doId2do[doId]
|
|
elif self.cache.contains(doId):
|
|
teleportNotify.debug('found friend %s in cache' % doId)
|
|
avatar = self.cache.dict[doId]
|
|
elif self.playerFriendsManager.getAvHandleFromId(doId):
|
|
teleportNotify.debug('found friend %s in playerFriendsManager' % doId)
|
|
avatar = base.cr.playerFriendsManager.getAvHandleFromId(doId)
|
|
else:
|
|
self.notify.warning("Don't know who friend %s is." % doId)
|
|
return
|
|
if not ((isinstance(avatar, DistributedToon.DistributedToon) and avatar.__class__ is DistributedToon.DistributedToon) or isinstance(avatar, DistributedPet.DistributedPet)):
|
|
self.notify.warning('friendsNotify%s: invalid friend object %s' % (choice(source, '(%s)' % source, ''), doId))
|
|
return
|
|
if base.wantPets:
|
|
if avatar.isPet():
|
|
if avatar.bFake:
|
|
handle = PetHandle.PetHandle(avatar)
|
|
else:
|
|
handle = avatar
|
|
else:
|
|
handle = FriendHandle.FriendHandle(doId, avatar.getName(), avatar.style, avatar.getPetId())
|
|
else:
|
|
handle = FriendHandle.FriendHandle(doId, avatar.getName(), avatar.style, '')
|
|
teleportNotify.debug('adding %s to friendsMap' % doId)
|
|
self.friendsMap[doId] = handle
|
|
return handle
|
|
|
|
def identifyPlayer(self, pId):
|
|
return base.cr.playerFriendsManager.getFriendInfo(pId)
|
|
|
|
def identifyAvatar(self, doId):
|
|
if doId in self.doId2do:
|
|
return self.doId2do[doId]
|
|
else:
|
|
return self.identifyFriend(doId)
|
|
|
|
def isFriendsMapComplete(self):
|
|
for friendId, flags in base.localAvatar.friendsList:
|
|
if self.identifyFriend(friendId) == None:
|
|
return 0
|
|
|
|
if base.wantPets and base.localAvatar.hasPet():
|
|
print(str(self.friendsMap))
|
|
print(str(base.localAvatar.getPetId() in self.friendsMap))
|
|
if (base.localAvatar.getPetId() in self.friendsMap) == None:
|
|
return 0
|
|
return 1
|
|
|
|
def removeFriend(self, avatarId):
|
|
base.localAvatar.sendUpdate('friendsNotify', [base.localAvatar.doId, 1], sendToId=avatarId)
|
|
datagram = PyDatagram()
|
|
datagram.addUint16(CLIENT_REMOVE_FRIEND)
|
|
datagram.addUint32(avatarId)
|
|
self.send(datagram)
|
|
self.estateMgr.removeFriend(base.localAvatar.doId, avatarId)
|
|
for pair in base.localAvatar.friendsList:
|
|
friendId = pair[0]
|
|
if friendId == avatarId:
|
|
base.localAvatar.friendsList.remove(pair)
|
|
return
|
|
|
|
def clearFriendState(self):
|
|
self.friendsMap = {}
|
|
self.friendsOnline = {}
|
|
self.friendsMapPending = 0
|
|
self.friendsListError = 0
|
|
|
|
def sendGetFriendsListRequest(self):
|
|
if self.astronSupport:
|
|
print('sendGetFriendsListRequest TODO')
|
|
else:
|
|
self.friendsMapPending = 1
|
|
self.friendsListError = 0
|
|
datagram = PyDatagram()
|
|
datagram.addUint16(CLIENT_GET_FRIEND_LIST)
|
|
self.send(datagram)
|
|
|
|
def cleanPetsFromFriendsMap(self):
|
|
for objId, obj in list(self.friendsMap.items()):
|
|
from toontown.pets import DistributedPet
|
|
if isinstance(obj, DistributedPet.DistributedPet):
|
|
print('Removing %s reference from the friendsMap' % obj.getName())
|
|
del self.friendsMap[objId]
|
|
|
|
def removePetFromFriendsMap(self):
|
|
doId = base.localAvatar.getPetId()
|
|
if doId and doId in self.friendsMap:
|
|
del self.friendsMap[doId]
|
|
|
|
def addPetToFriendsMap(self, callback = None):
|
|
doId = base.localAvatar.getPetId()
|
|
if not doId or doId in self.friendsMap:
|
|
if callback:
|
|
callback()
|
|
return
|
|
|
|
def petDetailsCallback(petAvatar):
|
|
handle = PetHandle.PetHandle(petAvatar)
|
|
self.friendsMap[doId] = handle
|
|
petAvatar.disable()
|
|
petAvatar.delete()
|
|
if callback:
|
|
callback()
|
|
if self._proactiveLeakChecks:
|
|
petAvatar.detectLeaks()
|
|
|
|
PetDetail.PetDetail(doId, petDetailsCallback)
|
|
|
|
def handleGetFriendsList(self, di):
|
|
error = di.getUint8()
|
|
if error:
|
|
self.notify.warning('Got error return from friends list.')
|
|
self.friendsListError = 1
|
|
else:
|
|
count = di.getUint16()
|
|
for i in range(0, count):
|
|
doId = di.getUint32()
|
|
name = di.getString()
|
|
dnaString = di.getString()
|
|
dna = ToonDNA.ToonDNA()
|
|
dna.makeFromNetString(dnaString)
|
|
petId = di.getUint32()
|
|
handle = FriendHandle.FriendHandle(doId, name, dna, petId)
|
|
self.friendsMap[doId] = handle
|
|
if doId in self.friendsOnline:
|
|
self.friendsOnline[doId] = handle
|
|
if doId in self.friendPendingChatSettings:
|
|
self.notify.debug('calling setCommonAndWL %s' % str(self.friendPendingChatSettings[doId]))
|
|
handle.setCommonAndWhitelistChatFlags(*self.friendPendingChatSettings[doId])
|
|
|
|
if base.wantPets and base.localAvatar.hasPet():
|
|
|
|
def handleAddedPet():
|
|
self.friendsMapPending = 0
|
|
messenger.send('friendsMapComplete')
|
|
|
|
self.addPetToFriendsMap(handleAddedPet)
|
|
return
|
|
self.friendsMapPending = 0
|
|
messenger.send('friendsMapComplete')
|
|
|
|
def handleGetFriendsListExtended(self, di):
|
|
avatarHandleList = []
|
|
error = di.getUint8()
|
|
if error:
|
|
self.notify.warning('Got error return from friends list extended.')
|
|
else:
|
|
count = di.getUint16()
|
|
for i in range(0, count):
|
|
abort = 0
|
|
doId = di.getUint32()
|
|
name = di.getString()
|
|
if name == '':
|
|
abort = 1
|
|
dnaString = di.getString()
|
|
if dnaString == '':
|
|
abort = 1
|
|
else:
|
|
dna = ToonDNA.ToonDNA()
|
|
dna.makeFromNetString(dnaString)
|
|
petId = di.getUint32()
|
|
if not abort:
|
|
handle = FriendHandle.FriendHandle(doId, name, dna, petId)
|
|
avatarHandleList.append(handle)
|
|
|
|
if avatarHandleList:
|
|
messenger.send('gotExtraFriendHandles', [avatarHandleList])
|
|
|
|
def handleFriendOnline(self, di):
|
|
doId = di.getUint32()
|
|
commonChatFlags = 0
|
|
whitelistChatFlags = 0
|
|
if di.getRemainingSize() > 0:
|
|
commonChatFlags = di.getUint8()
|
|
if di.getRemainingSize() > 0:
|
|
whitelistChatFlags = di.getUint8()
|
|
self.notify.debug('Friend %d now online. common=%d whitelist=%d' % (doId, commonChatFlags, whitelistChatFlags))
|
|
if doId not in self.friendsOnline:
|
|
self.friendsOnline[doId] = self.identifyFriend(doId)
|
|
messenger.send('friendOnline', [doId, commonChatFlags, whitelistChatFlags])
|
|
if not self.friendsOnline[doId]:
|
|
self.friendPendingChatSettings[doId] = (commonChatFlags, whitelistChatFlags)
|
|
|
|
def handleFriendOffline(self, di):
|
|
doId = di.getUint32()
|
|
self.notify.debug('Friend %d now offline.' % doId)
|
|
try:
|
|
del self.friendsOnline[doId]
|
|
messenger.send('friendOffline', [doId])
|
|
except:
|
|
pass
|
|
|
|
def getFirstBattle(self):
|
|
from toontown.battle import DistributedBattleBase
|
|
for dobj in list(self.doId2do.values()):
|
|
if isinstance(dobj, DistributedBattleBase.DistributedBattleBase):
|
|
return dobj
|
|
|
|
def forbidCheesyEffects(self, forbid):
|
|
wasAllowed = self.__forbidCheesyEffects != 0
|
|
if forbid:
|
|
self.__forbidCheesyEffects += 1
|
|
else:
|
|
self.__forbidCheesyEffects -= 1
|
|
isAllowed = self.__forbidCheesyEffects != 0
|
|
if wasAllowed != isAllowed:
|
|
for av in Avatar.Avatar.ActiveAvatars:
|
|
if hasattr(av, 'reconsiderCheesyEffect'):
|
|
av.reconsiderCheesyEffect()
|
|
|
|
base.localAvatar.reconsiderCheesyEffect()
|
|
|
|
def areCheesyEffectsAllowed(self):
|
|
return self.__forbidCheesyEffects == 0
|
|
|
|
def getNextSetZoneDoneEvent(self):
|
|
return '%s-%s' % (ToontownClientRepository.EmuSetZoneDoneEvent, self.setZonesEmulated + 1)
|
|
|
|
def getLastSetZoneDoneEvent(self):
|
|
return '%s-%s' % (ToontownClientRepository.EmuSetZoneDoneEvent, self.setZonesEmulated)
|
|
|
|
def getQuietZoneLeftEvent(self):
|
|
return 'leftQuietZone-%s' % (id(self),)
|
|
|
|
def sendSetZoneMsg(self, zoneId, visibleZoneList = None):
|
|
event = self.getNextSetZoneDoneEvent()
|
|
self.setZonesEmulated += 1
|
|
parentId = base.localAvatar.defaultShard
|
|
self.sendSetLocation(base.localAvatar.doId, parentId, zoneId)
|
|
localAvatar.setLocation(parentId, zoneId)
|
|
interestZones = zoneId
|
|
if visibleZoneList is not None:
|
|
interestZones = visibleZoneList
|
|
self._addInterestOpToQueue(ToontownClientRepository.SetInterest, [parentId, interestZones, 'OldSetZoneEmulator'], event)
|
|
return
|
|
|
|
def resetInterestStateForConnectionLoss(self):
|
|
OTPClientRepository.OTPClientRepository.resetInterestStateForConnectionLoss(self)
|
|
self.old_setzone_interest_handle = None
|
|
self.setZoneQueue.clear()
|
|
return
|
|
|
|
def _removeEmulatedSetZone(self, doneEvent):
|
|
self._addInterestOpToQueue(ToontownClientRepository.ClearInterest, None, doneEvent)
|
|
return
|
|
|
|
def _addInterestOpToQueue(self, op, args, event):
|
|
self.setZoneQueue.push([op, args, event])
|
|
if len(self.setZoneQueue) == 1:
|
|
self._sendNextSetZone()
|
|
|
|
def _sendNextSetZone(self):
|
|
op, args, event = self.setZoneQueue.top()
|
|
if op == ToontownClientRepository.SetInterest:
|
|
parentId, interestZones, name = args
|
|
if self.old_setzone_interest_handle == None:
|
|
self.old_setzone_interest_handle = self.addInterest(parentId, interestZones, name, ToontownClientRepository.SetZoneDoneEvent)
|
|
else:
|
|
self.alterInterest(self.old_setzone_interest_handle, parentId, interestZones, name, ToontownClientRepository.SetZoneDoneEvent)
|
|
elif op == ToontownClientRepository.ClearInterest:
|
|
self.removeInterest(self.old_setzone_interest_handle, ToontownClientRepository.SetZoneDoneEvent)
|
|
self.old_setzone_interest_handle = None
|
|
else:
|
|
self.notify.error('unknown setZone op: %s' % op)
|
|
return
|
|
|
|
def _handleEmuSetZoneDone(self):
|
|
op, args, event = self.setZoneQueue.pop()
|
|
queueIsEmpty = self.setZoneQueue.isEmpty()
|
|
if event is not None:
|
|
if not base.killInterestResponse:
|
|
messenger.send(event)
|
|
elif not hasattr(self, '_dontSendSetZoneDone'):
|
|
import random
|
|
if random.random() < 0.05:
|
|
self._dontSendSetZoneDone = True
|
|
else:
|
|
messenger.send(event)
|
|
if not queueIsEmpty:
|
|
self._sendNextSetZone()
|
|
return
|
|
|
|
def _isPlayerDclass(self, dclass):
|
|
return dclass == self._playerAvDclass
|
|
|
|
def _isValidPlayerLocation(self, parentId, zoneId):
|
|
if not self.distributedDistrict:
|
|
return False
|
|
if parentId != self.distributedDistrict.doId:
|
|
return False
|
|
if parentId == self.distributedDistrict.doId and zoneId == OTPGlobals.UberZone:
|
|
return False
|
|
return True
|
|
|
|
def sendQuietZoneRequest(self):
|
|
if self.astronSupport:
|
|
self.sendSetZoneMsg(OTPGlobals.QuietZone, [])
|
|
else:
|
|
self.sendSetZoneMsg(OTPGlobals.QuietZone)
|
|
|
|
if not config.GetBool('astron-support', True):
|
|
def handleQuietZoneGenerateWithRequired(self, di):
|
|
parentId = di.getUint32()
|
|
zoneId = di.getUint32()
|
|
classId = di.getUint16()
|
|
doId = di.getUint32()
|
|
dclass = self.dclassesByNumber[classId]
|
|
if dclass.getClassDef().neverDisable:
|
|
dclass.startGenerate()
|
|
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
|
|
dclass.stopGenerate()
|
|
|
|
def handleQuietZoneGenerateWithRequiredOther(self, di):
|
|
parentId = di.getUint32()
|
|
zoneId = di.getUint32()
|
|
classId = di.getUint16()
|
|
doId = di.getUint32()
|
|
dclass = self.dclassesByNumber[classId]
|
|
if dclass.getClassDef().neverDisable:
|
|
dclass.startGenerate()
|
|
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
|
|
dclass.stopGenerate()
|
|
else:
|
|
def handleQuietZoneGenerateWithRequired(self, di):
|
|
doId = di.getUint32()
|
|
parentId = di.getUint32()
|
|
zoneId = di.getUint32()
|
|
classId = di.getUint16()
|
|
dclass = self.dclassesByNumber[classId]
|
|
if dclass.getClassDef().neverDisable:
|
|
dclass.startGenerate()
|
|
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
|
|
dclass.stopGenerate()
|
|
|
|
def handleQuietZoneGenerateWithRequiredOther(self, di):
|
|
doId = di.getUint32()
|
|
parentId = di.getUint32()
|
|
zoneId = di.getUint32()
|
|
classId = di.getUint16()
|
|
dclass = self.dclassesByNumber[classId]
|
|
if dclass.getClassDef().neverDisable:
|
|
dclass.startGenerate()
|
|
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
|
|
dclass.stopGenerate()
|
|
|
|
def handleGenerateWithRequiredOtherOwner(self, di):
|
|
# OwnerViews are only used for LocalToon in Toontown.
|
|
if self.loginFSM.getCurrentState().getName() == 'waitForSetAvatarResponse':
|
|
doId = di.getUint32()
|
|
parentId = di.getUint32()
|
|
zoneId = di.getUint32()
|
|
classId = di.getUint16()
|
|
self.handleAvatarResponseMsg(doId, di)
|
|
|
|
def handleQuietZoneUpdateField(self, di):
|
|
di2 = DatagramIterator(di)
|
|
doId = di2.getUint32()
|
|
if doId in self.deferredDoIds:
|
|
args, deferrable, dg0, updates = self.deferredDoIds[doId]
|
|
dclass = args[2]
|
|
if not dclass.getClassDef().neverDisable:
|
|
return
|
|
else:
|
|
do = self.getDo(doId)
|
|
if do:
|
|
if not do.neverDisable:
|
|
return
|
|
OTPClientRepository.OTPClientRepository.handleUpdateField(self, di)
|
|
|
|
def handleDelete(self, di):
|
|
doId = di.getUint32()
|
|
self.deleteObject(doId)
|
|
|
|
def deleteObject(self, doId, ownerView = False):
|
|
if doId in self.doId2do:
|
|
obj = self.doId2do[doId]
|
|
del self.doId2do[doId]
|
|
obj.deleteOrDelay()
|
|
if obj.getDelayDeleteCount() <= 0:
|
|
obj.detectLeaks()
|
|
elif self.cache.contains(doId):
|
|
self.cache.delete(doId)
|
|
else:
|
|
self.notify.warning('Asked to delete non-existent DistObj ' + str(doId))
|
|
|
|
def _abandonShard(self):
|
|
for doId, obj in list(self.doId2do.items()):
|
|
if obj.parentId == localAvatar.defaultShard and obj is not localAvatar:
|
|
self.deleteObject(doId)
|
|
|
|
def askAvatarKnown(self, avId):
|
|
if not hasattr(base, 'localAvatar'):
|
|
return 0
|
|
for friendPair in base.localAvatar.friendsList:
|
|
if friendPair[0] == avId:
|
|
return 1
|
|
|
|
return 0
|
|
|
|
def requestAvatarInfo(self, avId):
|
|
if avId == 0:
|
|
return
|
|
datagram = PyDatagram()
|
|
datagram.addUint16(CLIENT_GET_FRIEND_LIST_EXTENDED)
|
|
datagram.addUint16(1)
|
|
datagram.addUint32(avId)
|
|
base.cr.send(datagram)
|
|
|
|
def queueRequestAvatarInfo(self, avId):
|
|
removeTask = 0
|
|
if not hasattr(self, 'avatarInfoRequests'):
|
|
self.avatarInfoRequests = []
|
|
if self.avatarInfoRequests:
|
|
taskMgr.remove('avatarRequestQueueTask')
|
|
if avId not in self.avatarInfoRequests:
|
|
self.avatarInfoRequests.append(avId)
|
|
taskMgr.doMethodLater(0.1, self.sendAvatarInfoRequests, 'avatarRequestQueueTask')
|
|
|
|
def sendAvatarInfoRequests(self, task = None):
|
|
print('Sending request Queue for AV Handles')
|
|
if not hasattr(self, 'avatarInfoRequests'):
|
|
return
|
|
if len(self.avatarInfoRequests) == 0:
|
|
return
|
|
datagram = PyDatagram()
|
|
datagram.addUint16(CLIENT_GET_FRIEND_LIST_EXTENDED)
|
|
datagram.addUint16(len(self.avatarInfoRequests))
|
|
for avId in self.avatarInfoRequests:
|
|
datagram.addUint32(avId)
|
|
|
|
base.cr.send(datagram)
|