Пример #1
0
class ToontownAIRepository(ToontownInternalRepository):

    def __init__(self, baseChannel, stateServerChannel, districtName, startTime=6):
        ToontownInternalRepository.__init__(self, baseChannel, stateServerChannel, dcSuffix='AI')
        self.districtName = districtName
        self.notify.setInfo(True)
        self.hoods = []
        self.hoodId2Hood = {}
        self.cogHeadquarters = []
        self.dnaStoreMap = {}
        self.dnaDataMap = {}
        self.suitPlanners = {}
        self.buildingManagers = {}
        self.sillyMeterMgr = None
        self.factoryMgr = None
        self.mintMgr = None
        self.lawOfficeMgr = None
        self.countryClubMgr = None
        self.boardofficeMgr = None
        self.startTime = startTime
        import pymongo
        self.isRaining = False
        self.betaEventTTC = None
        self.betaEventBDHQ = None
        self.invLastPop = None
        self.invLastStatus = None

        import pymongo

        # Mongo stuff to store seperate database things
        self.dbConn = pymongo.MongoClient(config.GetString('mongodb-url', 'localhost'))
        self.dbGlobalCursor = self.dbConn.altis
        self.dbCursor = self.dbGlobalCursor['air-%d' % self.ourChannel]
        self.zoneAllocator = UniqueIdAllocator(ToontownGlobals.DynamicZonesBegin,
                                               ToontownGlobals.DynamicZonesEnd)
        self.zoneDataStore = AIZoneDataStore()

        self.wantFishing = self.config.GetBool('want-fishing', True)
        self.wantHousing = self.config.GetBool('want-housing', True)
        self.wantPets = self.config.GetBool('want-pets', True)
        self.wantParties = self.config.GetBool('want-parties', True)
        self.wantCogbuildings = self.config.GetBool('want-cogbuildings', True)
        self.wantCogdominiums = self.config.GetBool('want-cogdominiums', True)
        self.doLiveUpdates = self.config.GetBool('want-live-updates', False)
        self.wantTrackClsends = self.config.GetBool('want-track-clsends', False)
        self.wantAchievements = self.config.GetBool('want-achievements', True)
        self.wantCharityScreen = self.config.GetBool('want-charity-screen', False)
        self.baseXpMultiplier = self.config.GetFloat('base-xp-multiplier', 1.0)
        self.wantHalloween = self.config.GetBool('want-halloween', False)
        self.wantChristmas = self.config.GetBool('want-christmas', False)
        self.wantGardening = self.config.GetBool('want-gardening', False)
        self.cogSuitMessageSent = False
        self.weatherCycleDuration = self.config.GetInt('weather-cycle-duration', 100)

    def createManagers(self):
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)
        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(2)
        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)
        self.safeZoneManager = SafeZoneManagerAI(self)
        self.safeZoneManager.generateWithRequired(2)
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)
        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(2)
        self.questManager = QuestManagerAI(self)
        self.banManager = BanManagerAI.BanManagerAI(self)
        self.achievementsManager = AchievementsManagerAI(self)
        self.certManager = CertificateManagerAI(self)
        self.suitInvasionManager = SuitInvasionManagerAI(self)
        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(2)
        self.cogSuitMgr = CogSuitManagerAI.CogSuitManagerAI(self)
        self.promotionMgr = PromotionManagerAI.PromotionManagerAI(self)
        self.experienceMgr = ExperienceRewardManagerAI.ExperienceRewardManagerAI(self)
        self.cogPageManager = CogPageManagerAI.CogPageManagerAI()
        self.sillyMeterMgr = DistributedSillyMeterMgrAI.DistributedSillyMeterMgrAI(self)
        self.sillyMeterMgr.generateWithRequired(2)
        self.hydrantZeroMgr = DistributedHydrantZeroMgrAI.DistributedHydrantZeroMgrAI(self)
        self.hydrantZeroMgr.generateWithRequired(2)
        self.mailboxZeroMgr = DistributedMailboxZeroMgrAI.DistributedMailboxZeroMgrAI(self)
        self.mailboxZeroMgr.generateWithRequired(2)
        self.trashcanZeroMgr = DistributedTrashcanZeroMgrAI.DistributedTrashcanZeroMgrAI(self)
        self.trashcanZeroMgr.generateWithRequired(2)
        self.dialogueManager = DialogueManagerAI(self)
        self.bingoHolidayMgr = BingoHolidayMgrAI(self, ToontownGlobals.FISH_BINGO_NIGHT)
        self.bingoWeekendMgr = BingoWeekendMgrAI(self, ToontownGlobals.SILLY_SATURDAY_BINGO)
        self.trolleyHolidayMgr = TrolleyHolidayMgrAI(self, ToontownGlobals.TROLLEY_HOLIDAY)
        self.trolleyWeekendMgr = TrolleyWeekendMgrAI(self, ToontownGlobals.TROLLEY_WEEKEND)
        self.holidayManager = HolidayManagerAI(self)


        if self.wantFishing:
            self.fishManager = FishManagerAI(self)

        if self.wantHousing:
            self.estateManager = EstateManagerAI(self)
            self.estateManager.generateWithRequired(2)
            self.catalogManager = CatalogManagerAI(self)
            self.catalogManager.generateWithRequired(2)
            self.deliveryManager = self.generateGlobalObject(OTP_DO_ID_TOONTOWN_DELIVERY_MANAGER, 'DistributedDeliveryManager')
            self.mailManager = self.generateGlobalObject(OTP_DO_ID_TOONTOWN_MAIL_MANAGER, 'DistributedMailManager')

        if self.wantPets:
            self.petMgr = PetManagerAI(self)

        self.publicPetMgr = DistributedPublicPetMgrAI.DistributedPublicPetMgrAI(self)
        self.publicPetMgr.generateWithRequired(2)

        if self.wantParties:
            self.partyManager = DistributedPartyManagerAI(self)
            self.partyManager.generateWithRequired(2)
            self.globalPartyMgr = self.generateGlobalObject(OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        self.codeRedemptionMgr = TTCodeRedemptionMgrAI(self)
        self.codeRedemptionMgr.generateWithRequired(2)
        self.chatAgent = simbase.air.generateGlobalObject(OTP_DO_ID_CHAT_MANAGER, 'ChatAgent')

    def createSafeZones(self):
        NPCToons.generateZone2NpcDict()
        if self.config.GetBool('want-toontown-central', True):
            hood = TTHoodAI.TTHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        if self.config.GetBool('want-donalds-dock', True):
            hood = DDHoodAI.DDHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        if self.config.GetBool('want-daisys-garden', True):
            hood = DGHoodAI.DGHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        if self.config.GetBool('want-minnies-melodyland', True):
            hood = MMHoodAI.MMHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        if self.config.GetBool('want-the-burrrgh', True):
            hood = BRHoodAI.BRHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        if self.config.GetBool('want-donalds-dreamland', True):
            hood = DLHoodAI.DLHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        if self.config.GetBool('want-goofy-speedway', True):
            hood = GSHoodAI.GSHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        if self.config.GetBool('want-outdoor-zone', True):
            hood = OZHoodAI.OZHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        if self.config.GetBool('want-golf-zone', True):
            hood = GZHoodAI.GZHoodAI(self)
            self.hoods.append(hood)
            self.hoodId2Hood[hood.zoneId] = hood
        hood = TTOHoodAI.TTOHoodAI(self)
        self.hoods.append(hood)
        self.hoodId2Hood[hood.zoneId] = hood

    def createCogHeadquarters(self):
        NPCToons.generateZone2NpcDict()
        if self.config.GetBool('want-sellbot-headquarters', True):
            self.factoryMgr = FactoryManagerAI.FactoryManagerAI(self)
            self.cogHeadquarters.append(SellbotHQAI.SellbotHQAI(self))
        if self.config.GetBool('want-cashbot-headquarters', True):
            self.mintMgr = MintManagerAI.MintManagerAI(self)
            self.cogHeadquarters.append(CashbotHQAI.CashbotHQAI(self))
        if self.config.GetBool('want-lawbot-headquarters', True):
            self.lawOfficeMgr = LawOfficeManagerAI.LawOfficeManagerAI(self)
            self.cogHeadquarters.append(LawbotHQAI.LawbotHQAI(self))
        if self.config.GetBool('want-bossbot-headquarters', True):
            self.countryClubMgr = CountryClubManagerAI.CountryClubManagerAI(self)
            self.cogHeadquarters.append(BossbotHQAI.BossbotHQAI(self))
        if self.config.GetBool('want-bdhq', True):
            self.boardofficeMgr = BoardOfficeManagerAI.BoardOfficeManagerAI(self)
            self.cogHeadquarters.append(BoardbotHQAI.BoardbotHQAI(self))

    def handleConnected(self):
        self.registerForChannel(MESSENGER_CHANNEL_AI)

        self.districtId = self.allocateChannel()
        self.notify.info('Creating ToontownDistrictAI(%d)...' % self.districtId)
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)

        self.notify.info('Claiming ownership of channel ID: %d...' % self.districtId)
        self.setAI(self.districtId, self.ourChannel)

        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(),
            self.getGameDoId(), 3)

        self.notify.info('Created ToontownDistrictStats(%d)' % self.districtStats.doId)

        self.notify.info('Creating managers...')
        self.createManagers()
        if self.config.GetBool('want-safe-zones', True):
            self.notify.info('Creating safe zones...')
            self.createSafeZones()

        if self.config.GetBool('want-cog-headquarters', True):
            self.notify.info('Creating Cog headquarters...')
            self.createCogHeadquarters()

        self.notify.info('Making district available...')
        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('Done.')

        self.notify.info("Starting Invasion Tracker...")
        taskMgr.doMethodLater(2, self.updateInvasionTrackerTask, 'updateInvasionTracker-%d' % self.ourChannel)
        self.notify.info("Invasion Tracker Started!")
        self.sendNetEvent('registerShard', [self.districtId, True], channels=[MESSENGER_CHANNEL_UD])

        atexit.register(self.shardDeath)

    def shardDeath(self):
        self.sendNetEvent('registerShard', [self.districtId, False], channels=[MESSENGER_CHANNEL_UD])

    def lookupDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phaseNum = ToontownGlobals.phaseMap[hoodId]
        else:
            phaseNum = ToontownGlobals.streetPhaseMap[hoodId]

        return 'phase_%s/dna/%s_%s.pdna' % (phaseNum, hood, zoneId)

    def loadDNAFileAI(self, dnastore, filename):
        return loadDNAFileAI(dnastore, filename)

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(self.districtStats.getAvatarCount() + 1)

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(self.districtStats.getAvatarCount() - 1)

    def setHour(self, hour):
        pass # Todo: Hour on district page

    def allocateZone(self):
        return self.zoneAllocator.allocate()

    def deallocateZone(self, zone):
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getTrackClsends(self):
        return self.wantTrackClsends

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % (avId)

    def trueUniqueName(self, name):
        return self.uniqueName(name)

    def updateInvasionTrackerTask(self, task):
        task.delayTime = 10 # Set it to 10 after doing it the first time
        statusToType = {
        0: 'None',
        1: 'Bossbot',
        2: 'Lawbot',
        3: 'Cashbot',
        4: 'Sellbot',
        5: 'Boardbot'}
        pop = self.districtStats.getAvatarCount()
        invstatus = statusToType.get(self.districtStats.getInvasionStatus(), 'None')
        total = self.districtStats.getInvasionTotal()
        defeated = total - self.districtStats.getInvasionRemaining()
        tupleStatus = (self.districtStats.getInvasionStatus(), self.districtStats.getInvasionType())
        invstatus = self.statusToType(tupleStatus)
        timeleft = self.districtStats.getInvasionTimeRemaining()

        self.invLastPop = pop
        self.invLastStatus = invstatus

        return task.again

    def statusToType(self, tupleInvasionStatus):
        try:
            statusToSuit = {
                0: 'None',
                1: 'Bossbot',
                2: 'Lawbot',
                3: 'Cashbot',
                4: 'Sellbot',
                5: 'Boardbot'
            }
            suit = statusToSuit.get(tupleInvasionStatus[0], 'None')
            if suit == 'None':
                return suit

            Type = SuitInvasionGlobals.comboToType.get(str(tupleInvasionStatus[0]) + str(tupleInvasionStatus[1]), 'None')
            Type = Type.replace(' ', '%20')
            if Type == 'None':
                return Type
            return Type + '|' + suit
        except:
            return 'None'
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self, baseChannel, stateServerChannel, districtName):
        ToontownInternalRepository.__init__(self,
                                            baseChannel,
                                            stateServerChannel,
                                            dcSuffix='AI')

        self.districtName = districtName

        self.notify.setInfo(True)  # Our AI repository should always log info.
        self.hoods = []
        self.cogHeadquarters = []
        self.dnaStoreMap = {}
        self.dnaDataMap = {}
        self.suitPlanners = {}
        self.buildingManagers = {}
        self.factoryMgr = None
        self.mintMgr = None
        self.lawOfficeMgr = None
        self.countryClubMgr = None

        # For when in game events occur
        self.globalOccurrenceMgr = self.generateGlobalObject(
            OTP_DO_ID_GLOBAL_OCCURRENCE_MANAGER,
            'GlobalOccurrenceManager')  # OCCURRENCE-MANAGER-AI

        self.zoneAllocator = UniqueIdAllocator(
            ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd)
        self.zoneDataStore = AIZoneDataStore()

        self.wantFishing = self.config.GetBool('want-fishing', True)
        self.wantHousing = self.config.GetBool('want-housing', True)
        self.wantPets = self.config.GetBool('want-pets', True)
        self.wantParties = self.config.GetBool('want-parties', True)
        self.wantCogbuildings = self.config.GetBool('want-cogbuildings', True)
        self.wantCogdominiums = self.config.GetBool('want-cogdominiums', True)
        self.doLiveUpdates = self.config.GetBool('want-live-updates', False)
        self.wantTrackClsends = self.config.GetBool('want-track-clsends',
                                                    False)
        self.baseXpMultiplier = self.config.GetFloat('base-xp-multiplier', 1.0)
        self.wantHalloween = self.config.GetBool('want-halloween', False)
        self.wantChristmas = self.config.GetBool('want-christmas', False)
        self.wantFireworks = self.config.GetBool('want-fireworks', False)

        self.cogSuitMessageSent = False

    def createManagers(self):
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)
        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(2)
        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)

        self.holidayManager = HolidayManagerAI(self)

        self.safeZoneManager = SafeZoneManagerAI(self)
        self.safeZoneManager.generateWithRequired(2)
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)
        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(2)
        self.questManager = QuestManagerAI(self)
        self.banManager = BanManagerAI.BanManagerAI(self)
        self.suitInvasionManager = SuitInvasionManagerAI(self)
        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(2)
        self.cogSuitMgr = CogSuitManagerAI.CogSuitManagerAI(self)
        self.promotionMgr = PromotionManagerAI.PromotionManagerAI(self)
        self.cogPageManager = CogPageManagerAI.CogPageManagerAI()

        if self.wantFishing:
            self.fishManager = FishManagerAI(self)
        if self.wantHousing:
            self.estateManager = EstateManagerAI(self)
            self.estateManager.generateWithRequired(2)
            self.catalogManager = CatalogManagerAI(self)
            self.catalogManager.generateWithRequired(2)
            self.deliveryManager = self.generateGlobalObject(
                OTP_DO_ID_TOONTOWN_DELIVERY_MANAGER,
                'DistributedDeliveryManager')
        if self.wantPets:
            self.petMgr = PetManagerAI(self)

        if self.wantParties:
            self.partyManager = DistributedPartyManagerAI(self)
            self.partyManager.generateWithRequired(2)
            # Setup view of global ub party manager
            self.globalPartyMgr = self.generateGlobalObject(
                OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        self.wantLeaderBoardMgr = True
        if self.wantLeaderBoardMgr:
            self.leaderBoardMgr = DistributedLeaderBoardManagerAI(self)

        # Need work
        self.codeRedemptionManager = TTCodeRedemptionMgrAI(self)
        self.codeRedemptionManager.generateWithRequired(2)

    def createSafeZones(self):
        NPCToons.generateZone2NpcDict()
        if self.config.GetBool('want-toontown-central', True):
            self.hoods.append(TTHoodAI.TTHoodAI(self))
        if self.config.GetBool('want-donalds-dock', True):
            self.hoods.append(DDHoodAI.DDHoodAI(self))
        if self.config.GetBool('want-daisys-garden', True):
            self.hoods.append(DGHoodAI.DGHoodAI(self))
        if self.config.GetBool('want-minnies-melodyland', True):
            self.hoods.append(MMHoodAI.MMHoodAI(self))
        if self.config.GetBool('want-the-burrrgh', True):
            self.hoods.append(BRHoodAI.BRHoodAI(self))
        if self.config.GetBool('want-donalds-dreamland', True):
            self.hoods.append(DLHoodAI.DLHoodAI(self))
        if self.config.GetBool('want-goofy-speedway', True):
            self.hoods.append(GSHoodAI.GSHoodAI(self))
        if self.config.GetBool('want-outdoor-zone', True):
            self.hoods.append(OZHoodAI.OZHoodAI(self))
        if self.config.GetBool('want-golf-zone', True):
            self.hoods.append(GZHoodAI.GZHoodAI(self))

    def createCogHeadquarters(self):
        if self.config.GetBool('want-sellbot-headquarters', True):
            self.factoryMgr = FactoryManagerAI.FactoryManagerAI(self)
            self.cogHeadquarters.append(SellbotHQAI.SellbotHQAI(self))
        if self.config.GetBool('want-cashbot-headquarters', True):
            self.mintMgr = MintManagerAI.MintManagerAI(self)
            self.cogHeadquarters.append(CashbotHQAI.CashbotHQAI(self))
        if self.config.GetBool('want-lawbot-headquarters', True):
            self.lawOfficeMgr = LawOfficeManagerAI.LawOfficeManagerAI(self)
            self.cogHeadquarters.append(LawbotHQAI.LawbotHQAI(self))
        if self.config.GetBool('want-bossbot-headquarters', True):
            self.countryClubMgr = CountryClubManagerAI.CountryClubManagerAI(
                self)
            self.cogHeadquarters.append(BossbotHQAI.BossbotHQAI(self))

    def handleConnected(self):
        self.districtId = self.allocateChannel()
        self.notify.info('Creating ToontownDistrictAI(%d)...' %
                         self.districtId)
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)
        self.notify.info('Claiming ownership of channel ID: %d...' %
                         self.districtId)
        self.claimOwnership(self.districtId)

        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(),
                                                     self.getGameDoId(), 3)
        self.notify.info('Created ToontownDistrictStats(%d)' %
                         self.districtStats.doId)

        self.notify.info('Creating managers...')
        self.createManagers()
        if self.config.GetBool('want-safe-zones', True):
            self.notify.info('Creating safe zones...')
            self.createSafeZones()
        if self.config.GetBool('want-cog-headquarters', True):
            self.notify.info('Creating Cog headquarters...')
            self.createCogHeadquarters()

        self.notify.info('Starting Holiday Manager...')
        self.holidayManager.start()

        self.notify.info('Making district available...')
        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('Done.')

    def claimOwnership(self, channelId):
        datagram = PyDatagram()
        datagram.addServerHeader(channelId, self.ourChannel,
                                 STATESERVER_OBJECT_SET_AI)
        datagram.addChannel(self.ourChannel)
        self.send(datagram)

    def lookupDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phaseNum = ToontownGlobals.phaseMap[hoodId]
        else:
            phaseNum = ToontownGlobals.streetPhaseMap[hoodId]
        return 'phase_%s/dna/%s_%s.pdna' % (phaseNum, hood, zoneId)

    def loadDNAFileAI(self, dnastore, filename):
        return loadDNAFileAI(dnastore, filename)

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() + 1)

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() - 1)

    def allocateZone(self):
        return self.zoneAllocator.allocate()

    def deallocateZone(self, zone):
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getTrackClsends(self):
        return self.wantTrackClsends

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def trueUniqueName(self, name):
        return self.uniqueName(name)
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self, baseChannel, serverId, districtName):
        ToontownInternalRepository.__init__(self,
                                            baseChannel,
                                            serverId,
                                            dcSuffix='AI')

        self.districtName = districtName

        self.zoneAllocator = UniqueIdAllocator(
            ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd)
        self.zoneId2owner = {}

        NPCToons.generateZone2NpcDict()

        self.hoods = []
        self.zoneDataStore = AIZoneDataStore()
        self.dnaStoreMap = {}
        self.dnaDataMap = {}

        self.currentHour = 0
        self.isRaining = False

        self.useAllMinigames = self.config.GetBool('want-all-minigames', False)
        self.doLiveUpdates = self.config.GetBool('want-live-updates', True)
        self.wantFishing = self.config.GetBool('want-fishing', True)
        self.wantHousing = self.config.GetBool('want-housing', True)
        self.wantPets = self.config.GetBool('want-pets', True)
        self.wantParties = self.config.GetBool('want-parties', True)
        self.wantCogbuildings = self.config.GetBool('want-cogbuildings', True)
        self.wantCogdominiums = self.config.GetBool('want-cogdominiums', True)
        self.doLiveUpdates = self.config.GetBool('want-live-updates', False)
        self.wantTrackClsends = self.config.GetBool('want-track-clsends',
                                                    False)
        self.baseXpMultiplier = self.config.GetFloat('base-xp-multiplier', 1.0)
        self.wantHalloween = self.config.GetBool('want-halloween', False)
        self.wantChristmas = self.config.GetBool('want-christmas', False)

        self.holidayManager = HolidayManagerAI(self)

        self.fishManager = FishManagerAI()
        self.questManager = QuestManagerAI(self)
        self.cogPageManager = CogPageManagerAI()
        self.factoryMgr = FactoryManagerAI(self)
        self.mintMgr = MintManagerAI(self)
        self.lawOfficeMgr = LawOfficeManagerAI(self)
        self.countryClubMgr = CountryClubManagerAI(self)
        self.promotionMgr = PromotionManagerAI(self)
        self.cogSuitMgr = CogSuitManagerAI(self)
        self.suitInvasionManager = SuitInvasionManagerAI(self)
        self.wantCogdominiums = self.config.GetBool('want-cogdominums', False)
        self.temperatureManager = TemperatureManagerAI(self)

        self.statusSender = ShardStatusSender(self)

        self.dnaStoreMap = {}

        self.buildingManagers = {}
        self.suitPlanners = {}

    def getTrackClsends(self):
        return False

    def handleConnected(self):
        ToontownInternalRepository.handleConnected(self)
        self.districtId = self.allocateChannel()
        self.notify.info('Creating new district (%d)...' % self.districtId)
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)

        # Claim ownership of that district...
        self.notify.info('Claiming ownership of district (%d)...' %
                         self.districtId)
        dg = PyDatagram()
        dg.addServerHeader(self.districtId, self.ourChannel,
                           STATESERVER_OBJECT_SET_AI)
        dg.addChannel(self.ourChannel)
        self.send(dg)
        self.notify.info('Creating global objects...')
        self.createGlobals()
        self.notify.info('Creating zones (Playgrounds and Cog HQs)...')
        self.createZones()

        self.statusSender.start()
        self.notify.info('Making district available to enter...')
        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('District is now ready. Have fun in Toontown!')

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() + 1)
        self.statusSender.sendStatus()

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() - 1)
        self.statusSender.sendStatus()

    def setHour(self, hour):
        self.districtStats.b_setHour(hour)
        self.statusSender.sendStatus()

    def allocateZone(self, owner=None):
        zoneId = self.zoneAllocator.allocate()
        if owner:
            self.zoneId2owner[zoneId] = owner
        return zoneId

    def deallocateZone(self, zone):
        if self.zoneId2owner.get(zone):
            del self.zoneId2owner[zone]
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def createGlobals(self):
        """
        Create "global" objects, e.g. TimeManager et al.
        """
        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(),
                                                     self.getGameDoId(), 3)
        self.notify.info('Created district stats AI (%d).' %
                         self.districtStats.doId)
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)

        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)

        self.staffManager = StaffManagerAI(self)
        self.staffManager.generateWithRequired(2)

        self.banManager = BanManagerAI(self)
        self.banManager.generateWithRequired(2)

        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(2)

        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(2)

        if config.GetBool('want-parties', True):
            self.partyManager = DistributedPartyManagerAI(self)
            self.partyManager.generateWithRequired(2)

            # setup our view of the global party manager ud
            self.globalPartyMgr = self.generateGlobalObject(
                OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        self.estateManager = EstateManagerAI(self)
        self.estateManager.generateWithRequired(2)

        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(2)

        if config.GetBool('want-pets', True):
            self.petMgr = PetManagerAI(self)
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)

        self.catalogManager = CatalogManagerAI(self)
        self.catalogManager.generateWithRequired(2)

        self.codeRedemptionManager = TTCodeRedemptionMgrAI(self)
        self.codeRedemptionManager.generateWithRequired(2)

    def createZones(self):
        """
        Spawn safezone objects, streets, doors, NPCs, etc.
        """
        start = time.clock()

        def clearQueue():
            '''So the TCP window doesn't fill up and we get the axe'''
            while self.readerPollOnce():
                pass

        self.hoods.append(TTHoodAI.TTHoodAI(self))
        clearQueue()
        self.hoods.append(DDHoodAI.DDHoodAI(self))
        clearQueue()
        self.hoods.append(DGHoodAI.DGHoodAI(self))
        clearQueue()
        self.hoods.append(BRHoodAI.BRHoodAI(self))
        clearQueue()
        self.hoods.append(MMHoodAI.MMHoodAI(self))
        clearQueue()
        self.hoods.append(DLHoodAI.DLHoodAI(self))
        clearQueue()
        self.hoods.append(GSHoodAI.GSHoodAI(self))
        clearQueue()
        self.hoods.append(OZHoodAI.OZHoodAI(self))
        clearQueue()
        self.hoods.append(GZHoodAI.GZHoodAI(self))
        clearQueue()

        if config.GetBool('want-sbhq', True):
            self.hoods.append(SellbotHQAI.SellbotHQAI(self))
            clearQueue()

        if config.GetBool('want-cbhq', True):
            self.hoods.append(CashbotHQAI.CashbotHQAI(self))
            clearQueue()

        if config.GetBool('want-lbhq', True):
            self.hoods.append(LawbotHQAI.LawbotHQAI(self))
            clearQueue()

        if config.GetBool('want-bbhq', True):
            self.hoods.append(BossbotHQAI.BossbotHQAI(self))
            clearQueue()

        for sp in self.suitPlanners.values():
            sp.assignInitialSuitBuildings()

    def lookupDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phase = ToontownGlobals.phaseMap[hoodId]
        else:
            phase = ToontownGlobals.streetPhaseMap[hoodId]

        return 'phase_%s/dna/%s_%s.pdna' % (phase, hood, zoneId)

    def loadDNAFileAI(self, dnastore, filename):
        return loadDNAFileAI(dnastore, filename)
