From 239de4ae62c4a7043dadf683d3e40c5e38e3bda5 Mon Sep 17 00:00:00 2001 From: Open Toontown Date: Fri, 15 Nov 2019 21:15:38 -0500 Subject: [PATCH] login: avatar list retrieval --- etc/otp.dc | 14 +++- etc/toon.dc | 3 +- otp/distributed/OTPClientRepository.py | 27 +++++-- otp/distributed/OTPInternalRepository.py | 3 + otp/login/AstronLoginManager.py | 7 ++ otp/login/AstronLoginManagerUD.py | 89 ++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 8 deletions(-) diff --git a/etc/otp.dc b/etc/otp.dc index 937921a..1151600 100755 --- a/etc/otp.dc +++ b/etc/otp.dc @@ -226,7 +226,7 @@ dclass DistributedAvatar : DistributedSmoothNode, TalkPath_owner, TalkPath_whisp confirmAvOnShard(uint32, int8); }; -struct friendEntry { +struct FriendEntry { uint32 friendId; uint8 friendCode; } @@ -244,7 +244,7 @@ dclass DistributedPlayer : DistributedAvatar { setWhitelistChatFlags(uint8) broadcast ownrecv ram airecv; setSC(uint16) broadcast ownsend airecv; setSCCustom(uint16) broadcast ownsend airecv; - setFriendsList(friendEntry[]) ownrecv required db airecv; + setFriendsList(FriendEntry[]) ownrecv required db airecv; setDISLname(string) broadcast ownrecv ram; setDISLid(uint32) broadcast ownrecv ram db airecv required; OwningAccount(uint32); @@ -521,7 +521,17 @@ dclass CallbackObject { callback(uint32, bool, uint8); }; +struct PotentialAvatar { + uint32 avNum; + string avName; + string avDNA; + uint8 avPosition; + uint8 nameState; +}; + dclass AstronLoginManager : DistributedObject { requestLogin(string) clsend; loginResponse(blob); + requestAvatarList() clsend; + avatarListResponse(PotentialAvatar[]); }; diff --git a/etc/toon.dc b/etc/toon.dc index 2d266cd..0f74750 100755 --- a/etc/toon.dc +++ b/etc/toon.dc @@ -459,7 +459,7 @@ dclass DistributedToon : DistributedPlayer { setTrackBonusLevel(int8[]) required broadcast ownrecv db; setInventory(blob) required ownrecv db; setMaxNPCFriends(uint16) required ownrecv db; - setNPCFriendsDict(friendEntry[]) required ownrecv db; + setNPCFriendsDict(FriendEntry[]) required ownrecv db; setDefaultShard(uint32) required ownrecv db; setDefaultZone(uint32) required ownrecv db; setShtickerBook(blob) required ownrecv db; @@ -3269,4 +3269,3 @@ dclass DistributedTrashcanZeroMgr : DistributedPhaseEventMgr { dclass DistributedSillyMeterMgr : DistributedPhaseEventMgr { }; - diff --git a/otp/distributed/OTPClientRepository.py b/otp/distributed/OTPClientRepository.py index d0f52a3..945e401 100644 --- a/otp/distributed/OTPClientRepository.py +++ b/otp/distributed/OTPClientRepository.py @@ -959,10 +959,7 @@ class OTPClientRepository(ClientRepositoryBase): if not self.astronSupport: self.sendGetAvatarsMsg() else: - # TODO SET UP PROPERLY - #self.astronLoginManager.sendRequestAvatarList() - self.avList = [] - self.loginFSM.request('chooseAvatar', [self.avList]) + self.astronLoginManager.sendRequestAvatarList() self.waitForDatabaseTimeout(requestName='WaitForAvatarList') self.acceptOnce(OtpAvatarManager.OtpAvatarManager.OnlineEvent, self._requestAvatarList) @@ -2356,6 +2353,28 @@ class OTPClientRepository(ClientRepositoryBase): # We're done. dclass.stopGenerate() + def handleAvatarListResponse(self, avatarList): + avList = [] + for avNum, avName, avDNA, avPosition, nameState in avatarList: + avNames = ['', + '', + '', + ''] + avNames[0] = avName + if nameState == 2: # Pending + avNames[1] = avName + elif nameState == 3: # Approved + avNames[2] = avName + elif nameState == 4: # Rejected + avNames[3] = avName + + aname = int(nameState == 1) + potAv = PotentialAvatar(avNum, avNames, avDNA, avPosition, aname) + avList.append(potAv) + + self.avList = avList + self.loginFSM.request('chooseAvatar', [self.avList]) + def handleGenerateWithRequiredOtherOwner(self, di): classId = di.getUint16() doId = di.getUint32() diff --git a/otp/distributed/OTPInternalRepository.py b/otp/distributed/OTPInternalRepository.py index 8f64971..77972be 100644 --- a/otp/distributed/OTPInternalRepository.py +++ b/otp/distributed/OTPInternalRepository.py @@ -12,3 +12,6 @@ class OTPInternalRepository(AstronInternalRepository): def handleConnected(self): AstronInternalRepository.handleConnected(self) + + def getAccountIdFromSender(self): + return (self.getMsgSender() >> 32) & 0xFFFFFFFF diff --git a/otp/login/AstronLoginManager.py b/otp/login/AstronLoginManager.py index 19825dd..f8c465b 100644 --- a/otp/login/AstronLoginManager.py +++ b/otp/login/AstronLoginManager.py @@ -5,6 +5,7 @@ import time from direct.distributed.DistributedObjectGlobal import DistributedObjectGlobal from direct.directnotify import DirectNotifyGlobal from otp.uberdog.AccountDetailRecord import AccountDetailRecord +from otp.distributed.PotentialAvatar import PotentialAvatar class AstronLoginManager(DistributedObjectGlobal): notify = DirectNotifyGlobal.directNotify.newCategory('AstronLoginManager') @@ -113,3 +114,9 @@ class AstronLoginManager(DistributedObjectGlobal): self.notify.warning('account days is negative %s' % accountDays) self.notify.debug('result=%s' % result) return result + + def sendRequestAvatarList(self): + self.sendUpdate('requestAvatarList') + + def avatarListResponse(self, avatarList): + self.cr.handleAvatarListResponse(avatarList) diff --git a/otp/login/AstronLoginManagerUD.py b/otp/login/AstronLoginManagerUD.py index 46b5713..384b513 100644 --- a/otp/login/AstronLoginManagerUD.py +++ b/otp/login/AstronLoginManagerUD.py @@ -163,6 +163,7 @@ class LoginOperation: } responseBlob = json.dumps(responseData) self.loginManager.sendUpdateToChannel(self.sender, 'loginResponse', [responseBlob]) + del self.loginManager.sender2loginOperation[self.sender] def getLastLoggedInStr(self): return '' # TODO @@ -186,6 +187,79 @@ class LoginOperation: return accountDays +class GetAvatarsOperation: + + def __init__(self, loginManager, sender): + self.loginManager = loginManager + self.sender = sender + self.account = None + self.avList = [] + self.pendingAvatars = None + self.avatarFields = None + + def start(self): + self.loginManager.air.dbInterface.queryObject(self.loginManager.air.dbId, self.sender, self.__handleAccountRetrieved) + + def __handleAccountRetrieved(self, dclass, fields): + if dclass != self.loginManager.air.dclassesByName['AstronAccountUD']: + # no uwu + return + + self.account = fields + self.avList = self.account['ACCOUNT_AV_SET'] + self.avList = self.avList[:6] + self.avList += [0] * (6 - len(self.avList)) + self.__handleQueryAvatars() + + def __handleQueryAvatars(self): + self.pendingAvatars = set() + self.avatarFields = {} + for avId in self.avList: + if avId: + self.pendingAvatars.add(avId) + def response(dclass, fields, avId=avId): + if dclass != self.loginManager.air.dclassesByName['DistributedToonUD']: + # mayonnaise + return + + self.avatarFields[avId] = fields + self.pendingAvatars.remove(avId) + if not self.pendingAvatars: + self.__handleSendAvatars() + + self.loginManager.air.dbInterface.queryObject(self.loginManager.air.dbId, avId, response) + + if not self.pendingAvatars: + self.__handleSendAvatars() + + def __handleSendAvatars(self): + potentialAvatars = [] + for avId, fields in self.avatarFields.items(): + index = self.avList.index(avId) + wishNameState = fields.get('WishNameState', [''])[0] + name = fields['setName'][0] + nameState = 0 + if wishNameState == 'OPEN': + nameState = 1 + elif wishNameState == 'PENDING': + nameState = 2 + elif wishNameState == 'APPROVED': + nameState = 3 + name = fields['WishName'][0] + elif wishNameState == 'REJECTED': + nameState = 4 + elif wishNameState == 'LOCKED': + nameState = 0 + else: + # unknown name state. + nameState = 0 + + potentialAvatars.append([avId, name, fields['setDNAString'][0], index, nameState]) + + self.loginManager.sendUpdateToAccountId(self.sender, 'avatarListResponse', [potentialAvatars]) + del self.loginManager.account2operation[self.sender] + + class AstronLoginManagerUD(DistributedObjectGlobalUD): notify = DirectNotifyGlobal.directNotify.newCategory('AstronLoginManagerUD') @@ -193,6 +267,7 @@ class AstronLoginManagerUD(DistributedObjectGlobalUD): DistributedObjectGlobalUD.__init__(self, air) self.accountDb = None self.sender2loginOperation = {} + self.account2operation = {} def announceGenerate(self): DistributedObjectGlobalUD.announceGenerate(self) @@ -212,3 +287,17 @@ class AstronLoginManagerUD(DistributedObjectGlobalUD): newLoginOperation = LoginOperation(self, sender) self.sender2loginOperation[sender] = newLoginOperation newLoginOperation.start(playToken) + + def requestAvatarList(self): + sender = self.air.getAccountIdFromSender() + if not sender: + # TODO KILL CONNECTION + return + + if sender in self.account2operation: + # BAD!!!! + return + + newOperation = GetAvatarsOperation(self, sender) + self.account2operation[sender] = newOperation + newOperation.start()