mirror of
https://port.numenaute.org/aleajactaest/clientbot.git
synced 2024-11-28 10:26:13 +00:00
adding select profile
This commit is contained in:
parent
2e521c0267
commit
733000a09c
1 changed files with 123 additions and 24 deletions
139
client.py
139
client.py
|
@ -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.CurrentState == TState.st_connect:
|
||||||
if self.world.CShardNames != []:
|
if self.world.CShardNames != []:
|
||||||
if self.world.CharacterSummaries != [] and self.clientTick > 5:
|
if self.stepAction == 0 and self.world.CharacterSummaries != [] and self.clientTick > 0:
|
||||||
if self.world.CharacterSummaries[0].People == TPeople.Unknown:
|
if self.world.CharacterSummaries[0].People == TPeople.Unknown:
|
||||||
bms = self.world.CreaterCharacter(self.msgXml)
|
bms = self.world.CreaterCharacter(self.msgXml)
|
||||||
self.push(bms)
|
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()
|
||||||
|
|
Loading…
Reference in a new issue