Пример #4
0
class ToontownAIRepository(ToontownInternalRepository):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'ToontownAIRepository')

    def __init__(self, baseChannel, serverId, districtName):
        ToontownInternalRepository.__init__(self,
                                            baseChannel,
                                            serverId,
                                            dcSuffix='AI')
        self.districtName = districtName
        self.doLiveUpdates = self.config.GetBool('want-live-updates', True)
        self.wantCogdominiums = self.config.GetBool('want-cogdominiums', True)
        self.wantEmblems = self.config.GetBool('want-emblems', True)
        self.useAllMinigames = self.config.GetBool('want-all-minigames', True)
        self.districtId = None
        self.district = None
        self.districtStats = None
        self.timeManager = None
        self.newsManager = None
        self.holidayManager = None
        self.welcomeValleyManager = None
        self.catalogManager = None
        self.zoneDataStore = None
        self.inGameNewsMgr = None
        self.trophyMgr = None
        self.petMgr = None
        self.dnaStoreMap = {}
        self.dnaDataMap = {}
        self.zoneTable = {}
        self.hoods = []
        self.buildingManagers = {}
        self.suitPlanners = {}
        self.suitInvasionManager = None
        self.zoneAllocator = None
        self.zoneId2owner = {}
        self.questManager = None
        self.cogPageManager = None
        self.fishManager = None
        self.factoryMgr = None
        self.mintMgr = None
        self.lawMgr = None
        self.countryClubMgr = None
        self.promotionMgr = None
        self.cogSuitMgr = None
        self.partyManager = None
        self.safeZoneManager = None
        self.raceMgr = None
        self.polarPlaceEffectMgr = None
        self.resistanceEmoteMgr = None
        self.tutorialManager = None
        self.friendManager = None
        self.toontownTimeManager = None
        self.estateMgr = None
        self.magicWordManager = None
        self.deliveryManager = None
        self.defaultAccessLevel = OTPGlobals.accessLevelValues.get(
            'TTOFF_DEVELOPER')

    def getTrackClsends(self):
        return False

    def handleConnected(self):
        ToontownInternalRepository.handleConnected(self)

        # Generate our district...
        self.districtId = self.allocateChannel()
        self.notify.info('Creating district (%d)...' % self.districtId)
        self.district = ToontownDistrictAI(self)
        self.district.setName(self.districtName)
        self.district.generateWithRequiredAndId(self.districtId,
                                                self.getGameDoId(),
                                                OTP_ZONE_ID_MANAGEMENT)

        # Claim ownership of that district...
        self.notify.info('Claiming ownership of district (%d)...' %
                         self.districtId)
        datagram = PyDatagram()
        datagram.addServerHeader(self.districtId, self.ourChannel,
                                 STATESERVER_OBJECT_SET_AI)
        datagram.addChannel(self.ourChannel)
        self.send(datagram)

        # Create our local objects.
        self.notify.info('Creating local objects...')
        self.createLocals()

        # Create our global objects.
        self.notify.info('Creating global objects...')
        self.createGlobals()

        # Create our zones.
        self.notify.info('Creating zones (Playgrounds and Cog HQs)...')
        self.createZones()

        # Make our district available, and we're done.
        self.notify.info('Making district available...')
        self.district.b_setAvailable(1)
        self.notify.info('District is now ready. Have fun in Toontown Online!')

    def createLocals(self):
        """
        Creates "local" objects.
        """

        # Create our holiday manager...
        self.holidayManager = HolidayManagerAI(self)

        # Create our zone data store...
        self.zoneDataStore = AIZoneDataStore()

        # Create our pet manager...
        self.petMgr = PetManagerAI(self)

        # Create our suit invasion manager...
        self.suitInvasionManager = SuitInvasionManagerAI(self)

        # Create our zone allocator...
        self.zoneAllocator = UniqueIdAllocator(
            ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd)

        # Create our quest manager...
        self.questManager = QuestManagerAI(self)

        # Create our Cog page manager...
        self.cogPageManager = CogPageManagerAI(self)

        # Create our fish manager...
        self.fishManager = FishManagerAI(self)

        # Create our factory manager...
        self.factoryMgr = FactoryManagerAI(self)

        # Create our mint manager...
        self.mintMgr = MintManagerAI(self)

        # Create our law office manager...
        self.lawMgr = LawOfficeManagerAI(self)

        # Create our country club manager...
        self.countryClubMgr = CountryClubManagerAI(self)

        # Create our promotion manager...
        self.promotionMgr = PromotionManagerAI(self)

        # Create our Cog suit manager...
        self.cogSuitMgr = CogSuitManagerAI(self)

        # Create our race manager...
        self.raceMgr = RaceManagerAI(self)

        # Create our Toontown time manager...
        self.toontownTimeManager = ToontownTimeManager(
            serverTimeUponLogin=int(time.time()),
            globalClockRealTimeUponLogin=globalClock.getRealTime())

    def createGlobals(self):
        """
        Creates "global" objects.
        """

        # Generate our district stats...
        districtStatsId = self.allocateChannel()
        self.notify.info('Creating district stats AI (%d)...' %
                         districtStatsId)
        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(districtStatsId,
                                                     self.getGameDoId(),
                                                     OTP_ZONE_ID_DISTRICTS)

        # Generate our time manager...
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our news manager...
        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our Welcome Valley manager...
        self.welcomeValleyManager = WelcomeValleyManagerAI(self)
        self.welcomeValleyManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our catalog manager...
        self.catalogManager = CatalogManagerAI(self)
        self.catalogManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our in-game news manager...
        self.inGameNewsMgr = DistributedInGameNewsMgrAI(self)
        self.inGameNewsMgr.setLatestIssueStr('2013-08-22 23:49:46')
        self.inGameNewsMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our trophy manager...
        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our party manager...
        self.partyManager = DistributedPartyManagerAI(self)
        self.partyManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our safezone manager...
        self.safeZoneManager = SafeZoneManagerAI(self)
        self.safeZoneManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our Polar Place effect manager...
        self.polarPlaceEffectMgr = DistributedPolarPlaceEffectMgrAI(self)
        self.polarPlaceEffectMgr.generateWithRequired(3821)

        # Generate our resistance emote manager...
        self.resistanceEmoteMgr = DistributedResistanceEmoteMgrAI(self)
        self.resistanceEmoteMgr.generateWithRequired(9720)

        # Generate our tutorial manager...
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our friend manager...
        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our estate manager...
        self.estateMgr = EstateManagerAI(self)
        self.estateMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)

        # Generate our delivery manager...
        self.deliveryManager = self.generateGlobalObject(
            OTP_DO_ID_TOONTOWN_DELIVERY_MANAGER, 'DistributedDeliveryManager')

    def createHood(self, hoodCtr, zoneId):
        # Bossbot HQ doesn't use DNA, so we skip over that.
        if zoneId != ToontownGlobals.BossbotHQ:
            self.dnaStoreMap[zoneId] = DNAStorage()
            self.dnaDataMap[zoneId] = loadDNAFileAI(
                self.dnaStoreMap[zoneId], self.genDNAFileName(zoneId))
            if zoneId in ToontownGlobals.HoodHierarchy:
                for streetId in ToontownGlobals.HoodHierarchy[zoneId]:
                    self.dnaStoreMap[streetId] = DNAStorage()
                    self.dnaDataMap[streetId] = loadDNAFileAI(
                        self.dnaStoreMap[streetId],
                        self.genDNAFileName(streetId))

        hood = hoodCtr(self, zoneId)
        hood.startup()
        self.hoods.append(hood)

    def createZones(self):
        # First, generate our zone2NpcDict...
        NPCToons.generateZone2NpcDict()

        # Toontown Central
        self.zoneTable[ToontownGlobals.ToontownCentral] = (
            (ToontownGlobals.ToontownCentral, 1,
             0), (ToontownGlobals.SillyStreet, 1,
                  1), (ToontownGlobals.LoopyLane, 1,
                       1), (ToontownGlobals.PunchlinePlace, 1, 1))
        self.createHood(TTHoodDataAI, ToontownGlobals.ToontownCentral)

        # Donald's Dock
        self.zoneTable[ToontownGlobals.DonaldsDock] = (
            (ToontownGlobals.DonaldsDock, 1,
             0), (ToontownGlobals.BarnacleBoulevard, 1,
                  1), (ToontownGlobals.SeaweedStreet, 1,
                       1), (ToontownGlobals.LighthouseLane, 1, 1))
        self.createHood(DDHoodDataAI, ToontownGlobals.DonaldsDock)

        # Daisy Gardens
        self.zoneTable[ToontownGlobals.DaisyGardens] = (
            (ToontownGlobals.DaisyGardens, 1,
             0), (ToontownGlobals.ElmStreet, 1,
                  1), (ToontownGlobals.MapleStreet, 1,
                       1), (ToontownGlobals.OakStreet, 1, 1))
        self.createHood(DGHoodDataAI, ToontownGlobals.DaisyGardens)

        # Minnie's Melodyland
        self.zoneTable[ToontownGlobals.MinniesMelodyland] = (
            (ToontownGlobals.MinniesMelodyland, 1,
             0), (ToontownGlobals.AltoAvenue, 1,
                  1), (ToontownGlobals.BaritoneBoulevard, 1,
                       1), (ToontownGlobals.TenorTerrace, 1, 1))
        self.createHood(MMHoodDataAI, ToontownGlobals.MinniesMelodyland)

        # The Brrrgh
        self.zoneTable[ToontownGlobals.TheBrrrgh] = (
            (ToontownGlobals.TheBrrrgh, 1,
             0), (ToontownGlobals.WalrusWay, 1,
                  1), (ToontownGlobals.SleetStreet, 1,
                       1), (ToontownGlobals.PolarPlace, 1, 1))
        self.createHood(BRHoodDataAI, ToontownGlobals.TheBrrrgh)

        # Donald's Dreamland
        self.zoneTable[ToontownGlobals.DonaldsDreamland] = (
            (ToontownGlobals.DonaldsDreamland, 1,
             0), (ToontownGlobals.LullabyLane, 1,
                  1), (ToontownGlobals.PajamaPlace, 1, 1))
        self.createHood(DLHoodDataAI, ToontownGlobals.DonaldsDreamland)

        # Sellbot HQ
        self.zoneTable[ToontownGlobals.SellbotHQ] = (
            (ToontownGlobals.SellbotHQ, 0,
             1), (ToontownGlobals.SellbotFactoryExt, 0, 1))
        self.createHood(CSHoodDataAI, ToontownGlobals.SellbotHQ)

        # Cashbot HQ
        self.zoneTable[ToontownGlobals.CashbotHQ] = ((
            ToontownGlobals.CashbotHQ, 0, 1), )
        self.createHood(CashbotHQDataAI, ToontownGlobals.CashbotHQ)

        # Lawbot HQ
        self.zoneTable[ToontownGlobals.LawbotHQ] = ((ToontownGlobals.LawbotHQ,
                                                     0, 1), )
        self.createHood(LawbotHQDataAI, ToontownGlobals.LawbotHQ)

        # Bossbot HQ
        self.zoneTable[ToontownGlobals.BossbotHQ] = ((
            ToontownGlobals.BossbotHQ, 0, 0), )
        self.createHood(BossbotHQDataAI, ToontownGlobals.BossbotHQ)

        # Goofy Speedway
        self.zoneTable[ToontownGlobals.GoofySpeedway] = ((
            ToontownGlobals.GoofySpeedway, 1, 0), )
        self.createHood(GSHoodDataAI, ToontownGlobals.GoofySpeedway)

        # Chip 'n Dale's Acorn Acres
        self.zoneTable[ToontownGlobals.OutdoorZone] = ((
            ToontownGlobals.OutdoorZone, 1, 0), )
        self.createHood(OZHoodDataAI, ToontownGlobals.OutdoorZone)

        # Chip 'n Dale's MiniGolf
        self.zoneTable[ToontownGlobals.GolfZone] = ((ToontownGlobals.GolfZone,
                                                     1, 0), )
        self.createHood(GZHoodDataAI, ToontownGlobals.GolfZone)

        # Welcome Valley hoods (Toontown Central & Goofy Speedway)
        self.notify.info('Creating ' + TTLocalizer.WelcomeValley[2] + '...')
        self.welcomeValleyManager.createWelcomeValleyHoods()

        # Assign the initial suit buildings.
        self.notify.info(
            'Assigning initial Cog buildings and Field Offices...')
        for suitPlanner in self.suitPlanners.values():
            suitPlanner.assignInitialSuitBuildings()

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() + 1)

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() - 1)

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def getZoneDataStore(self):
        return self.zoneDataStore

    def genDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phase = ToontownGlobals.phaseMap[hoodId]
        else:
            phase = ToontownGlobals.streetPhaseMap[hoodId]

        if 'outdoor_zone' in hood or 'golf_zone' in hood:
            phase = '6'

        return 'phase_%s/dna/%s_%s.dna' % (phase, hood, zoneId)

    def findFishingPonds(self, dnaData, zoneId, area):
        fishingPonds = []
        fishingPondGroups = []
        if isinstance(dnaData, DNAGroup) and ('fishing_pond'
                                              in dnaData.getName()):
            fishingPondGroups.append(dnaData)
            pond = self.fishManager.generatePond(area, zoneId)
            fishingPonds.append(pond)
        elif isinstance(dnaData, DNAVisGroup):
            zoneId = ZoneUtil.getTrueZoneId(
                int(dnaData.getName().split(':')[0]), zoneId)

        for i in xrange(dnaData.getNumChildren()):
            foundFishingPonds, foundFishingPondGroups = self.findFishingPonds(
                dnaData.at(i), zoneId, area)
            fishingPonds.extend(foundFishingPonds)
            fishingPondGroups.extend(foundFishingPondGroups)

        return fishingPonds, fishingPondGroups

    def findFishingSpots(self, dnaData, fishingPond):
        fishingSpots = []
        if isinstance(dnaData, DNAGroup) and ('fishing_spot'
                                              in dnaData.getName()):
            spot = self.fishManager.generateSpots(dnaData, fishingPond)
            fishingSpots.append(spot)

        for i in xrange(dnaData.getNumChildren()):
            foundFishingSpots = self.findFishingSpots(dnaData.at(i),
                                                      fishingPond)
            fishingSpots.extend(foundFishingSpots)

        return fishingSpots

    def findPartyHats(self, dnaData, zoneId):
        return []

    def loadDNAFileAI(self, dnaStore, dnaFileName):
        return loadDNAFileAI(dnaStore, dnaFileName)

    def allocateZone(self, owner=None):
        zoneId = self.zoneAllocator.allocate()
        if owner:
            self.zoneId2owner[zoneId] = owner

        return zoneId

    def deallocateZone(self, zone):
        if self.zoneId2owner.get(zone):
            del self.zoneId2owner[zone]

        self.zoneAllocator.free(zone)

    def trueUniqueName(self, idString):
        return self.uniqueName(idString)

    def findRacingPads(self,
                       dnaData,
                       zoneId,
                       area,
                       type='racing_pad',
                       overrideDNAZone=False):
        racingPads, racingPadGroups = [], []
        if type in dnaData.getName():
            if type == 'racing_pad':
                nameSplit = dnaData.getName().split('_')
                racePad = DistributedRacePadAI(self)
                racePad.setArea(area)
                racePad.index = int(nameSplit[2])
                racePad.genre = nameSplit[3]
                trackInfo = RaceGlobals.getNextRaceInfo(
                    -1, racePad.genre, racePad.index)
                racePad.setTrackInfo([trackInfo[0], trackInfo[1]])
                racePad.laps = trackInfo[2]
                racePad.generateWithRequired(zoneId)
                racingPads.append(racePad)
                racingPadGroups.append(dnaData)
            elif type == 'viewing_pad':
                viewPad = DistributedViewPadAI(self)
                viewPad.setArea(area)
                viewPad.generateWithRequired(zoneId)
                racingPads.append(viewPad)
                racingPadGroups.append(dnaData)

        for i in xrange(dnaData.getNumChildren()):
            foundRacingPads, foundRacingPadGroups = self.findRacingPads(
                dnaData.at(i), zoneId, area, type, overrideDNAZone)
            racingPads.extend(foundRacingPads)
            racingPadGroups.extend(foundRacingPadGroups)

        return racingPads, racingPadGroups

    def findStartingBlocks(self, dnaData, pad):
        startingBlocks = []
        for i in xrange(dnaData.getNumChildren()):
            groupName = dnaData.getName()
            blockName = dnaData.at(i).getName()
            if 'starting_block' in blockName:
                cls = DistributedStartingBlockAI if 'racing_pad' in groupName else DistributedViewingBlockAI
                x, y, z = dnaData.at(i).getPos()
                h, p, r = dnaData.at(i).getHpr()
                padLocationId = int(dnaData.at(i).getName()[-1])
                startingBlock = cls(self, pad, x, y, z, h, p, r, padLocationId)
                startingBlock.generateWithRequired(pad.zoneId)
                startingBlocks.append(startingBlock)

        return startingBlocks

    def getAvatarDisconnectReason(self, avId):
        return self.timeManager.avId2disconnectcode.get(
            avId, ToontownGlobals.DisconnectUnknown)

    def lookupDNAFileName(self, dnaFile):
        searchPath = DSearchPath()
        searchPath.appendDirectory(Filename('/phase_3.5/dna'))
        searchPath.appendDirectory(Filename('/phase_4/dna'))
        searchPath.appendDirectory(Filename('/phase_5/dna'))
        searchPath.appendDirectory(Filename('/phase_5.5/dna'))
        searchPath.appendDirectory(Filename('/phase_6/dna'))
        searchPath.appendDirectory(Filename('/phase_8/dna'))
        searchPath.appendDirectory(Filename('/phase_9/dna'))
        searchPath.appendDirectory(Filename('/phase_10/dna'))
        searchPath.appendDirectory(Filename('/phase_11/dna'))
        searchPath.appendDirectory(Filename('/phase_12/dna'))
        searchPath.appendDirectory(Filename('/phase_13/dna'))
        filename = Filename(dnaFile)
        found = vfs.resolveFilename(filename, searchPath)
        if not found:
            self.notify.warning('lookupDNAFileName - %s not found on:' %
                                dnaFile)
            print searchPath
        else:
            return filename.getFullpath()

    def findLeaderBoards(self, dnaData, zoneId):
        leaderboards = []
        if 'leaderBoard' in dnaData.getName():
            x, y, z = dnaData.getPos()
            h, p, r = dnaData.getHpr()
            leaderboard = DistributedLeaderBoardAI(self, dnaData.getName(), x,
                                                   y, z, h, p, r)
            leaderboard.generateWithRequired(zoneId)
            leaderboards.append(leaderboard)

        for i in xrange(dnaData.getNumChildren()):
            foundLeaderBoards = self.findLeaderBoards(dnaData.at(i), zoneId)
            leaderboards.extend(foundLeaderBoards)

        return leaderboards
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self, baseChannel, stateServerChannel, districtName):
        ToontownInternalRepository.__init__(
            self, baseChannel, stateServerChannel, dcSuffix='AI')

        self.districtName = districtName

        self.notify.setInfo(True)  # Our AI repository should always log info.
        self.hoods = []
        self.cogHeadquarters = []
        self.dnaStoreMap = {}
        self.dnaDataMap = {}
        self.suitPlanners = {}
        self.buildingManagers = {}
        self.factoryMgr = None
        self.mintMgr = None
        self.lawOfficeMgr = None
        self.countryClubMgr = None

        self.zoneAllocator = UniqueIdAllocator(ToontownGlobals.DynamicZonesBegin,
                                               ToontownGlobals.DynamicZonesEnd)
        self.zoneDataStore = AIZoneDataStore()

        self.wantFishing = self.config.GetBool('want-fishing', True)
        self.wantHousing = self.config.GetBool('want-housing', True)
        self.wantPets = self.config.GetBool('want-pets', True)
        self.wantKarts = self.config.GetBool('want-karts', True)
        self.wantParties = self.config.GetBool('want-parties', True)
        self.wantEmblems = self.config.GetBool('want-emblems', True)
        self.wantCogbuildings = self.config.GetBool('want-cogbuildings', True)
        self.wantCogdominiums = self.config.GetBool('want-cogdominiums', True)
        self.wantTrackClsends = self.config.GetBool('want-track-clsends', False)
        self.wantTopToons = self.config.GetBool('want-top-toons', True)
        self.baseXpMultiplier = self.config.GetFloat('base-xp-multiplier', 1.0)

        self.cogSuitMessageSent = False

    def createManagers(self):
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)
        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(2)
        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)
        self.safeZoneManager = SafeZoneManagerAI(self)
        self.safeZoneManager.generateWithRequired(2)
        self.topToonsMgr = TopToonsManagerAI(self)
        #self.topToonsMgr.generateWithRequired(2)
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)
        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(2)
        self.questManager = QuestManagerAI(self)       
        self.banManager = BanManagerAI.BanManagerAI(self)
        self.suitInvasionManager = SuitInvasionManagerAI(self)
        self.blackCatMgr = DistributedBlackCatMgrAI(self)
        self.blackCatMgr.generateWithRequired(2)
        self.reportMgr = DistributedReportMgrAI(self)
        self.reportMgr.generateWithRequired(2)
        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(2)
        self.cogSuitMgr = CogSuitManagerAI.CogSuitManagerAI()
        self.promotionMgr = PromotionManagerAI.PromotionManagerAI(self)
        self.cogPageManager = CogPageManagerAI.CogPageManagerAI()
        self.codeRedemptionMgr = TTCodeRedemptionMgrAI(self)
        self.codeRedemptionMgr.generateWithRequired(2)
        self.buildingQueryMgr = DistributedBuildingQueryMgrAI(self)
        self.buildingQueryMgr.generateWithRequired(2)
        if self.wantTopToons:
            self.topToonsMgr = TopToonsManagerAI(self)
        if self.wantKarts:
            self.leaderboardMgr = LeaderboardMgrAI(self)
        if self.wantFishing:
            self.fishManager = FishManagerAI(self)
        if self.wantHousing:
            self.estateManager = EstateManagerAI(self)
            self.estateManager.generateWithRequired(2)
            self.catalogManager = CatalogManagerAI(self)
            self.catalogManager.generateWithRequired(2)
        if self.wantPets:
            self.petMgr = PetManagerAI(self)
        if self.wantParties:
            self.partyManager = DistributedPartyManagerAI(self)
            self.partyManager.generateWithRequired(2)
            self.globalPartyMgr = self.generateGlobalObject(
                OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')
        #self.lobbyManager = DistributedLobbyManagerAI(self)
        #self.lobbyManager.generateWithRequired(2)
        #self.globalLobbyMgr = self.generateGlobalObject(
        #    OTP_DO_ID_GLOBAL_LOBBY_MANAGER, 'GlobalLobbyManager')

    def createSafeZones(self):
        NPCToons.generateZone2NpcDict()
        if self.config.GetBool('want-toontown-central', True):
            self.hoods.append(TTHoodAI.TTHoodAI(self))
        if self.config.GetBool('want-donalds-dock', True):
            self.hoods.append(DDHoodAI.DDHoodAI(self))
        if self.config.GetBool('want-daisys-garden', True):
            self.hoods.append(DGHoodAI.DGHoodAI(self))
        if self.config.GetBool('want-minnies-melodyland', True):
            self.hoods.append(MMHoodAI.MMHoodAI(self))
        if self.config.GetBool('want-the-brrrgh', True):
            self.hoods.append(BRHoodAI.BRHoodAI(self))
        if self.config.GetBool('want-donalds-dreamland', True):
            self.hoods.append(DLHoodAI.DLHoodAI(self))
        if self.config.GetBool('want-goofy-speedway', True):
            self.hoods.append(GSHoodAI.GSHoodAI(self))
        if self.config.GetBool('want-outdoor-zone', True):
            self.hoods.append(OZHoodAI.OZHoodAI(self))
        if self.config.GetBool('want-golf-zone', True):
            self.hoods.append(GZHoodAI.GZHoodAI(self))

    def createCogHeadquarters(self):
        NPCToons.generateZone2NpcDict()
        if self.config.GetBool('want-sellbot-headquarters', True):
            self.factoryMgr = FactoryManagerAI.FactoryManagerAI(self)
            self.cogHeadquarters.append(SellbotHQAI.SellbotHQAI(self))
        if self.config.GetBool('want-cashbot-headquarters', True):
            self.mintMgr = MintManagerAI.MintManagerAI(self)
            self.cogHeadquarters.append(CashbotHQAI.CashbotHQAI(self))
        if self.config.GetBool('want-lawbot-headquarters', True):
            self.lawOfficeMgr = LawOfficeManagerAI.LawOfficeManagerAI(self)
            self.cogHeadquarters.append(LawbotHQAI.LawbotHQAI(self))
        if self.config.GetBool('want-bossbot-headquarters', True):
            self.countryClubMgr = CountryClubManagerAI.CountryClubManagerAI(self)
            self.cogHeadquarters.append(BossbotHQAI.BossbotHQAI(self))

    def handleConnected(self):
        ToontownInternalRepository.handleConnected(self)
        threading.Thread(target=self.startDistrict).start()
    
    def startDistrict(self):
        self.districtId = self.allocateChannel()
        self.notify.info('Creating ToontownDistrictAI(%d)...' % self.districtId)
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)
        self.notify.info('Claiming ownership of channel ID: %d...' % self.districtId)
        self.claimOwnership(self.districtId)

        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.setDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(
            self.allocateChannel(), self.getGameDoId(), 3)
        self.notify.info('Created ToontownDistrictStats(%d)' % self.districtStats.doId)

        self.notify.info('Creating managers...')
        self.createManagers()
        if self.config.GetBool('want-safe-zones', True):
            self.notify.info('Creating safe zones...')
            self.createSafeZones()
        if self.config.GetBool('want-cog-headquarters', True):
            self.notify.info('Creating Cog headquarters...')
            self.createCogHeadquarters()

        self.notify.info('Making district available...')
        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('Done.')

    def claimOwnership(self, channelId):
        datagram = PyDatagram()
        datagram.addServerHeader(channelId, self.ourChannel, STATESERVER_OBJECT_SET_AI)
        datagram.addChannel(self.ourChannel)
        self.send(datagram)

    def lookupDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phaseNum = ToontownGlobals.phaseMap[hoodId]
        else:
            phaseNum = ToontownGlobals.streetPhaseMap[hoodId]
        return 'phase_%s/dna/%s_%s.pdna' % (phaseNum, hood, zoneId)

    def loadDNAFileAI(self, dnastore, filename):
        return loadDNAFileAI(dnastore, filename)

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(self.districtStats.getAvatarCount() + 1)

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(self.districtStats.getAvatarCount() - 1)

    def allocateZone(self):
        return self.zoneAllocator.allocate()

    def deallocateZone(self, zone):
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getTrackClsends(self):
        return self.wantTrackClsends

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def trueUniqueName(self, name):
        return self.uniqueName(name)
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self, baseChannel, serverId, districtName):
        ToontownInternalRepository.__init__(self, baseChannel, serverId, dcSuffix='AI')

        self.districtName = districtName

        self.zoneAllocator = UniqueIdAllocator(ToontownGlobals.DynamicZonesBegin,
                                               ToontownGlobals.DynamicZonesEnd)

        NPCToons.generateZone2NpcDict()
        
        self.use_libpandadna = simbase.config.GetBool('use-libpandadna', False)
        
        self.hoods = []
        self._dnaStoreMap = {}
        
        if self.use_libpandadna:
            self.__loader = DNALoader()
        
        self.zoneDataStore = AIZoneDataStore()

        self.useAllMinigames = self.config.GetBool('want-all-minigames', False)
        self.doLiveUpdates = True
        
        self.wantCogdominiums = self.config.GetBool('want-cogdo', False)
        self.wantParties = self.config.GetBool('want-parties', False)
        self.wantEmblems = self.config.GetBool('want-emblems', True)
        
        self.questManager = QuestManagerAI(self)
        self.promotionMgr = PromotionManagerAI(self)
        self.cogPageManager = CogPageManagerAI(self)
        self.cogSuitMgr = CogSuitManagerAI(self)

        self.trophyMgr = DistributedTrophyMgrAI(self)
        
        self.fishManager = FishManagerAI()
		
        self.dnaStoreMap = {}
        
        self.mintMgr = MintManagerAI.MintManagerAI(self)
        self.factoryMgr = FactoryManagerAI.FactoryManagerAI(self)
        self.lawMgr = LawOfficeManagerAI.LawOfficeManagerAI(self)
        self.countryClubMgr = CountryClubManagerAI.CountryClubManagerAI(self)
        
        self.buildingManagers = {}
        self.suitPlanners = {}
        
        self.wantMegaInvasions = str(self.ourChannel // 1000000) in self.config.GetString('mega-invasion-shards', '402 403').split()            

    def getTrackClsends(self):
        return False
        
    def handleConnected(self):
        self.districtId = self.allocateChannel()
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(simbase.air.districtId, self.getGameDoId(), 2)

        dg = PyDatagram()
        dg.addServerHeader(simbase.air.districtId, simbase.air.ourChannel, STATESERVER_OBJECT_SET_AI)
        dg.addChannel(simbase.air.ourChannel)
        simbase.air.send(dg)

        self.createGlobals()
        self.createZones()

    def __ready(self):
        dg = PyDatagram()
        dg.addServerHeader(self.districtStats.doId, self.ourChannel, STATESERVER_OBJECT_DELETE_RAM)
        dg.addUint32(self.districtStats.doId)
        self.addPostRemove(dg)
        
        self.apiMgr = self.generateGlobalObject(100001, "ShardAPIManager")
        self.apiMgr.start()
        self.apiMgr.d_setShardData()
        
        self.banMgr = self.generateGlobalObject(100002, "BanManager")
        
        self.trophyMgr.updateToonData()
        
    def gotUberdogAPISync(self):
        if not self.distributedDistrict.getAvailable():
            self.notify.info("Got UD API sync, opening shard...")
            messenger.send("startShardActivity")
            self.distributedDistrict.b_setAvailable(1)

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(self.districtStats.getAvatarCount() + 1)

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(self.districtStats.getAvatarCount() - 1)

    def allocateZone(self):
        return self.zoneAllocator.allocate()

    def deallocateZone(self, zone):
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def createGlobals(self):
        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(), self.getGameDoId(), 2)
		
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)

        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)

        self.holidayManager = HolidayManagerAI(self)

        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(2)

        self.safeZoneManager = SafeZoneManagerAI(self)
        self.safeZoneManager.generateWithRequired(2)
		
        self.petMgr = PetManagerAI(self)

        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(2)

        self.partyManager = DistributedPartyManagerAI(self)
        self.partyManager.generateWithRequired(2)
		
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)
		
        self.globalPartyMgr = self.generateGlobalObject(OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        self.estateManager = EstateManagerAI(self)
        self.estateManager.generateWithRequired(2)
        
        self.suitInvasionManager = DistributedSuitInvasionManagerAI(self)
        self.suitInvasionManager.generateWithRequired(2)

        self.bankMgr = DistributedBankMgrAI(self)
        self.bankMgr.generateWithRequired(2)
        
        self.catalogManager = CatalogManagerAI(self)
        self.catalogManager.generateWithRequired(2)
        
        self.huntId = 0
        
        if self.holidayManager.isHolidayRunning(ToontownGlobals.TRICK_OR_TREAT):
            import DistributedTrickOrTreatTargetAI
            self.trickOrTreatMgr = DistributedTrickOrTreatTargetAI.DistributedTrickOrTreatTargetAI(self)
            self.trickOrTreatMgr.generateWithRequired(2)
            
        self.handleBlackCatMgr()
        self.handleBloodsuckerInvasion()
        self.handleSkelCogWeekInvasion()
        
        if config.GetBool('want-resistance-emote', True):
            self.resistanceMgr = DistributedResistanceEmoteMgrAI.DistributedResistanceEmoteMgrAI(self)
            self.resistanceMgr.generateWithRequired(9720)

        if config.GetBool('want-polar-effect', True):
            self.polarMgr = DistributedPolarPlaceEffectMgrAI.DistributedPolarPlaceEffectMgrAI(self)
            self.polarMgr.generateWithRequired(3821)
            
    def handleBlackCatMgr(self):
        today = datetime.datetime.now()
        start = datetime.datetime(today.year, 10, 31)
        end = datetime.datetime(today.year, 11, 3)
        
        def createBlackCatMgr(task=None):
            import DistributedBlackCatMgrAI
            self.blackCatMgr = DistributedBlackCatMgrAI.DistributedBlackCatMgrAI(self)
            self.blackCatMgr.generateWithRequired(2513)
            if not self.config.GetBool('force-black-cat-mgr', False):
                self.blackCatMgr.expire((end - today).total_seconds())
            return Task.done
        
        if start <= today < end or self.config.GetBool('force-black-cat-mgr', False):
            createBlackCatMgr(None)
            
        elif start >= today:
            taskMgr.doMethodLater((start - today).total_seconds(), createBlackCatMgr, 'air-createBlackCatMgr')
            
    def handleBloodsuckerInvasion(self):
        if not self.wantMegaInvasions:
            return
            
        today = datetime.datetime.now()
        start = datetime.datetime(today.year, 10, 31)
        end = datetime.datetime(today.year, 11, 3)
        
        if start <= today < end:
            self.startMegaInvasion(9, end=end)
            
        elif start > today:
            taskMgr.doMethodLater((start - today).total_seconds(), self.startMegaInvasion, 'air-mega-invasion-9', extraArgs=[9, False, end])
            
    def handleSkelCogWeekInvasion(self):
        if not self.wantMegaInvasions:
            return
            
        today = datetime.datetime.now()
        start = datetime.datetime(2014, 11, 10)
        end = datetime.datetime(2014, 11, 17)
        
        if start <= today < end:
            self.startMegaInvasion(-1, skel=True, end=end)
            
        elif start > today:
            taskMgr.doMethodLater((start - today).total_seconds(), self.startMegaInvasion, 'air-mega-invasion-skel', extraArgs=[-1, True, end])
            
    def startMegaInvasion(self, suitIndex, skel=False, end=None):
        if suitIndex >= 0:
            suitName = SuitDNA.suitHeadTypes[suitIndex]
            
        else:
            suitName = None
            
        if self.suitInvasionManager.hasInvading():
            if self.suitInvasionManager.isMega():
                return Task.done
                
            self.suitInvasionManager.abort()
            
        self.suitInvasionManager.startInvasion(suitName, skel, mega=True)
        if end:
            def doAbort(task):
                self.suitInvasionManager.abort()
                return task.done

            today = datetime.datetime.now()
            taskMgr.doMethodLater((end - today).total_seconds(), doAbort, 'air-abort-mega-invasion')
        
    def getStorage(self, zone):
        s = self._dnaStoreMap.get(zone)
        if not s:
            s = DNAStorage()
            self.loadDNAFileAI(s, self.genDNAFileName(zone))
            self._dnaStoreMap[zone] = s
        
        return s

    def createZones(self):
        self.zoneTable = {
                          1000: ((1000, 1, 0), (1100, 1, 1), (1200, 1, 1), (1300, 1, 1)),
                          2000: ((2000, 1, 0), (2100, 1, 1), (2200, 1, 1), (2300, 1, 1)),
                          3000: ((3000, 1, 0), (3100, 1, 1), (3200, 1, 1), (3300, 1, 1)),
                          4000: ((4000, 1, 0), (4100, 1, 1), (4200, 1, 1), (4300, 1, 1)),
                          5000: ((5000, 1, 0), (5100, 1, 1), (5200, 1, 1), (5300, 1, 1)),
                          9000: ((9000, 1, 0), (9100, 1, 1), (9200, 1, 1)),
                          
                          6000: (),
                          7000: ((7000, 1, 0), (7100, 1, 1)), # XXX to do: planner at 7100
                          8000: ((8000, 1, 0),),
                          10000: (),
                          11000: (),
                          12000: (),
                          13000: (),
                          17000: (),
                         }
        
        self.__nextHood(0)
                         
    def __nextHood(self, hoodIndex):
        if hoodIndex >= len(hoods):
            self.__ready()
            return Task.done
                         
        self.hoods.append(hoods[hoodIndex](self))
        taskMgr.doMethodLater(0, ToontownAIRepository.__nextHood, 'nextHood', [self, hoodIndex + 1])
        return Task.done

    def genDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phase = ToontownGlobals.phaseMap[hoodId]
        else:
            phase = ToontownGlobals.streetPhaseMap[hoodId]

        return 'phase_%s/dna/%s_%s.dna' % (phase, hood, zoneId)

    def loadDNAFileAI(self, dnastore, filename):
        if self.use_libpandadna:
            f = Filename('../resources/' + str(filename))
            f.setExtension('pdna')
            x = self.__loader.loadDNAFileAI(dnastore, f)
            
        else:
            f = Filename(filename)
            f = Filename('etc/dnabkp/' + f.getBasename())
            x = loadDNAFileAI(dnastore, str(f))
        
        return x

    def sendSetZone(self, obj, zoneId):
        obj.b_setLocation(obj.parentId, zoneId)
        
    def getDisconnectReason(self, avId):
        return self.timeManager.disconnectReasonMap.get(avId, 1) # Default: user closed window
        
    def killToon(self, avId, force = True):
        """
        Kills given toon if within this shard.
        If force is False, then checks getDisconnectReason.
        """
        toon = self.doId2do.get(avId)
        
        if not toon:
            self.notify.warning("Tried to kill non-existing toon %s" % avId)
            return False
            
        if not force:
            if self.getDisconnectReason(avId) == 3: # Python Error
                return False
            
        toon.b_setHp(0)
        
        inventory = toon.inventory
        inventory.zeroInv()
        toon.b_setInventory(inventory.makeNetString())
        
        self.notify.info("Killed toon %s, RIP!" % avId)
        return True
        
    def handleObjExit(self, di):
        doId = di.getUint32()

        if doId not in self.doId2do:
            self.notify.warning('Received AI exit for unknown object %d' % (doId))
            return

        do = self.doId2do[doId]
        do.sendDeleteEvent()
        self.removeDOFromTables(do)
        do.delete()
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self, baseChannel, serverId, districtName):
        ToontownInternalRepository.__init__(self, baseChannel, serverId, dcSuffix='AI')

        self.dnaSpawner = DNASpawnerAI(self)

        self.districtName = districtName

        self.zoneAllocator = UniqueIdAllocator(ToontownGlobals.DynamicZonesBegin,
                                               ToontownGlobals.DynamicZonesEnd)
        self.zoneId2owner = {}

        NPCToons.generateZone2NpcDict()

        self.hoods = []
        self.zoneDataStore = AIZoneDataStore()

        self.useAllMinigames = self.config.GetBool('want-all-minigames', False)
        self.doLiveUpdates = self.config.GetBool('want-live-updates', True)

        self.holidayManager = HolidayManagerAI(self)

        self.fishManager = FishManagerAI()
        self.questManager = QuestManagerAI(self)
        self.cogPageManager = CogPageManagerAI()
        self.factoryMgr = FactoryManagerAI(self)
        self.mintMgr = MintManagerAI(self)
        self.lawOfficeMgr = LawOfficeManagerAI(self)
        self.countryClubMgr = CountryClubManagerAI(self)
        self.promotionMgr = PromotionManagerAI(self)
        self.cogSuitMgr = CogSuitManagerAI(self)
        self.suitInvasionManager = SuitInvasionManagerAI(self)

        self.statusSender = ShardStatusSender(self)

        self.dnaStoreMap = {}

        self.buildingManagers = {}
        self.suitPlanners = {}

    def getTrackClsends(self):
        return False

    def handleConnected(self):
        ToontownInternalRepository.handleConnected(self)
        self.districtId = self.allocateChannel()
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(self.districtId,
                                                           self.getGameDoId(), 2)

        # Claim ownership of that district...
        dg = PyDatagram()
        dg.addServerHeader(self.districtId, self.ourChannel, STATESERVER_OBJECT_SET_AI)
        dg.addChannel(self.ourChannel)
        self.send(dg)

        self.createGlobals()
        self.createZones()

        self.statusSender.start()

        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('District is now ready.')

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(self.districtStats.getAvatarCount() + 1)
        self.statusSender.sendStatus()

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(self.districtStats.getAvatarCount() - 1)
        self.statusSender.sendStatus()

    def allocateZone(self, owner=None):
        zoneId = self.zoneAllocator.allocate()
        if owner:
            self.zoneId2owner[zoneId] = owner
        return zoneId

    def deallocateZone(self, zone):
        if self.zoneId2owner.get(zone):
            del self.zoneId2owner[zone]
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def createGlobals(self):
        """
        Create "global" objects, e.g. TimeManager et al.
        """
        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(),
                                                     self.getGameDoId(), 3)

        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)

        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)

        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(2)

        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(2)

        if config.GetBool('want-parties', True):
            self.partyManager = DistributedPartyManagerAI(self)
            self.partyManager.generateWithRequired(2)
            self.globalPartyMgr = self.generateGlobalObject(OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        self.estateManager = EstateManagerAI(self)
        self.estateManager.generateWithRequired(2)

        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(2)

        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)

        self.catalogManager = CatalogManagerAI(self)
        self.catalogManager.generateWithRequired(2)

        self.codeRedemptionManager = TTCodeRedemptionMgrAI(self)
        self.codeRedemptionManager.generateWithRequired(2)

    def createZones(self):
        """
        Spawn safezone objects, streets, doors, NPCs, etc.
        """
        start = time.clock()
        def clearQueue():
            '''So the TCP window doesn't fill up and we get the axe'''
            while self.readerPollOnce():
                pass

        self.hoods.append(TTHoodAI.TTHoodAI(self))
        clearQueue()
        self.hoods.append(DDHoodAI.DDHoodAI(self))
        clearQueue()
        self.hoods.append(DGHoodAI.DGHoodAI(self))
        clearQueue()
        self.hoods.append(BRHoodAI.BRHoodAI(self))
        clearQueue()
        self.hoods.append(MMHoodAI.MMHoodAI(self))
        clearQueue()
        self.hoods.append(DLHoodAI.DLHoodAI(self))
        clearQueue()
        self.hoods.append(GSHoodAI.GSHoodAI(self))
        clearQueue()
        self.hoods.append(OZHoodAI.OZHoodAI(self))
        clearQueue()
        self.hoods.append(GZHoodAI.GZHoodAI(self))
        clearQueue()
        self.hoods.append(SellbotHQAI.SellbotHQAI(self))
        clearQueue()
        self.hoods.append(CashbotHQAI.CashbotHQAI(self))
        clearQueue()
        self.hoods.append(LawbotHQAI.LawbotHQAI(self))
        clearQueue()
        self.hoods.append(BossbotHQAI.BossbotHQAI(self))
        clearQueue()
        print('Done creating Zones!')

        for sp in self.suitPlanners.values():
            sp.assignInitialSuitBuildings()

    def genDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phase = ToontownGlobals.phaseMap[hoodId]
        else:
            phase = ToontownGlobals.streetPhaseMap[hoodId]

        return 'phase_%s/dna/%s_%s.xml' % (phase, hood, zoneId)

    def loadDNA(self, filename):
        with open('/' + filename) as f:
            tree = DNAParser.parse(f)

        return tree
