From dba9006efaca75acf823cf7809dd845cee517b9a Mon Sep 17 00:00:00 2001 From: John Cote Date: Mon, 28 Jun 2021 20:32:29 -0400 Subject: [PATCH] login: Handle all remaining close connection TODOs --- otp/login/AstronLoginManagerUD.py | 114 ++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 20 deletions(-) diff --git a/otp/login/AstronLoginManagerUD.py b/otp/login/AstronLoginManagerUD.py index e48dbc9..44754b1 100644 --- a/otp/login/AstronLoginManagerUD.py +++ b/otp/login/AstronLoginManagerUD.py @@ -162,10 +162,14 @@ class LoginOperation(GameOperation): self.__handleAccountRetrieved) def __handleAccountRetrieved(self, dclass, fields): + # Checks if the queried object is valid and if it is, calls + # the __handleSetAccount function. Otherwise, the connection is closed. if dclass != self.loginManager.air.dclassesByName['AstronAccountUD']: - # TODO: Kill the connection + # This is not an account object! Close the connection. + self._handleCloseConnection('Your account object (%s) was not found in the database!' % dclass) return + # We can now call the __handleSetAccount function. self.account = fields self.__handleSetAccount() @@ -183,10 +187,18 @@ class LoginOperation(GameOperation): self.account, self.__handleAccountCreated) def __handleAccountCreated(self, accountId): + # This function handles successful & unsuccessful account creations. if not accountId: - # TODO: Kill the connection + # If we don't have an accountId, then that means the database was unable + # to create an account object for us, for whatever reason. Close the connection. + self.notify.warning('Database failed to create an account object!') + self._handleCloseConnection('Your account object could not be created in the game database.') return + # Otherwise, the account object was created successfully! + self.loginManager.air.writeServerEvent('account-created', accountId) + + # We can now call the __storeAccountId function. self.accountId = accountId self.__storeAccountId() @@ -195,9 +207,12 @@ class LoginOperation(GameOperation): def __handleAccountIdStored(self, success=True): if not success: - # TODO: Kill the connection + # The account bridge was unable to store the account ID, + # for whatever reason. Close the connection. + self._handleCloseConnection('The account server could not save your account database ID!') return + # We are all set with account creation now! It's time to call the __handleSetAccount function. self.__handleSetAccount() def __handleSetAccount(self): @@ -287,7 +302,8 @@ class AvatarOperation(GameOperation): def __handleAccountRetrieved(self, dclass, fields): if dclass != self.loginManager.air.dclassesByName['AstronAccountUD']: - # TODO: Kill the connection + # This is not an account object! Close the connection: + self._handleCloseConnection('Your account object (%s) was not found in the database!' % dclass) return # Set the account & avList: @@ -312,25 +328,38 @@ class GetAvatarsOperation(AvatarOperation): self.avatarFields = None def _handleQueryAvatars(self): + # Now, we will query the avatars that exist in the account. self.pendingAvatars = set() self.avatarFields = {} + + # Loop through the list of avatars: for avId in self.avList: if avId: + # This index contains an avatar! Add it to the pending avatars. self.pendingAvatars.add(avId) + # This is our callback function that queryObject + # will call when done querying each avatar object. def response(dclass, fields, avId=avId): if dclass != self.loginManager.air.dclassesByName['DistributedToonUD']: - # TODO: Kill the connection + # The dclass is invalid! Close the connection: + self._handleCloseConnection('One of the account\'s avatars is invalid! dclass = %s, expected = %s' % ( + dclass, self.loginManager.air.dclassesByName['DistributedToonUD'].getName())) return + # Otherwise, we're all set! Add the queried avatar fields to the + # avatarFields array, remove from the pending list, and call the + # __handleSendAvatars function. self.avatarFields[avId] = fields self.pendingAvatars.remove(avId) if not self.pendingAvatars: self.__handleSendAvatars() + # Query the avatar object. self.loginManager.air.dbInterface.queryObject(self.loginManager.air.dbId, avId, response) if not self.pendingAvatars: + # No pending avatars! Call the __handleSendAvatars function: self.__handleSendAvatars() def __handleSendAvatars(self): @@ -369,19 +398,25 @@ class CreateAvatarOperation(GameOperation): self.avDNA = None def start(self, avDNA, avPosition): + # First, perform some basic sanity checking. if avPosition >= 6: - # TODO: Kill the connection + # This index is invalid! Close the connection. + self._handleCloseConnection('Invalid index specified!') return + # Check if this DNA is valid: dna = ToonDNA() valid = dna.isValidNetString(avDNA) if not valid: - # TODO: Kill the connection + # This DNA is invalid! Close the connection. + self._handleCloseConnection('Invalid DNA specified!') return + # Store these values: self.avPosition = avPosition self.avDNA = avDNA + # Now we can query their account. self.__handleRetrieveAccount() def __handleRetrieveAccount(self): @@ -390,17 +425,25 @@ class CreateAvatarOperation(GameOperation): def __handleAccountRetrieved(self, dclass, fields): if dclass != self.loginManager.air.dclassesByName['AstronAccountUD']: - # TODO: Kill the connection + # This is not an account object! Close the connection. + self._handleCloseConnection('Your account object (%s) was not found in the database!' % dclass) return + # Now we will get our avList. self.account = fields self.avList = self.account['ACCOUNT_AV_SET'] + + # We will now sanitize the avList. self.avList = self.avList[:6] self.avList += [0] * (6 - len(self.avList)) + + # Check if the index is open: if self.avList[self.avPosition]: - # TODO: Kill the connection + # This index is not open! Close the connection. + self._handleCloseConnection('This avatar slot is already taken by another avatar!') return + # All set, now let's create the avatar! self.__handleCreateAvatar() def __handleCreateAvatar(self): @@ -421,9 +464,11 @@ class CreateAvatarOperation(GameOperation): def __handleToonCreated(self, avId): if not avId: - # TODO: Kill the connection + # The database was unable to create a new avatar object! Close the connection. + self._handleCloseConnection('Database failed to create the new avatar object!') return + # We can now store the avatar. self.avId = avId self.__handleStoreAvatar() @@ -437,9 +482,12 @@ class CreateAvatarOperation(GameOperation): def __handleAvatarStored(self, fields): if fields: - # TODO: Kill the connection + # The new avatar was not associated with the account! Close the connection. + self._handleCloseConnection('Database failed to associate the new avatar to your account!') return + # Otherwise, we're done! + self.loginManager.air.writeServerEvent('avatar-created', self.avId, self.sender, self.avPosition) self.loginManager.sendUpdateToAccountId(self.sender, 'createAvatarResponse', [self.avId]) self._handleDone() @@ -458,22 +506,31 @@ class SetNamePatternOperation(AvatarOperation): AvatarOperation.start(self) def __handleRetrieveAvatar(self): + # Retrieves the avatar from the database. if self.avId and self.avId not in self.avList: - # TODO: Kill the connection + # The avatar exists, but it's not an avatar that is + # associated with this account. Close the connection. + self._handleCloseConnection('Tried to name an avatar not in the account!') return + # Query the database for the avatar. self.__handleAvatarRetrieved is + # our callback which will be called upon queryObject's completion. self.loginManager.air.dbInterface.queryObject(self.loginManager.air.dbId, self.avId, self.__handleAvatarRetrieved) def __handleAvatarRetrieved(self, dclass, fields): if dclass != self.loginManager.air.dclassesByName['DistributedToonUD']: - # TODO: Kill the connection + # This dclass is not a valid avatar! Close the connection. + self._handleCloseConnection('One of the account\'s avatars is invalid!') return if fields['WishNameState'][0] != 'OPEN': - # TODO: Kill the connection + # This avatar's wish name state is not set + # to a nameable state. Close the connection. + self._handleCloseConnection('Avatar is not in a nameable state!') return + # Otherwise, we can set the name: self.__handleSetName() def __handleSetName(self): @@ -521,22 +578,31 @@ class SetNameTypedOperation(AvatarOperation): self.__handleJudgeName() def __handleRetrieveAvatar(self): + # Retrieves the avatar from the database. if self.avId and self.avId not in self.avList: - # TODO: Kill the connection + # The avatar exists, but it's not an avatar that is + # associated with this account. Close the connection. + self._handleCloseConnection('Tried to name an avatar not in the account!') return + # Query the database for the avatar. self.__handleAvatarRetrieved is + # our callback which will be called upon queryObject's completion. self.loginManager.air.dbInterface.queryObject(self.loginManager.air.dbId, self.avId, self.__handleAvatarRetrieved) def __handleAvatarRetrieved(self, dclass, fields): if dclass != self.loginManager.air.dclassesByName['DistributedToonUD']: - # TODO: Kill the connection + # This dclass is not a valid avatar! Close the connection. + self._handleCloseConnection('One of the account\'s avatars is invalid!') return if fields['WishNameState'][0] != 'OPEN': - # TODO: Kill the connection + # This avatar's wish name state is not set + # to a nameable state. Close the connection. + self._handleCloseConnection('Avatar is not in a nameable state!') return + # Now we can move on to the judging! self.__handleJudgeName() def __handleJudgeName(self): @@ -563,10 +629,15 @@ class AcknowledgeNameOperation(AvatarOperation): AvatarOperation.start(self) def __handleGetTargetAvatar(self): + # Make sure that the target avatar is part of the account: if self.avId not in self.avList: - # TODO: Kill the connection + # The sender tried to acknowledge name on an avatar not on the account! + # Close the connection. + self._handleCloseConnection('Tried to acknowledge name on an avatar not in the account!') return + # We can now query the database for the avatar. self.__handleAvatarRetrieved is the + # callback which will be called upon the completion of queryObject. self.loginManager.air.dbInterface.queryObject(self.loginManager.air.dbId, self.avId, self.__handleAvatarRetrieved) @@ -612,8 +683,10 @@ class RemoveAvatarOperation(GetAvatarsOperation): GetAvatarsOperation.start(self) def __handleRemoveAvatar(self): + # Make sure that the target avatar is part of the account: if self.avId not in self.avList: - # TODO: Kill the connection + # The sender tried to remove an avatar not on the account! Close the connection. + self._handleCloseConnection('Tried to remove an avatar not on the account!') return index = self.avList.index(self.avId) @@ -637,7 +710,8 @@ class RemoveAvatarOperation(GetAvatarsOperation): def __handleAvatarRemoved(self, fields): if fields: - # TODO: Kill the connection + # The avatar was unable to be removed from the account! Close the account. + self._handleCloseConnection('Database failed to mark the avatar as removed!') return self._handleQueryAvatars()