makeatoon: Typing a name works
This commit is contained in:
parent
e3b96e2cfd
commit
dcacd391ed
6 changed files with 293 additions and 61 deletions
|
@ -538,4 +538,8 @@ dclass AstronLoginManager : DistributedObject {
|
||||||
createAvatarResponse(uint32);
|
createAvatarResponse(uint32);
|
||||||
setNamePattern(uint32, int16, uint8, int16, uint8, int16, uint8, int16, uint8) clsend;
|
setNamePattern(uint32, int16, uint8, int16, uint8, int16, uint8, int16, uint8) clsend;
|
||||||
namePatternAnswer(uint32, uint8);
|
namePatternAnswer(uint32, uint8);
|
||||||
|
setNameTyped(uint32, string) clsend;
|
||||||
|
nameTypedResponse(uint32, uint8);
|
||||||
|
acknowledgeAvatarName(uint32) clsend;
|
||||||
|
acknowledgeAvatarNameResponse();
|
||||||
};
|
};
|
||||||
|
|
|
@ -135,3 +135,17 @@ class AstronLoginManager(DistributedObjectGlobal):
|
||||||
|
|
||||||
def namePatternAnswer(self, avId, status):
|
def namePatternAnswer(self, avId, status):
|
||||||
self._callback(avId, status)
|
self._callback(avId, status)
|
||||||
|
|
||||||
|
def sendSetNameTyped(self, avId, name, callback):
|
||||||
|
self._callback = callback
|
||||||
|
self.sendUpdate('setNameTyped', [avId, name])
|
||||||
|
|
||||||
|
def nameTypedResponse(self, avId, status):
|
||||||
|
self._callback(avId, status)
|
||||||
|
|
||||||
|
def sendAcknowledgeAvatarName(self, avId, callback):
|
||||||
|
self._callback = callback
|
||||||
|
self.sendUpdate('acknowledgeAvatarName', [avId])
|
||||||
|
|
||||||
|
def acknowledgeAvatarNameResponse(self):
|
||||||
|
self._callback()
|
||||||
|
|
|
@ -421,6 +421,134 @@ class SetNamePatternOperation:
|
||||||
del self.loginManager.account2operation[self.sender]
|
del self.loginManager.account2operation[self.sender]
|
||||||
|
|
||||||
|
|
||||||
|
class SetNameTypedOperation:
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory('SetNameTypedOperation')
|
||||||
|
|
||||||
|
def __init__(self, loginManager, sender):
|
||||||
|
self.loginManager = loginManager
|
||||||
|
self.sender = sender
|
||||||
|
self.avId = None
|
||||||
|
self.name = None
|
||||||
|
|
||||||
|
def start(self, avId, name):
|
||||||
|
self.avId = avId
|
||||||
|
self.name = name
|
||||||
|
if self.avId:
|
||||||
|
self.__handleRetrieveAccount()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__handleJudgeName()
|
||||||
|
|
||||||
|
def __handleRetrieveAccount(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.__handleRetrieveAvatar()
|
||||||
|
|
||||||
|
def __handleRetrieveAvatar(self):
|
||||||
|
if self.avId and self.avId not in self.avList:
|
||||||
|
# You have no chance to survive make your time
|
||||||
|
# Hahaha
|
||||||
|
return
|
||||||
|
|
||||||
|
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']:
|
||||||
|
# How are you gentlemen?
|
||||||
|
# All your base are belong to us
|
||||||
|
return
|
||||||
|
|
||||||
|
if fields['WishNameState'][0] != 'OPEN':
|
||||||
|
# You are on your way to destruction
|
||||||
|
# What you say?
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__handleJudgeName()
|
||||||
|
|
||||||
|
def __handleJudgeName(self):
|
||||||
|
status = 1 # TODO Make this useful
|
||||||
|
if self.avId and status:
|
||||||
|
self.loginManager.air.dbInterface.updateObject(self.loginManager.air.dbId, self.avId,
|
||||||
|
self.loginManager.air.dclassesByName['DistributedToonUD'],
|
||||||
|
{'WishNameState': ('PENDING',),
|
||||||
|
'WishName': (self.name,)})
|
||||||
|
|
||||||
|
self.loginManager.sendUpdateToAccountId(self.sender, 'nameTypedResponse', [self.avId, status])
|
||||||
|
del self.loginManager.account2operation[self.sender]
|
||||||
|
|
||||||
|
|
||||||
|
class AcknowledgeNameOperation:
|
||||||
|
notify = DirectNotifyGlobal.directNotify.newCategory('AcknowledgeNameOperation')
|
||||||
|
|
||||||
|
def __init__(self, loginManager, sender):
|
||||||
|
self.loginManager = loginManager
|
||||||
|
self.sender = sender
|
||||||
|
self.avId = None
|
||||||
|
|
||||||
|
def start(self, avId):
|
||||||
|
self.avId = avId
|
||||||
|
self.__handleRetrieveAccount()
|
||||||
|
|
||||||
|
def __handleRetrieveAccount(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.__handleGetTargetAvatar()
|
||||||
|
|
||||||
|
def __handleGetTargetAvatar(self):
|
||||||
|
if self.avId not in self.avList:
|
||||||
|
# welp
|
||||||
|
return
|
||||||
|
|
||||||
|
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']:
|
||||||
|
return
|
||||||
|
|
||||||
|
wishNameState = fields['WishNameState'][0]
|
||||||
|
wishName = fields['WishName'][0]
|
||||||
|
name = fields['setName'][0]
|
||||||
|
if wishNameState == 'APPROVED':
|
||||||
|
wishNameState = 'LOCKED'
|
||||||
|
name = wishName
|
||||||
|
wishName = ''
|
||||||
|
elif wishNameState == 'REJECTED':
|
||||||
|
wishNameState = 'OPEN'
|
||||||
|
wishName = ''
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.loginManager.air.dbInterface.updateObject(self.loginManager.air.dbId, self.avId,
|
||||||
|
self.loginManager.air.dclassesByName['DistributedToonUD'],
|
||||||
|
{'WishNameState': (wishNameState,),
|
||||||
|
'WishName': (wishName,),
|
||||||
|
'setName': (name,)},
|
||||||
|
{'WishNameState': fields['WishNameState'],
|
||||||
|
'WishName': fields['WishName'],
|
||||||
|
'setName': fields['setName']})
|
||||||
|
|
||||||
|
self.loginManager.sendUpdateToAccountId(self.sender, 'acknowledgeAvatarNameResponse', [])
|
||||||
|
del self.loginManager.account2operation[self.sender]
|
||||||
|
|
||||||
|
|
||||||
class AstronLoginManagerUD(DistributedObjectGlobalUD):
|
class AstronLoginManagerUD(DistributedObjectGlobalUD):
|
||||||
notify = DirectNotifyGlobal.directNotify.newCategory('AstronLoginManagerUD')
|
notify = DirectNotifyGlobal.directNotify.newCategory('AstronLoginManagerUD')
|
||||||
|
|
||||||
|
@ -497,3 +625,31 @@ class AstronLoginManagerUD(DistributedObjectGlobalUD):
|
||||||
self.account2operation[sender] = newOperation
|
self.account2operation[sender] = newOperation
|
||||||
newOperation.start(avId, [(p1, f1), (p2, f2),
|
newOperation.start(avId, [(p1, f1), (p2, f2),
|
||||||
(p3, f3), (p4, f4)])
|
(p3, f3), (p4, f4)])
|
||||||
|
|
||||||
|
def setNameTyped(self, avId, name):
|
||||||
|
sender = self.air.getAccountIdFromSender()
|
||||||
|
if not sender:
|
||||||
|
# TODO KILL CONNECTION
|
||||||
|
return
|
||||||
|
|
||||||
|
if sender in self.account2operation:
|
||||||
|
# BAD!!!!
|
||||||
|
return
|
||||||
|
|
||||||
|
newOperation = SetNameTypedOperation(self, sender)
|
||||||
|
self.account2operation[sender] = newOperation
|
||||||
|
newOperation.start(avId, name)
|
||||||
|
|
||||||
|
def acknowledgeAvatarName(self, avId):
|
||||||
|
sender = self.air.getAccountIdFromSender()
|
||||||
|
if not sender:
|
||||||
|
# TODO KILL CONNECTION
|
||||||
|
return
|
||||||
|
|
||||||
|
if sender in self.account2operation:
|
||||||
|
# BAD!!!!
|
||||||
|
return
|
||||||
|
|
||||||
|
newOperation = AcknowledgeNameOperation(self, sender)
|
||||||
|
self.account2operation[sender] = newOperation
|
||||||
|
newOperation.start(avId)
|
||||||
|
|
|
@ -87,7 +87,7 @@ def checkName(name, otherCheckFuncs = [], font = None):
|
||||||
tn = TextNode('NameCheck')
|
tn = TextNode('NameCheck')
|
||||||
tn.setFont(font)
|
tn.setFont(font)
|
||||||
for c in name:
|
for c in name:
|
||||||
if not tn.hasCharacter(ord(c)):
|
if not tn.hasCharacter(unicode(c)):
|
||||||
notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(c))
|
notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(c))
|
||||||
return OTPLocalizer.NCBadCharacter % TextEncoder().encodeWtext(c)
|
return OTPLocalizer.NCBadCharacter % TextEncoder().encodeWtext(c)
|
||||||
|
|
||||||
|
|
|
@ -179,12 +179,16 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository):
|
||||||
del self.okButton
|
del self.okButton
|
||||||
del self.acceptedText
|
del self.acceptedText
|
||||||
del self.acceptedBanner
|
del self.acceptedBanner
|
||||||
datagram = PyDatagram()
|
if not self.astronSupport:
|
||||||
datagram.addUint16(CLIENT_SET_WISHNAME_CLEAR)
|
datagram = PyDatagram()
|
||||||
datagram.addUint32(avatarChoice.id)
|
datagram.addUint16(CLIENT_SET_WISHNAME_CLEAR)
|
||||||
datagram.addUint8(1)
|
datagram.addUint32(avatarChoice.id)
|
||||||
self.send(datagram)
|
datagram.addUint8(1)
|
||||||
self.loginFSM.request('waitForSetAvatarResponse', [avatarChoice])
|
self.send(datagram)
|
||||||
|
self.loginFSM.request('waitForSetAvatarResponse', [avatarChoice])
|
||||||
|
else:
|
||||||
|
self.astronLoginManager.sendAcknowledgeAvatarName(avatarChoice.id,
|
||||||
|
lambda: self.loginFSM.request('waitForSetAvatarResponse', [avatarChoice]))
|
||||||
|
|
||||||
def betterlucknexttime(self, avList, index):
|
def betterlucknexttime(self, avList, index):
|
||||||
self.rejectDoneEvent = 'rejectDone'
|
self.rejectDoneEvent = 'rejectDone'
|
||||||
|
@ -195,8 +199,9 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository):
|
||||||
|
|
||||||
def __handleReject(self, avList, index):
|
def __handleReject(self, avList, index):
|
||||||
self.rejectDialog.cleanup()
|
self.rejectDialog.cleanup()
|
||||||
datagram = PyDatagram()
|
if not self.astronSupport:
|
||||||
datagram.addUint16(CLIENT_SET_WISHNAME_CLEAR)
|
datagram = PyDatagram()
|
||||||
|
datagram.addUint16(CLIENT_SET_WISHNAME_CLEAR)
|
||||||
avid = 0
|
avid = 0
|
||||||
for k in avList:
|
for k in avList:
|
||||||
if k.position == index:
|
if k.position == index:
|
||||||
|
@ -204,10 +209,13 @@ class ToontownClientRepository(OTPClientRepository.OTPClientRepository):
|
||||||
|
|
||||||
if avid == 0:
|
if avid == 0:
|
||||||
self.notify.error('Avatar rejected not found in avList. Index is: ' + str(index))
|
self.notify.error('Avatar rejected not found in avList. Index is: ' + str(index))
|
||||||
datagram.addUint32(avid)
|
if not self.astronSupport:
|
||||||
datagram.addUint8(0)
|
datagram.addUint32(avid)
|
||||||
self.send(datagram)
|
datagram.addUint8(0)
|
||||||
self.loginFSM.request('waitForAvatarList')
|
self.send(datagram)
|
||||||
|
self.loginFSM.request('waitForAvatarList')
|
||||||
|
else:
|
||||||
|
self.astronLoginManager.sendAcknowledgeAvatarName(avId, lambda: self.loginFSM.request('waitForAvatarList'))
|
||||||
|
|
||||||
def enterChooseAvatar(self, avList):
|
def enterChooseAvatar(self, avList):
|
||||||
ModelPool.garbageCollect()
|
ModelPool.garbageCollect()
|
||||||
|
|
|
@ -954,74 +954,124 @@ class NameShop(StateData.StateData):
|
||||||
self.notify.debug('checkNameTyped')
|
self.notify.debug('checkNameTyped')
|
||||||
if self._submitTypeANameAsPickAName():
|
if self._submitTypeANameAsPickAName():
|
||||||
return
|
return
|
||||||
datagram = PyDatagram()
|
if not base.cr.astronSupport:
|
||||||
datagram.addUint16(CLIENT_SET_WISHNAME)
|
datagram = PyDatagram()
|
||||||
|
datagram.addUint16(CLIENT_SET_WISHNAME)
|
||||||
if justCheck:
|
if justCheck:
|
||||||
avId = 0
|
avId = 0
|
||||||
else:
|
else:
|
||||||
avId = self.avId
|
avId = self.avId
|
||||||
datagram.addUint32(avId)
|
if not base.cr.astronSupport:
|
||||||
datagram.addString(self.nameEntry.get())
|
datagram.addUint32(avId)
|
||||||
messenger.send('nameShopPost', [datagram])
|
datagram.addString(self.nameEntry.get())
|
||||||
|
messenger.send('nameShopPost', [datagram])
|
||||||
|
else:
|
||||||
|
base.cr.astronLoginManager.sendSetNameTyped(avId, self.nameEntry.get(), self.handleSetNameTypedAnswerMsg)
|
||||||
self.waitForServer()
|
self.waitForServer()
|
||||||
|
|
||||||
def handleSetNameTypedAnswerMsg(self, di):
|
if not config.GetBool('astron-support', True):
|
||||||
self.notify.debug('handleSetNameTypedAnswerMsg')
|
def handleSetNameTypedAnswerMsg(self, di):
|
||||||
self.cleanupWaitForServer()
|
self.notify.debug('handleSetNameTypedAnswerMsg')
|
||||||
newavId = di.getUint32()
|
self.cleanupWaitForServer()
|
||||||
if newavId and newavId != self.avId:
|
newavId = di.getUint32()
|
||||||
self.notify.debug("doid's don't match up!")
|
if newavId and newavId != self.avId:
|
||||||
self.rejectName(TTLocalizer.NameError)
|
self.notify.debug("doid's don't match up!")
|
||||||
returnCode = di.getUint16()
|
self.rejectName(TTLocalizer.NameError)
|
||||||
if newavId == 0:
|
returnCode = di.getUint16()
|
||||||
if returnCode == 0:
|
if newavId == 0:
|
||||||
pendingname = di.getString()
|
if returnCode == 0:
|
||||||
|
pendingname = di.getString()
|
||||||
|
approvedname = di.getString()
|
||||||
|
rejectedname = di.getString()
|
||||||
|
if pendingname != '':
|
||||||
|
self.notify.debug('name check pending')
|
||||||
|
self.fsm.request('Approval')
|
||||||
|
elif approvedname != '':
|
||||||
|
self.notify.debug('name check accepted')
|
||||||
|
self.nameAction = 2
|
||||||
|
self.serverCreateAvatar()
|
||||||
|
elif rejectedname != '':
|
||||||
|
self.notify.debug('name check rejected')
|
||||||
|
self.fsm.request('TypeAName')
|
||||||
|
self.rejectName(TTLocalizer.NameError)
|
||||||
|
else:
|
||||||
|
self.notify.debug('typed name response did not contain any return fields')
|
||||||
|
self.rejectName(TTLocalizer.NameError)
|
||||||
|
elif returnCode == 0:
|
||||||
|
wishname = di.getString()
|
||||||
approvedname = di.getString()
|
approvedname = di.getString()
|
||||||
rejectedname = di.getString()
|
rejectedname = di.getString()
|
||||||
if pendingname != '':
|
if approvedname != '':
|
||||||
|
style = self.toon.getStyle()
|
||||||
|
avDNA = style.makeNetString()
|
||||||
|
self.names[0] = self.nameEntry.get()
|
||||||
|
self.notify.debug('typed name accepted')
|
||||||
|
newPotAv = PotentialAvatar.PotentialAvatar(newavId, self.names, avDNA, self.index, 0)
|
||||||
|
self.avList.append(newPotAv)
|
||||||
|
self.fsm.request('Accepted')
|
||||||
|
elif wishname != '':
|
||||||
|
style = self.toon.getStyle()
|
||||||
|
avDNA = style.makeNetString()
|
||||||
|
self.names[1] = self.nameEntry.get()
|
||||||
|
self.notify.debug('typed name needs approval')
|
||||||
|
newPotAv = PotentialAvatar.PotentialAvatar(newavId, self.names, avDNA, self.index, 1)
|
||||||
|
if not self.newwarp:
|
||||||
|
self.avList.append(newPotAv)
|
||||||
|
self.fsm.request('ApprovalAccepted')
|
||||||
|
elif rejectedname != '':
|
||||||
|
self.fsm.request('Rejected')
|
||||||
|
else:
|
||||||
|
self.notify.debug("name typed accepted but didn't fill any return fields")
|
||||||
|
self.rejectName(TTLocalizer.NameError)
|
||||||
|
else:
|
||||||
|
self.notify.debug('name typed rejected')
|
||||||
|
self.rejectName(TTLocalizer.NameError)
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
def handleSetNameTypedAnswerMsg(self, newavId, returnCode):
|
||||||
|
self.notify.debug('handleSetNameTypedAnswerMsg')
|
||||||
|
self.cleanupWaitForServer()
|
||||||
|
if newavId and newavId != self.avId:
|
||||||
|
self.notify.debug("doid's don't match up!")
|
||||||
|
self.rejectName(TTLocalizer.NameError)
|
||||||
|
if newavId == 0:
|
||||||
|
if returnCode == 1:
|
||||||
self.notify.debug('name check pending')
|
self.notify.debug('name check pending')
|
||||||
self.fsm.request('Approval')
|
self.fsm.request('Approval')
|
||||||
elif approvedname != '':
|
elif returnCode == 2:
|
||||||
self.notify.debug('name check accepted')
|
self.notify.debug('name check accepted')
|
||||||
self.nameAction = 2
|
self.nameAction = 2
|
||||||
self.serverCreateAvatar()
|
self.serverCreateAvatar()
|
||||||
elif rejectedname != '':
|
elif returnCode == 0:
|
||||||
self.notify.debug('name check rejected')
|
self.notify.debug('name check rejected')
|
||||||
self.fsm.request('TypeAName')
|
self.fsm.request('TypeAName')
|
||||||
self.rejectName(TTLocalizer.NameError)
|
self.rejectName(TTLocalizer.NameError)
|
||||||
else:
|
else:
|
||||||
self.notify.debug('typed name response did not contain any return fields')
|
self.notify.debug('typed name response did not contain any return fields')
|
||||||
self.rejectName(TTLocalizer.NameError)
|
self.rejectName(TTLocalizer.NameError)
|
||||||
elif returnCode == 0:
|
|
||||||
wishname = di.getString()
|
|
||||||
approvedname = di.getString()
|
|
||||||
rejectedname = di.getString()
|
|
||||||
if approvedname != '':
|
|
||||||
style = self.toon.getStyle()
|
|
||||||
avDNA = style.makeNetString()
|
|
||||||
self.names[0] = self.nameEntry.get()
|
|
||||||
self.notify.debug('typed name accepted')
|
|
||||||
newPotAv = PotentialAvatar.PotentialAvatar(newavId, self.names, avDNA, self.index, 0)
|
|
||||||
self.avList.append(newPotAv)
|
|
||||||
self.fsm.request('Accepted')
|
|
||||||
elif wishname != '':
|
|
||||||
style = self.toon.getStyle()
|
|
||||||
avDNA = style.makeNetString()
|
|
||||||
self.names[1] = self.nameEntry.get()
|
|
||||||
self.notify.debug('typed name needs approval')
|
|
||||||
newPotAv = PotentialAvatar.PotentialAvatar(newavId, self.names, avDNA, self.index, 1)
|
|
||||||
if not self.newwarp:
|
|
||||||
self.avList.append(newPotAv)
|
|
||||||
self.fsm.request('ApprovalAccepted')
|
|
||||||
elif rejectedname != '':
|
|
||||||
self.fsm.request('Rejected')
|
|
||||||
else:
|
else:
|
||||||
self.notify.debug("name typed accepted but didn't fill any return fields")
|
if returnCode == 2:
|
||||||
self.rejectName(TTLocalizer.NameError)
|
style = self.toon.getStyle()
|
||||||
else:
|
avDNA = style.makeNetString()
|
||||||
self.notify.debug('name typed rejected')
|
self.names[0] = self.nameEntry.get()
|
||||||
self.rejectName(TTLocalizer.NameError)
|
self.notify.debug('typed name accepted')
|
||||||
return None
|
newPotAv = PotentialAvatar.PotentialAvatar(newavId, self.names, avDNA, self.index, 0)
|
||||||
|
self.avList.append(newPotAv)
|
||||||
|
self.fsm.request('Accepted')
|
||||||
|
elif returnCode == 1:
|
||||||
|
style = self.toon.getStyle()
|
||||||
|
avDNA = style.makeNetString()
|
||||||
|
self.names[1] = self.nameEntry.get()
|
||||||
|
self.notify.debug('typed name needs approval')
|
||||||
|
newPotAv = PotentialAvatar.PotentialAvatar(newavId, self.names, avDNA, self.index, 1)
|
||||||
|
if not self.newwarp:
|
||||||
|
self.avList.append(newPotAv)
|
||||||
|
self.fsm.request('ApprovalAccepted')
|
||||||
|
elif returnCode == 0:
|
||||||
|
self.fsm.request('Rejected')
|
||||||
|
else:
|
||||||
|
self.notify.debug("name typed accepted but didn't fill any return fields")
|
||||||
|
self.rejectName(TTLocalizer.NameError)
|
||||||
|
|
||||||
def serverCreateAvatar(self, skipTutorial = False):
|
def serverCreateAvatar(self, skipTutorial = False):
|
||||||
self.notify.debug('serverCreateAvatar')
|
self.notify.debug('serverCreateAvatar')
|
||||||
|
|
Loading…
Reference in a new issue