from direct.directnotify import DirectNotifyGlobal from direct.distributed.DistributedObjectAI import DistributedObjectAI from direct.task import Task from otp.distributed.OtpDoGlobals import * from panda3d.core import * from toontown.parties.DistributedPartyAI import DistributedPartyAI from datetime import datetime from toontown.parties.PartyGlobals import * from otp.ai.MagicWordGlobal import * class DistributedPartyManagerAI(DistributedObjectAI): notify = DirectNotifyGlobal.directNotify.newCategory("DistributedPartyManagerAI") def announceGenerate(self): DistributedObjectAI.announceGenerate(self) self.partyId2Zone = {} self.partyId2PlanningZone = {} self.partyId2Host = {} self.host2PartyId = {} self.avId2PartyId = {} self.id2Party = {} self.pubPartyInfo = {} self.idPool = range(self.air.ourChannel, self.air.ourChannel + 100000) # get 100 ids at the start and top up #taskMgr.doMethodLater(0, self.__getIds, 'DistributedPartyManagerAI___getIds') def receiveId(self, ids): self.idPool += ids # def __getIds(self, task): # if len(self.idPool) < 50: # self.air.globalPartyMgr.allocIds(100 - len(self.idPool)) # taskMgr.doMethodLater(180, self.__getIds, 'DistributedPartyManagerAI___getIds') def _makePartyDict(self, struct): PARTY_TIME_FORMAT = '%Y-%m-%d %H:%M:%S' party = {} party['partyId'] = struct[0] party['hostId'] = struct[1] start = '%s-%s-%s %s:%s:00' % (struct[2], struct[3], struct[4], struct[5], struct[6]) party['start'] = datetime.strptime(start, PARTY_TIME_FORMAT) end = '%s-%s-%s %s:%s:00' % (struct[7], struct[8], struct[9], struct[10], struct[11]) party['end'] = datetime.strptime(end, PARTY_TIME_FORMAT) party['isPrivate'] = struct[12] party['inviteTheme'] = struct[13] party['activities'] = struct[14] party['decorations'] = struct[15] # struct[16] = partystatus return party # Management stuff def partyManagerUdStartingUp(self): # This is sent in reply to the GPMAI's hello self.notify.info("uberdog has said hello") def partyManagerUdLost(self): # well fuck. ud died. self.notify.warning("uberdog lost!") def canBuyParties(self): return True def addPartyRequest(self, hostId, startTime, endTime, isPrivate, inviteTheme, activities, decorations, inviteeIds): if hostId != simbase.air.getAvatarIdFromSender(): self.air.writeServerEvent('suspicious',simbase.air.getAvatarIdFromSender(),'Toon tried to create a party as someone else!') return print 'party requested: host %s, start %s, end %s, private %s, invitetheme %s, activities omitted, decor omitted, invitees %s' % (hostId, startTime, endTime, isPrivate, inviteTheme, inviteeIds) simbase.air.globalPartyMgr.sendAddParty(hostId, self.host2PartyId[hostId], startTime, endTime, isPrivate, inviteTheme, activities, decorations, inviteeIds) def addPartyResponseUdToAi(self, partyId, errorCode, partyStruct): avId = partyStruct[1] print 'responding to client now that ud got back to us' self.sendUpdateToAvatarId(avId, 'addPartyResponse', [avId, errorCode]) # We also need to remember to update the field on the DToon indicating parties he's hosting self.air.doId2do[avId].sendUpdate('setHostedParties', [[partyStruct]]) pass def markInviteAsReadButNotReplied(self, todo0, todo1): pass def respondToInvite(self, todo0, todo1, todo2, todo3, todo4): pass def respondToInviteResponse(self, todo0, todo1, todo2, todo3, todo4): pass def changePrivateRequest(self, todo0, todo1): pass def changePrivateRequestAiToUd(self, todo0, todo1, todo2): pass def changePrivateResponseUdToAi(self, todo0, todo1, todo2, todo3): pass def changePrivateResponse(self, todo0, todo1, todo2): pass def changePartyStatusRequest(self, partyId, newPartyStatus): pass def changePartyStatusRequestAiToUd(self, todo0, todo1, todo2): pass def changePartyStatusResponseUdToAi(self, todo0, todo1, todo2, todo3): pass def changePartyStatusResponse(self, todo0, todo1, todo2, todo3): pass def partyInfoOfHostFailedResponseUdToAi(self, todo0): pass def givePartyRefundResponse(self, todo0, todo1, todo2, todo3, todo4): pass def getPartyZone(self, hostId, zoneId, isAvAboutToPlanParty): self.notify.debug('getPartyZone(hostId = %s, zoneId = %s, isAboutToPlan = %s' % (hostId, zoneId, isAvAboutToPlanParty)) avId = self.air.getAvatarIdFromSender() if isAvAboutToPlanParty: partyId = self.idPool.pop() print 'pid %s' % partyId self.partyId2Host[partyId] = hostId self.partyId2PlanningZone[partyId] = zoneId self.host2PartyId[hostId] = partyId print 'Responding to a get party zone when planning, av,party,zone: %s %s %s' % (avId, partyId, zoneId) else: if hostId not in self.host2PartyId: # Uhh, we don't know if the host even has a party. Better ask the ud self.air.globalPartyMgr.queryPartyForHost(hostId) print 'querying for details against hostId %s ' % hostId return partyId = self.host2PartyId[hostId] # Is the party already running? if partyId in self.partyId2Zone: # Yep! zoneId = self.partyId2Zone[partyId] else: self.notify.warning("getPartyZone did not match a case!") self.sendUpdateToAvatarId(avId, 'receivePartyZone', [hostId, partyId, zoneId]) def partyInfoOfHostResponseUdToAi(self, partyStruct, inviteeIds): party = self._makePartyDict(partyStruct) av = self.air.doId2do.get(party['hostId'], None) if not av: return # The host isn't on the district... wat do party['inviteeIds'] = inviteeIds partyId = party['partyId'] # This is issued in response to a request for the party to start, essentially. So let's alloc a zone zoneId = self.air.allocateZone() self.partyId2Zone[partyId] = zoneId self.host2PartyId[party['hostId']] = partyId # We need to setup the party itself on our end, so make an ai party partyAI = DistributedPartyAI(self.air, party['hostId'], zoneId, party) partyAI.generateWithRequiredAndId(self.air.allocateChannel(), self.air.districtId, zoneId) self.id2Party[partyId] = partyAI # Alert the UD self.air.globalPartyMgr.d_partyStarted(partyId, self.air.ourChannel, zoneId, av.getName()) # Don't forget this was initially started by a getPartyZone, so we better tell the host the partyzone self.sendUpdateToAvatarId(party['hostId'], 'receivePartyZone', [party['hostId'], partyId, zoneId]) # And last, set up our cleanup stuff taskMgr.doMethodLater(PARTY_DURATION, self.closeParty, 'DistributedPartyManagerAI_cleanup%s' % partyId, [partyId]) def closeParty(self, partyId): partyAI = self.id2Party[partyId] self.air.globalPartyMgr.d_partyDone(partyId) for av in partyAI.avIdsAtParty: self.sendUpdateToAvatarId(av, 'sendAvToPlayground', [av, 0]) partyAI.b_setPartyState(PartyStatus.Finished) taskMgr.doMethodLater(10, self.__deleteParty, 'closeParty%d' % partyId, extraArgs=[partyId]) def __deleteParty(self, partyId): partyAI = self.id2Party[partyId] for av in partyAI.avIdsAtParty: self.sendUpdateToAvatarId(av, 'sendAvToPlayground', [av, 1]) partyAI.requestDelete() zoneId = self.partyId2Zone[partyId] del self.partyId2Zone[partyId] del self.id2Party[partyId] del self.pubPartyInfo[partyId] self.air.deallocateZone(zoneId) def freeZoneIdFromPlannedParty(self, hostId, zoneId): sender = self.air.getAvatarIdFromSender() # Only the host of a party can free its zone if sender != hostId: self.air.writeServerEvent('suspicious',sender,'Toon tried to free zone for someone else\'s party!') return partyId = self.host2PartyId[hostId] if partyId in self.partyId2PlanningZone: self.air.deallocateZone(self.partyId2PlanningZone[partyId]) del self.partyId2PlanningZone[partyId] del self.host2PartyId[hostId] del self.partyId2Host[partyId] return def sendAvToPlayground(self, todo0, todo1): pass def exitParty(self, partyZone): avId = simbase.air.getAvatarIdFromSender() for partyInfo in self.pubPartyInfo.values(): if partyInfo['zoneId'] == partyZone: party = self.id2Party.get(partyInfo['partyId']) if party: party._removeAvatar(avId) def removeGuest(self, ownerId, avId): pass def partyManagerAIStartingUp(self, todo0, todo1): pass def partyManagerAIGoingDown(self, todo0, todo1): pass def toonHasEnteredPartyAiToUd(self, todo0): pass def toonHasExitedPartyAiToUd(self, todo0): pass def partyHasFinishedUdToAllAi(self, partyId): # FIXME I bet i have to do some cleanup del self.pubPartyInfo[partyId] def updateToPublicPartyInfoUdToAllAi(self, shardId, zoneId, partyId, hostId, numGuests, maxGuests, hostName, activities, minLeft): # The uberdog is informing us of a public party. # Note that we never update the publicPartyInfo of our own parties without going through the UD. It's just good practice :) started = None self.pubPartyInfo[partyId] = { 'shardId': shardId, 'zoneId': zoneId, 'partyId': partyId, 'hostId': hostId, 'numGuests': numGuests, 'maxGuests': maxGuests, 'hostName': hostName, 'minLeft': minLeft, 'started': datetime.now(), 'activities': activities } def updateToPublicPartyCountUdToAllAi(self, partyCount, partyId): # Update the number of guests at a party if partyId in self.pubPartyInfo.keys(): self.pubPartyInfo[partyId]['numGuests'] = partyCount def getPublicParties(self): p = [] for partyId in self.pubPartyInfo: party = self.pubPartyInfo[partyId] # calculate time left minLeft = party['minLeft'] - int((datetime.now() - party['started']).seconds / 60) #less band-aidy bandaid guests = party.get('numGuests', 0) if guests > 255: guests = 255 elif guests < 0: guests = 0 p.append([party['shardId'], party['zoneId'], guests, party.get('hostName', ''), party.get('activities', []), minLeft]) return p def requestShardIdZoneIdForHostId(self, todo0): pass def sendShardIdZoneIdToAvatar(self, todo0, todo1): pass def updateAllPartyInfoToUd(self, todo0, todo1, todo2, todo3, todo4, todo5, todo6, todo7, todo8): pass def forceCheckStart(self): pass def requestMw(self, todo0, todo1, todo2, todo3): pass def mwResponseUdToAllAi(self, todo0, todo1, todo2, todo3): pass