Friends: True friends work for the most part now

This commit is contained in:
DarthM 2025-01-28 03:16:56 -05:00
parent 05d73cb4fb
commit 653122c76e
5 changed files with 114 additions and 5 deletions

View File

@ -2874,7 +2874,9 @@ dclass ToontownFriendsManager : DistributedObject {
makeFriendsResponse(uint32, uint32, uint8, uint32) airecv;
removeFriend(uint32) clsend;
requestSecret(uint32);
submitSecret(uint32, string);
requestSecretResponse(uint8, string, uint32) airecv;
submitSecretResponse(uint8, uint32, uint32) airecv;
};
dclass TTSpeedchatRelay : SpeedchatRelay {

View File

@ -18,6 +18,11 @@ class FriendManagerAI(DistributedObjectGlobalAI):
# forget who has declined friendships from whom.
DeclineFriendshipTimeout = 600.0
# This is the length of time, in seconds, to sit on a secret guess
# # before processing it. This serves to make it difficult to guess
# # passwords at random.
SecretDelay = 1.0
# This subclass is used to record currently outstanding
# in-the-game invitation requests.
class Invite:
@ -51,10 +56,12 @@ class FriendManagerAI(DistributedObjectGlobalAI):
# via the AIR.
self.accept("makeFriendsReply", self.makeFriendsReply)
self.accept("requestSecretReply", self.requestSecretReply)
self.accept('submitSecretReply', self.submitSecretReply)
def delete(self):
self.ignore("makeFriendsReply")
self.ignore("requestSecretReply")
self.ignore('submitSecretReply')
DistributedObjectGlobalAI.delete(self)
### Messages sent from inviter client to AI
@ -223,6 +230,51 @@ class FriendManagerAI(DistributedObjectGlobalAI):
self.sendUpdateToAvatarId(recipient, "friendResponse", [yesNoMaybe, context])
self.notify.debug("AI: friendResponse(%d, %d)" % (yesNoMaybe, context))
def submitSecret(self, secret):
"""submitSecret(self, string secret)
Sent by the client to the AI to submit a "secret" typed in by
the user.
"""
avId = self.air.getAvatarIdFromSender()
# We have to sit on this request for a few seconds before
# processing it. This delay is solely to discourage password
# guessing.
taskName = "secret-" + str(avId)
taskMgr.remove(taskName)
if FriendManagerAI.SecretDelay:
taskMgr.doMethodLater(FriendManagerAI.SecretDelay,
self.continueSubmission,
taskName,
extraArgs = (avId, secret))
else:
# No delay
self.continueSubmission(avId, secret)
def continueSubmission(self, avId, secret):
"""continueSubmission(self, avId, secret)
Finishes the work of submitSecret, a short time later.
"""
self.air.submitSecret(avId, secret)
def submitSecretReply(self, result, recipient, avId):
self.down_submitSecretResponse(recipient, result, avId)
def down_submitSecretResponse(self, recipient, result, avId):
"""submitSecret(self, int8 result, int32 avId)
Sent by the AI to the client in response to submitSecret().
result is one of:
0 - Failure. The secret is unknown or has timed out.
1 - Success. You are now friends with the indicated avId.
2 - Failure. One of the avatars has too many friends already.
3 - Failure. You just used up your own secret.
"""
self.sendUpdateToAvatarId(recipient, 'submitSecretResponse', [result, avId])
### Support methods
def newInvite(self, inviterId, inviteeId):
@ -414,7 +466,7 @@ class FriendManagerAI(DistributedObjectGlobalAI):
def requestSecretReply(self, result, secret, requesterId):
self.down_requestSecretResponse(requesterId, result, secret)
def down_requestSecretResponse(self, recipient, result, secret):
"""requestSecret(self, int8 result, string secret)

View File

@ -547,6 +547,19 @@ class ToontownAIRepository(ToontownInternalRepository):
if __astron__:
self.toontownFriendsManager.sendRequestSecret(requesterId)
def submitSecret(self, avId, secret):
"""
avId: the avatar id of the friend who requested the secret
secret: the secret that was requested
Submits a secret that was previously requested.
Will submit through the friends manager.
When the secret is submitted, a "submitSecretReply" message will
be thrown with two parameters: the result code (0 or 1,
indicating failure or success), and the requesterId again.
"""
if __astron__:
self.toontownFriendsManager.sendSubmitSecret(avId, secret)
def setupFiles(self):
if not os.path.exists(self.dataFolder):
os.mkdir(self.dataFolder)

View File

@ -27,3 +27,9 @@ class ToontownFriendsManagerAI(DistributedObjectGlobalAI):
def sendRequestSecret(self, requesterId):
self.sendUpdate('requestSecret', [requesterId])
def sendSubmitSecret(self, avId, secret):
self.sendUpdate('submitSecret', [avId, secret])
def submitSecretResponse(self, result, recipient, requesterId):
messenger.send("submitSecretReply", [result, recipient, requesterId])

View File

@ -1,7 +1,7 @@
from direct.directnotify import DirectNotifyGlobal
from direct.distributed.DistributedObjectGlobalUD import DistributedObjectGlobalUD
from direct.distributed.PyDatagram import *
from direct.distributed.MsgTypes import *
from otp.otpbase import OTPGlobals
import random
import string
@ -709,8 +709,7 @@ class GenerateSecretOperation(FriendsOperation):
TT 3 random letters/numbers 3 random letters/numbers
"""
self.requesterId = requesterId
# first check if friends list is full
self.friendsManager.loadSecretsDB()
# check if too many secrets
# TODO
self.secret = ''
@ -728,6 +727,7 @@ class GenerateSecretOperation(FriendsOperation):
Handle the completion of the operation.
"""
FriendsOperation._handleDone(self)
self.friendsManager.updateSecretsDB()
# send the response to the requester that it was a success, the result and the secret
self.friendsManager.sendRequestSecretResponse(self.requesterId, 1, self.secret)
@ -907,6 +907,32 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD):
"""
self.runServerOperation(GenerateSecretOperation, requesterId)
def submitSecret(self, avId, secret):
"""
Handle a request to submit a secret.
:param avId: The avatar ID.
:param secret: The secret.
"""
self.loadSecretsDB()
recipient = self.secrets.get(secret, None)
if recipient:
self.runServerOperation(MakeFriendsOperation, avId, recipient, 0, 0)
self.sendSubmitSecretResponse(avId, 1, recipient)
else:
self.sendSubmitSecretResponse(avId, 0, recipient)
def sendSubmitSecretResponse(self, requesterId, success, recipient):
"""
Send a response to a secret submission.
:param requesterId: The requester's ID.
:param success: Whether the operation was successful.
:param secret: The secret.
:param recipient: The recipient's ID.
"""
self.sendUpdate('submitSecretResponse', [success, recipient, requesterId])
def comingOnline(self, avId, friendsList):
"""
Handle a request for an avatar coming online.
@ -935,6 +961,16 @@ class ToontownFriendsManagerUD(DistributedObjectGlobalUD):
self.sendUpdate('requestSecretResponse', [success, secret, requesterId])
def updateSecretsDB(self):
with open('astron/databases/secrets.json', 'w') as f:
json.dump(self.secrets, f)
self.notify.debug('Updated secrets database')
def loadSecretsDB(self):
try:
with open('astron/databases/secrets.json', 'r') as f:
self.secrets = json.load(f)
self.notify.debug('Loaded secrets database')
except:
self.notify.warning('Failed to load secrets database')