Пример #8
0
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self, baseChannel, serverId, districtName):
        ToontownInternalRepository.__init__(self,
                                            baseChannel,
                                            serverId,
                                            dcSuffix='AI')

        self.dnaSpawner = DNASpawnerAI(self)

        self.districtName = districtName

        self.zoneAllocator = UniqueIdAllocator(
            ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd)
        self.zoneId2owner = {}

        NPCToons.generateZone2NpcDict()

        self.hoods = []
        self.zoneDataStore = AIZoneDataStore()

        self.useAllMinigames = self.config.GetBool('want-all-minigames', False)
        self.doLiveUpdates = self.config.GetBool('want-live-updates', True)
        self.baseXpMultiplier = self.config.GetFloat('base-xp-multiplier', 1.0)
        self.wantHalloween = self.config.GetBool('want-halloween', False)
        self.wantChristmas = self.config.GetBool('want-christmas', False)
        self.holidayManager = HolidayManagerAI(self)
        if config.GetBool('want-pets', True):
            self.PetManager = PetManagerAI(self)
        self.fishManager = FishManagerAI()
        self.questManager = QuestManagerAI(self)
        self.cogPageManager = CogPageManagerAI()
        self.factoryMgr = FactoryManagerAI(self)
        self.mintMgr = MintManagerAI(self)
        self.lawOfficeMgr = LawOfficeManagerAI(self)
        self.countryClubMgr = CountryClubManagerAI(self)
        self.promotionMgr = PromotionManagerAI(self)
        self.cogSuitMgr = CogSuitManagerAI(self)
        self.suitInvasionManager = SuitInvasionManagerAI(self)

        self.statusSender = ShardStatusSender(self)

        self.dnaStoreMap = {}

        self.buildingManagers = {}
        self.suitPlanners = {}

    def getTrackClsends(self):
        return False

    def handleConnected(self):
        self.notify.info('Yarn. Waking up (This may take a while!).')
        ToontownInternalRepository.handleConnected(self)
        self.districtId = self.allocateChannel()
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)

        # Claim ownership of that district...
        dg = PyDatagram()
        dg.addServerHeader(self.districtId, self.ourChannel,
                           STATESERVER_OBJECT_SET_AI)
        dg.addChannel(self.ourChannel)
        self.send(dg)

        self.notify.info('Creating Global Managers')
        self.createGlobals()
        self.notify.info('Creating Toontown')
        self.createZones()

        self.statusSender.start()

        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('District is now ready.')

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() + 1)
        self.statusSender.sendStatus()

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() - 1)
        self.statusSender.sendStatus()

    def allocateZone(self, owner=None):
        zoneId = self.zoneAllocator.allocate()
        if owner:
            self.zoneId2owner[zoneId] = owner
        return zoneId

    def deallocateZone(self, zone):
        if self.zoneId2owner.get(zone):
            del self.zoneId2owner[zone]
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def createGlobals(self):
        """
        Create "global" objects, e.g. TimeManager et al.
        """
        self.notify.info('Creating District Stats')
        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(),
                                                     self.getGameDoId(), 3)
        self.notify.info('Creating Time Manager')
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)

        self.notify.info('Creating News Manager')
        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)

        if config.GetBool('want-mw-manager', True):
            self.notify.info('Creating Magic Words Manager')
            self.magicWordManager = MagicWordManagerAI(self)
            self.magicWordManager.generateWithRequired(2)

        if config.GetBool('want-friends-manager', True):
            self.notify.info('Creating Friends Manager')
            self.friendManager = FriendManagerAI(self)
            self.friendManager.generateWithRequired(2)

        if config.GetBool('want-parties', True):
            self.notify.info('Creating Parties Manager')
            self.partyManager = DistributedPartyManagerAI(self)
            self.partyManager.generateWithRequired(2)

            # Setup our view of the global party manager ud
            self.globalPartyMgr = self.generateGlobalObject(
                OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        if config.GetBool('want-estates-manager', True):
            self.notify.info('Creating Estates')
            self.estateManager = EstateManagerAI(self)
            self.estateManager.generateWithRequired(2)

        self.notify.info('Creating TrophyMgr')
        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(2)

        self.notify.info('Creating Toontorial Manager')
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)

        self.notify.info('Creating Catalog Manager')
        self.catalogManager = CatalogManagerAI(self)
        self.catalogManager.generateWithRequired(2)
        if config.GetBool('want-pets', True):
            self.notify.info('Creating Pets Manager')
            self.PetManager = PetManagerAI(self)

        self.notify.info('Creating Code Redemption Manager')
        self.codeRedemptionManager = TTCodeRedemptionMgrAI(self)
        self.codeRedemptionManager.generateWithRequired(2)

    def createZones(self):
        """
        Spawn safezone objects, streets, doors, NPCs, etc.
        """
        start = time.clock()

        def clearQueue():
            '''So the TCP window doesn't fill up and we get the axe'''
            while self.readerPollOnce():
                pass

        self.notify.info('Creating TTC (Toontown Central) ')
        self.hoods.append(TTHoodAI.TTHoodAI(self))
        clearQueue()
        self.notify.info('Creating DD (Donalds Dock)')
        self.hoods.append(DDHoodAI.DDHoodAI(self))
        clearQueue()
        self.notify.info('Creating DG (Daisy Gardens) ')
        self.hoods.append(DGHoodAI.DGHoodAI(self))
        clearQueue()
        self.notify.info('Creating BR (The Brrrgh) ')
        self.hoods.append(BRHoodAI.BRHoodAI(self))
        clearQueue()
        self.notify.info('Creating MML (Minnie Melody Land) ')
        self.hoods.append(MMHoodAI.MMHoodAI(self))
        clearQueue()
        self.notify.info('Creating DDL (Donalds Dream Land) ')
        self.hoods.append(DLHoodAI.DLHoodAI(self))
        clearQueue()
        self.notify.info('Creating GS (SpeedWay) ')
        self.hoods.append(GSHoodAI.GSHoodAI(self))
        clearQueue()
        self.notify.info('Creating OZ (Outdoor Zone)')
        self.hoods.append(OZHoodAI.OZHoodAI(self))
        clearQueue()
        self.notify.info('Creating GZ (Golf Zone) ')
        self.hoods.append(GZHoodAI.GZHoodAI(self))
        clearQueue()
        self.notify.info('Creating TF (Toonfest) ')
        self.hoods.append(TFHoodAI.TFHoodAI(self))
        clearQueue()

        if config.GetBool('want-sbhq', True):
            self.notify.info('Creating SBHQ (Sellbot HQ) ')
            self.hoods.append(SellbotHQAI.SellbotHQAI(self))
            clearQueue()

        if config.GetBool('want-cbhq', True):
            self.notify.info('Creating CBHQ (Cashbot HQ) ')
            self.hoods.append(CashbotHQAI.CashbotHQAI(self))
            clearQueue()

        if config.GetBool('want-lbhq', True):
            self.notify.info('Creating LBHQ (Lawbot HQ) ')
            self.hoods.append(LawbotHQAI.LawbotHQAI(self))
            clearQueue()

        if config.GetBool('want-bbhq', True):
            self.notify.info('Creating BBHQ (Bossbot HQ) ')
            self.hoods.append(BossbotHQAI.BossbotHQAI(self))
            clearQueue()

        for sp in self.suitPlanners.values():
            sp.assignInitialSuitBuildings()

    def genDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phase = ToontownGlobals.phaseMap[hoodId]
        else:
            phase = ToontownGlobals.streetPhaseMap[hoodId]

        return 'phase_%s/dna/%s_%s.xml' % (phase, hood, zoneId)

    def loadDNA(self, filename):
        with open('/' + filename) as f:
            tree = DNAParser.parse(f)

        return tree
