clientbot/tools/Impulse.py

894 lines
39 KiB
Python

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# module Impulse
#
# Copyright (C) 2019 AleaJactaEst
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
from tools import getPowerOf2
from tools import BitStream
from tools import Enum
# from tools import Enum
ItemPropStr = [
"SHEET", # 32
"QUALITY", # 10
"QUANTITY", # 10
"USER_COLOR", # 3
"CREATE_TIME", # 32
"SERIAL", # 32
"LOCKED", # 10
"WEIGHT", # 16
"NAMEID", # 32
"ENCHANT", # 10
"RM_CLASS_TYPE", # 3
"RM_FABER_STAT_TYPE", # 5
"PRICE", # 32
"RESALE_FLAG", # 2
"PREREQUISIT_VALID", # 1
"WORNED" # 1
]
DataBitSize = [32, 10, 10, 3, 32, 32, 10, 16, 32, 10, 3, 5, 32, 2, 1, 1]
LOGGER='Impulse'
class ImpulseNoElement(Exception):
pass
class ImpulseBase:
def __init__(self):
self.name = ""
self.id = ""
self.param = {}
#self.Reference = []
def set_name(self, name):
self.name = name.replace(':', '_')
def get_name(self):
return self.name
def add_reference(self, ref):
#self.Reference.append(ref)
self.param.setdefault('Reference', [])
self.param['Reference'].append(ref)
def get_reference(self):
return self.param['Reference']
def get_parameter(self):
return self.param
def add_parameter(self, key, value):
self.param.setdefault(key, [])
self.param[key].append(value)
def add_value(self, key, value):
self.param.setdefault(key, "")
self.param[key] = value
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).error("Not define")
def readBool(self, msgin, id):
value = msgin.readBool(id)
self.param.setdefault(id, value)
return value
def readUint8(self, msgin, id):
value = msgin.readUint8(id)
self.param.setdefault(id, value)
return value
def readSint8(self, msgin, id):
value = msgin.readSint8(id)
self.param.setdefault(id, value)
return value
def readUint16(self, msgin, id):
value = msgin.readUint16(id)
self.param.setdefault(id, value)
return value
def readSint16(self, msgin, id):
value = msgin.readSint16(id)
self.param.setdefault(id, value)
return value
def readUint32(self, msgin, id):
value = msgin.readUint32(id)
self.param.setdefault(id, value)
return value
def readSint32(self, msgin, id):
value = msgin.readSint32(id)
self.param.setdefault(id, value)
return value
def readUint64(self, msgin, id):
value = msgin.readUint64(id)
self.param.setdefault(id, value)
return value
def readSint64(self, msgin, id):
value = msgin.readSint64(id)
self.param.setdefault(id, value)
return value
def readSerial(self, msgin, nbBits, id):
if nbBits == 1:
value = msgin.readSerial(nbBits, id, typeName="bool/1 bit")
else:
value = msgin.readSerial(nbBits, id, typeName="%d bits" % nbBits)
self.param.setdefault(id, value)
return value
def readSerialEnum(self, msgin, nbBits, id, typeEnum):
if nbBits == 1:
value = msgin.readSerial(nbBits, id, typeName="bool/1 bit", decode=False)
else:
value = msgin.readSerial(nbBits, id, typeName="%d bits" % nbBits, decode=False)
nameValue = Enum.GetNameIntEnum(typeEnum, value)
if nbBits == 1:
value = msgin.readSerial(nbBits, id, typeName="bool/1 bit", commentValue=" " + typeEnum.__name__ + "." + nameValue)
else:
value = msgin.readSerial(nbBits, id, typeName="%d bits" % nbBits, commentValue=" " + typeEnum.__name__ + "." + nameValue)
self.param.setdefault(id, value)
self.param.setdefault(id + "_name", typeEnum.__name__ + "." + nameValue)
return value
def readUString(self, msgin, id):
value = msgin.readUString(id)
self.param.setdefault(id, value)
return value
def readUtf8String(self, msgin, id):
value = msgin.readUtf8String(id)
self.param.setdefault(id, value)
return value
def readString(self, msgin, id):
value = msgin.readString(id)
self.param.setdefault(id, value)
return value
def readFloat(self, msgin, id):
value = msgin.readFloat(id)
self.param.setdefault(id, value)
return value
def readVersion(self, msgin, id):
value = msgin.readUint8(id)
if value == 255: #0xFF: # 0xFF
value = msgin.readUint32(id + '_extended')
self.param.setdefault(id, value)
return value
def readDatabases(self, world, decodeDatabase):
return None
class ImpulseBotchatSetFilters(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint32(msgin, 'qualityMin')
self.readUint32(msgin, 'qualityMax')
self.readUint32(msgin, 'priceMin')
self.readUint32(msgin, 'priceMax')
self.readUint8(msgin, 'classMin')
self.readUint8(msgin, 'classMax')
self.readUint8(msgin, 'itemPart')
self.readUint8(msgin, 'itemType')
class ImpulseConnectionAskName(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUString(msgin, 'Name')
self.readUint32(msgin, 'HomeSessionId')
class ImpulseConnectionCreateChar(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint8(msgin, 'Slot')
self.readUint32(msgin, 'SheetId')
self.readUint32(msgin, 'CSessionId')
self.readUString(msgin, 'name')
self.readUint8(msgin, 'People')
self.readUint8(msgin, 'Sex')
self.readUint8(msgin, 'NbPointFighter')
self.readUint8(msgin, 'NbPointCaster')
self.readUint8(msgin, 'NbPointCrafter')
self.readUint8(msgin, 'NbPointHarvester')
self.readSint32(msgin, 'StartPoint')
self.readSint8(msgin, 'HairType')
self.readSint8(msgin, 'HairColor')
self.readSint8(msgin, 'GabaritHeight')
self.readSint8(msgin, 'GabaritTorsoWidth')
self.readSint8(msgin, 'GabaritArmsWidth')
self.readSint8(msgin, 'GabaritLegsWidth')
self.readSint8(msgin, 'GabaritBreastSize')
self.readSint8(msgin, 'MorphTarget1')
self.readSint8(msgin, 'MorphTarget2')
self.readSint8(msgin, 'MorphTarget3')
self.readSint8(msgin, 'MorphTarget4')
self.readSint8(msgin, 'MorphTarget5')
self.readSint8(msgin, 'MorphTarget6')
self.readSint8(msgin, 'MorphTarget7')
self.readSint8(msgin, 'MorphTarget8')
self.readSint8(msgin, 'EyesColor')
self.readSint8(msgin, 'Tattoo')
self.readSint8(msgin, 'JacketColor')
self.readSint8(msgin, 'TrousersColor')
self.readSint8(msgin, 'HatColor')
self.readSint8(msgin, 'ArmsColor')
self.readSint8(msgin, 'HandsColor')
self.readSint8(msgin, 'FeetColor')
class ImpulseConnectionReady(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readString(msgin, 'LanguageCode')
class ImpulseConnectionSelectChar(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint8(msgin, 'SelectCharMsg')
class ImpulseConnectionUserChar(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readSint32(msgin, 'X')
self.readSint32(msgin, 'Y')
self.readSint32(msgin, 'Z')
self.readFloat(msgin, 'Heading')
self.readSerial(msgin, 3, 'season')
self.readSerial(msgin, 3, 'userRole')
self.readUint32(msgin, 'highestMainlandSessionId')
self.readUint32(msgin, 'firstConnectedTime')
self.readUint32(msgin, 'playedTime')
class ImpulseConnectionShardId(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint32(msgin, 'shardId')
self.readString(msgin, 'webHost')
class ImpulseConnectionValidName(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint8(msgin, 'valide')
class ImpulseDebugPing(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint32(msgin, 'localTime')
class ImpulseGuildFemaleTitles(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readSerial(msgin, 1, 'UseFemaleTitles')
class ImpulseNpcIconSetDesc(ImpulseBase):
def __init__(self):
super().__init__()
self.data = BitStream.BitStream()
def read(self, name, msgin, world, databaseXml):
'''
khanat-opennel-code/code/ryzom/server/src/entities_game_service/player_manager/character.cpp:20976 void CCharacter::sendNpcMissionGiverIconDesc( const std::vector<uint32>& npcKeys )
'''
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
nb8 = self.readUint8(msgin, 'nb8')
self.data.pushUint8(nb8)
for i in range(0, nb8):
npcAlias = self.readUint32(msgin, 'NpcIconSetDesc_%d_npcAlias' % nb8)
self.data.pushUint32(npcAlias)
state = self.readUint32(msgin, 'NpcIconSetDesc_%d_state' % nb8)
self.data.pushUint32(state)
def readDatabases(self, world, decodeDatabase):
return decodeDatabase.execute(self.data, world)
class ImpulsePhraseDownload(ImpulseBase):
def __init__(self):
super().__init__()
def readSerialPhrase(self, msgin, id):
self.readUtf8String(msgin, id)
size = self.readSint32(msgin, id + '_len')
for i in range(0, size):
self.readUint16(msgin, '%s_compBricks_%d' % (id, i))
def readSerialPhrases(self, msgin, id):
"""
khanat-opennel-code/code/ryzom/server/src/entities_game_service/player_manager/character.cpp:13586 void CCharacter::sendPhrasesToClient()
khanat-opennel-code/code/nel/include/nel/misc/stream.h:1089 void serialVector(T &cont)
khanat-opennel-code/code/ryzom/common/src/game_share/sphrase_com.cpp:57 void CSPhraseCom::serial(NLMISC::IStream &impulse)
"""
size = self.readSint32(msgin, id + '_len')
for i in range(0, size):
#self.param.setdefault('%d:Phrase' % i, msgin.readUtf8String('%d:Phrase:Name' % i))
#self.param.setdefault('%d:Phrase' % i, msgin.readString('%d:Phrase' % i))
self.readSerialPhrase(msgin, '%s_%d_Phrase' % (id, i))
self.readUint16(msgin, '%s_%d_KnownSlot' % (id, i))
self.readUint32(msgin, '%s_%d_PhraseSheetId' % (id, i))
#self.param.setdefault('%d:PhraseSheetId:Type' % i, msgin.readUint32('%d:PhraseSheetId:IdInfos:Type' % i))
#self.param.setdefault('%d:PhraseSheetId:Type' % i, msgin.readUint32('%d:PhraseSheetId:IdInfos:Id' % i))
def readSerialMemorizedPhrases(self, msgin, id):
size = self.readSint32(msgin, id + '_len')
for i in range(0, size):
self.readUint8(msgin, '%s_%d_MemoryLineId' % (id, i))
self.readUint8(msgin, '%s_%d_MemorySlotId' % (id, i))
self.readUint16(msgin, '%s_%d_PhraseId' % (id, i))
# tmp = {}
# for i in range(0, size):
# data = {}
# data.setdefault('MemoryLineId', msgin.readUint8('%d:MemoryLineId' % i))
# data.setdefault('MemorySlotId', msgin.readUint8('%d:MemorySlotId' % i))
# data.setdefault('PhraseId', msgin.readUint16('%d:PhraseId' %i))
# tmp.setdefault('MemorizedPhrase_%d' % i, data)
# self.param.setdefault("MemorizedPhrase", tmp)
def read(self, name, msgin, world, databaseXml):
"""
khanat-opennel-code/code/ryzom/server/src/entities_game_service/player_manager/character.cpp:13586 void CCharacter::sendPhrasesToClient()
"""
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
# return
#self.param.setdefault(id + 'phrases', msgin.readString('phrases'))
#self.param.setdefault(id + 'memorizedPhrases', msgin.readString('memorizedPhrases'))
self.readSerialPhrases(msgin, 'KnownPhrases')
self.readSerialMemorizedPhrases(msgin, 'MemorizedPhrases')
#logging.getLogger(LOGGER).error("[Client -> Server] msg:%s" % msgin.showAllData())
#raise ValueError
class ImpulsePosition(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
# khanat-opennel-code/code/ryzom/server/src/gpm_service/client_messages.cpp void cbClientPosition( CMessage& msgin, const string &serviceName, NLNET::TServiceId serviceId )
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readBool(msgin, '')
self.readSint32(msgin, 'X')
self.readSint32(msgin, 'Y')
self.readSint32(msgin, 'Z')
self.readFloat(msgin, 'Heading')
class ImpulseSringDynString(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint32(msgin, 'phraseId')
class ImpulseSringManagerReloadCache(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint32(msgin, 'timestamp')
class ImpulseSringManagerPhraseSend(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
id = 'SringManagerPhrase'
#self.param.setdefault('%s_seqNum' %(id), msgin.readUint32('%s_seqNum' % (id)))
#self.param.setdefault('%s_id'%(id), msgin.readUint32('%s_id'%(id)))
self.readUint32(msgin, '%s_dynId' % id)
self.readUint32(msgin, '%s_StringId' % id)
i = 0
while msgin.needRead() >= 32:
self.readUint32(msgin, '%s_StringId_%d' % (id, i))
i += 1
class ImpulseSringManagerStringResp(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint32(msgin, 'stringId')
self.readUtf8String(msgin, 'strUtf8')
class ImpulseSringManagerStringRq(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint32(msgin, 'stringId')
class impulseGuildUpdatePlayerTitle(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readBool(msgin, 'bUnblock')
id = "vTitle"
size = self.readSint32(msgin, '%s_len' % id)
for i in range(0, size):
self.readUint16(msgin, '%s_%d' % (id, i))
class impulseDeathRespawnPoint(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
id = "CRespawnPointsMsg"
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readBool(msgin, '%s_NeedToReset' % id)
size = self.readSint32(msgin, '%s_len' % id)
for i in range(0, size):
self.readSint32(msgin, '%s_%d_x' % (id, i))
self.readSint32(msgin, '%s_%d_y' % (id, i))
class impulseEncyclopediaInit(ImpulseBase):
def __init__(self):
super().__init__()
def read_thema(self, id, msgin):
size_thema = self.readSint32(msgin, '%s_thema_len' % (id))
for ii in range(0, size_thema):
self.readUint32(msgin, '%s_thema_%d_Name' % (id, ii))
StateNbTask = self.readUint8(msgin, '%s_thema_%d_StateNbTask' % (id, ii))
State = StateNbTask & 0x3;
NbTask = StateNbTask >> 2 ;
if State == 2:
self.readUint32(msgin, '%s_thema_%d_RewardText' % (id, ii))
self.readUint32(msgin, '%s_thema_%d_RewardSheet' % (id, ii))
for iii in range(0, NbTask):
self.readUint32(msgin, '%s_thema_%d_Task_%d_Name' % (id, ii, iii))
self.readUint32(msgin, '%s_thema_%d_Task_%d_NPCName' % (id, ii, iii))
self.readUint16(msgin, '%s_thema_%d_RiteTaskStatePacked' % (id, ii))
def read_album(self, id, msgin):
self.readUint32(msgin, '%s_Album_Name' % (id))
self.readUint32(msgin, '%s_Album_RewardBrick' % (id))
self.readUint8(msgin, '%s_Album_State' % (id))
self.read_thema(id, msgin)
def read(self, name, msgin, world, databaseXml):
id = "EncyclopediaInit"
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
type = self.readSint32(msgin, '%s_Type' % id)
if type == 0: # UpdateInit
id += '_AllAlbums'
size = self.readSint32(msgin, '%s_len' % id)
for i in range(0, size):
self.read_album(id, msgin)
elif type == 1: # UpdateAlbum
id += '_UpdateAlbum'
self.read_album(id, msgin)
else: # type == 2: # UpdateThema
id += '_UpdateThema'
self.readUint32(msgin, '%s_AlbumName' % (id))
self.read_thema(id, msgin)
class impulseInitInventory(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
# khanat-opennel-code/code/ryzom/client/src/net_manager.cpp void updateInventoryFromStream (NLMISC::CBitMemStream &impulse, const CInventoryCategoryTemplate *templ, bool notifyItemSheetChanges)
# khanat-opennel-code/code/ryzom/server/src/entities_game_service/inventory_updater.cpp void CInventoryUpdaterForCharacter::sendAllUpdates( const NLMISC::CEntityId& destEntityId )
id = "InitInventory"
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
#self.readSint32(msgin, '%s_pos' % id)
self.readUint32(msgin, '%s_serverTick' % id)
for invId in range(0, Enum.TInventoryId.NbInventoryIds):
hasContent = self.readBool(msgin, '%s_%d_hasContent' % (id, invId))
if hasContent == False:
continue;
nbChanges = self.readSerial(msgin, 3, '%s_%d_nbChanges' % (id, invId)) # INVENTORIES::LowNumberBits = 3
if nbChanges == 7: # == INVENTORIES::LowNumberBound = 7
nbChanges = self.readSerial(msgin, 32, '%s_%d_nbChanges_next' % (id, invId)) # INVENTORIES::LowNumberBits = 3
for itu in range(0, nbChanges):
iuInfoVersion = self.readSerial(msgin, 1, '%s_%d_%d_itu_iuInfoVersion' % (id, invId, itu))
if iuInfoVersion == 1:
_ = self.readSerial(msgin, 10, '%s_%d_%d_itu_iuInfoVersion_slotIndex' % (id, invId, itu)) # ICInventoryCategoryTemplate::SlotBitSize = 10
#self.param.setdefault('%s_%d_infoVersion' % (id, i), msgin.readUint8('%s_%d_infoVersion' % (id, i)))
else:
iuAll = self.readSerial(msgin, 1, '%s_%d_%d_iuAll' % (id, invId, itu))
if iuAll == 1:
_ = self.readSerial(msgin, 10, '%s_%d_%d_iuAll_slotIndex' % (id, invId, itu)) # ICInventoryCategoryTemplate::SlotBitSize = 10
for ii in range(0, 6):
#ItemSlot = msgin.readSerial( DataBitSize[ii], '%s_%d_ItemSlot_%s' % (id, i, ItemPropStr[ii]))
self.readSerial(msgin, DataBitSize[ii], '%s_%d_%d_iuAll_ItemProp_%s' % (id, invId, itu, ItemPropStr[ii]))
for ii in range(6, Enum.TItemPropId.NbItemPropId):
b = self.readBool(msgin, '%s_%d_%d_iuAll_ItemProp_%s_compressed' %(id, invId, itu, ItemPropStr[ii]))
if b:
pass
else:
#ItemProp = msgin.readSerial(DataBitSize(ii), '%s_%d_ItemSlot_%d_ItemProp' %(id , i, ii))
self.readSerial(msgin, DataBitSize[ii], '%s_%d_%d_iuAll_ItemProp_%s_ItemProp' %(id, invId, itu, ItemPropStr[ii]))
else:
iuOneProp = self.readSerial(msgin, 1, '%s_%d_%d_iuOneProp' % (id, invId, itu))
if iuOneProp == 1:
# bms.serial( _SlotIndex, CInventoryCategoryTemplate::SlotBitSize ); 10
_ = self.readSerial(msgin, 10, '%s_%d_%d_iuOneProp_SlotIndex' %(id, invId, itu))
ItemPropIdUint32 = self.readSerial(msgin, 4, '%s_%d_%d_iuOneProp_ItemPropId' %(id, invId, itu))
_ = self.readSerial(msgin, DataBitSize[ItemPropIdUint32], '%s_%d_%d_iuOneProp_ItemPropValue' %(id, invId, itu))
# bms.serial( _OneProp );
# bms.serial((uint32&)ItemPropIdUint32, NbBitsForItemPropId);
# bms.serial((uint32&)ItemPropValue, CItemSlot::DataBitSize[ItemPropId]);
else: # iuReset
_ = self.readSerial(msgin, 10, '%s_%d_%d_iuReset_SlotIndex' %(id, invId, itu))
#self.param.setdefault('%s_%d_y' % (id, i), msgin.readSint32('%s_%d_y' % (id, i)))
class ImpulseConnectionUserChars(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
# khanat-opennel-code/code/ryzom/client/src/net_manager.cpp void impulseUserChars(NLMISC::CBitMemStream &impulse)
# khanat-opennel-code/code/ryzom/server/src/entities_game_service/entity_manager/entity_callbacks.cpp void sendCharactersSummary( CPlayer *player, bool AllAutorized, uint32 bitfieldOwnerOfActiveAnimSession, uint32 bitfieldOwnerOfEditSession )
id = "ConnectionUserChars"
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
_ = self.readUint8(msgin, '%s_ServerPeopleActive' % id)
_ = self.readUint8(msgin, '%s_ServerCareerActive' % id)
CharacterSummaries_Len = self.readUint32(msgin, '%s_CharacterSummaries_Len' % id)
for i in range(0, CharacterSummaries_Len):
self.readVersion(msgin, "%s_CharacterSummaries_%d_Version" % (id, i))
self.readUint32(msgin, '%s_CharacterSummaries_%d_Mainland' % (id, i))
self.readUString(msgin, '%s_CharacterSummaries_%d_Name' % (id, i))
self.readSint32(msgin, '%s_CharacterSummaries_%d_People' % (id, i))
self.readUint32(msgin, '%s_CharacterSummaries_%d_Location' % (id, i))
self.readUint64(msgin, '%s_CharacterSummaries_%d_VisualPropA' % (id, i))
self.readUint64(msgin, '%s_CharacterSummaries_%d_VisualPropB' % (id, i))
self.readUint64(msgin, '%s_CharacterSummaries_%d_VisualPropC' % (id, i))
self.readUint32(msgin, '%s_CharacterSummaries_%d_SheetId' % (id, i))
self.readSint32(msgin, '%s_CharacterSummaries_%d_Title' % (id, i))
self.readUint8(msgin, '%s_CharacterSummaries_%d_CharacterSlot' % (id, i))
self.readBool(msgin, '%s_CharacterSummaries_%d_InRingSession' % (id, i))
self.readBool(msgin, '%s_CharacterSummaries_%d_HasEditSession' % (id, i))
self.readBool(msgin, '%s_CharacterSummaries_%d_InNewbieland' % (id, i))
shardNames_Len = self.readUint32(msgin, '%s_ShardNames_Len' % id)
for i in range(0, shardNames_Len):
self.readString(msgin, '%s_ShardNames_%d' % (id, i))
_ = self.readString(msgin, '%s_Privileges' % id)
self.readBool(msgin, '%s_FreeTrial' % (id))
Mainlands_Len = self.readUint32(msgin, '%s_Mainlands_Len' % id)
for i in range(0, Mainlands_Len):
self.readUint32(msgin, '%s_Mainlands_%d_id' % (id, i))
self.readUString(msgin, '%s_Mainlands_%d_Name' % (id, i))
self.readUString(msgin, '%s_Mainlands_%d_Description' % (id, i))
self.readString(msgin, '%s_Mainlands_%d_LanguageCode' % (id, i))
self.readBool(msgin, '%s_Mainlands_%d_Online' % (id, i))
class impulseDatabaseInitPlayer(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
# khanat-opennel-code/code/ryzom/client/src/net_manager.cpp void impulseDatabaseInitPlayer(NLMISC::CBitMemStream &impulse)
# khanat-opennel-code/code/ryzom/server/src/simulation_service/simulated_editor.cpp void impulseDatabaseInitPlayer(NLMISC::CBitMemStream &impulse)
id = "DatabaseInitPlayer"
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint32(msgin, '%s_serverTick' % id)
propertyCount = self.readUint16(msgin, '%s_propertyCount' % id)
# for i in range(0, propertyCount):
# _ = self.readUint32(msgin, '%s_property' % id)
for i in range(0, propertyCount):
logging.getLogger(LOGGER).debug("read i:%d" % i)
logging.getLogger(LOGGER).debug("#" * 80)
databaseXml.execute(msgin, world)
#raise "TODO"
if msgin.needRead() > 5:
logging.getLogger(LOGGER).debug(msgin.showAllData())
logging.getLogger(LOGGER).debug(msgin.showAllData())
#raise "TODO"
class ImpulseConnectionDeleteChar(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
id = "ConnectionDeleteChar"
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
self.readUint8(msgin, '%s_slot' % id)
class impulseTeamContactInit(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
id = "TeamContactInit"
logging.getLogger(LOGGER).debug("read")
self.name = name.replace(':', '_')
friend_string_ids_len = self.readUint32(msgin, '%s_friend_string_ids_len' % id)
for i in range(0, friend_string_ids_len):
_ = self.readUint32(msgin, '%s_friend_string_ids_%d' % (id, i))
nb_state = self.readUint32(msgin, '%s_nb_state' % id)
for i in range(0, nb_state):
_ = self.readUint32(msgin, '%s_friend_online_status_%d' % (id, i))
ignore_list_len = self.readUint32(msgin, '%s_ignore_list_len' % id)
for i in range(0, ignore_list_len):
_ = self.readUString(msgin, '%s_ignore_list_%d' % (id, i))
class impulseNpcIconGetDesc(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
# khanat-opennel-code/code/ryzom/server/src/frontend_service/id_impulsions.cpp void cbImpulsionGetNpcIconDesc( CEntityId& sender, CBitMemStream &bms, TGameCycle gamecycle, uint16 serviceId )
id = "ClientNpcIcon"
logging.getLogger(LOGGER).debug("read %s" % id)
self.name = name.replace(':', '_')
nb8 = self.readUint8(msgin, '%s_nb8' % id)
for i in range(0, nb8):
_ = self.readUint32(msgin, '%s_NPCIconCacheKey_%d' % (id, i))
class impulseUserBars(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
# khanat-opennel-code/code/ryzom/server/src/entities_game_service/player_manager/character.cpp void CCharacter::barUpdate()
id = "UserBars"
logging.getLogger(LOGGER).debug("read %s" % id)
self.name = name.replace(':', '_')
_ = self.readUint8(msgin, '%s_barsenttoplayermsgnumber' % id)
_ = self.readSint32(msgin, '%s_oldchascore1barsenttoplayer' % id)
_ = self.readSint32(msgin, '%s_oldchascore2barsenttoplayer' % id)
_ = self.readSint32(msgin, '%s_oldchascore3barsenttoplayer' % id)
_ = self.readSint32(msgin, '%s_oldchascore4barsenttoplayer' % id)
class impulseDbGroupInitBank(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
# khanat/khanat-opennel-code/code/ryzom/client/src/net_manager.cpp void impulseDatabaseInitBank(NLMISC::CBitMemStream &impulse)
id = "DbGroupInitBank"
logging.getLogger(LOGGER).debug("read %s" % id)
self.name = name.replace(':', '_')
_ = self.readUint32(msgin, '%s_serverTick' % id)
bank = self.readSerialEnum(msgin, Enum.TCDBBank.NB_BITS_FOR_CDBBANK, '%s_bank' % id, Enum.TCDBBank)
propertyCount = self.readUint16(msgin, '%s_propertyCount' % id)
for i in range(0, propertyCount):
raise "TODO"
class impulseDatabaseUpdatePlayer(ImpulseBase):
def __init__(self):
super().__init__()
def read(self, name, msgin, world, databaseXml):
# khanat/khanat-opennel-code/code/ryzom/client/src/net_manager.cpp void impulseDatabaseUpdatePlayer(NLMISC::CBitMemStream &impulse)
id = "DbUpdPlr"
logging.getLogger(LOGGER).debug("read %s" % id)
self.name = name.replace(':', '_')
_ = self.readUint32(msgin, '%s_serverTick' % id)
propertyCount = self.readUint16(msgin, '%s_propertyCount' % id)
for i in range(0, propertyCount):
databaseXml.execute(msgin, world)
#raise "TODO"
if msgin.needRead() > 5:
logging.getLogger(LOGGER).debug(msgin.showAllData())
#raise "TODO"
#raise "TODO"
class DecodeImpulseSimple:
def __init__(self):
'''
khanat-opennel-code/code/ryzom/client/src/net_manager.cpp # void initializeNetwork()
'''
self.msgXml = None
self.databaseXml = None
self.GenericMsgHeaderMngr = {}
self.initializeNetwork()
def initializeNetwork(self):
# Send by client
self.GenericMsgHeaderMngr.setdefault( "BOTCHAT:SET_FILTERS", ImpulseBotchatSetFilters )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:ASK_NAME", ImpulseConnectionAskName )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:CREATE_CHAR", ImpulseConnectionCreateChar )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:DELETE_CHAR", ImpulseConnectionDeleteChar )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:READY", ImpulseConnectionReady )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:SELECT_CHAR", ImpulseConnectionSelectChar )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:SHARD_ID", ImpulseConnectionShardId )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:USER_CHAR", ImpulseConnectionUserChar )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:USER_CHARS", ImpulseConnectionUserChars )
self.GenericMsgHeaderMngr.setdefault( "CONNECTION:VALID_NAME", ImpulseConnectionValidName )
self.GenericMsgHeaderMngr.setdefault( "DEBUG:PING", ImpulseDebugPing )
self.GenericMsgHeaderMngr.setdefault( "DEATH:RESPAWN_POINT", impulseDeathRespawnPoint)
self.GenericMsgHeaderMngr.setdefault( "GUILD:UPDATE_PLAYER_TITLE", impulseGuildUpdatePlayerTitle)
self.GenericMsgHeaderMngr.setdefault( "GUILD:USE_FEMALE_TITLES", ImpulseGuildFemaleTitles )
self.GenericMsgHeaderMngr.setdefault( "NPC_ICON:SET_DESC", ImpulseNpcIconSetDesc )
self.GenericMsgHeaderMngr.setdefault( "PHRASE:DOWNLOAD", ImpulsePhraseDownload )
self.GenericMsgHeaderMngr.setdefault( "POSITION", ImpulsePosition )
self.GenericMsgHeaderMngr.setdefault( "STRING:DYN_STRING", ImpulseSringDynString )
self.GenericMsgHeaderMngr.setdefault( "STRING_MANAGER:RELOAD_CACHE", ImpulseSringManagerReloadCache )
self.GenericMsgHeaderMngr.setdefault( "STRING_MANAGER:PHRASE_SEND", ImpulseSringManagerPhraseSend )
self.GenericMsgHeaderMngr.setdefault( "STRING_MANAGER:STRING_RESP", ImpulseSringManagerStringResp )
self.GenericMsgHeaderMngr.setdefault( "STRING_MANAGER:STRING_RQ", ImpulseSringManagerStringRq )
self.GenericMsgHeaderMngr.setdefault( "ENCYCLOPEDIA:INIT", impulseEncyclopediaInit )
self.GenericMsgHeaderMngr.setdefault( "DB_INIT:INV", impulseInitInventory)
self.GenericMsgHeaderMngr.setdefault( "DB_INIT:PLR", impulseDatabaseInitPlayer)
self.GenericMsgHeaderMngr.setdefault( "TEAM:CONTACT_INIT", impulseTeamContactInit)
self.GenericMsgHeaderMngr.setdefault( "NPC_ICON:GET_DESC", impulseNpcIconGetDesc)
self.GenericMsgHeaderMngr.setdefault( "USER:BARS", impulseUserBars)
self.GenericMsgHeaderMngr.setdefault( "DB_GROUP:INIT_BANK", impulseDbGroupInitBank)
self.GenericMsgHeaderMngr.setdefault( "DB_UPD_PLR", impulseDatabaseUpdatePlayer)
def execute(self, msgin, world, references = [], name=""):
'''
khanat-opennel-code/code/ryzom/client/src/net_manager.cpp:3746 void impulseCallBack(NLMISC::CBitMemStream &impulse, sint32 packet, void *arg)
khanat-opennel-code/code/ryzom/common/src/game_share/generic_xml_msg_mngr.cpp:121 void CGenericXmlMsgHeaderManager::execute(CBitMemStream &strm)
khanat-opennel-code/code/ryzom/common/src/game_share/generic_xml_msg_mngr.h:431 CNode *select(NLMISC::CBitMemStream &strm)
uint32 index = 0;
uint NbBits;
strm.serialAndLog2(index, node->NbBits);
'''
logging.getLogger(LOGGER).debug("execute")
head = self.msgXml
listpath = []
while True:
nbBit = getPowerOf2.getPowerOf2(len(head))
#logging.getLogger(LOGGER).error("nbBit : %d " % nbBit)
#for child in head:
# print(child.tag, child.attrib)
try:
id = msgin.readSerial(nbBit, name='MsgXML', typeName='Number', emulate=True)
except BitStream.OverflowError:
raise ImpulseNoElement
if id is None:
raise ImpulseNoElement
try:
ele = head[id]
except IndexError as e:
logging.getLogger(LOGGER).error("Error to decode message: %s" % msgin.showAllData() )
raise e
command = ele.attrib['name']
listpath.append(command)
fullname = ':'.join(listpath)
id = msgin.readSerial(nbBit, name='MsgXML', typeName='XML <' + command + '>')
if fullname in self.GenericMsgHeaderMngr:
logging.getLogger(LOGGER).debug("Found : %s" % fullname)
impulse = self.GenericMsgHeaderMngr[fullname]()
impulse.read(fullname, msgin, world, self.databaseXml)
logging.getLogger(LOGGER).debug("MessageXML decoded: %s" % msgin.showAllData() )
impulse.add_value("command", fullname)
for reference in references:
impulse.add_reference(reference)
impulse.add_value("Message", msgin.extractAllData())
# check we decode all message
nbBitNotRead = msgin.needRead()
if nbBitNotRead == 0:
return impulse
elif nbBitNotRead < 8:
a = msgin.readSerial(nbBitNotRead, decode=False)
if a == 0:
return impulse
logging.getLogger(LOGGER).error("MessageXML not decoded: [%s] %s [size:%d, not read:%d]" % (fullname, msgin.showAllData(), nbBitNotRead, a))
elif nbBitNotRead < 32:
a = msgin.readSerial(nbBitNotRead, decode=False)
if a == 0:
return impulse
logging.getLogger(LOGGER).error("MessageXML not decoded: [%s] %s [size:%d, not read:%d]" % (fullname, msgin.showAllData(), nbBitNotRead, a))
logging.getLogger(LOGGER).error("MessageXML not decoded: [%s] %s [size:%d]" % (fullname, msgin.showAllData(), nbBitNotRead))
return None
else:
#logging.getLogger(LOGGER).debug("Non trouve")
for ele in head:
if ele.attrib['name'] == command:
head = ele
break
if head != ele:
logging.getLogger(LOGGER).error("MessageXML not decoded: [%s] %s" % (fullname, msgin.showAllData() ))
return None
# End While
logging.getLogger(LOGGER).error("MessageXML not decoded: [%s] %s" % (fullname, msgin.showAllData() ))
return None
def loadMsg(self, msgXml):
logging.getLogger(LOGGER).debug("msgXml")
self.msgXml = msgXml
def loadDatabase(self, databaseXml):
self.databaseXml = databaseXml