adding select profile

This commit is contained in:
AleaJactaEst 2019-07-28 00:39:49 +02:00
parent 2e521c0267
commit 733000a09c

147
client.py
View file

@ -49,6 +49,13 @@ import inspect
INVALID_SLOT = 0xff INVALID_SLOT = 0xff
def convertUStringToString(name):
ret = ''
for car in name:
if ord(car) >= 32 and ord(car)<=127:
ret += car
return ret
class BitStream(): class BitStream():
def __init__(self): def __init__(self):
self._pos = 0 self._pos = 0
@ -485,13 +492,13 @@ class BitStream():
source.putRead(0) source.putRead(0)
need = 8 - (self._pos % 8) need = 8 - (self._pos % 8)
if need != 8: if need != 8:
self.internalSerial(source.readSerial(need), need, decode=False) self.internalSerial(source.readSerial(need, decode=False), need, decode=False)
while source.needRead() >= 8: while source.needRead() >= 8:
self.pushUint8(source.readSerial(8, False), decode=False) self.pushUint8(source.readSerial(8, decode=False), decode=False)
need = source.needRead() need = source.needRead()
if need > 0: if need > 0:
self.internalSerial(source.readSerial(need, False), need, decode=False) self.internalSerial(source.readSerial(need, decode=False), need, decode=False)
source.putRead(srcRead) source.putRead(srcRead)
p2 = self._pos p2 = self._pos
@ -657,7 +664,7 @@ class BitStream():
ret = BitStream() ret = BitStream()
v1 = self._read v1 = self._read
for i in range(0, size): for i in range(0, size):
ret.pushUint8(self.readUint8('', decode=False)) ret.pushUint8(self.readUint8('', decode=False), decode=False)
v2 = self._read v2 = self._read
self._groupRead.append((v1, v2, name, 'StreamUint8', '')) self._groupRead.append((v1, v2, name, 'StreamUint8', ''))
return ret return ret
@ -1190,6 +1197,66 @@ class TType(IntEnum):
NB_TYPE = 11 NB_TYPE = 11
class TState(IntEnum):
# initial state
st_start = 0
# display login screen and options
st_login = 1
# auto login using cmd lien parameters (used with patch reboot)
st_auto_login = 2
# display the shard list
st_shard_list = 3
# lauch the configurator and close ryzom
st_start_config = 4
# run the scan data thread
st_scan_data = 5
# display the eula and wait for validation
st_display_eula = 6
# check the data to determine need for patch
st_check_patch = 7
# display the list of optional patch category for patching
st_display_cat = 8
# run the patch process and display progress
st_patch = 9
# terminate the client and quit
st_close_client = 10
# display the reboot screen and wait validation
st_reboot_screen = 11
# restart the client with login bypass params
st_restart_client = 12
# connect to the FS (start the 'in game' mode)
st_connect = 13
# show the outgame browser
st_browser_screen = 14
# ingame state
st_ingame = 15
# leave the current shard (the exit action progress, Far TP part 1.1; Server Hop part 1-2)
st_leave_shard = 16
# let the main loop finish the current frame and leave it (Far TP part 1.2)
st_enter_far_tp_main_loop = 17
# disconnect from the FS (Far TP part 2)
st_disconnect = 18
# connect to a new FS (Far TP & Server Hop part 3.1)
st_reconnect_fs = 19
# after reconnecting, bypass character selection ui & select the same character (Far TP & Server Hop part 3.2)
st_reconnect_select_char = 20
# after reconnecting and receiving ready, send ready (Far TP part 3.3)
st_reconnect_ready = 21
# between global menu exit and sending ready (Server Hop part 3.3)
st_exit_global_menu = 22
# error while reconnecting
st_reconnect_error = 23
# Rate a ring session. should pop a web windows pointing the rate session page
st_rate_session = 24
# create account
st_create_account = 25
# try to login with alternate login system
st_alt_login = 26
# pseudo state to leave the state machine
st_end = 27
st_unknown = 28
class EGender(IntEnum): class EGender(IntEnum):
male = 0 male = 0
female = 1 female = 1
@ -2112,7 +2179,7 @@ class CCharacterSummary():
''' '''
self.version = msgin.readUint8('version') self.version = msgin.readUint8('version')
self.Mainland = msgin.readUint32('Mainland') self.Mainland = msgin.readUint32('Mainland')
self.Name = msgin.readUString('Name') self.Name = convertUStringToString(msgin.readUString('Name'))
self.People = msgin.readSint32('People') self.People = msgin.readSint32('People')
self.Location = msgin.readUint32('Location') self.Location = msgin.readUint32('Location')
self.sPropVisualA.read(msgin) self.sPropVisualA.read(msgin)
@ -2171,7 +2238,7 @@ def CodeMsgXml(msgXml, key):
for ele in head: for ele in head:
if ele.attrib['name'] == id: if ele.attrib['name'] == id:
found = True found = True
ret.append([nbBit, i]) ret.append([nbBit, i, id])
break break
i +=1 i +=1
if not found: if not found:
@ -2237,6 +2304,8 @@ class World():
self.UserPrivileges = '' self.UserPrivileges = ''
self.FreeTrial = False self.FreeTrial = False
self.HeadName = HeadName self.HeadName = HeadName
self.CurrentState = TState.st_unknown
self.UseFemaleTitles = False
def CreaterCharacter(self, msgXml): def CreaterCharacter(self, msgXml):
''' '''
@ -2295,8 +2364,8 @@ class World():
msgout = BitStream() msgout = BitStream()
# GenericMsgHeaderMngr.pushNameToStream("CONNECTION:CREATE_CHAR", out)) # GenericMsgHeaderMngr.pushNameToStream("CONNECTION:CREATE_CHAR", out))
ref = CodeMsgXml(msgXml, 'CONNECTION:CREATE_CHAR') ref = CodeMsgXml(msgXml, 'CONNECTION:CREATE_CHAR')
for size, value in ref: for size, value, id in ref:
msgout.internalSerial(value, size) msgout.internalSerial(value, size, typeName=id)
# khanat-opennel-code/code/ryzom/common/src/game_share/msg_client_server.h # void serialBitMemStream(NLMISC::CBitMemStream &f) # khanat-opennel-code/code/ryzom/common/src/game_share/msg_client_server.h # void serialBitMemStream(NLMISC::CBitMemStream &f)
msgout.pushUint8(Slot) msgout.pushUint8(Slot)
msgout.pushUint32(SheetId) msgout.pushUint32(SheetId)
@ -2356,6 +2425,18 @@ class World():
#msgout = CMessage("CREATE_CHAR") #msgout = CMessage("CREATE_CHAR")
#msgout.serial(uid, bms) #msgout.serial(uid, bms)
def SelectChar(self, msgXml, PlayerSelectedSlot):
'''
khanat-opennel-code/code/ryzom/client/src/far_tp.cpp # void CFarTP::selectCharAndEnter()
'''
msgout = BitStream()
ref = CodeMsgXml(msgXml, 'CONNECTION:SELECT_CHAR')
for size, value, id in ref:
msgout.internalSerial(value, size, typeName=id)
msgout.pushUint8(PlayerSelectedSlot)
return msgout
class CPersistentDataRecord: class CPersistentDataRecord:
def __init__(self, log): def __init__(self, log):
self.log = log self.log = log
@ -3197,6 +3278,10 @@ class DecodeImpulse():
def impulsePhraseSend(self, msgin): def impulsePhraseSend(self, msgin):
dynId = msgin.readUint32('dynId')
self.log.debug("dynId:%d" % dynId)
StringId = msgin.readUint32('StringId')
self.log.debug("dynId:%d StringId:%s" % (dynId, StringId))
self.log.debug("TODO") self.log.debug("TODO")
def impulseStringResp(self, msgin): def impulseStringResp(self, msgin):
@ -3240,8 +3325,7 @@ class DecodeImpulse():
def impulseGuildUpdatePlayerTitle(self, msgin): def impulseGuildUpdatePlayerTitle(self, msgin):
self.log.debug("TODO") self.log.debug("TODO")
def impulseGuildUseFemaleTitles(self, msgin): def impulseGuildUseFemaleTitles(self, msgin):
self.log.debug("TODO") self.world.UseFemaleTitles = msgin.readBool('UseFemaleTitles')
def impulseCloseTempInv(self, msgin): def impulseCloseTempInv(self, msgin):
self.log.debug("TODO") self.log.debug("TODO")
@ -3514,11 +3598,11 @@ class DecodeImpulse():
return ret return ret
def execute(self, msgin): def execute(self, msgin):
self.log.debug("execute")
head = self.msgXml head = self.msgXml
listpath = [] listpath = []
while True: while True:
nbBit = getPowerOf2(len(head)) nbBit = getPowerOf2(len(head))
# def readSerial(self, nbits, name="", decode=True, typeName='', emulate=False):
id = msgin.readSerial(nbBit, name='MsgXML', typeName='Number', emulate=True) id = msgin.readSerial(nbBit, name='MsgXML', typeName='Number', emulate=True)
ele = head[id] ele = head[id]
@ -3527,6 +3611,7 @@ class DecodeImpulse():
fullname = ':'.join(listpath) fullname = ':'.join(listpath)
id = msgin.readSerial(nbBit, name='MsgXML', typeName='XML <' + name + '>') id = msgin.readSerial(nbBit, name='MsgXML', typeName='XML <' + name + '>')
self.log.debug(fullname)
if fullname in self.GenericMsgHeaderMngr: if fullname in self.GenericMsgHeaderMngr:
self.log.debug("Found : %s" % fullname) self.log.debug("Found : %s" % fullname)
self.GenericMsgHeaderMngr[fullname](msgin) self.GenericMsgHeaderMngr[fullname](msgin)
@ -3688,7 +3773,7 @@ class CActionGeneric(CAction):
decodeImpulse.execute(self._Message) decodeImpulse.execute(self._Message)
def __str__(self): def __str__(self):
return "CActionGeneric" + super().__str__() + "[" + self._Message.showAllData() + ']' return "CActionGeneric" + super().__str__() + "[read:" + self._Message.showAllData() + '/write:' + self._Message.showAllDataWrite() + ']'
def size(self): def size(self):
size = super().size() size = super().size()
@ -3762,7 +3847,7 @@ class CActionGenericMultiPart(CAction):
decodeImpulse.GenericMultiPartTemp.setGenericMultiPartTemp(self.Number, self.Part, self.NbBlock, self.PartCont, decodeImpulse) decodeImpulse.GenericMultiPartTemp.setGenericMultiPartTemp(self.Number, self.Part, self.NbBlock, self.PartCont, decodeImpulse)
def __str__(self): def __str__(self):
return "CActionGenericMultiPart" + super().__str__() + "[" + str(self.Number) + ',' + str(self.Part) + ',' + str(self.NbBlock) + ',' + self.PartCont.showAllData() + ']' return "CActionGenericMultiPart" + super().__str__() + "[" + str(self.Number) + ',' + str(self.Part) + ',' + str(self.NbBlock) + ',read:' + self.PartCont.showAllData() + ',write:' + self.PartCont.showAllDataWrite() + ']'
def size(self): def size(self):
size = super().size() size = super().size()
@ -3879,7 +3964,7 @@ class CActionBlock:
self.Cycle = 0 self.Cycle = 0
self.FirstPacket = 0 self.FirstPacket = 0
self.Actions = [] self.Actions = []
self.Sucess = True self.Success = True
def serial(self, msgout, actionFactory): def serial(self, msgout, actionFactory):
msgout.pushUint32(self.Cycle) msgout.pushUint32(self.Cycle)
@ -3908,6 +3993,8 @@ class CActionBlock:
def push_back(self, action): def push_back(self, action):
self.Actions.append(action) self.Actions.append(action)
def __str__(self):
return "CActionBlock [Cycle:" + str(self.Cycle) + ', FirstPacket:' + str(self.FirstPacket) + ', Data:' + ', '.join([ str(x) for x in self.Actions]) + "]"
class CImpulseDecoder: class CImpulseDecoder:
@ -4040,6 +4127,7 @@ class ClientNetworkConnection:
self._LastSendTime = 0 self._LastSendTime = 0
self._ImpulseMultiPartNumber = 0 self._ImpulseMultiPartNumber = 0
self.clientTick = 0 self.clientTick = 0
self.stepAction = 0
def signal_exit(self, sig, frame): def signal_exit(self, sig, frame):
self.log.warning("Receive signal to quit program") self.log.warning("Receive signal to quit program")
@ -4307,8 +4395,8 @@ class ClientNetworkConnection:
self.log.debug("Message not read (%d) %s" % (msgin.needRead(), msgin.showLastData() )) self.log.debug("Message not read (%d) %s" % (msgin.needRead(), msgin.showLastData() ))
# remove all old actions that are acked # remove all old actions that are acked
while self._Actions and self._Actions[0].FirstPacket != 0 and self._Actions[0].FirstPacket : while self._Actions and self._Actions[0].FirstPacket != 0 and self._Actions[0].FirstPacket < self._LastReceivedAck:
self.log.debug("remove old action") self.log.debug("remove old action [%d/%d] : %s" % (self._Actions[0].FirstPacket, self._LastReceivedAck, self._Actions[0]))
self._Actions.pop(0) self._Actions.pop(0)
self._CurrentServerTick = self._CurrentReceivedNumber * 2 + self._Synchronize self._CurrentServerTick = self._CurrentReceivedNumber * 2 + self._Synchronize
@ -4657,6 +4745,7 @@ class ClientNetworkConnection:
cycle = self._CurrentServerTick cycle = self._CurrentServerTick
bitSize = 32*8 # block size is 32 (cycle) + 8 (number of actions bitSize = 32*8 # block size is 32 (cycle) + 8 (number of actions
if len(self._Actions) == 0 or self._Actions[-1].Cycle != 0: if len(self._Actions) == 0 or self._Actions[-1].Cycle != 0:
self.log.debug("No Action")
pass pass
else: else:
block = self._Actions[-1] block = self._Actions[-1]
@ -4682,14 +4771,24 @@ class ClientNetworkConnection:
# cmd = self.world.Commands.pop(0) # cmd = self.world.Commands.pop(0)
def analyze(self): def analyze(self):
if self.world.CShardNames != []: if self.world.CurrentState == TState.st_connect:
if self.world.CharacterSummaries != [] and self.clientTick > 5: if self.world.CShardNames != []:
if self.world.CharacterSummaries[0].People == TPeople.Unknown: if self.stepAction == 0 and self.world.CharacterSummaries != [] and self.clientTick > 0:
bms = self.world.CreaterCharacter(self.msgXml) if self.world.CharacterSummaries[0].People == TPeople.Unknown:
self.push(bms) bms = self.world.CreaterCharacter(self.msgXml)
self.push(bms)
self.stepAction = 1
else:
self.stepAction = 1
elif self.stepAction == 1 and self.world.CharacterSummaries != []:
if self.world.CharacterSummaries[0].People != TPeople.Unknown:
self.log.info("Account defined %s" % self.world.CharacterSummaries[0].Name)
bms = self.world.SelectChar(self.msgXml, 0)
self.push(bms)
self.stepAction = 2
def EmulateFirst(self, msgRawXml, databaseRawXml): def EmulateFirst(self, msgRawXml, databaseRawXml):
self.world.CurrentState = TState.st_start
self.msgXml = ET.fromstring(msgRawXml) self.msgXml = ET.fromstring(msgRawXml)
#ET.dump(msgXml) #ET.dump(msgXml)
self.databaseXml = ET.fromstring(databaseRawXml) self.databaseXml = ET.fromstring(databaseRawXml)
@ -4701,16 +4800,16 @@ class ClientNetworkConnection:
self.decodeImpulse.loadMsg(self.msgXml) self.decodeImpulse.loadMsg(self.msgXml)
self.decodeImpulse.loadDatabase(self.databaseXml) self.decodeImpulse.loadDatabase(self.databaseXml)
#CodeMsgXml(self.msgXml, 'CONNECTION:CREATE_CHAR')
self.connect() self.connect()
self.log.info("Client Login") self.log.info("Client Login")
self.sendSystemLogin() self.sendSystemLogin()
self.world.CurrentState = TState.st_connect
self.log.info("Receive Message") self.log.info("Receive Message")
self.clientTick = 0 self.clientTick = 0
for _ in range(0, 50): for _ in range(0, 50):
#while True: #while True:
self.log.debug("%s [%s: %d] %s" % ("*" * 40, "Loop", self.clientTick,"*" * 40)) self.log.debug("%s [%s: %d / %d] %s" % ("*" * 40, "Loop", self.clientTick, self.stepAction, "*" * 40))
self.update() self.update()
self.analyze() self.analyze()
self.send() self.send()