Пример #9
0
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self, baseChannel, serverId, districtName, holidayPasscode,
                 serverDescription, miniserverId):
        ToontownInternalRepository.__init__(self,
                                            baseChannel,
                                            serverId,
                                            dcSuffix='AI')
        self.districtName = districtName
        self.holidayPasscode = holidayPasscode
        self.holidayValue = 0
        self.serverDescription = serverDescription
        self.zoneAllocator = UniqueIdAllocator(
            ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd)
        self.zoneId2owner = {}
        NPCToons.generateZone2NpcDict()
        self.zoneTable = {}
        self.hoodArray = []
        self.hoods = []
        self._dnaStoreMap = {}
        self.zoneDataStore = AIZoneDataStore()
        self.useAllMinigames = self.config.GetBool('want-all-minigames', False)
        self.doLiveUpdates = self.config.GetBool('want-live-updates', True)
        self.reachedPlayerLimit = False
        self.fishManager = FishManagerAI()
        self.questManager = QuestManagerAI(self)
        self.cogPageManager = CogPageManagerAI()
        self.factoryMgr = FactoryManagerAI(self)
        self.mintMgr = MintManagerAI(self)
        self.lawOfficeMgr = LawOfficeManagerAI(self)
        self.countryClubMgr = CountryClubManagerAI(self)
        self.promotionMgr = PromotionManagerAI(self)
        self.cogSuitMgr = CogSuitManagerAI(self)
        self.wantCogdominiums = self.config.GetBool('want-cogdominums', False)
        self.buildingManagers = {}
        self.suitPlanners = {}
        self.inEpisode = False
        self.cutsceneActivated = False
        self.currentEpisode = None
        self.wantMiniServer = config.GetBool('want-mini-server', False)
        if not self.wantMiniServer:
            self.wantPrologue = config.GetBool('want-prologue', False)
        else:
            self.wantPrologue = False
        return

    def getTrackClsends(self):
        return False

    def handleConnected(self):
        ToontownInternalRepository.handleConnected(self)
        if self.holidayPasscode != '':
            self.initServerHoliday()
        self.districtId = self.allocateChannel()
        self.notify.info('Creating district (%d)...' % self.districtId)
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.setDescription(self.serverDescription)
        self.distributedDistrict.setHolidayPasscode(self.holidayValue)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), OTP_ZONE_ID_MANAGEMENT)
        self.notify.info('Claiming ownership of district (%d)...' %
                         self.districtId)
        dg = PyDatagram()
        dg.addServerHeader(self.districtId, self.ourChannel,
                           STATESERVER_OBJECT_SET_AI)
        dg.addChannel(self.ourChannel)
        self.send(dg)
        self.notify.info('Creating global objects...')
        self.createGlobals()
        self.notify.info('Creating zones (Playgrounds and Cog HQs)...')
        self.createZones()

    def districtReady(self):
        for sp in self.suitPlanners.values():
            sp.assignInitialSuitBuildings()

        self.notify.info('Making district available...')
        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('District is now ready. Have fun in Toontown!')
        self.sendPing()
        taskMgr.doMethodLater(30, self.sendPing, 'pingWebsite')

    def HTTPReq(self, url, data=None):
        if type(data) == dict:
            data = urllib.urlencode(data)
            data = data.encode('utf-8')
        context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64)'}
        request = urllib2.Request(url, data, headers=headers)
        response = urllib2.urlopen(request, context=context)
        data = json.loads(response.read().decode())
        return data

    def sendPing(self, task=None):
        if self.wantMiniServer:
            serverId = config.GetString('server-id', '')
            if serverId != '':
                gameMode = 'Elections' if config.GetBool(
                    'want-doomsday', False) else 'Normal'
                try:
                    self.sendPingToAPI(
                        serverId,
                        name=self.districtName,
                        desc=self.serverDescription,
                        population=self.districtStats.getAvatarCount(),
                        mode=gameMode)
                except:
                    self.notify.info('Could not ping the website! ')

                return Task.again
        return Task.done

    def getColumns(self):
        data = self.HTTPReq('https://ttoffline.com/api/miniservers/columns')
        return data

    def sendPingToAPI(self, serverId, **kwargs):
        columns = self.getColumns()
        data = {'uniqueId': serverId}
        for arg in kwargs.keys():
            if arg in columns:
                data['%s' % arg] = kwargs[arg]
                continue
            self.notify.info('%s is not a valid argument!' % arg)

        resp = self.HTTPReq('https://ttoffline.com/api/miniservers/ping',
                            data=data)
        if not resp['success']:
            self.notify.info('Could not ping the website! (Message: %s)' %
                             resp['message'])

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() + 1)
        self.avatarCountCheck()
        self.sendPing()

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() - 1)
        self.avatarCountCheck()
        self.sendPing()

    def avatarCountCheck(self):
        if not self.reachedPlayerLimit and self.districtStats.getAvatarCount(
        ) >= config.GetInt('miniserver-player-limit',
                           ToontownGlobals.DefaultMiniserverLimit):
            self.reachedPlayerLimit = True
            self.notify.warning(
                'Reached player limit! Making district unavailable...')
            self.distributedDistrict.b_setAvailable(0)
            self.notify.warning(
                'District is now unavailable. Incoming connections will be rejected.'
            )
        if self.reachedPlayerLimit and self.districtStats.getAvatarCount(
        ) < config.GetInt('miniserver-player-limit',
                          ToontownGlobals.DefaultMiniserverLimit):
            self.reachedPlayerLimit = False
            self.notify.info(
                'Player count dropped! Making district available...')
            self.distributedDistrict.b_setAvailable(1)
            self.notify.info(
                'District is now available. Incoming connections will be accepted.'
            )

    def allocateZone(self, owner=None):
        zoneId = self.zoneAllocator.allocate()
        if owner:
            self.zoneId2owner[zoneId] = owner
        return zoneId

    def deallocateZone(self, zone):
        if self.zoneId2owner.get(zone):
            del self.zoneId2owner[zone]
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def getAvatarZoneChangeEvent(self, avId):
        return 'DOChangeZone-%d' % avId

    def avIsInEpisode(self):
        return self.currentEpisode is not None

    def createGlobals(self):
        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(),
                                                     self.getGameDoId(),
                                                     OTP_ZONE_ID_DISTRICTS)
        self.notify.info('Created district stats AI (%d).' %
                         self.districtStats.doId)
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.suitInvasionManager = SuitInvasionManagerAI(self)
        self.holidayManager = HolidayManagerAI(self)
        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.sillyMeterMgr = DistributedSillyMeterMgrAI(self)
        self.sillyMeterMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        if config.GetBool('want-code-redemption', True):
            self.codeRedemptionMgr = TTCodeRedemptionMgrAI(self)
            self.codeRedemptionMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        if config.GetBool('want-parties', True):
            self.partyManager = DistributedPartyManagerAI(self)
            self.partyManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
            self.globalPartyMgr = self.generateGlobalObject(
                OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')
        if config.GetBool('want-estates', True):
            self.estateManager = EstateManagerAI(self)
            self.estateManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        if simbase.wantPets:
            self.petMgr = PetManagerAI(self)
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.catalogManager = CatalogManagerAI(self)
        self.catalogManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        if config.GetBool('want-event-manager', False):
            self.eventManager = DistributedEventManagerAI(self)
            self.eventManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        if config.GetBool('want-news-page', False):
            self.inGameNewsMgr = DistributedInGameNewsMgrAI(self)
            self.inGameNewsMgr.setLatestIssueStr('2013-08-22 23:49:46')
            self.inGameNewsMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.banManager = self.generateGlobalObject(OTP_DO_ID_BAN_MANAGER,
                                                    'BanManager')

    def createZones(self):
        if config.GetBool('want-playgrounds', True):
            if config.GetBool('want-toontown-central', True):
                self.hoodArray.append(TTHoodDataAI.TTHoodDataAI)
                self.zoneTable[2000] = ((2000, 1, 0), (2100, 1, 1),
                                        (2200, 1, 1), (2300, 1, 1))
            if config.GetBool('want-donalds-dock', True):
                self.hoodArray.append(DDHoodDataAI.DDHoodDataAI)
                self.zoneTable[1000] = ((1000, 1, 0), (1100, 1, 1),
                                        (1200, 1, 1), (1300, 1, 1))
            if config.GetBool('want-daisy-gardens', True):
                self.hoodArray.append(DGHoodDataAI.DGHoodDataAI)
                self.zoneTable[5000] = ((5000, 1, 0), (5100, 1, 1),
                                        (5200, 1, 1), (5300, 1, 1))
            if config.GetBool('want-minnies-melodyland', True):
                self.hoodArray.append(MMHoodDataAI.MMHoodDataAI)
                self.zoneTable[4000] = ((4000, 1, 0), (4100, 1, 1),
                                        (4200, 1, 1), (4300, 1, 1))
            if config.GetBool('want-the-brrrgh', True):
                self.hoodArray.append(BRHoodDataAI.BRHoodDataAI)
                self.zoneTable[3000] = ((3000, 1, 0), (3100, 1, 1),
                                        (3200, 1, 1), (3300, 1, 1))
            if config.GetBool('want-donalds-dreamland', True):
                self.hoodArray.append(DLHoodDataAI.DLHoodDataAI)
                self.zoneTable[9000] = ((9000, 1, 0), (9100, 1, 1), (9200, 1,
                                                                     1))
            if config.GetBool('want-goofy-speedway', True):
                self.hoodArray.append(GSHoodDataAI.GSHoodDataAI)
                self.zoneTable[8000] = ((8000, 1, 0), )
            if config.GetBool('want-acorn-acres', True):
                self.hoodArray.append(OZHoodDataAI.OZHoodDataAI)
                self.zoneTable[6000] = ((6000, 1, 0), )
            if config.GetBool('want-toonfest', True):
                self.hoodArray.append(TFHoodDataAI.TFHoodDataAI)
                self.zoneTable[ToontownGlobals.ToonFest] = ((
                    ToontownGlobals.ToonFest, 1, 0), )
            if config.GetBool('want-minigolf', True):
                self.hoodArray.append(GZHoodDataAI.GZHoodDataAI)
                self.zoneTable[17000] = ((17000, 1, 0), )
            if not self.wantMiniServer:
                if config.GetBool('want-scrooge-bank', True):
                    self.hoodArray.append(SBHoodDataAI.SBHoodDataAI)
                    self.zoneTable[1002000] = ()
                if config.GetBool('want-old-daisy-gardens', True):
                    self.hoodArray.append(ODGHoodDataAI.ODGHoodDataAI)
                    self.zoneTable[21000] = ((21000, 1, 0), (21300, 1, 1))
        if config.GetBool('want-cog-headquarters', True):
            if config.GetBool('want-sellbot-hq', True):
                self.hoodArray.append(CSHoodDataAI.CSHoodDataAI)
                self.zoneTable[11000] = ((11000, 1, 0), (11200, 1, 0))
            if config.GetBool('want-cashbot-hq', True):
                self.hoodArray.append(CashbotHQDataAI.CashbotHQDataAI)
                self.zoneTable[12000] = ((12000, 1, 0), )
            if config.GetBool('want-lawbot-hq', True):
                self.hoodArray.append(LawbotHQDataAI.LawbotHQDataAI)
                self.zoneTable[13000] = ((13000, 1, 0), )
            if config.GetBool('want-bossbot-hq', True):
                self.hoodArray.append(BossbotHQDataAI.BossbotHQDataAI)
                self.zoneTable[10000] = ((10000, 0, 0), (10900, 1, 0))
        self.__nextHood(0)

    def __nextHood(self, hoodIndex):
        if hoodIndex >= len(self.hoodArray):
            self.districtReady()
            return Task.done
        self.hoods.append(self.hoodArray[hoodIndex](self))
        taskMgr.doMethodLater(0, ToontownAIRepository.__nextHood, 'nextHood',
                              [self, hoodIndex + 1])
        return Task.done

    def dnaStoreMap(self, zone):
        dnaStore = self._dnaStoreMap.get(zone)
        if not dnaStore:
            dnaStore = DNAStorage()
            self.loadDNAFileAI(dnaStore, self.genDNAFileName(zone))
            self._dnaStoreMap[zone] = dnaStore
        return dnaStore

    def genDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phase = ToontownGlobals.phaseMap[hoodId]
        else:
            phase = ToontownGlobals.streetPhaseMap[hoodId]
        return 'phase_%s/dna/%s_%s.jazz' % (phase, hood, zoneId)

    def loadDNAFileAI(self, dnaStore, filename):
        return loadDNAFileAI(dnaStore, filename)

    def initServerHoliday(self):
        self.notify.info('Holiday Passcode detected. Initalizing Holiday...')
        holidayPasscodes = [
            'holidayHW2017811154', 'holidayHW2017421808',
            'holidayHW2017475201', 'holidayHW2017669818',
            'holidayHW2017001496', 'holidayHW2017139447'
        ]
        for passcode in holidayPasscodes:
            if passcode == self.holidayPasscode:
                self.holidayValue = holidayPasscodes.index(passcode) + 1

        if self.holidayPasscode in holidayPasscodes:
            self.notify.info(
                "Holdiay Passcode '%s' is active on this District!" %
                self.holidayPasscode)
        else:
            self.notify.info("Holdiay Passcode '%s' is not a valid Passcode!" %
                             self.holidayPasscode)
Пример #10
0
class ToontownAIRepository(ToontownInternalRepository):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'ToontownAIRepository')

    def __init__(self, baseChannel, serverId, expMultiplier, meritMultiplier,
                 doodleMultiplier, defaultMaxToon, defaultZone, districtName,
                 districtLimit, districtDescription, districtWebsiteId,
                 eventId, defaultAccessLevel):
        ToontownInternalRepository.__init__(self,
                                            baseChannel,
                                            serverId,
                                            dcSuffix='AI')
        self.expMultiplier = expMultiplier
        self.meritMultiplier = meritMultiplier
        self.doodleMultiplier = doodleMultiplier
        self.defaultMaxToon = defaultMaxToon
        self.defaultZone = defaultZone
        self.districtName = districtName
        self.districtLimit = districtLimit
        if self.districtLimit < ToontownGlobals.MIN_POP:
            self.districtLimit = ToontownGlobals.MIN_POP
        elif self.districtLimit > ToontownGlobals.HIGH_POP:
            self.districtLimit = ToontownGlobals.HIGH_POP
        self.districtDescription = districtDescription
        self.districtWebsiteId = districtWebsiteId
        self.eventId = eventId
        self.defaultAccessLevel = defaultAccessLevel
        self.doLiveUpdates = self.config.GetBool('want-live-updates', True)
        self.wantCogdominiums = self.config.GetBool('want-cogdominiums', True)
        self.wantEmblems = self.config.GetBool('want-emblems', True)
        self.useAllMinigames = self.config.GetBool('want-all-minigames', True)
        self.wantEmblems = self.config.GetBool('want-emblems', True)
        self.districtId = None
        self.district = None
        self.districtStats = None
        self.districtFull = False
        self.timeManager = None
        self.newsManager = None
        self.holidayManager = None
        self.welcomeValleyManager = None
        self.catalogManager = None
        self.zoneDataStore = None
        self.inGameNewsMgr = None
        self.trophyMgr = None
        self.petMgr = None
        self.dnaStoreMap = {}
        self.dnaDataMap = {}
        self.zoneTable = {}
        self.hoods = []
        self.buildingManagers = {}
        self.suitPlanners = {}
        self.suitInvasionManager = None
        self.zoneAllocator = None
        self.zoneId2owner = {}
        self.questManager = None
        self.cogPageManager = None
        self.fishManager = None
        self.factoryMgr = None
        self.mintMgr = None
        self.lawMgr = None
        self.countryClubMgr = None
        self.promotionMgr = None
        self.cogSuitMgr = None
        self.partyManager = None
        self.safeZoneManager = None
        self.raceMgr = None
        self.polarPlaceEffectMgr = None
        self.resistanceEmoteMgr = None
        self.tutorialManager = None
        self.friendManager = None
        self.chatManager = None
        self.toontownTimeManager = None
        self.estateMgr = None
        self.magicWordManager = None
        self.deliveryManager = None
        self.cogSuitMessageSent = False
        self.propGenerators = {}
        self.propGeneratorsLocked = False
        self.moddingManager = None
        self.discordManager = None
        return

    def getTrackClsends(self):
        return False

    def handleConnected(self):
        ToontownInternalRepository.handleConnected(self)
        self.districtId = self.allocateChannel()
        self.notify.info('Creating district (%d)...' % self.districtId)
        self.district = ToontownDistrictAI(self)
        self.district.setName(self.districtName)
        self.district.setDescription(self.districtDescription)
        self.district.generateWithRequiredAndId(self.districtId,
                                                self.getGameDoId(),
                                                OTP_ZONE_ID_MANAGEMENT)
        self.notify.info('Claiming ownership of district (%d)...' %
                         self.districtId)
        datagram = PyDatagram()
        datagram.addServerHeader(self.districtId, self.ourChannel,
                                 STATESERVER_OBJECT_SET_AI)
        datagram.addChannel(self.ourChannel)
        self.send(datagram)
        self.notify.info('Creating local objects...')
        self.createLocals()
        self.notify.info('Creating global objects...')
        self.createGlobals()
        self.notify.info('Creating zones (Playgrounds and Cog HQs)...')
        self.createZones()
        self.notify.info('Making district available...')
        self.district.b_setAvailable(1)
        self.notify.info(
            'District is now ready. Have fun in Toontown Offline!')

    def createLocals(self):
        self.holidayManager = HolidayManagerAI(self)
        self.zoneDataStore = AIZoneDataStore()
        self.petMgr = PetManagerAI(self)
        self.suitInvasionManager = SuitInvasionManagerAI(self)
        self.zoneAllocator = UniqueIdAllocator(
            ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd)
        self.questManager = QuestManagerAI(self)
        self.cogPageManager = CogPageManagerAI(self)
        self.fishManager = FishManagerAI(self)
        self.factoryMgr = FactoryManagerAI(self)
        self.mintMgr = MintManagerAI(self)
        self.lawMgr = LawOfficeManagerAI(self)
        self.countryClubMgr = CountryClubManagerAI(self)
        self.promotionMgr = PromotionManagerAI(self)
        self.cogSuitMgr = CogSuitManagerAI(self)
        self.raceMgr = RaceManagerAI(self)
        self.toontownTimeManager = ToontownTimeManager(
            serverTimeUponLogin=int(time.time()),
            globalClockRealTimeUponLogin=globalClock.getRealTime())

    def createGlobals(self):
        districtStatsId = self.allocateChannel()
        self.notify.info('Creating district stats AI (%d)...' %
                         districtStatsId)
        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(districtStatsId,
                                                     self.getGameDoId(),
                                                     OTP_ZONE_ID_DISTRICTS)
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.newsManager.d_setExpMultiplier(self.expMultiplier)
        self.catalogManager = CatalogManagerAI(self)
        self.catalogManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.inGameNewsMgr = DistributedInGameNewsMgrAI(self)
        self.inGameNewsMgr.setLatestIssueStr('2013-08-22 23:49:46')
        self.inGameNewsMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.partyManager = DistributedPartyManagerAI(self)
        self.partyManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.safeZoneManager = SafeZoneManagerAI(self)
        self.safeZoneManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.polarPlaceEffectMgr = DistributedPolarPlaceEffectMgrAI(self)
        self.polarPlaceEffectMgr.generateWithRequired(3821)
        self.resistanceEmoteMgr = DistributedResistanceEmoteMgrAI(self)
        self.resistanceEmoteMgr.generateWithRequired(9720)
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.chatManager = TTOffChatManagerAI(self)
        self.chatManager.generateWithRequiredAndId(OTP_DO_ID_CHAT_MANAGER,
                                                   self.getGameDoId(),
                                                   OTP_ZONE_ID_MANAGEMENT)
        self.estateMgr = EstateManagerAI(self)
        self.estateMgr.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.magicWordManager = TTOffMagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(OTP_ZONE_ID_MANAGEMENT)
        self.deliveryManager = self.generateGlobalObject(
            OTP_DO_ID_TOONTOWN_DELIVERY_MANAGER, 'DistributedDeliveryManager')
        self.banManager = self.generateGlobalObject(OTP_DO_ID_BAN_MANAGER,
                                                    'BanManager')
        self.moddingManager = ModdingManagerAI(self)
        self.moddingManager.generateWithRequiredAndId(
            OTP_DO_ID_MODDING_MANAGER, self.getGameDoId(),
            OTP_ZONE_ID_MANAGEMENT)
        self.moddingManager.setColorsAiToUd(self.moddingManager.getColors())
        self.moddingManager.setCardsAiToUd(self.moddingManager.getCards())
        self.moddingManager.d_setDefaultMaxToon(self.defaultMaxToon)
        self.moddingManager.d_setDefaultZone(self.defaultZone)
        self.discordManager = DiscordManagerAI(self)
        self.discordManager.generateWithRequiredAndId(
            OTP_DO_ID_DISCORD_MANAGER, self.getGameDoId(),
            OTP_ZONE_ID_MANAGEMENT)

    def createHood(self, hoodCtr, zoneId):
        if zoneId != ToontownGlobals.BossbotHQ:
            self.dnaStoreMap[zoneId] = DNAStorage()
            self.dnaDataMap[zoneId] = self.loadDNAFileAI(
                self.dnaStoreMap[zoneId], self.genDNAFileName(zoneId))
            if zoneId in ToontownGlobals.HoodHierarchy:
                for streetId in ToontownGlobals.HoodHierarchy[zoneId]:
                    self.dnaStoreMap[streetId] = DNAStorage()
                    self.dnaDataMap[streetId] = self.loadDNAFileAI(
                        self.dnaStoreMap[streetId],
                        self.genDNAFileName(streetId))

        hood = hoodCtr(self, zoneId)
        hood.startup()
        self.hoods.append(hood)

    def createZones(self):
        NPCToons.generateZone2NpcDict()
        self.zoneTable[ToontownGlobals.ToontownCentral] = (
            (ToontownGlobals.ToontownCentral, 1,
             0), (ToontownGlobals.SillyStreet, 1,
                  1), (ToontownGlobals.LoopyLane, 1,
                       1), (ToontownGlobals.PunchlinePlace, 1, 1))
        self.createHood(TTHoodDataAI, ToontownGlobals.ToontownCentral)
        self.zoneTable[ToontownGlobals.DonaldsDock] = (
            (ToontownGlobals.DonaldsDock, 1,
             0), (ToontownGlobals.BarnacleBoulevard, 1,
                  1), (ToontownGlobals.SeaweedStreet, 1,
                       1), (ToontownGlobals.LighthouseLane, 1, 1))
        self.createHood(DDHoodDataAI, ToontownGlobals.DonaldsDock)
        self.zoneTable[ToontownGlobals.DaisyGardens] = (
            (ToontownGlobals.DaisyGardens, 1,
             0), (ToontownGlobals.ElmStreet, 1,
                  1), (ToontownGlobals.MapleStreet, 1,
                       1), (ToontownGlobals.OakStreet, 1, 1))
        self.createHood(DGHoodDataAI, ToontownGlobals.DaisyGardens)
        self.zoneTable[ToontownGlobals.MinniesMelodyland] = (
            (ToontownGlobals.MinniesMelodyland, 1,
             0), (ToontownGlobals.AltoAvenue, 1,
                  1), (ToontownGlobals.BaritoneBoulevard, 1,
                       1), (ToontownGlobals.TenorTerrace, 1, 1))
        self.createHood(MMHoodDataAI, ToontownGlobals.MinniesMelodyland)
        self.zoneTable[ToontownGlobals.TheBrrrgh] = (
            (ToontownGlobals.TheBrrrgh, 1,
             0), (ToontownGlobals.WalrusWay, 1,
                  1), (ToontownGlobals.SleetStreet, 1,
                       1), (ToontownGlobals.PolarPlace, 1, 1))
        self.createHood(BRHoodDataAI, ToontownGlobals.TheBrrrgh)
        self.zoneTable[ToontownGlobals.DonaldsDreamland] = (
            (ToontownGlobals.DonaldsDreamland, 1,
             0), (ToontownGlobals.LullabyLane, 1,
                  1), (ToontownGlobals.PajamaPlace, 1, 1))
        self.createHood(DLHoodDataAI, ToontownGlobals.DonaldsDreamland)
        self.zoneTable[ToontownGlobals.SellbotHQ] = (
            (ToontownGlobals.SellbotHQ, 0,
             1), (ToontownGlobals.SellbotFactoryExt, 0, 1))
        self.createHood(CSHoodDataAI, ToontownGlobals.SellbotHQ)
        self.zoneTable[ToontownGlobals.CashbotHQ] = ((
            ToontownGlobals.CashbotHQ, 0, 1), )
        self.createHood(CashbotHQDataAI, ToontownGlobals.CashbotHQ)
        self.zoneTable[ToontownGlobals.LawbotHQ] = ((ToontownGlobals.LawbotHQ,
                                                     0, 1), )
        self.createHood(LawbotHQDataAI, ToontownGlobals.LawbotHQ)
        self.zoneTable[ToontownGlobals.BossbotHQ] = ((
            ToontownGlobals.BossbotHQ, 0, 0), )
        self.createHood(BossbotHQDataAI, ToontownGlobals.BossbotHQ)
        self.zoneTable[ToontownGlobals.GoofySpeedway] = ((
            ToontownGlobals.GoofySpeedway, 1, 0), )
        self.createHood(GSHoodDataAI, ToontownGlobals.GoofySpeedway)
        self.zoneTable[ToontownGlobals.OutdoorZone] = ((
            ToontownGlobals.OutdoorZone, 1, 0), )
        self.createHood(OZHoodDataAI, ToontownGlobals.OutdoorZone)
        self.zoneTable[ToontownGlobals.GolfZone] = ((ToontownGlobals.GolfZone,
                                                     1, 0), )
        self.createHood(GZHoodDataAI, ToontownGlobals.GolfZone)
        self.zoneTable[ToontownGlobals.ToontownOutskirts] = (
            (ToontownGlobals.ToontownOutskirts, 1,
             0), (ToontownGlobals.TutorialTerrace, 1, 1))
        self.createHood(SpecialHoodDataAI, ToontownGlobals.ToontownOutskirts)
        self.zoneTable[ToontownGlobals.ToontownCentralBeta] = ((
            ToontownGlobals.ToontownCentralBeta, 1, 0), )
        self.createHood(TTBetaHoodDataAI, ToontownGlobals.ToontownCentralBeta)
        self.zoneTable[ToontownGlobals.DaisyGardensBeta] = (
            (ToontownGlobals.DaisyGardensBeta, 1,
             0), (ToontownGlobals.OakStreetBeta, 1, 0))
        self.createHood(DGBetaHoodDataAI, ToontownGlobals.DaisyGardensBeta)
        self.notify.info(
            'Assigning initial Cog buildings and Field Offices...')
        for suitPlanner in self.suitPlanners.values():
            suitPlanner.assignInitialSuitBuildings()

    def sendPing(self, task=None):
        if self.districtWebsiteId != '' and config.GetBool(
                'mini-server', False):
            gameMode = TTLocalizer.MiniserverLegit if self.defaultAccessLevel == 'NO_ACCESS' else TTLocalizer.MiniserverCheats
            try:
                self.sendPingToAPI(
                    self.districtWebsiteId,
                    name=self.districtName,
                    desc=self.districtDescription,
                    population=self.districtStats.getAvatarCount(),
                    mode=gameMode)
            except:
                self.notify.info(
                    'Could not ping the Toontown Offline website! Make sure you are connected to the Internet.'
                )

            return Task.again
        return Task.done

    def sendPingToAPI(self, serverId, **kwargs):
        columns = self.getColumns()
        data = {'uniqueId': serverId}
        for arg in kwargs.keys():
            if arg in columns:
                data['%s' % arg] = kwargs[arg]
                continue
            self.notify.info('%s is not a valid argument!' % arg)

        resp = self.HTTPReq('http://localhost/api/miniservers/ping', data=data)
        if not resp['success']:
            self.notify.info('Could not ping the website! (Message: %s)' %
                             resp['message'])
            return
        data = {'uniqueId': serverId}
        resp = self.HTTPReq('http://localhost/api/miniservers/id2icon',
                            data=data)
        if not resp['success']:
            self.notify.info('Could not retrieve server icon! (Message: %s)' %
                             resp['message'])
            return
        if resp['message']:
            self.district.b_setIconPath(resp['message'])

    def getColumns(self):
        data = self.HTTPReq('http://localhost/api/miniservers/columns')
        return data

    def HTTPReq(self, url, data=None):
        if type(data) == dict:
            data = urllib.urlencode(data)
            data = data.encode('utf-8')
        context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64)',
            'Authorization': 'Basic dHRvZmY6SmF6enlTdHVkaW9z'
        }
        request = urllib2.Request(url, data, headers=headers)
        response = urllib2.urlopen(request, context=context)
        data = json.loads(response.read().decode())
        return data

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() + 1)
        self.avatarCountCheck()

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() - 1)
        self.avatarCountCheck()

    def avatarCountCheck(self):
        self.sendPing()
        if not self.districtFull and self.districtStats.getAvatarCount(
        ) >= self.districtLimit:
            self.districtFull = True
            self.notify.warning(
                'Reached player limit! Making district unavailable...')
            self.district.b_setFull(0)
            self.notify.warning(
                'District is now unavailable. Incoming connections will be rejected.'
            )
        if self.districtFull and self.districtStats.getAvatarCount(
        ) < self.districtLimit:
            self.districtFull = False
            self.notify.info(
                'Player count dropped! Making district available...')
            self.district.b_setFull(1)
            self.notify.info(
                'District is now available. Incoming connections will be accepted.'
            )

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def getZoneDataStore(self):
        return self.zoneDataStore

    def genDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phase = ToontownGlobals.phaseMap[hoodId]
        else:
            phase = ToontownGlobals.streetPhaseMap[hoodId]
        if 'outdoor_zone' in hood or 'golf_zone' in hood:
            phase = '6'
        return 'phase_%s/dna/%s_%s.dna' % (phase, hood, zoneId)

    def findFishingPonds(self, dnaData, zoneId, area):
        fishingPonds = []
        fishingPondGroups = []
        if isinstance(dnaData,
                      DNAGroup) and 'fishing_pond' in dnaData.getName():
            fishingPondGroups.append(dnaData)
            pond = self.fishManager.generatePond(area, zoneId)
            fishingPonds.append(pond)
        else:
            if isinstance(dnaData, DNAVisGroup):
                zoneId = ZoneUtil.getTrueZoneId(
                    int(dnaData.getName().split(':')[0]), zoneId)
            for i in xrange(dnaData.getNumChildren()):
                foundFishingPonds, foundFishingPondGroups = self.findFishingPonds(
                    dnaData.at(i), zoneId, area)
                fishingPonds.extend(foundFishingPonds)
                fishingPondGroups.extend(foundFishingPondGroups)

        return (fishingPonds, fishingPondGroups)

    def findFishingSpots(self, dnaData, fishingPond):
        fishingSpots = []
        if isinstance(dnaData,
                      DNAGroup) and dnaData.getName()[:13] == 'fishing_spot_':
            spot = self.fishManager.generateSpots(dnaData, fishingPond)
            fishingSpots.append(spot)
        for i in xrange(dnaData.getNumChildren()):
            foundFishingSpots = self.findFishingSpots(dnaData.at(i),
                                                      fishingPond)
            fishingSpots.extend(foundFishingSpots)

        return fishingSpots

    def findClassicFishingSpots(self, dnaData, fishingPond):
        fishingSpots = []
        if isinstance(dnaData, DNAGroup) and dnaData.getName(
        )[:21] == 'classic_fishing_spot_':
            spot = self.fishManager.generateClassicSpots(dnaData, fishingPond)
            fishingSpots.append(spot)
        for i in xrange(dnaData.getNumChildren()):
            foundFishingSpots = self.findClassicFishingSpots(
                dnaData.at(i), fishingPond)
            fishingSpots.extend(foundFishingSpots)

        return fishingSpots

    def findPartyHats(self, dnaData, zoneId):
        return []

    def loadDNAFileAI(self, dnaStore, dnaFileName):
        return loadDNAFileAI(dnaStore, dnaFileName)

    def allocateZone(self, owner=None):
        zoneId = self.zoneAllocator.allocate()
        if owner:
            self.zoneId2owner[zoneId] = owner
        return zoneId

    def deallocateZone(self, zone):
        if self.zoneId2owner.get(zone):
            del self.zoneId2owner[zone]
        self.zoneAllocator.free(zone)

    def trueUniqueName(self, idString):
        return self.uniqueName(idString)

    def findRacingPads(self,
                       dnaData,
                       zoneId,
                       area,
                       type='racing_pad',
                       overrideDNAZone=False):
        racingPads, racingPadGroups = [], []
        if type in dnaData.getName():
            if type == 'racing_pad':
                nameSplit = dnaData.getName().split('_')
                racePad = DistributedRacePadAI(self)
                racePad.setArea(area)
                racePad.index = int(nameSplit[2])
                racePad.genre = nameSplit[3]
                trackInfo = RaceGlobals.getNextRaceInfo(
                    -1, racePad.genre, racePad.index)
                racePad.setTrackInfo([trackInfo[0], trackInfo[1]])
                racePad.laps = trackInfo[2]
                racePad.generateWithRequired(zoneId)
                racingPads.append(racePad)
                racingPadGroups.append(dnaData)
            elif type == 'viewing_pad':
                viewPad = DistributedViewPadAI(self)
                viewPad.setArea(area)
                viewPad.generateWithRequired(zoneId)
                racingPads.append(viewPad)
                racingPadGroups.append(dnaData)
        for i in xrange(dnaData.getNumChildren()):
            foundRacingPads, foundRacingPadGroups = self.findRacingPads(
                dnaData.at(i), zoneId, area, type, overrideDNAZone)
            racingPads.extend(foundRacingPads)
            racingPadGroups.extend(foundRacingPadGroups)

        return (racingPads, racingPadGroups)

    def findStartingBlocks(self, dnaData, pad):
        startingBlocks = []
        for i in xrange(dnaData.getNumChildren()):
            groupName = dnaData.getName()
            blockName = dnaData.at(i).getName()
            if 'starting_block' in blockName:
                cls = DistributedStartingBlockAI if 'racing_pad' in groupName else DistributedViewingBlockAI
                x, y, z = dnaData.at(i).getPos()
                h, p, r = dnaData.at(i).getHpr()
                padLocationId = int(dnaData.at(i).getName()[(-1)])
                startingBlock = cls(self, pad, x, y, z, h, p, r, padLocationId)
                startingBlock.generateWithRequired(pad.zoneId)
                startingBlocks.append(startingBlock)

        return startingBlocks

    def getAvatarDisconnectReason(self, avId):
        return self.timeManager.avId2disconnectcode.get(
            avId, ToontownGlobals.DisconnectUnknown)

    def findLeaderBoards(self, dnaData, zoneId):
        leaderboards = []
        if 'leaderBoard' in dnaData.getName():
            x, y, z = dnaData.getPos()
            h, p, r = dnaData.getHpr()
            leaderboard = DistributedLeaderBoardAI(self, dnaData.getName(), x,
                                                   y, z, h, p, r)
            leaderboard.generateWithRequired(zoneId)
            leaderboards.append(leaderboard)
        for i in xrange(dnaData.getNumChildren()):
            foundLeaderBoards = self.findLeaderBoards(dnaData.at(i), zoneId)
            leaderboards.extend(foundLeaderBoards)

        return leaderboards

    def systemMessage(self, message):
        for doId, do in self.doId2do.items():
            if isinstance(do, DistributedPlayerAI):
                if str(doId)[0] != str(self.districtId)[0]:
                    do.d_setSystemMessage(0, message, WhisperPopup.WTSystem)

    def announceMaintenance(self, reason, type, time):
        self.systemMessage(
            TTLocalizer.ServerShutdownAnnouncement.format(type, time))
        taskMgr.doMethodLater(time,
                              self.shutdownMaintenance,
                              'shutdownMaintenance',
                              extraArgs=[reason])
        if time - 60.0 > 1:
            taskMgr.doMethodLater(
                time - 60.0,
                self.systemMessage,
                'shutdownMaintenance',
                extraArgs=[TTLocalizer.ServerShutdownWarning.format(type)])

    def shutdownMaintenance(self, reason):
        for doId, do in self.doId2do.items():
            if isinstance(do, DistributedPlayerAI):
                if str(doId)[0] != str(self.districtId)[0]:
                    do.sendSetKick(reason=reason, target=do, silent=3)
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self, baseChannel, serverId, districtName):
        ToontownInternalRepository.__init__(self,
                                            baseChannel,
                                            serverId,
                                            dcSuffix='AI')

        self.districtName = districtName

        self.zoneAllocator = UniqueIdAllocator(
            ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd)

        NPCToons.generateZone2NpcDict()

        self.use_libpandadna = simbase.config.GetBool('use-libpandadna', False)

        self.hoods = []
        self._dnaStoreMap = {}

        if self.use_libpandadna:
            self.__loader = DNALoader()

        self.zoneDataStore = AIZoneDataStore()

        self.useAllMinigames = self.config.GetBool('want-all-minigames', False)
        self.doLiveUpdates = True

        self.wantCogdominiums = self.config.GetBool('want-cogdo', False)
        self.wantParties = self.config.GetBool('want-parties', False)
        self.wantEmblems = self.config.GetBool('want-emblems', True)

        self.questManager = QuestManagerAI(self)
        self.promotionMgr = PromotionManagerAI(self)
        self.cogPageManager = CogPageManagerAI(self)
        self.cogSuitMgr = CogSuitManagerAI(self)

        self.trophyMgr = DistributedTrophyMgrAI(self)

        self.fishManager = FishManagerAI()

        self.dnaStoreMap = {}

        self.mintMgr = MintManagerAI.MintManagerAI(self)
        self.factoryMgr = FactoryManagerAI.FactoryManagerAI(self)
        self.lawMgr = LawOfficeManagerAI.LawOfficeManagerAI(self)
        self.countryClubMgr = CountryClubManagerAI.CountryClubManagerAI(self)

        self.buildingManagers = {}
        self.suitPlanners = {}

        self.wantMegaInvasions = str(
            self.ourChannel // 1000000) in self.config.GetString(
                'mega-invasion-shards', '402 403').split()

    def getTrackClsends(self):
        return False

    def handleConnected(self):
        self.districtId = self.allocateChannel()
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            simbase.air.districtId, self.getGameDoId(), 2)

        dg = PyDatagram()
        dg.addServerHeader(simbase.air.districtId, simbase.air.ourChannel,
                           STATESERVER_OBJECT_SET_AI)
        dg.addChannel(simbase.air.ourChannel)
        simbase.air.send(dg)

        self.createGlobals()
        self.createZones()

    def __ready(self):
        dg = PyDatagram()
        dg.addServerHeader(self.districtStats.doId, self.ourChannel,
                           STATESERVER_OBJECT_DELETE_RAM)
        dg.addUint32(self.districtStats.doId)
        self.addPostRemove(dg)

        self.apiMgr = self.generateGlobalObject(100001, "ShardAPIManager")
        self.apiMgr.start()
        self.apiMgr.d_setShardData()

        self.banMgr = self.generateGlobalObject(100002, "BanManager")

        self.trophyMgr.updateToonData()

    def gotUberdogAPISync(self):
        if not self.distributedDistrict.getAvailable():
            self.notify.info("Got UD API sync, opening shard...")
            messenger.send("startShardActivity")
            self.distributedDistrict.b_setAvailable(1)

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() + 1)

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() - 1)

    def allocateZone(self):
        return self.zoneAllocator.allocate()

    def deallocateZone(self, zone):
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % avId

    def createGlobals(self):
        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(),
                                                     self.getGameDoId(), 2)

        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)

        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)

        self.holidayManager = HolidayManagerAI(self)

        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(2)

        self.safeZoneManager = SafeZoneManagerAI(self)
        self.safeZoneManager.generateWithRequired(2)

        self.petMgr = PetManagerAI(self)

        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(2)

        self.partyManager = DistributedPartyManagerAI(self)
        self.partyManager.generateWithRequired(2)

        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)

        self.globalPartyMgr = self.generateGlobalObject(
            OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        self.estateManager = EstateManagerAI(self)
        self.estateManager.generateWithRequired(2)

        self.suitInvasionManager = DistributedSuitInvasionManagerAI(self)
        self.suitInvasionManager.generateWithRequired(2)

        self.bankMgr = DistributedBankMgrAI(self)
        self.bankMgr.generateWithRequired(2)

        self.catalogManager = CatalogManagerAI(self)
        self.catalogManager.generateWithRequired(2)

        self.huntId = 0

        if self.holidayManager.isHolidayRunning(
                ToontownGlobals.TRICK_OR_TREAT):
            import DistributedTrickOrTreatTargetAI
            self.trickOrTreatMgr = DistributedTrickOrTreatTargetAI.DistributedTrickOrTreatTargetAI(
                self)
            self.trickOrTreatMgr.generateWithRequired(2)

        self.handleBlackCatMgr()
        self.handleBloodsuckerInvasion()
        self.handleSkelCogWeekInvasion()

        if config.GetBool('want-resistance-emote', True):
            self.resistanceMgr = DistributedResistanceEmoteMgrAI.DistributedResistanceEmoteMgrAI(
                self)
            self.resistanceMgr.generateWithRequired(9720)

        if config.GetBool('want-top-toons', True):
            self.topToonsMgr = self.generateGlobalObject(
                OTP_DO_ID_TOONTOWN_TOP_TOONS_MGR, 'DistributedTopToonsManager')

        else:
            self.topToonsMgr = None

        if config.GetBool('want-polar-effect', True):
            self.polarMgr = DistributedPolarPlaceEffectMgrAI.DistributedPolarPlaceEffectMgrAI(
                self)
            self.polarMgr.generateWithRequired(3821)

    def handleBlackCatMgr(self):
        today = datetime.datetime.now()
        start = datetime.datetime(today.year, 10, 31)
        end = datetime.datetime(today.year, 11, 3)

        def createBlackCatMgr(task=None):
            import DistributedBlackCatMgrAI
            self.blackCatMgr = DistributedBlackCatMgrAI.DistributedBlackCatMgrAI(
                self)
            self.blackCatMgr.generateWithRequired(2513)
            if not self.config.GetBool('force-black-cat-mgr', False):
                self.blackCatMgr.expire((end - today).total_seconds())
            return Task.done

        if start <= today < end or self.config.GetBool('force-black-cat-mgr',
                                                       False):
            createBlackCatMgr(None)

        elif start >= today:
            taskMgr.doMethodLater((start - today).total_seconds(),
                                  createBlackCatMgr, 'air-createBlackCatMgr')

    def handleBloodsuckerInvasion(self):
        if not self.wantMegaInvasions:
            return

        today = datetime.datetime.now()
        start = datetime.datetime(today.year, 10, 31)
        end = datetime.datetime(today.year, 11, 3)

        if start <= today < end:
            self.startMegaInvasion(9, end=end)

        elif start > today:
            taskMgr.doMethodLater((start - today).total_seconds(),
                                  self.startMegaInvasion,
                                  'air-mega-invasion-9',
                                  extraArgs=[9, False, end])

    def handleSkelCogWeekInvasion(self):
        if not self.wantMegaInvasions:
            return

        today = datetime.datetime.now()
        start = datetime.datetime(2014, 11, 10)
        end = datetime.datetime(2014, 11, 17)

        if start <= today < end:
            self.startMegaInvasion(-1, skel=True, end=end)

        elif start > today:
            taskMgr.doMethodLater((start - today).total_seconds(),
                                  self.startMegaInvasion,
                                  'air-mega-invasion-skel',
                                  extraArgs=[-1, True, end])

    def startMegaInvasion(self, suitIndex, skel=False, end=None):
        if suitIndex >= 0:
            suitName = SuitDNA.suitHeadTypes[suitIndex]

        else:
            suitName = None

        if self.suitInvasionManager.hasInvading():
            if self.suitInvasionManager.isMega():
                return Task.done

            self.suitInvasionManager.abort()

        self.suitInvasionManager.startInvasion(suitName, skel, mega=True)
        if end:

            def doAbort(task):
                self.suitInvasionManager.abort()
                return task.done

            today = datetime.datetime.now()
            taskMgr.doMethodLater((end - today).total_seconds(), doAbort,
                                  'air-abort-mega-invasion')

    def getStorage(self, zone):
        s = self._dnaStoreMap.get(zone)
        if not s:
            s = DNAStorage()
            self.loadDNAFileAI(s, self.genDNAFileName(zone))
            self._dnaStoreMap[zone] = s

        return s

    def createZones(self):
        self.zoneTable = {
            1000: ((1000, 1, 0), (1100, 1, 1), (1200, 1, 1), (1300, 1, 1)),
            2000: ((2000, 1, 0), (2100, 1, 1), (2200, 1, 1), (2300, 1, 1)),
            3000: ((3000, 1, 0), (3100, 1, 1), (3200, 1, 1), (3300, 1, 1)),
            4000: ((4000, 1, 0), (4100, 1, 1), (4200, 1, 1), (4300, 1, 1)),
            5000: ((5000, 1, 0), (5100, 1, 1), (5200, 1, 1), (5300, 1, 1)),
            9000: ((9000, 1, 0), (9100, 1, 1), (9200, 1, 1)),
            6000: (),
            7000: ((7000, 1, 0), (7100, 1, 1)),  # XXX to do: planner at 7100
            8000: ((8000, 1, 0), ),
            10000: (),
            11000: (),
            12000: (),
            13000: (),
            17000: (),
        }

        self.__nextHood(0)

    def __nextHood(self, hoodIndex):
        if hoodIndex >= len(hoods):
            self.__ready()
            return Task.done

        self.hoods.append(hoods[hoodIndex](self))
        taskMgr.doMethodLater(0, ToontownAIRepository.__nextHood, 'nextHood',
                              [self, hoodIndex + 1])
        return Task.done

    def genDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phase = ToontownGlobals.phaseMap[hoodId]
        else:
            phase = ToontownGlobals.streetPhaseMap[hoodId]

        return 'phase_%s/dna/%s_%s.dna' % (phase, hood, zoneId)

    def loadDNAFileAI(self, dnastore, filename):
        if self.use_libpandadna:
            f = Filename('../resources/' + str(filename))
            f.setExtension('pdna')
            x = self.__loader.loadDNAFileAI(dnastore, f)

        else:
            f = Filename(filename)
            f = Filename('etc/dnabkp/' + f.getBasename())
            x = loadDNAFileAI(dnastore, str(f))

        return x

    def sendSetZone(self, obj, zoneId):
        obj.b_setLocation(obj.parentId, zoneId)

    def getDisconnectReason(self, avId):
        return self.timeManager.disconnectReasonMap.get(
            avId, 1)  # Default: user closed window

    def killToon(self, avId, force=True):
        """
        Kills given toon if within this shard.
        If force is False, then checks getDisconnectReason.
        """
        toon = self.doId2do.get(avId)

        if not toon:
            self.notify.warning("Tried to kill non-existing toon %s" % avId)
            return False

        if not force:
            if self.getDisconnectReason(avId) == 3:  # Python Error
                return False

        toon.b_setHp(0)

        inventory = toon.inventory
        inventory.zeroInv()
        toon.b_setInventory(inventory.makeNetString())

        self.notify.info("Killed toon %s, RIP!" % avId)
        return True

    def handleObjExit(self, di):
        doId = di.getUint32()

        if doId not in self.doId2do:
            self.notify.warning('Received AI exit for unknown object %d' %
                                (doId))
            return

        do = self.doId2do[doId]
        do.sendDeleteEvent()
        self.removeDOFromTables(do)
        do.delete()
Пример #12
0
class ToontownAIRepository(ToontownInternalRepository):
    def __init__(self,
                 baseChannel,
                 stateServerChannel,
                 districtName,
                 startTime=6):
        ToontownInternalRepository.__init__(self,
                                            baseChannel,
                                            stateServerChannel,
                                            dcSuffix='AI')

        self.districtName = districtName
        self.notify.setInfo(True)
        self.hoods = []
        self.cogHeadquarters = []
        self.dnaStoreMap = {}
        self.dnaDataMap = {}
        self.suitPlanners = {}
        self.buildingManagers = {}
        self.sillyMeterMgr = None
        self.factoryMgr = None
        self.mintMgr = None
        self.lawOfficeMgr = None
        self.countryClubMgr = None
        self.startTime = startTime

        self.zoneAllocator = UniqueIdAllocator(
            ToontownGlobals.DynamicZonesBegin, ToontownGlobals.DynamicZonesEnd)
        self.zoneDataStore = AIZoneDataStore()

        self.wantFishing = self.config.GetBool('want-fishing', True)
        self.wantHousing = self.config.GetBool('want-housing', True)
        self.wantPets = self.config.GetBool('want-pets', True)
        self.wantParties = self.config.GetBool('want-parties', True)
        self.wantCogbuildings = self.config.GetBool('want-cogbuildings', True)
        self.wantCogdominiums = self.config.GetBool('want-cogdominiums', True)
        self.doLiveUpdates = self.config.GetBool('want-live-updates', False)
        self.wantTrackClsends = self.config.GetBool('want-track-clsends',
                                                    False)
        self.wantAchievements = self.config.GetBool('want-achievements', True)
        self.wantCharityScreen = self.config.GetBool('want-charity-screen',
                                                     False)
        self.baseXpMultiplier = self.config.GetFloat('base-xp-multiplier', 1.0)
        self.wantHalloween = self.config.GetBool('want-halloween', False)
        self.wantChristmas = self.config.GetBool('want-christmas', False)
        self.cogSuitMessageSent = False
        self.weatherCycleDuration = self.config.GetInt(
            'weather-cycle-duration', 100)

    def createManagers(self):
        self.timeManager = TimeManagerAI(self)
        self.timeManager.generateWithRequired(2)
        self.magicWordManager = MagicWordManagerAI(self)
        self.magicWordManager.generateWithRequired(2)
        self.newsManager = NewsManagerAI(self)
        self.newsManager.generateWithRequired(2)
        self.safeZoneManager = SafeZoneManagerAI(self)
        self.safeZoneManager.generateWithRequired(2)
        self.tutorialManager = TutorialManagerAI(self)
        self.tutorialManager.generateWithRequired(2)
        self.friendManager = FriendManagerAI(self)
        self.friendManager.generateWithRequired(2)
        self.questManager = QuestManagerAI(self)
        self.banManager = BanManagerAI.BanManagerAI(self)
        self.achievementsManager = AchievementsManagerAI(self)
        self.suitInvasionManager = SuitInvasionManagerAI(self)
        self.trophyMgr = DistributedTrophyMgrAI(self)
        self.trophyMgr.generateWithRequired(2)
        self.cogSuitMgr = CogSuitManagerAI.CogSuitManagerAI(self)
        self.promotionMgr = PromotionManagerAI.PromotionManagerAI(self)
        self.experienceMgr = ExperienceRewardManagerAI.ExperienceRewardManagerAI(
            self)
        self.cogPageManager = CogPageManagerAI.CogPageManagerAI()
        self.sillyMeterMgr = DistributedSillyMeterMgrAI.DistributedSillyMeterMgrAI(
            self)
        self.sillyMeterMgr.generateWithRequired(2)
        self.hydrantZeroMgr = DistributedHydrantZeroMgrAI.DistributedHydrantZeroMgrAI(
            self)
        self.hydrantZeroMgr.generateWithRequired(2)
        self.mailboxZeroMgr = DistributedMailboxZeroMgrAI.DistributedMailboxZeroMgrAI(
            self)
        self.mailboxZeroMgr.generateWithRequired(2)
        self.trashcanZeroMgr = DistributedTrashcanZeroMgrAI.DistributedTrashcanZeroMgrAI(
            self)
        self.trashcanZeroMgr.generateWithRequired(2)
        self.dialogueManager = DialogueManagerAI(self)
        self.holidayManager = HolidayManagerAI(self)

        if self.wantFishing:
            self.fishManager = FishManagerAI(self)

        if self.wantHousing:
            self.estateManager = EstateManagerAI(self)
            self.estateManager.generateWithRequired(2)
            self.catalogManager = CatalogManagerAI(self)
            self.catalogManager.generateWithRequired(2)
            self.popularItemManager = PopularItemManagerAI(self)
            self.deliveryManager = self.generateGlobalObject(
                OTP_DO_ID_TOONTOWN_DELIVERY_MANAGER,
                'DistributedDeliveryManager')
            self.mailManager = self.generateGlobalObject(
                OTP_DO_ID_TOONTOWN_MAIL_MANAGER, 'DistributedMailManager')

        if self.wantPets:
            self.petMgr = PetManagerAI(self)

        if self.wantParties:
            self.partyManager = DistributedPartyManagerAI(self)
            self.partyManager.generateWithRequired(2)
            self.globalPartyMgr = self.generateGlobalObject(
                OTP_DO_ID_GLOBAL_PARTY_MANAGER, 'GlobalPartyManager')

        if self.wantCharityScreen:
            self.charityCounter = CharityScreenAI(self)
            self.charityCounter.generateWithRequired(2)
            self.charityCounter.start()

        self.codeRedemptionMgr = simbase.air.generateGlobalObject(
            OTP_DO_ID_TOONTOWN_CODE_REDEMPTION_MANAGER, 'TTCodeRedemptionMgr')
        self.chatAgent = simbase.air.generateGlobalObject(
            OTP_DO_ID_CHAT_MANAGER, 'ChatAgent')

    def createSafeZones(self):
        NPCToons.generateZone2NpcDict()
        if self.config.GetBool('want-toontown-central', True):
            self.hoods.append(TTHoodAI.TTHoodAI(self))
        if self.config.GetBool('want-donalds-dock', True):
            self.hoods.append(DDHoodAI.DDHoodAI(self))
        if self.config.GetBool('want-daisys-garden', True):
            self.hoods.append(DGHoodAI.DGHoodAI(self))
        if self.config.GetBool('want-minnies-melodyland', True):
            self.hoods.append(MMHoodAI.MMHoodAI(self))
        if self.config.GetBool('want-the-burrrgh', True):
            self.hoods.append(BRHoodAI.BRHoodAI(self))
        if self.config.GetBool('want-donalds-dreamland', True):
            self.hoods.append(DLHoodAI.DLHoodAI(self))
        if self.config.GetBool('want-goofy-speedway', True):
            self.hoods.append(GSHoodAI.GSHoodAI(self))
        if self.config.GetBool('want-outdoor-zone', True):
            self.hoods.append(OZHoodAI.OZHoodAI(self))
        if self.config.GetBool('want-golf-zone', True):
            self.hoods.append(GZHoodAI.GZHoodAI(self))

    def createCogHeadquarters(self):
        NPCToons.generateZone2NpcDict()
        if self.config.GetBool('want-sellbot-headquarters', True):
            self.factoryMgr = FactoryManagerAI.FactoryManagerAI(self)
            self.cogHeadquarters.append(SellbotHQAI.SellbotHQAI(self))
        if self.config.GetBool('want-cashbot-headquarters', True):
            self.mintMgr = MintManagerAI.MintManagerAI(self)
            self.cogHeadquarters.append(CashbotHQAI.CashbotHQAI(self))
        if self.config.GetBool('want-lawbot-headquarters', True):
            self.lawOfficeMgr = LawOfficeManagerAI.LawOfficeManagerAI(self)
            self.cogHeadquarters.append(LawbotHQAI.LawbotHQAI(self))
        if self.config.GetBool('want-bossbot-headquarters', True):
            self.countryClubMgr = CountryClubManagerAI.CountryClubManagerAI(
                self)
            self.cogHeadquarters.append(BossbotHQAI.BossbotHQAI(self))

    def handleConnected(self):
        self.districtId = self.allocateChannel()
        self.notify.info('Creating ToontownDistrictAI(%d)...' %
                         self.districtId)
        self.distributedDistrict = ToontownDistrictAI(self)
        self.distributedDistrict.setName(self.districtName)
        self.distributedDistrict.generateWithRequiredAndId(
            self.districtId, self.getGameDoId(), 2)

        self.notify.info('Claiming ownership of channel ID: %d...' %
                         self.districtId)
        self.setAI(self.districtId, self.ourChannel)

        self.districtStats = ToontownDistrictStatsAI(self)
        self.districtStats.settoontownDistrictId(self.districtId)
        self.districtStats.generateWithRequiredAndId(self.allocateChannel(),
                                                     self.getGameDoId(), 3)

        self.notify.info('Created ToontownDistrictStats(%d)' %
                         self.districtStats.doId)

        self.notify.info('Creating managers...')
        self.createManagers()
        if self.config.GetBool('want-safe-zones', True):
            self.notify.info('Creating safe zones...')
            self.createSafeZones()

        if self.config.GetBool('want-cog-headquarters', True):
            self.notify.info('Creating Cog headquarters...')
            self.createCogHeadquarters()

        self.notify.info('Making district available...')
        self.distributedDistrict.b_setAvailable(1)
        self.notify.info('Done.')

    def lookupDNAFileName(self, zoneId):
        zoneId = ZoneUtil.getCanonicalZoneId(zoneId)
        hoodId = ZoneUtil.getCanonicalHoodId(zoneId)
        hood = ToontownGlobals.dnaMap[hoodId]
        if hoodId == zoneId:
            zoneId = 'sz'
            phaseNum = ToontownGlobals.phaseMap[hoodId]
        else:
            phaseNum = ToontownGlobals.streetPhaseMap[hoodId]

        return 'phase_%s/dna/%s_%s.pdna' % (phaseNum, hood, zoneId)

    def loadDNAFileAI(self, dnastore, filename):
        return loadDNAFileAI(dnastore, filename)

    def incrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() + 1)

    def decrementPopulation(self):
        self.districtStats.b_setAvatarCount(
            self.districtStats.getAvatarCount() - 1)

    def setHour(self, hour):
        pass  # Todo: Hour on district page

    def allocateZone(self):
        return self.zoneAllocator.allocate()

    def deallocateZone(self, zone):
        self.zoneAllocator.free(zone)

    def getZoneDataStore(self):
        return self.zoneDataStore

    def getTrackClsends(self):
        return self.wantTrackClsends

    def getAvatarExitEvent(self, avId):
        return 'distObjDelete-%d' % (avId)

    def trueUniqueName(self, name):
        return self.uniqueName(name)