diff --git a/client.py b/client.py index 0d107b0..6bc9c32 100755 --- a/client.py +++ b/client.py @@ -44,6 +44,8 @@ import xml.etree.ElementTree as ET import hashlib import time import signal +import inspect + INVALID_SLOT = 0xff @@ -53,6 +55,7 @@ class BitStream(): self._read = 0 self._tampon = [] self._groupRead = [] + self._groupWrite = [] def __len__(self): return (self._pos + 7) // 8 @@ -72,13 +75,17 @@ class BitStream(): def getPos(self): return self._pos + def buffer(self): + return self._tampon + def putRead(self, value): if value > self._pos: raise ValueError self._read = value # ------------------------------------ - def internalSerial(self, value, nbits): + def internalSerial(self, value, nbits, decode=True, typeName=''): + p1 = self._pos if nbits == 0: return elif nbits > 32: @@ -86,7 +93,6 @@ class BitStream(): pos = self._pos % 8 if pos == 0: self._tampon.append(0) - # print(">", pos, value) value = c_uint32(value).value if nbits != 32: mask = (1 << nbits) - 1; @@ -95,93 +101,416 @@ class BitStream(): v = value; _FreeBits = 8 - (self._pos % 8) if nbits > _FreeBits: - #print(">A") self._tampon[-1] |= (v >> ( nbits - _FreeBits)) self._pos += _FreeBits - self.internalSerial( v , nbits - _FreeBits) + self.internalSerial( v , nbits - _FreeBits, decode=False) else: - #print(">B") self._tampon[-1] |= (v << ( _FreeBits - nbits)) self._pos += nbits + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+nbits, name, typeName, value)) - def pushBool(self, valeur): - if valeur: + def pushBool(self, value, decode=True): + p1 = self._pos + if value: v = 1 else: v = 0 - self.internalSerial(v, 1) + self.internalSerial(v, 1, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+1, name, 'Bool', value)) - def pushUint32(self, valeur): - self.internalSerial(valeur, 32) + def pushUint32(self, value, decode=True, typeName='Uint32'): + p1 = self._pos + self.internalSerial(value, 32, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+32, name, typeName, value)) - def pushSint32(self, valeur): - self.internalSerial(valeur, 32) + def pushSint32(self, value, decode=True): + p1 = self._pos + self.internalSerial(value, 32, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+32, name, 'Sint32', value)) - def pushUint16(self, valeur): - self.internalSerial(valeur, 16) + def pushUint16(self, value, decode=True): + p1 = self._pos + self.internalSerial(value, 16, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+16, name, 'Uint16', value)) - def pushSint16(self, valeur): - self.internalSerial(valeur, 16) + def pushSint16(self, value, decode=True): + p1 = self._pos + self.internalSerial(value, 16, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+16, name, 'Sint16', value)) - def pushUint8(self, valeur): - self.internalSerial(valeur, 8) + def pushUint8(self, value, decode=True): + p1 = self._pos + self.internalSerial(value, 8, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+8, name, 'Uint8', value)) - def pushSint8(self, valeur): - self.internalSerial(valeur, 8) + def pushSint8(self, value, decode=True): + p1 = self._pos + self.internalSerial(value, 8, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+8, name, 'Sint8', value)) - def pushUint64(self, valeur): - self.internalSerial(valeur, 32) - self.internalSerial(valeur >> 32, 32) + def pushUint64(self, value, decode=True): + p1 = self._pos + self.internalSerial(value, 32, decode=False) + self.internalSerial(value >> 32, 32, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+64, name, 'Uint64', value)) - def pushSint64(self, valeur): - self.internalSerial(valeur, 32) - self.internalSerial(valeur >> 32, 32) + def pushSint64(self, value, decode=True): + p1 = self._pos + self.internalSerial(value, 32, decode=False) + self.internalSerial(value >> 32, 32, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+64, name, 'Sint64', value)) - def pushFloat(self, valeur): - v = c_float(valeur).value + def pushFloat(self, value, decode=True): + p1 = self._pos + v = c_float(value).value v1 = struct.pack('f', v) v2 = struct.unpack('> 32, 32) + self.internalSerial(v2, 32, decode=False) + self.internalSerial(v2 >> 32, 32, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+64, name, 'Float', value)) - def pushChar(self, valeur): - v = ord(valeur) - self.internalSerial(v, 8) + def pushChar(self, value, decode=True): + p1 = self._pos + v = ord(value) + self.internalSerial(v, 8, decode=False) + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p1+8, name, 'Char', value)) - def pushString(self, valeur): - #size=len(valeur) - #self.internalSerial(size, 32) - self.pushUint32(len(valeur)) - for x in valeur: - self.pushChar(x) - #y = ord(x) - #self.internalSerial(y, 8) - def pushArrayUint8(self, valeur): + def pushString(self, value, decode=True): + lenValue = len(value) + self.pushUint32(lenValue, decode=True, typeName='String:len') + p1 = self._pos + for _char in value: + self.pushChar(_char, decode=False) + p2 = self._pos + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p2, name, 'String', value)) + + def pushUString(self, value, decode=True): + lenValue = len(value) + self.pushUint32(lenValue, decode=True, typeName='UString:len') + p1 = self._pos + for x in value: + _char16bit = ord(x) + self.internalSerial(_char16bit, 16, decode=False) + p2 = self._pos + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p2, name, 'UString', value)) + + def pushArrayUint8(self, value, decode=True): ' ex.: pushArrayChar([0,1,3,4]) ' - for i in valeur: - self.pushUint8(i) + p1 = self._pos + for i in value: + self.pushUint8(i, decode=False) + p2 = self._pos + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p2, name, 'ArrayUint8', value)) - def pushBitStream(self, source): + def pushBuffer(self, source, decode=True): + ''' + Push BitStream with all byte (extend to byte if necessary) + ''' + p1 = self._pos + srcRead = source.getRead() + source.putRead(0) + for ele in source._tampon: + self.pushUint8(ele, decode=False) + source.putRead(srcRead) + p2 = self._pos + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p2, name, 'Buffer', '')) + + def pushBitStream(self, source, decode=True): + p1 = self._pos srcRead = source.getRead() source.putRead(0) need = 8 - (self._pos % 8) if need != 8: - self.internalSerial(source.readSerial(need), need) + self.internalSerial(source.readSerial(need), need, decode=False) while source.needRead() >= 8: - self.pushUint8(source.readSerial(8, False)) + self.pushUint8(source.readSerial(8, False), decode=False) need = source.needRead() if need > 0: - self.internalSerial(source.readSerial(need, False), need) + self.internalSerial(source.readSerial(need, False), need, decode=False) source.putRead(srcRead) + p2 = self._pos + if decode: + frame = inspect.currentframe() + frame = inspect.getouterframes(frame)[1] + string = inspect.getframeinfo(frame[0]).code_context[0].strip() + args = string[string.find('(') + 1:-1].split(',') + name = '?' + for i in args: + if i.find('=') != -1: + if i.split('=')[0].strip() == "value": + name = i.split('=')[1].strip() + break + else: + name = i + break + name = name.strip().split(' ')[0].strip() + self._groupWrite.append((p1, p2, name, 'BitStream', '')) # ------------------------------------ def readSerial(self, nbits, name="", decode=True, typeName='', emulate=False): @@ -191,6 +520,8 @@ class BitStream(): elif nbits > 32: raise "Out of range" if self._read + nbits > self._pos: + logging.getLogger('myLogger').debug(self.showAllData()) + logging.getLogger('myLogger').error("Stream Overflow - nbits:%d name:%s decode:%s typeName:%s emulate:%s" %(nbits, name, str(decode), typeName, str(emulate))) raise "Stream Overflow" if emulate: oldRead = self._read @@ -261,22 +592,22 @@ class BitStream(): return c_int64(v2).value def readFloat(self, name): - v1 = self._read + p1 = self._read v = self.readSerial(32, name=name, decode=False, typeName='Float') v1 = struct.pack('I', v) v2 = struct.unpack('= 8: + nsize = 8 + else: + nsize = self._pos - self._read + data = self.readSerial(nsize, decode=False) + if nsize == 1: + ret += "{0:01b}".format(data) + elif nsize == 2: + ret += "{0:02b}".format(data) + elif nsize == 3: + ret += "{0:03b}".format(data) + elif nsize == 4: + ret += "{0:04b}".format(data) + elif nsize == 5: + ret += "{0:05b}".format(data) + elif nsize == 6: + ret += "{0:06b}".format(data) + elif nsize == 7: + ret += "{0:07b}".format(data) + else: + ret += "{0:08b}".format(data) + self._read = readBefore + ret2 = "" + + last = 0 + for x, y, name, typeName, value in self._groupWrite: + ret2 += "[<" + str(x) + ':' + str(y-1) + "> " + str(name) + ' (' + typeName + ') : ' + ret[x:y] + ' => ' + str(value) + "]" + last = y + if last < self._pos: + ret2 += "{" + ret[last:] + "}" + + return ret2 + def showAllDataRaw(self): ret = "" readBefore = self._read @@ -461,7 +831,8 @@ class BitStream(): def TestBitStream(): a = BitStream() - a.pushBool(True) + vrai = True + a.pushBool(decode=True, value=vrai) a.pushBool(False) a.pushBool(True) a.pushBool(True) @@ -471,12 +842,15 @@ def TestBitStream(): a.pushSint16(-12345) a.pushUint8(123) a.pushSint8(-123) - a.pushFloat(-3.3999999521443642e+38) #-3.4E+38) # 1.2339999675750732) + #-3.4E+38) # 1.2339999675750732) + a.pushFloat(-3.3999999521443642e+38) a.pushDouble(-1.7E+308) a.pushUint64(16045690709418696365) a.pushSint64(-1) a.pushChar('a') a.pushString("Test A Faire") + print("-" * 40) + print(a.showAllData()) print('raw:') print(a.showAllDataRaw()) print("-" * 20) @@ -603,8 +977,7 @@ class CBitSet: self.data[i] = 0 def set(self, bitNumber, value): - log = logging.getLogger('myLogger') - log.debug("CBitSet::set %d %s" % (bitNumber, str(value))) + logging.getLogger('myLogger').debug("CBitSet::set %d %s" % (bitNumber, str(value))) mask = bitNumber & (NL_BITLEN-1) mask = 1 << mask if value: @@ -636,9 +1009,11 @@ class CBitSet: log = logging.getLogger('myLogger') log.debug("CBitSet::writeSerial NumBits:%d len:%d" % (self.NumBits, len(self.data))) - msgout.pushUint8(0) # currentVersion = 0 + currentVersion = 0 + msgout.pushUint8(currentVersion) msgout.pushUint32(self.NumBits) - msgout.pushUint32(len(self.data)) # il est lié à 'self.NumBits' dommage que l'on envoie celui-la + # il est lié à 'self.NumBits' dommage que l'on envoie celui-la + msgout.pushUint32(len(self.data)) for x in self.data: msgout.pushUint32(x) @@ -815,6 +1190,178 @@ class TType(IntEnum): NB_TYPE = 11 +class EGender(IntEnum): + male = 0 + female = 1 + neutral = 2 + unknown = 4 + + +class TPeople(IntEnum): + Undefined = -1 + Humanoid = 0 + Playable = 0 + Fyros = 0 + Matis = 1 + Tryker = 2 + Zorai = 3 + EndPlayable = 4 + Karavan = 4 + Tribe = 5 + Common = 6 + EndHumanoid = 7 + Creature = 7 + Fauna = 7 + Arma = 7 + Balduse = 8 + Bul = 9 + Capryni = 10 + Chonari = 11 + Clapclap = 12 + Cococlaw = 13 + Cute = 14 + Dag = 15 + Diranak = 16 + Estrasson = 17 + Filin = 18 + Frahar = 19 + Gibbai = 20 + Hachtaha = 21 + Jungler = 22 + Kakty = 23 + Kalab = 24 + Kami = 25 + Kazoar = 26 + Kitin = 27 + Kitins = 28 + Kitifly = 28 + Kitihank = 29 + Kitiharak = 30 + Kitikil = 31 + Kitimandib = 32 + Kitinagan = 33 + Kitinega = 34 + Kitinokto = 35 + EndKitins = 36 + Lightbird = 36 + Mektoub = 37 + MektoubPacker = 38 + MektoubMount = 39 + Pucetron = 40 + Regus = 41 + Ryzerb = 42 + Ryzoholo = 43 + Ryzoholok = 44 + Vampignon = 45 + Varinx = 46 + Yber = 47 + Zerx = 48 + race_c1 = 49 + race_c2 = 50 + race_c3 = 51 + race_c4 = 52 + race_c5 = 53 + race_c6 = 54 + race_c7 = 55 + race_h1 = 56 + race_h2 = 57 + race_h3 = 58 + race_h4 = 59 + race_h5 = 60 + race_h6 = 61 + race_h7 = 62 + race_h8 = 63 + race_h9 = 64 + race_h10 = 65 + race_h11 = 66 + race_h12 = 67 + EndFauna = 68 + Flora = 68 + Cephaloplant = 68 + Electroalgs = 69 + Phytopsy = 70 + SapEnslaver = 71 + SpittingWeeds = 72 + Swarmplants = 73 + EndFlora = 74 + Goo = 74 + GooFauna = 74 + GooArma = 74 + GooBalduse = 75 + GooBul = 76 + GooCapryni = 77 + GooChonari = 78 + GooClapclap = 79 + GooCococlaw = 80 + GooCute = 81 + GooDag = 82 + GooDiranak = 83 + GooEstrasson = 84 + GooFilin = 85 + GooFrahar = 86 + GooGibbai = 87 + GooHachtaha = 88 + GooJungler = 89 + GooKakty = 90 + GooKalab = 91 + GooKami = 92 + GooKazoar = 93 + GooKitifly = 94 + GooKitihank = 95 + GooKitiharak = 96 + GooKitikil = 97 + GooKitimandib = 98 + GooKitin = 99 + GooKitinagan = 100 + GooKitinega = 101 + GooKitinokto = 102 + GooLightbird = 103 + GooMektoub = 104 + GooMektoubPacker = 105 + GooMektoubMount = 106 + GooPucetron = 107 + GooRegus = 108 + GooRyzerb = 109 + GooRyzoholo = 110 + GooRyzoholok = 111 + GooVampignon = 112 + GooVarinx = 113 + GooYber = 114 + GooZerx = 115 + Goorace_c1 = 116 + Goorace_c2 = 117 + Goorace_c3 = 118 + Goorace_c4 = 119 + Goorace_c5 = 120 + Goorace_c6 = 121 + Goorace_c7 = 122 + Goorace_h1 = 123 + Goorace_h2 = 124 + Goorace_h3 = 125 + Goorace_h4 = 126 + Goorace_h5 = 127 + Goorace_h6 = 128 + Goorace_h7 = 129 + Goorace_h8 = 130 + Goorace_h9 = 131 + Goorace_h10 = 132 + Goorace_h11 = 133 + Goorace_h12 = 134 + EndGooFauna = 135 + GooPlant = 135 + GooCephaloplant = 135 + GooElectroalgs = 136 + GooPhytopsy = 137 + GooSapEnslaver = 138 + GooSpittingWeeds = 139 + GooSwarmplants = 140 + EndGooPlant = 141 + EndGoo = 141 + EndCreature = 141 + ___TPeople_useSize = 142 + Unknown = 142 + EndPeople = 142 + class TExtendType: ET_SHEET_ID = 0 ET_64_BIT_EXTENDED_TYPES = 0x80000000 @@ -1547,7 +2094,7 @@ class CCharacterSummary(): self.version = -1 self.Mainland = 0 # CSessionId self.Name = "" - self.People = 142 + self.People = TPeople.Unknown self.Location = 0 self.sPropVisualA = SPropVisualA() self.sPropVisualB = SPropVisualB() @@ -1565,7 +2112,7 @@ class CCharacterSummary(): ''' self.version = msgin.readUint8('version') self.Mainland = msgin.readUint32('Mainland') - self.Name = msgin.readString('Name') + self.Name = msgin.readUString('Name') self.People = msgin.readSint32('People') self.Location = msgin.readUint32('Location') self.sPropVisualA.read(msgin) @@ -1580,10 +2127,12 @@ class CCharacterSummary(): class CSessionId(): - def __init__(self): - self.id = 0 + def __init__(self, id = 0): + self.id = id def read(self, msgin): self.id = msgin.readUint32('id') + def push(self, msgout): + msgout.pushUint32(self.id) class CMainlandSummary(): @@ -1611,10 +2160,74 @@ class CShardName(): self.ShortName = ShortName -class World(): +def CodeMsgXml(msgXml, key): + head = msgXml + listpath = key.split(':') + ret = [] + for id in listpath: + nbBit = getPowerOf2(len(head)) + found = False + i = 0 + for ele in head: + if ele.attrib['name'] == id: + found = True + ret.append([nbBit, i]) + break + i +=1 + if not found: + log = logging.getLogger('myLogger') + log.error("Impossible to found value (all key:%s, value:%s)" % (key, id)) + raise ValueError + head = ele + return ret + + + +class GenericMultiPartTemp(): def __init__(self, log): self.log = log - self.GenericMultiPartTemp = {} + self.data = {} + + def addGenericMultiPartTemp(self, id): + self.data.setdefault(id, CGenericMultiPartTemp(self.log)) + + def setGenericMultiPartTemp(self, Number, Part, NbBlock, PartCont, decodeImpulse): + self.data[Number].set(Number, Part, NbBlock, PartCont, decodeImpulse) + + +class TStreamFormat(IntEnum): + UseDefault = 0 + Binary = 1 + String = 2 + +class TMessageType(IntEnum): + OneWay = 0 + Request = 1 + Response = 2 + Except = 3 + +#class CMessage(): +# def __init__(self, name, inputStream=False, streamformat=TStreamFormat.UseDefault, defaultCapacity=1000 ): +# self._Name = name +# self._Type = TMessageType.OneWay +# self._SubMessagePosR = 0 +# self._LengthR = 0 +# self._HeaderSize = 0xFFFFFFFF +# self._TypeSet = False +# if streamformat == TStreamFormat.UseDefault: +# self._DefaultStringMode = False +# else: +# self._DefaultStringMode = (streamformat == TStreamFormat.String) +# self.msgout = BitStream() +# +# def serial(self, uid, bms): +# self.msgout.pushUint64(uid) + + +class World(): + def __init__(self, log, HeadName): + self.log = log + #self.GenericMultiPartTemp = {} self.timestamp = 0 self.ServerPeopleActive = 255 self.ServerCareerActive = 255 @@ -1623,12 +2236,125 @@ class World(): self.CShardNames = [] self.UserPrivileges = '' self.FreeTrial = False + self.HeadName = HeadName - def addGenericMultiPartTemp(self, id): - self.GenericMultiPartTemp.setdefault(id, CGenericMultiPartTemp(self.log)) + def CreaterCharacter(self, msgXml): + ''' + khanat-opennel-code/code/ryzom/client/src/connection.cpp # class CAHAskCreateChar : public IActionHandler + khanat-opennel-code/code/ryzom/common/src/game_share/msg_client_server.h # void setupFromCharacterSummary (const CCharacterSummary &cs) + khanat-opennel-code/code/ryzom/common/src/game_share/msg_client_server.h # void serialBitMemStream(NLMISC::CBitMemStream &f) + ''' + Slot = 0 + SheetId = 0 + #Mainland= 302 + cSessionId = CSessionId(self.CShardNames[0].SessionId) - def setGenericMultiPartTemp(self, Number, Part, NbBlock, PartCont, decodeImpulse): - self.GenericMultiPartTemp[Number].set(Number, Part, NbBlock, PartCont, decodeImpulse) + # [A-Za-z]{3,15} # quand je pense qu'ils ont code pour avoir du UTF !!!!! + name = '' + for car in self.HeadName: + if car >= 'a' and car <= 'z': + pass + elif car >= 'A' and car <= 'Z': + pass + elif car >= '0' and car <= '9': + car = chr(ord(car)+ord('A')-ord('0')) + else: + car ='Z' + name += car + #name = 'Tester' + People = 1 + Sex = 0 + StartPoint = 1 + NbPointFighter = 2 + NbPointCaster = 1 + NbPointCrafter = 1 + NbPointHarvester = 1 + GabaritHeight = 9 + GabaritTorsoWidth = 10 + GabaritArmsWidth = 7 + GabaritLegsWidth = 4 + GabaritBreastSize = 7 + MorphTarget1 = 3 + MorphTarget2 = 3 + MorphTarget3 = 3 + MorphTarget4 = 5 + MorphTarget5 = 5 + MorphTarget6 = 5 + MorphTarget7 = 4 + MorphTarget8 = 4 + EyesColor = 0 + Tattoo = 0 + HairType = 5 + HairColor = 1 + JacketColor = 0 + TrousersColor = 0 + HatColor = 1 + ArmsColor = 0 + HandsColor = 0 + FeetColor = 0 + msgout = BitStream() + # GenericMsgHeaderMngr.pushNameToStream("CONNECTION:CREATE_CHAR", out)) + ref = CodeMsgXml(msgXml, 'CONNECTION:CREATE_CHAR') + for size, value in ref: + msgout.internalSerial(value, size) + # khanat-opennel-code/code/ryzom/common/src/game_share/msg_client_server.h # void serialBitMemStream(NLMISC::CBitMemStream &f) + msgout.pushUint8(Slot) + msgout.pushUint32(SheetId) + cSessionId.push(msgout) + msgout.pushUString(name) + msgout.pushUint8(People) + msgout.pushUint8(Sex) + + msgout.pushUint8(NbPointFighter) + msgout.pushUint8(NbPointCaster) + msgout.pushUint8(NbPointCrafter) + msgout.pushUint8(NbPointHarvester) + + msgout.pushSint32(StartPoint) + + msgout.pushSint8(HairType) + msgout.pushSint8(HairColor) + + # GabaritHeight => 0 - 15 + msgout.pushSint8(GabaritHeight) + msgout.pushSint8(GabaritTorsoWidth) + msgout.pushSint8(GabaritArmsWidth) + msgout.pushSint8(GabaritLegsWidth) + msgout.pushSint8(GabaritBreastSize) + + # MorphTarget1 => 0 - 7 + msgout.pushSint8(MorphTarget1) + msgout.pushSint8(MorphTarget2) + msgout.pushSint8(MorphTarget3) + msgout.pushSint8(MorphTarget4) + msgout.pushSint8(MorphTarget5) + msgout.pushSint8(MorphTarget6) + msgout.pushSint8(MorphTarget7) + msgout.pushSint8(MorphTarget8) + # EyesColor => 0 - 7 + msgout.pushSint8(EyesColor) + # Tattoo) => 0 = neutral, 1 - 64 Tattoo + msgout.pushSint8(Tattoo) + + #// color for equipement slots (Only for pre-equipped perso created with sheet) + msgout.pushSint8(JacketColor) + msgout.pushSint8(TrousersColor) + msgout.pushSint8(HatColor) + msgout.pushSint8(ArmsColor) + msgout.pushSint8(HandsColor) + msgout.pushSint8(FeetColor) + + #self.Commands.append(msgout) + return msgout + + + def impulsionCreateChar(self, msgXml, uid): + ''' + khanat-opennel-code/code/ryzom/server/src/frontend_service/uid_impulsions.cpp # static void impulsionCreateChar(uint32 uid, NLMISC::CBitMemStream &bms, NLMISC::TGameCycle gameCycle) + ''' + bms = self.CreaterCharacter(msgXml) + #msgout = CMessage("CREATE_CHAR") + #msgout.serial(uid, bms) class CPersistentDataRecord: def __init__(self, log): @@ -2306,16 +3032,18 @@ def getPowerOf2(v): return ret class DecodeImpulse(): - def __init__(self, log, world): + def __init__(self, log, world, GenericMsgHeaderMngr, GenericMultiPartTemp): ''' khanat-opennel-code/code/ryzom/client/src/net_manager.cpp # void initializeNetwork() ''' self.log = log self.msgXml = None self.databaseXml = None - self.GenericMsgHeaderMngr = {} + self.GenericMsgHeaderMngr = GenericMsgHeaderMngr self.initializeNetwork() self.world = world + self.GenericMultiPartTemp = GenericMultiPartTemp + def updatePatcherPriorityBasedOnCharacters(self): self.log.debug('Load character') hasMainlandChar = False @@ -2330,7 +3058,6 @@ class DecodeImpulse(): msgout = BitStream() self.log.debug("TODO") - def impulseDatabaseUpdatePlayer(self, msgin): self.log.debug("TODO:%s" % msgin) def impulseUpdateInventory(self, msgin): @@ -2354,6 +3081,8 @@ class DecodeImpulse(): # impulse.serialCont (CharacterSummaries); self.world.CharacterSummaries = [] size = msgin.readUint32('CharacterSummaries:len') + self.log.debug(msgin.showAllData()) + self.log.debug("size:%d" % size) for _ in range(0, size): tmp = CCharacterSummary() tmp.read(msgin) @@ -2790,14 +3519,14 @@ class DecodeImpulse(): while True: nbBit = getPowerOf2(len(head)) # def readSerial(self, nbits, name="", decode=True, typeName='', emulate=False): - id = msgin.readSerial(nbBit, name='Ptr', typeName='Number', emulate=True) + id = msgin.readSerial(nbBit, name='MsgXML', typeName='Number', emulate=True) ele = head[id] name = ele.attrib['name'] listpath.append(name) fullname = ':'.join(listpath) - id = msgin.readSerial(nbBit, name='Ptr', typeName='MsgXML<' + name + '>') + id = msgin.readSerial(nbBit, name='MsgXML', typeName='XML <' + name + '>') if fullname in self.GenericMsgHeaderMngr: self.log.debug("Found : %s" % fullname) self.GenericMsgHeaderMngr[fullname](msgin) @@ -2835,8 +3564,17 @@ class CAction: def unpack(self, message): raise RuntimeError - def pack(self, message): - raise RuntimeError + def pack(self, msgout): + if self.Code < 4: + modeShort = True + msgout.pushBool(modeShort) + code = self.Code + msgout.internalSerial(self.Code, 2) + else: + modeShort = False + msgout.pushBool(modeShort) + code = self.Code + msgout.pushUint8(code) def serialIn(self, msgin): raise RuntimeError @@ -2845,7 +3583,12 @@ class CAction: raise RuntimeError def size(self): - raise RuntimeError + headerBitSize = 0 + if self.Code < 4: + headerBitSize = 1 + 2 + else: + headerBitSize = 1 + (1 * 8) + return headerBitSize def getMaxSizeInBit(self): raise RuntimeError @@ -2925,12 +3668,18 @@ class CActionGeneric(CAction): super().__init__(slot, code, world) self._Message = None + def set(self, message): + self._Message = message + def unpack(self, message): size = message.readUint32('size') self._Message = message.readBitStreamUint8(size, 'message') def pack(self, msgout): - msgout.pushArrayUint8(self._Message, len(self._Message) ) + super().pack(msgout) + sizeMessage = len(self._Message) + msgout.pushUint32(sizeMessage) + msgout.pushBuffer(self._Message) def reset(self): self._Message = None @@ -2941,6 +3690,13 @@ class CActionGeneric(CAction): def __str__(self): return "CActionGeneric" + super().__str__() + "[" + self._Message.showAllData() + ']' + def size(self): + size = super().size() + if self._Message: + return 4 + len(self._Message) * 8 + size + else: + return 4 + size + class CActionGenericMultiPart(CAction): ''' khanat-opennel-code/code/ryzom/common/src/game_share/action_generic_multi_part.h # class CActionGenericMultiPart @@ -2952,6 +3708,27 @@ class CActionGenericMultiPart(CAction): self.Part = 0 self.NbBlock = 0 + def set(self, number, part, buffer, bytelen, size, nbBlock): + ''' + khanat-opennel-code/code/ryzom/common/src/game_share/action_generic_multi_part.h # void set (uint8 number, uint16 part, const uint8 *buffer, uint32 bytelen, uint32 size, uint16 nbBlock) + ''' + logging.getLogger('myLogger').debug("number:%d part:%d bytelen:%d size:%d nbBlock:%d" %(number, part, bytelen, size, nbBlock)) + start = part*size + end = start + size + logging.getLogger('myLogger').debug("start:%d end:%d bytelen:%d" % (start, end, bytelen)) + if end > bytelen: + end = bytelen + + logging.getLogger('myLogger').debug("start:%d end:%d" % (start, end)) + self.PartCont = [] + # memcpy( &PartCont[0], buffer + start, end - start ); + for i in range(start, end): + logging.getLogger('myLogger').debug("Append : %d/%d" % (i, len(buffer))) + self.PartCont.append(buffer[i]) + self.Number = number + self.Part = part + self.NbBlock = nbBlock + def unpack(self, message): self.Number = message.readUint8('Number') self.Part = message.readUint16('Part') @@ -2962,8 +3739,8 @@ class CActionGenericMultiPart(CAction): self.log = logging.getLogger('myLogger') self.log.debug("unpack - Number:%d Part:%d NbBlock:%d" % (self.Number, self.Part, self.NbBlock)) - def pack(self, msgout): + super().pack(msgout) msgout.pushUint8(self.Number) msgout.pushUint16(self.Part) msgout.pushUint16(self.NbBlock) @@ -2981,12 +3758,21 @@ class CActionGenericMultiPart(CAction): ''' self.log = logging.getLogger('myLogger') self.log.debug("Number:%d Part:%d NbBlock:%d" % (self.Number, self.Part, self.NbBlock)) - self.world.addGenericMultiPartTemp(self.Number) - self.world.setGenericMultiPartTemp(self.Number, self.Part, self.NbBlock, self.PartCont, decodeImpulse) + decodeImpulse.GenericMultiPartTemp.addGenericMultiPartTemp(self.Number) + decodeImpulse.GenericMultiPartTemp.setGenericMultiPartTemp(self.Number, self.Part, self.NbBlock, self.PartCont, decodeImpulse) def __str__(self): return "CActionGenericMultiPart" + super().__str__() + "[" + str(self.Number) + ',' + str(self.Part) + ',' + str(self.NbBlock) + ',' + self.PartCont.showAllData() + ']' + def size(self): + size = super().size() + bytesize = 1 + 2 + 2 + 4 # header + # self.PartCont + for ele in self.PartCont: + bytesize += len(ele) + return bytesize * 8 + size + + class CActionSint64(CAction): def __init__(self, slot, code, world): super().__init__(slot, code, world) @@ -3086,20 +3872,13 @@ class CActionFactory: log = logging.getLogger('myLogger') log.warning('Unpacking an action with unknown code, skip it (%u)' % code) return action - def pack(self, action, msgout): - if action.Code < 4: - msgout.pushBool(True) - msgout.internalSerial(self.Code, 2) - else: - msgout.pushBool(False) - msgout.pushUint8(self.Code) - action.pack(message) + class CActionBlock: def __init__(self): self.Cycle = 0 self.FirstPacket = 0 - self.Actions = None + self.Actions = [] self.Sucess = True def serial(self, msgout, actionFactory): @@ -3111,6 +3890,26 @@ class CActionBlock: # msgPosAfter = msgout.getPosInBit() # actionSize = actionFactory.size(action) + def writeSerial(self, msgout): + msgout.pushUint32(self.Cycle) + numberActions = len(self.Actions) + msgout.pushUint8(numberActions) + for action in self.Actions: + action.pack(msgout) + + def insert(self, actions, begin, end): + for i in range(0, end): + if i>= begin: + self.Actions.append(actions[i]) + + def eraseToEnd(self, begin): + while len(self.Actions) >= begin: + self.Actions.pop() + + def push_back(self, action): + self.Actions.append(action) + + class CImpulseDecoder: ''' see : khanat-opennel-code/code/ryzom/client/src/impulse_decoder.cpp @@ -3185,10 +3984,13 @@ class ClientNetworkConnection: def __init__(self, khanat_host, khanat_port_frontend, + headAccount, LanguageCode="fr", checkMessageNumber = True): self.log = logging.getLogger('myLogger') self._CurrentSendNumber = 0 + self.GenericMsgHeaderMngr = {} + self.GenericMultiPartTemp = GenericMultiPartTemp(self.log) self.LanguageCode = LanguageCode self._QuitId = 0 self._ConnectionState = TConnectionState.NotInitialised @@ -3221,7 +4023,7 @@ class ClientNetworkConnection: self._AckBitMask = 0 self._LongAckBitField = CBitSet() self._LatestSyncTime = 0 - self.world = World(self.log) + self.world = World(self.log, headAccount) self._ImpulseDecoder = CImpulseDecoder(self.log, self.world) self._LongAckBitField.resize(1024) self._LatestProbeTime = 0 @@ -3231,11 +4033,13 @@ class ClientNetworkConnection: self._ReceivedAckQuit = False self._Actions = [] self._PacketStamps = [] - self.decodeImpulse = DecodeImpulse(self.log, self.world) + self.decodeImpulse = DecodeImpulse(self.log, self.world, self.GenericMsgHeaderMngr, self.GenericMultiPartTemp) self._InstantPing = 0 self._BestPing = 10000 self._MsPerTick = 100 self._LastSendTime = 0 + self._ImpulseMultiPartNumber = 0 + self.clientTick = 0 def signal_exit(self, sig, frame): self.log.warning("Receive signal to quit program") @@ -3265,11 +4069,13 @@ class ClientNetworkConnection: def buildSystemHeader(self, msgout): # code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::buildSystemHeader(NLMISC::CBitMemStream &msgout) msgout.pushSint32(self._CurrentSendNumber) - msgout.pushBool(True) # systemMode + systemMode = True + msgout.pushBool(systemMode) self._PacketStamps.append( TStampQueue(self._CurrentSendNumber, self._UpdateTime) ) self._CurrentSendNumber += 1 def sendSystemLogin(self): # code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::sendSystemLogin() + self.log.debug("sendSystemLogin") if self._sock is None: raise ValueError msgout = BitStream() @@ -3280,12 +4086,14 @@ class ClientNetworkConnection: msgout.pushUint32(self.UserId) msgout.pushString(self.LanguageCode) + self.log.debug("sendSystemLogin:%s" % msgout.showAllDataWrite()) self._sock.sendto(msgout.toBytes(), self.frontend) self._CurrentSendNumber += 1 self._ConnectionState = TConnectionState.Login def sendSystemQuit(self): # code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::sendSystemQuit() + self.log.debug("sendSystemQuit") # Disconnect if self._sock is None: raise ValueError @@ -3293,38 +4101,29 @@ class ClientNetworkConnection: msgout = BitStream() self.buildSystemHeader(msgout) msgout.pushUint8(CLFECOMMON.SYSTEM_QUIT_CODE) - msgout.pushSint32(self._QuitId) # _QuitId + msgout.pushSint32(self._QuitId) + self.log.debug("sendSystemQuit:%s" % msgout.showAllDataWrite()) self._sock.sendto(msgout.toBytes(), self.frontend) self._ConnectionState = TConnectionState.Quit - def sendSystemAckSync(self): # code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::sendSystemAckSync() + def sendSystemAckSync(self): + ''' + code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::sendSystemAckSync() + ''' self.log.debug("sendSystemAckSync _LastReceivedNumber:%d _LastAckInLongAck:%d _LatestSync:%d" % (self._LastReceivedNumber, self._LastAckInLongAck, self._LatestSync)) msgout = BitStream() self.buildSystemHeader(msgout) msgout.pushUint8(CLFECOMMON.SYSTEM_ACK_SYNC_CODE) msgout.pushSint32(self._LastReceivedNumber) msgout.pushSint32(self._LastAckInLongAck) - self._LongAckBitField.writeSerial(msgout) # Signale le nombre de packet perdu + self._LongAckBitField.writeSerial(msgout) msgout.pushSint32(self._LatestSync) + self.log.debug("sendSystemAckSync:%s" % msgout.showAllDataWrite()) self._sock.sendto(msgout.toBytes(), self.frontend) self._LatestSyncTime = self._UpdateTime - # Only to decode message send - msgout.readSint32('_CurrentSendNumber') - msgout.readBool('systemMode') - msgout.readUint8('SYSTEM_ACK_SYNC_CODE') - msgout.readSint32('_LastReceivedNumber') - msgout.readSint32('_LastAckInLongAck') - msgout.readUint8('currentVersion') # currentVersion = 0 - msgout.readUint32('NumBits') - size = msgout.readUint32('size') - for _ in range(0, size): - msgout.readUint32('data') - msgout.readSint32('_LatestSync') - self.log.debug("sendSystemAckSync : %s" % msgout.showAllData()) - def sendSystemAckProbe(self): self.log.debug("sendSystemAckProbe") msgout = BitStream() @@ -3334,6 +4133,7 @@ class ClientNetworkConnection: for data in self._LatestProbes: msgout.pushSint32(data) self._LatestProbes = [] + self.log.debug("sendSystemAckProbe:%s" % msgout.showAllDataWrite()) self._sock.sendto(msgout.toBytes(), self.frontend) @@ -3347,12 +4147,16 @@ class ClientNetworkConnection: self._sock.sendto(msgout.toBytes(), self.frontend) def sendNormalMessage(self): + ''' + khanat-opennel-code/code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::sendNormalMessage() + ''' self.log.debug("sendNormalMessage") if self._sock is None: raise ValueError msgout = BitStream() msgout.pushSint32(self._CurrentSendNumber) - msgout.pushBool(False) # Normal + systemMode = False # Normal + msgout.pushBool(systemMode) msgout.pushSint32(self._LastReceivedNumber) msgout.pushSint32(self._AckBitMask) @@ -3365,11 +4169,12 @@ class ClientNetworkConnection: if block.FirstPacket == 0: block.FirstPacket = self._CurrentSendNumber; - block.serial(message) + block.writeSerial(msgout) numPacked += 1 - if message.getPosInBit() > 480*8: # easy version + if msgout.getPosInBit() > 480*8: # easy version break + self.log.debug("Send:%s" % msgout.showAllDataWrite()) self._sock.sendto(msgout.toBytes(), self.frontend) self._LastSendTime = int(time.clock_gettime(1)*1000) @@ -3443,6 +4248,7 @@ class ClientNetworkConnection: return True def receiveSystemProbe(self, msg): + self.log.debug("receiveSystemProbe") self._LatestProbeTime = self._UpdateTime self._LatestProbe = msg.readSint32('LatestProbe') self.log.debug("LatestProbe: %d" % self._LatestProbe) @@ -3452,6 +4258,7 @@ class ClientNetworkConnection: self.log.debug("received STALLED") def receiveSystemSync(self, msg): + self.log.debug("receiveSystemSync") self._LatestSyncTime = self._UpdateTime self._Synchronize = msg.readUint32('Synchronize') stime = msg.readSint64('stime') @@ -3491,7 +4298,7 @@ class ClientNetworkConnection: return def receiveNormalMessage(self, msgin): - self.log.debug("received normal message Packet (%d) %s" % (msgin.needRead(), msgin.showLastData() )) + self.log.debug("receiveNormalMessage : received normal message Packet (%d) %s" % (msgin.needRead(), msgin.showLastData() )) actions = self._ImpulseDecoder.decode(msgin, self._CurrentReceivedNumber, self._LastReceivedAck, self._CurrentSendNumber ) if actions: self.log.debug('actions: ' +','.join( [ str(x) for x in actions] ) ) @@ -3603,6 +4410,7 @@ class ClientNetworkConnection: return False def stateSynchronize(self, msgin): + self.log.debug("stateSynchronize") self.decodeHeader(msgin) if self._SystemMode: message = msgin.readUint8('message') @@ -3643,7 +4451,7 @@ class ClientNetworkConnection: self.decodeHeader(msgin) if self._SystemMode: message = msgin.readUint8('message') - self.log.debug("_CurrentReceivedNumber:%d (mode:%s) %d [%d/%d/%d]" % (self._CurrentReceivedNumber, str(self._SystemMode), message, msgin.sizeData(), msgin.sizeRead(), msgin.needRead())) + self.log.debug("SystemMode _CurrentReceivedNumber:%d (mode:%s) %d [%d/%d/%d]" % (self._CurrentReceivedNumber, str(self._SystemMode), message, msgin.sizeData(), msgin.sizeRead(), msgin.needRead())) if message == CLFECOMMON.SYSTEM_PROBE_CODE: self.log.debug("Connected->probe") self._ConnectionState = TConnectionState.Probe @@ -3664,7 +4472,7 @@ class ClientNetworkConnection: return False else: self.log.warning("CNET: received system %d in state Connected" % message) - self.log.debug("_CurrentReceivedNumber:%d (mode:%s) %d [%d/%d/%d] '%s'" % (self._CurrentReceivedNumber, str(self._SystemMode), message, msgin.sizeData(), msgin.sizeRead(), msgin.needRead(), msgin.showLastData())) + self.log.debug("NormalMode _CurrentReceivedNumber:%d (mode:%s) %d [%d/%d/%d] '%s'" % (self._CurrentReceivedNumber, str(self._SystemMode), message, msgin.sizeData(), msgin.sizeRead(), msgin.needRead(), msgin.showLastData())) else: self.receiveNormalMessage(msgin); return True @@ -3798,10 +4606,89 @@ class ClientNetworkConnection: if counterLoop > 10: break - def send(self): + def push_back(self, action): + ''' + khanat-opennel-code/code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::push(CAction *action) + ''' + # search to aggregate Action (send by block) + if len(self._Actions) == 0 or self._Actions[-1].Cycle != 0: + self._Actions.append(CActionBlock()) + self._Actions[-1].push_back(action) + + def push(self, msgout): + ''' + khanat-opennel-code/code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::push(CBitMemStream &msg) + ''' + self.log.debug("Push :%s" % msgout.showAllDataWrite()) + maxImpulseBitSize = 1840 # = 230*8 + cp = CActionFactory(self.log, self.world) + ag = cp.createFactory(INVALID_SLOT, TActionCode.ACTION_GENERIC_CODE) + bytelen = (msgout.sizeData() + 7) // 8 + impulseMinBitSize = ag.size() + impulseBitSize = impulseMinBitSize + (4 + bytelen)*8 + self.log.debug("maxImpulseBitSize:%d bytelen:%d impulseMinBitSize:%d impulseBitSize:%d" %(maxImpulseBitSize, bytelen, impulseMinBitSize, impulseBitSize)) + if impulseBitSize < maxImpulseBitSize: + ag.set(msgout); + self.push_back(ag) + else: + agmp = cp.createFactory(INVALID_SLOT, TActionCode.ACTION_GENERIC_MULTI_PART_CODE) + minimumBitSizeForMP = agmp.size() + availableSize = (maxImpulseBitSize - minimumBitSizeForMP) // 8 + nbBlock = (bytelen + availableSize - 1) // availableSize + num = self._ImpulseMultiPartNumber + self._ImpulseMultiPartNumber += 1 + self.log.debug("minimumBitSizeForMP:%d availableSize:%d nbBlock:%d num:%d _ImpulseMultiPartNumber:%d" % (minimumBitSizeForMP, availableSize, nbBlock, num, self._ImpulseMultiPartNumber)) + for i in range(0, nbBlock): + self.log.debug("i:%d nbBlock:%d" % (i, nbBlock)) + if i != 0: + # Create a new CActionFactory + agmp = cp.createFactory(INVALID_SLOT, TActionCode.ACTION_GENERIC_MULTI_PART_CODE) + agmp.set(num, i, msgout.buffer(), bytelen, availableSize, nbBlock) + self.push_back(agmp) + + def sendFastMode(self): if self._ConnectionState == TConnectionState.Connected and self._LastSendTime > 100: self.sendNormalMessage() + def send(self): + ''' + khanat-opennel-code/code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::send(TGameCycle cycle) + ''' + cycle = self._CurrentServerTick + bitSize = 32*8 # block size is 32 (cycle) + 8 (number of actions + if len(self._Actions) == 0 or self._Actions[-1].Cycle != 0: + pass + else: + block = self._Actions[-1] + block.Cycle = cycle + # check last block isn't bigger than maximum allowed + i = 0 + for action in block.Actions: + bitSize += action.size() + if bitSize >= 480*8: + break + i += 1 + if i < len(self._Actions): + # Too big block -> split block + newBlock = CActionBlock() + newBlock.Cylce = 0 + newBlock.insert(self._Actions, i, len(block.Actions)) + block.eraseToEnd(i) + + if self._ConnectionState == TConnectionState.Connected: + self.sendNormalMessage() + + #if len(self.world.Commands) > 0: + # cmd = self.world.Commands.pop(0) + + def analyze(self): + if self.world.CShardNames != []: + if self.world.CharacterSummaries != [] and self.clientTick > 5: + if self.world.CharacterSummaries[0].People == TPeople.Unknown: + bms = self.world.CreaterCharacter(self.msgXml) + self.push(bms) + + def EmulateFirst(self, msgRawXml, databaseRawXml): self.msgXml = ET.fromstring(msgRawXml) #ET.dump(msgXml) @@ -3813,18 +4700,21 @@ class ClientNetworkConnection: self.decodeImpulse.loadMsg(self.msgXml) self.decodeImpulse.loadDatabase(self.databaseXml) + + #CodeMsgXml(self.msgXml, 'CONNECTION:CREATE_CHAR') self.connect() self.log.info("Client Login") self.sendSystemLogin() self.log.info("Receive Message") - i = 0 + self.clientTick = 0 for _ in range(0, 50): #while True: - self.log.debug("%s [%s: %d] %s" % ("*" * 40, "Loop", i,"*" * 40)) + self.log.debug("%s [%s: %d] %s" % ("*" * 40, "Loop", self.clientTick,"*" * 40)) self.update() + self.analyze() self.send() - i += 1 + self.clientTick += 1 self.log.info("Client Quit") self.sendSystemQuit() @@ -3865,7 +4755,7 @@ class ClientKhanat: self.log.debug("Temporary directory:%s" % self.tempdir) self.khanat_idx = CPersistentDataRecord(self.log) self.UserAddr, self.UserKey, self.UserId = None, None, None - self.clientNetworkConnection = ClientNetworkConnection(self.khanat_host, self.khanat_port_frontend) + self.clientNetworkConnection = ClientNetworkConnection(self.khanat_host, self.khanat_port_frontend, self.login) self.size_buffer_file = size_buffer_file self.cFileContainer = CFileContainer()