270 lines
11 KiB
Python
270 lines
11 KiB
Python
import os
|
|
from direct.task.Task import Task
|
|
import cPickle
|
|
from otp.ai.AIBaseGlobal import *
|
|
import DistributedBuildingAI
|
|
import HQBuildingAI
|
|
import GagshopBuildingAI
|
|
#import PetshopBuildingAI
|
|
from toontown.building.KartShopBuildingAI import KartShopBuildingAI
|
|
#from toontown.building import DistributedAnimBuildingAI
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from toontown.hood import ZoneUtil
|
|
import time
|
|
import random
|
|
from pymongo.errors import AutoReconnect
|
|
|
|
class DistributedBuildingMgrAI:
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedBuildingMgrAI')
|
|
|
|
def __init__(self, air, branchID, dnaStore, trophyMgr):
|
|
self.branchID = branchID
|
|
self.canonicalBranchID = ZoneUtil.getCanonicalZoneId(branchID)
|
|
self.air = air
|
|
self.__buildings = {}
|
|
self.dnaStore = dnaStore
|
|
self.trophyMgr = trophyMgr
|
|
self.shard = air.ourChannel
|
|
self.findAllLandmarkBuildings()
|
|
self.doLaterTask = None
|
|
self.air.buildingManagers[branchID] = self
|
|
return
|
|
|
|
def cleanup(self):
|
|
taskMgr.remove(str(self.branchID) + '_delayed_save-timer')
|
|
for building in self.__buildings.values():
|
|
building.cleanup()
|
|
|
|
self.__buildings = {}
|
|
|
|
def isValidBlockNumber(self, blockNumber):
|
|
return self.__buildings.has_key(blockNumber)
|
|
|
|
def delayedSaveTask(self, task):
|
|
self.save()
|
|
self.doLaterTask = None
|
|
return Task.done
|
|
|
|
def isSuitBlock(self, blockNumber):
|
|
return self.__buildings[blockNumber].isSuitBlock()
|
|
|
|
def getSuitBlocks(self):
|
|
blocks = []
|
|
for i in self.__buildings.values():
|
|
if i.isSuitBlock():
|
|
blocks.append(i.getBlock()[0])
|
|
|
|
return blocks
|
|
|
|
def getEstablishedSuitBlocks(self):
|
|
blocks = []
|
|
for i in self.__buildings.values():
|
|
if i.isEstablishedSuitBlock():
|
|
blocks.append(i.getBlock()[0])
|
|
|
|
return blocks
|
|
|
|
def getToonBlocks(self):
|
|
blocks = []
|
|
for i in self.__buildings.values():
|
|
if isinstance(i, HQBuildingAI.HQBuildingAI):
|
|
continue
|
|
if not i.isSuitBlock():
|
|
blocks.append(i.getBlock()[0])
|
|
|
|
return blocks
|
|
|
|
def getBuildings(self):
|
|
return self.__buildings.values()
|
|
|
|
def getFrontDoorPoint(self, blockNumber):
|
|
return self.__buildings[blockNumber].getFrontDoorPoint()
|
|
|
|
def getBuildingTrack(self, blockNumber):
|
|
return self.__buildings[blockNumber].track
|
|
|
|
def getBuilding(self, blockNumber):
|
|
return self.__buildings[blockNumber]
|
|
|
|
def setFrontDoorPoint(self, blockNumber, point):
|
|
return self.__buildings[blockNumber].setFrontDoorPoint(point)
|
|
|
|
def getDNABlockLists(self):
|
|
blocks = []
|
|
hqBlocks = []
|
|
gagshopBlocks = []
|
|
petshopBlocks = []
|
|
kartshopBlocks = []
|
|
animBldgBlocks = []
|
|
for blockId, block in self.dnaStore.getBlocks():
|
|
blockNumber = blockId
|
|
buildingType = block.buildingType
|
|
if buildingType == 'hq':
|
|
hqBlocks.append(blockNumber)
|
|
elif buildingType == 'gagshop':
|
|
gagshopBlocks.append(blockNumber)
|
|
elif buildingType == 'petshop':
|
|
petshopBlocks.append(blockNumber)
|
|
elif buildingType == 'kartshop':
|
|
kartshopBlocks.append(blockNumber)
|
|
elif buildingType == 'animbldg':
|
|
animBldgBlocks.append(blockNumber)
|
|
else:
|
|
blocks.append(blockNumber)
|
|
|
|
return (blocks,
|
|
hqBlocks,
|
|
gagshopBlocks,
|
|
petshopBlocks,
|
|
kartshopBlocks,
|
|
animBldgBlocks)
|
|
|
|
def findAllLandmarkBuildings(self):
|
|
buildings = self.load()
|
|
blocks, hqBlocks, gagshopBlocks, petshopBlocks, kartshopBlocks, animBldgBlocks = self.getDNABlockLists()
|
|
for block in blocks:
|
|
self.newBuilding(block, buildings.get(block, None))
|
|
|
|
for block in animBldgBlocks:
|
|
self.newAnimBuilding(block, buildings.get(block, None))
|
|
|
|
for block in hqBlocks:
|
|
self.newHQBuilding(block)
|
|
|
|
for block in gagshopBlocks:
|
|
self.newGagshopBuilding(block)
|
|
|
|
if simbase.wantPets:
|
|
for block in petshopBlocks:
|
|
self.newPetshopBuilding(block)
|
|
|
|
if simbase.wantKarts:
|
|
for block in kartshopBlocks:
|
|
self.newKartShopBuilding(block)
|
|
|
|
return
|
|
|
|
def newBuilding(self, blockNumber, blockData = None):
|
|
building = DistributedBuildingAI.DistributedBuildingAI(self.air, blockNumber, self.branchID, self.trophyMgr)
|
|
building.generateWithRequired(self.branchID)
|
|
if blockData:
|
|
building.track = blockData.get('track', 'c')
|
|
building.difficulty = int(blockData.get('difficulty', 1))
|
|
building.numFloors = int(blockData.get('numFloors', 1))
|
|
building.numFloors = max(1, min(5, building.numFloors))
|
|
if not ZoneUtil.isWelcomeValley(building.zoneId):
|
|
building.updateSavedBy(blockData.get('savedBy'))
|
|
else:
|
|
self.notify.warning('we had a cog building in welcome valley %d' % building.zoneId)
|
|
building.becameSuitTime = blockData.get('becameSuitTime', time.time())
|
|
if blockData['state'] == 'suit':
|
|
building.setState('suit')
|
|
elif blockData['state'] == 'cogdo':
|
|
if simbase.air.wantCogdominiums:
|
|
building.setState('cogdo')
|
|
else:
|
|
building.setState('toon')
|
|
else:
|
|
building.setState('toon')
|
|
self.__buildings[blockNumber] = building
|
|
return building
|
|
|
|
def newAnimBuilding(self, blockNumber, blockData = None):
|
|
return
|
|
building = DistributedAnimBuildingAI.DistributedAnimBuildingAI(self.air, blockNumber, self.branchID, self.trophyMgr)
|
|
building.generateWithRequired(self.branchID)
|
|
if blockData:
|
|
building.track = blockData.get('track', 'c')
|
|
building.difficulty = int(blockData.get('difficulty', 1))
|
|
building.numFloors = int(blockData.get('numFloors', 1))
|
|
if not ZoneUtil.isWelcomeValley(building.zoneId):
|
|
building.updateSavedBy(blockData.get('savedBy'))
|
|
else:
|
|
self.notify.warning('we had a cog building in welcome valley %d' % building.zoneId)
|
|
building.becameSuitTime = blockData.get('becameSuitTime', time.time())
|
|
if blockData['state'] == 'suit':
|
|
building.setState('suit')
|
|
else:
|
|
building.setState('toon')
|
|
else:
|
|
building.setState('toon')
|
|
self.__buildings[blockNumber] = building
|
|
return building
|
|
|
|
def newHQBuilding(self, blockNumber):
|
|
dnaStore = self.air.dnaStoreMap[self.canonicalBranchID]
|
|
exteriorZoneId = dnaStore.getBlock(blockNumber).zone
|
|
exteriorZoneId = ZoneUtil.getTrueZoneId(exteriorZoneId, self.branchID)
|
|
interiorZoneId = self.branchID - self.branchID % 100 + 500 + blockNumber
|
|
self.notify.debug("Spawning HQ ext: {0} int: {1}".format(exteriorZoneId, interiorZoneId))
|
|
building = HQBuildingAI.HQBuildingAI(self.air, exteriorZoneId, interiorZoneId, blockNumber)
|
|
self.__buildings[blockNumber] = building
|
|
return building
|
|
|
|
def newGagshopBuilding(self, blockNumber):
|
|
dnaStore = self.air.dnaStoreMap[self.canonicalBranchID]
|
|
exteriorZoneId = dnaStore.getBlock(blockNumber).zone
|
|
exteriorZoneId = ZoneUtil.getTrueZoneId(exteriorZoneId, self.branchID)
|
|
interiorZoneId = self.branchID - self.branchID % 100 + 500 + blockNumber
|
|
self.notify.debug("Spawning GagShop ext: {0} int: {1}".format(exteriorZoneId, interiorZoneId))
|
|
building = GagshopBuildingAI.GagshopBuildingAI(self.air, exteriorZoneId, interiorZoneId, blockNumber)
|
|
self.__buildings[blockNumber] = building
|
|
return building
|
|
|
|
def newPetshopBuilding(self, blockNumber):
|
|
return
|
|
dnaStore = self.air.dnaStoreMap[self.canonicalBranchID]
|
|
exteriorZoneId = dnaStore.getBlock(blockNumber).zone
|
|
exteriorZoneId = ZoneUtil.getTrueZoneId(exteriorZoneId, self.branchID)
|
|
interiorZoneId = self.branchID - self.branchID % 100 + 500 + blockNumber
|
|
building = PetshopBuildingAI.PetshopBuildingAI(self.air, exteriorZoneId, interiorZoneId, blockNumber)
|
|
self.__buildings[blockNumber] = building
|
|
return building
|
|
|
|
def newKartShopBuilding(self, blockNumber):
|
|
dnaStore = self.air.dnaStoreMap[self.canonicalBranchID]
|
|
exteriorZoneId = dnaStore.getBlock(blockNumber).zone
|
|
exteriorZoneId = ZoneUtil.getTrueZoneId(exteriorZoneId, self.branchID)
|
|
interiorZoneId = self.branchID - self.branchID % 100 + 500 + blockNumber
|
|
building = KartShopBuildingAI(self.air, exteriorZoneId, interiorZoneId, blockNumber)
|
|
self.__buildings[blockNumber] = building
|
|
return building
|
|
|
|
def save(self):
|
|
buildings = []
|
|
for i in self.__buildings.values():
|
|
if isinstance(i, HQBuildingAI.HQBuildingAI):
|
|
continue
|
|
buildings.append(i.getPickleData())
|
|
|
|
street = {'ai': self.shard, 'branch': self.branchID}
|
|
try:
|
|
self.air.mongodb.toontown.streets.update(street,
|
|
{'$setOnInsert': street,
|
|
'$set': {'buildings': buildings}},
|
|
upsert=True)
|
|
except AutoReconnect: # Something happened to our DB, but we can reconnect and retry.
|
|
taskMgr.doMethodLater(config.GetInt('mongodb-retry-time', 2), self.save, 'retrySave', extraArgs=[])
|
|
|
|
def load(self):
|
|
blocks = {}
|
|
|
|
# Ensure that toontown.streets is indexed. Doing this at loading time
|
|
# is a fine way to make sure that we won't upset players with a
|
|
# lagspike while we wait for the backend to handle the index request.
|
|
self.air.mongodb.toontown.streets.ensure_index([('ai', 1),
|
|
('branch', 1)])
|
|
|
|
street = {'ai': self.shard, 'branch': self.branchID}
|
|
try:
|
|
doc = self.air.mongodb.toontown.streets.find_one(street)
|
|
except AutoReconnect: # We're failing over - normally we'd wait to retry, but this is on AI startup so we might want to retry (or refactor the bldgMgr so we can sanely retry).
|
|
return blocks
|
|
|
|
if not doc:
|
|
return blocks
|
|
|
|
for building in doc.get('buildings', []):
|
|
blocks[int(building['block'])] = building
|
|
|
|
return blocks
|