diff --git a/otp/avatar/Avatar.py b/otp/avatar/Avatar.py index 4ea6bfd..f80e89b 100644 --- a/otp/avatar/Avatar.py +++ b/otp/avatar/Avatar.py @@ -21,7 +21,7 @@ def reconsiderAllUnderstandable(): class Avatar(Actor, ShadowCaster): - notify = directNotify.newCategory('Avatar') + notify = DirectNotifyGlobal.directNotify.newCategory('Avatar') ActiveAvatars = [] ManagesNametagAmbientLightChanged = False diff --git a/otp/distributed/OTPInternalRepository.py b/otp/distributed/OTPInternalRepository.py index 6b3fc93..4341a48 100644 --- a/otp/distributed/OTPInternalRepository.py +++ b/otp/distributed/OTPInternalRepository.py @@ -1,6 +1,8 @@ from direct.directnotify import DirectNotifyGlobal from direct.distributed.AstronInternalRepository import AstronInternalRepository from direct.distributed.PyDatagram import * +from direct.distributed.MsgTypes import * +from direct.showbase.PythonUtil import makeList # TODO: Remove Astron dependence. @@ -41,3 +43,7 @@ class OTPInternalRepository(AstronInternalRepository): dg.addUint16(fieldId) self.send(dg) + + def _getMsgName(self, msgId): + # TODO: Remove Astron dependence. + return makeList(MsgId2Names.get(msgId, f'UNKNOWN MESSAGE: {msgId}'))[0] diff --git a/otp/level/DistributedLevel.py b/otp/level/DistributedLevel.py index 7243f62..9adf7b7 100644 --- a/otp/level/DistributedLevel.py +++ b/otp/level/DistributedLevel.py @@ -440,7 +440,7 @@ class DistributedLevel(DistributedObject.DistributedObject, Level.Level): vizList = list(self.zoneNums) vizList.remove(LevelConstants.UberZoneEntId) uberZone = self.getZoneId(LevelConstants.UberZoneEntId) - visibleZoneIds = [OTPGlobals.UberZone, self.levelZone, uberZone] + visibleZoneIds = [self.levelZone, uberZone] for vz in vizList: if vz is not LevelConstants.UberZoneEntId: visibleZoneIds.append(self.getZoneId(vz)) diff --git a/toontown/battle/BattlePlace.py b/toontown/battle/BattlePlace.py index b004e35..e504cf8 100644 --- a/toontown/battle/BattlePlace.py +++ b/toontown/battle/BattlePlace.py @@ -97,13 +97,14 @@ class BattlePlace(Place.Place): if newZoneId != self.zoneId: if newZoneId != None: if __astron__: - if hasattr(self, 'zoneVisDict'): - visList = self.zoneVisDict[newZoneId] - else: - visList = base.cr.playGame.getPlace().loader.zoneVisDict[newZoneId] + # NOTE: This gets generated during the Quiet Zone transition. + # See: toontown/hood/QuietZoneState.py (getCogHQViszones) + visList = base.cr.playGame.getPlace().loader.zoneVisDict[newZoneId] if newZoneId not in visList: visList.append(newZoneId) + if ZoneUtil.getBranchZone(newZoneId) not in visList: + visList.append(ZoneUtil.getBranchZone(newZoneId)) base.cr.sendSetZoneMsg(newZoneId, visList) else: diff --git a/toontown/coghq/CogHQExterior.py b/toontown/coghq/CogHQExterior.py index 7df3905..cd1ec7c 100644 --- a/toontown/coghq/CogHQExterior.py +++ b/toontown/coghq/CogHQExterior.py @@ -76,8 +76,6 @@ class CogHQExterior(BattlePlace.BattlePlace): self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.nodeList, self.zoneId) how = requestStatus['how'] self.fsm.request(how, [requestStatus]) - if __astron__ and self.zoneId != ToontownGlobals.BossbotHQ: - self.handleInterests() def exit(self): self.fsm.requestFinalState() @@ -138,31 +136,3 @@ class CogHQExterior(BattlePlace.BattlePlace): def exitSquished(self): taskMgr.remove(base.localAvatar.uniqueName('finishSquishTask')) base.localAvatar.laffMeter.stop() - - if __astron__: - def handleInterests(self): - # First, we need to load the DNA file for this Cog HQ. - dnaStore = DNAStorage() - dnaFileName = self.genDNAFileName(self.zoneId) - loadDNAFileAI(dnaStore, dnaFileName) - - # Next, we need to collect all of the visgroup zone IDs. - self.zoneVisDict = {} - for i in range(dnaStore.getNumDNAVisGroupsAI()): - visGroup = dnaStore.getDNAVisGroupAI(i) - groupFullName = visGroup.getName() - visZoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName)) - visZoneId = ZoneUtil.getTrueZoneId(visZoneId, self.zoneId) - visibles = [] - for i in range(visGroup.getNumVisibles()): - visibles.append(int(visGroup.getVisibleName(i))) - - visibles.append(ZoneUtil.getBranchZone(visZoneId)) - self.zoneVisDict[visZoneId] = visibles - - # Finally, we want interest in all visgroups due to this being a Cog HQ. - visList = list(self.zoneVisDict.values())[0] - if self.zoneId not in visList: - visList.append(self.zoneId) - - base.cr.sendSetZoneMsg(self.zoneId, visList) diff --git a/toontown/coghq/CogHQLoader.py b/toontown/coghq/CogHQLoader.py index 4a48b01..b64b7b7 100644 --- a/toontown/coghq/CogHQLoader.py +++ b/toontown/coghq/CogHQLoader.py @@ -18,7 +18,7 @@ class CogHQLoader(StateData.StateData): self.parentFSMState = parentFSMState self.placeDoneEvent = 'cogHQLoaderPlaceDone' self.townBattleDoneEvent = 'town-battle-done' - self.fsm = ClassicFSM.ClassicFSM('CogHQLoader', [State.State('start', None, None, ['quietZone', 'cogHQExterior', 'cogHQBossBattle']), + self.fsm = ClassicFSM.ClassicFSM('CogHQLoader', [State.State('start', None, None, ['quietZone', 'cogHQExterior', 'factoryInterior', 'cogHQBossBattle']), State.State('cogHQExterior', self.enterCogHQExterior, self.exitCogHQExterior, ['quietZone', 'cogHQLobby']), State.State('cogHQLobby', self.enterCogHQLobby, self.exitCogHQLobby, ['quietZone', 'cogHQExterior', 'cogHQBossBattle']), State.State('cogHQBossBattle', self.enterCogHQBossBattle, self.exitCogHQBossBattle, ['quietZone']), @@ -149,3 +149,16 @@ class CogHQLoader(StateData.StateData): self.exitPlace() self.placeClass = None return + + if __astron__: + @staticmethod + def genDNAFileName(zoneId): + from toontown.toonbase import ToontownGlobals + zoneId = ZoneUtil.getCanonicalZoneId(zoneId) + hoodId = ZoneUtil.getCanonicalHoodId(zoneId) + hood = ToontownGlobals.dnaMap[hoodId] + phase = ToontownGlobals.streetPhaseMap[hoodId] + if hoodId == zoneId: + zoneId = 'sz' + + return 'phase_%s/dna/%s_%s.dna' % (phase, hood, zoneId) diff --git a/toontown/coghq/FactoryExterior.py b/toontown/coghq/FactoryExterior.py index 3d34355..f0fbedc 100644 --- a/toontown/coghq/FactoryExterior.py +++ b/toontown/coghq/FactoryExterior.py @@ -74,8 +74,6 @@ class FactoryExterior(BattlePlace.BattlePlace): self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.nodeList, self.zoneId) how = requestStatus['how'] self.fsm.request(how, [requestStatus]) - if __astron__ and self.zoneId != ToontownGlobals.LawbotOfficeExt: - self.handleInterests() def exit(self): self._telemLimiter.destroy() @@ -157,31 +155,3 @@ class FactoryExterior(BattlePlace.BattlePlace): messenger.send(self.doneEvent) else: self.notify.error('Unknown mode: ' + where + ' in handleElevatorDone') - - if __astron__: - def handleInterests(self): - # First, we need to load the DNA file for this Cog HQ. - dnaStore = DNAStorage() - dnaFileName = self.genDNAFileName(self.zoneId) - loadDNAFileAI(dnaStore, dnaFileName) - - # Next, we need to collect all of the visgroup zone IDs. - self.zoneVisDict = {} - for i in range(dnaStore.getNumDNAVisGroupsAI()): - visGroup = dnaStore.getDNAVisGroupAI(i) - groupFullName = visGroup.getName() - visZoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName)) - visZoneId = ZoneUtil.getTrueZoneId(visZoneId, self.zoneId) - visibles = [] - for i in range(visGroup.getNumVisibles()): - visibles.append(int(visGroup.getVisibleName(i))) - - visibles.append(ZoneUtil.getBranchZone(visZoneId)) - self.zoneVisDict[visZoneId] = visibles - - # Finally, we want interest in all visgroups due to this being a Cog HQ. - visList = list(self.zoneVisDict.values())[0] - if self.zoneId not in visList: - visList.append(self.zoneId) - - base.cr.sendSetZoneMsg(self.zoneId, visList) diff --git a/toontown/distributed/ToontownClientRepository.py b/toontown/distributed/ToontownClientRepository.py index 662ac58..6401f22 100644 --- a/toontown/distributed/ToontownClientRepository.py +++ b/toontown/distributed/ToontownClientRepository.py @@ -71,7 +71,9 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): self.catalogManager = None self.welcomeValleyManager = None self.newsManager = None - self.streetSign = None + self.wantStreetSign = ConfigVariableBool('want-street-sign', 0).value + if self.wantStreetSign: + self.streetSign = None self.distributedDistrict = None self.partyManager = None self.inGameNewsMgr = None @@ -84,7 +86,8 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): self.deliveryManager = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_TOONTOWN_DELIVERY_MANAGER, 'DistributedDeliveryManager') if ConfigVariableBool('want-code-redemption', 1).value: self.codeRedemptionManager = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_TOONTOWN_CODE_REDEMPTION_MANAGER, 'TTCodeRedemptionMgr') - self.streetSign = None + if self.wantStreetSign: + self.streetSign = None self.furnitureManager = None self.objectManager = None self.magicWordManager = None @@ -101,6 +104,7 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): self.old_setzone_interest_handle = None self.setZoneQueue = Queue() self.accept(ToontownClientRepository.SetZoneDoneEvent, self._handleEmuSetZoneDone) + self.previousInterestZones = None self._deletedSubShardDoIds = set() self.toonNameDict = {} self.gameFSM.addState(State.State('skipTutorialRequest', self.enterSkipTutorialRequest, self.exitSkipTutorialRequest, ['playGame', 'gameOff', 'tutorialQuestion'])) @@ -460,7 +464,8 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): base.localAvatar.defaultZone, -1]) self._userLoggingOut = False - if not self.streetSign: + + if self.wantStreetSign and not self.streetSign: self.streetSign = StreetSign.StreetSign() return @@ -1042,12 +1047,25 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository): if op == ToontownClientRepository.SetInterest: parentId, interestZones, name = args if self.old_setzone_interest_handle == None: + if interestZones == []: + # Empty zones at startup, don't do anything to save bandwidth, just send the event. + self._handleEmuSetZoneDone() + return 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) + if type(interestZones) == list: + interestZones.sort() + if self.previousInterestZones == interestZones: + # Don't do anything to save bandwidth, just send the event. + self._handleEmuSetZoneDone() + return + else: + self.alterInterest(self.old_setzone_interest_handle, parentId, interestZones, name, ToontownClientRepository.SetZoneDoneEvent) + self.previousInterestZones = interestZones elif op == ToontownClientRepository.ClearInterest: self.removeInterest(self.old_setzone_interest_handle, ToontownClientRepository.SetZoneDoneEvent) self.old_setzone_interest_handle = None + self.previousInterestZones = None else: self.notify.error('unknown setZone op: %s' % op) return diff --git a/toontown/hood/QuietZoneState.py b/toontown/hood/QuietZoneState.py index 5efd693..bb22453 100644 --- a/toontown/hood/QuietZoneState.py +++ b/toontown/hood/QuietZoneState.py @@ -1,7 +1,9 @@ from panda3d.core import * +from panda3d.toontown import * from direct.showbase.PythonUtil import Functor, PriorityCallbacks from direct.task import Task from toontown.distributed.ToontownMsgTypes import * +from toontown.toonbase import ToontownGlobals from otp.otpbase import OTPGlobals from direct.directnotify import DirectNotifyGlobal from direct.fsm import StateData @@ -284,18 +286,66 @@ class QuietZoneState(StateData.StateData): where = self._requestStatus['where'] base.cr.dumpAllSubShardObjects() base.cr.resetDeletedSubShardDoIds() - if __astron__ and where == 'street': - visZones = [ZoneUtil.getBranchZone(zoneId)] - # Assuming that the DNA have been loaded by bulk load before this. - loader = base.cr.playGame.hood.loader - visZones += [loader.node2zone[x] for x in loader.nodeDict[zoneId]] - if zoneId not in visZones: - visZones.append(zoneId) - base.cr.sendSetZoneMsg(zoneId, visZones) + if __astron__: + # Add viszones to streets and Cog HQs: + visZones = [] + if where == 'street': + visZones = self.getStreetViszones(zoneId) + if zoneId not in visZones: + visZones.append(zoneId) + base.cr.sendSetZoneMsg(zoneId, visZones) + elif where in ('cogHQExterior', 'factoryExterior'): + visZones = self.getCogHQViszones(zoneId) + if zoneId not in visZones: + visZones.append(zoneId) + if len(visZones) < 1 or (len(visZones) == 1 and visZones[0] == zoneId): + base.cr.sendSetZoneMsg(zoneId) + else: + base.cr.sendSetZoneMsg(zoneId, visZones) else: base.cr.sendSetZoneMsg(zoneId) self.waitForDatabase('WaitForSetZoneResponse') self.fsm.request('waitForSetZoneComplete') + + if __astron__: + def getStreetViszones(self, zoneId): + visZones = [ZoneUtil.getBranchZone(zoneId)] + # Assuming that the DNA have been loaded by bulk load before this (see Street.py). + loader = base.cr.playGame.hood.loader + visZones += [loader.node2zone[x] for x in loader.nodeDict[zoneId]] + self.notify.debug(f'getStreetViszones(zoneId={zoneId}): returning visZones: {visZones}') + return visZones + + def getCogHQViszones(self, zoneId): + loader = base.cr.playGame.hood.loader + + if zoneId in (ToontownGlobals.LawbotOfficeExt, ToontownGlobals.BossbotHQ): + # There are no viszones for these zones, just return an empty list. + return [] + + # First, we need to load the DNA file for this Cog HQ. + dnaStore = DNAStorage() + dnaFileName = loader.genDNAFileName(zoneId) + loadDNAFileAI(dnaStore, dnaFileName) + + # Next, we need to collect all of the visgroup zone IDs. + loader.zoneVisDict = {} + for i in range(dnaStore.getNumDNAVisGroupsAI()): + visGroup = dnaStore.getDNAVisGroupAI(i) + groupFullName = visGroup.getName() + visZoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName)) + visZoneId = ZoneUtil.getTrueZoneId(visZoneId, zoneId) + visibles = [] + for i in range(visGroup.getNumVisibles()): + visibles.append(int(visGroup.getVisibleName(i))) + + # Now we'll store it in the loader since we need them when we enter a Cog battle. + loader.zoneVisDict[visZoneId] = visibles + + # Finally, we want interest in all visgroups due to this being a Cog HQ. + visZones = list(loader.zoneVisDict.values())[0] + self.notify.debug(f'getCogHQViszones(zoneId={zoneId}): returning visZones: {visZones}') + return visZones def exitWaitForSetZoneResponse(self): self.notify.debug('exitWaitForSetZoneResponse()') diff --git a/toontown/spellbook/MagicWordIndex.py b/toontown/spellbook/MagicWordIndex.py index 8ee1667..d01e34e 100644 --- a/toontown/spellbook/MagicWordIndex.py +++ b/toontown/spellbook/MagicWordIndex.py @@ -397,6 +397,19 @@ class Quests(MagicWord): else: return "Valid commands: \"finish\"" +class Factory(MagicWord): + desc = "Quickly start a Sellbot Factory." + execLocation = MagicWordConfig.EXEC_LOC_SERVER + arguments = [('sideEnterace', int, False, 0)] + + def handleWord(self, invoker, avId, toon, *args): + if not hasattr(self.air, "factoryMgr"): + return "No factory manager." + + from toontown.toonbase import ToontownGlobals + zoneId = self.air.factoryMgr.createFactory(ToontownGlobals.SellbotFactoryInt, 1 if args[0] > 0 else 0, [avId]) + return "Created factory, teleporting...", avId, ["cogHQLoader", "factoryInterior", "", ToontownGlobals.SellbotHQ, zoneId, 0] + class BossBattle(MagicWord): aliases = ["boss"] desc = "Create a new or manupliate the current boss battle." diff --git a/toontown/town/Street.py b/toontown/town/Street.py index 0aa6b0a..14788b1 100644 --- a/toontown/town/Street.py +++ b/toontown/town/Street.py @@ -132,7 +132,8 @@ class Street(BattlePlace.BattlePlace): self.enterZone(requestStatus['zoneId']) self.tunnelOriginList = base.cr.hoodMgr.addLinkTunnelHooks(self, self.loader.nodeList, self.zoneId) self.fsm.request(requestStatus['how'], [requestStatus]) - self.replaceStreetSignTextures() + if base.cr.wantStreetSign: + self.replaceStreetSignTextures() return def exit(self, visibilityFlag = 1):