From 94498be11c0efb38b85f8ad6cd6c8baa2c97c933 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Thu, 6 Jun 2019 22:21:35 +0200 Subject: [PATCH] update script --- client.py | 146 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 131 insertions(+), 15 deletions(-) diff --git a/client.py b/client.py index b784860..25010f9 100755 --- a/client.py +++ b/client.py @@ -163,7 +163,7 @@ class BitStream(): self.pushChar(x) #y = ord(x) #self.internalSerial(y, 8) - def pushArrayUint8(self, valeur, size): + def pushArrayUint8(self, valeur): ' ex.: pushArrayChar([0,1,3,4]) ' for i in valeur: self.pushUint8(i) @@ -422,6 +422,9 @@ class BitStream(): self._read = readBefore return ret + def getPosInBit(self): + return self._pos + def TestBitStream(): a = BitStream() a.pushBool(True) @@ -1837,15 +1840,6 @@ class CPersistentDataRecord: break - -class CActionBlock: - def __init__(self): - self.Cycle = 0 - self.FirstPacket = 0 - self.Actions = None - self.Sucess = True - - def getPowerOf2(v): res=1; ret=0; @@ -2427,6 +2421,9 @@ class CActionGeneric(CAction): size = message.readUint32('size') self._Message = message.readBitStreamUint8(size, 'message') + def pack(self, msgout): + msgout.pushArrayUint8(self._Message, len(self._Message) ) + def reset(self): self._Message = None @@ -2455,6 +2452,13 @@ class CActionGenericMultiPart(CAction): size = message.readUint32('size') self.PartCont = message.readBitStreamUint8(size, 'PartCont') + + def pack(self, msgout): + msgout.pushUint8(self.Number) + msgout.pushUint16(self.Part) + msgout.pushUint16(self.NbBlock) + msgout.pushArrayUint8(self.PartCont) + def reset(self): self.PartCont = [] self.Number = 0 @@ -2572,6 +2576,30 @@ 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.Sucess = True + + def serial(self, msgout, actionFactory): + msgout.pushUint32(self.Cycle) + msgout.pushUint8(len(self.Actions)) + for action in self.Actions: + # msgPosBefore = msgout.getPosInBit() + actionFactory.pack(action, msgout) + # msgPosAfter = msgout.getPosInBit() + # actionSize = actionFactory.size(action) class CImpulseDecoder: ''' @@ -2630,6 +2658,11 @@ class CImpulseDecoder: self._LastAck1 = [-1, -1] self._LastAck2 = [-1, -1, -1, -1] +class TStampQueue: + def __init__(self, first=None, second=None): + self.first = first + self.second = second + class ClientNetworkConnection: ''' Partie client de la gestion de la communication reseau avec le serveur: @@ -2689,6 +2722,10 @@ class ClientNetworkConnection: self._Actions = [] self._PacketStamps = [] self.decodeImpulse = DecodeImpulse(self.log, self.world) + self._InstantPing = 0 + self._BestPing = 10000 + self._MsPerTick = 100 + self._LastSendTime = 0 def signal_exit(self, sig, frame): self.log.warning("Receive signal to quit program") @@ -2719,6 +2756,7 @@ 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 + self._PacketStamps.append( TStampQueue(self._CurrentSendNumber, self._UpdateTime) ) self._CurrentSendNumber += 1 def sendSystemLogin(self): # code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::sendSystemLogin() @@ -2774,6 +2812,7 @@ class ClientNetworkConnection: def sendSystemDisconnection(self): + self.log.debug("sendSystemDisconnection") if self._sock is None: raise ValueError msgout = BitStream() @@ -2781,6 +2820,36 @@ class ClientNetworkConnection: msgout.pushUint8(CLFECOMMON.SYSTEM_DISCONNECTION_CODE) self._sock.sendto(msgout.toBytes(), self.frontend) + def sendNormalMessage(self): + self.log.debug("sendNormalMessage") + if self._sock is None: + raise ValueError + msgout = BitStream() + msgout.pushSint32(self._CurrentSendNumber) + msgout.pushBool(False) # Normal + msgout.pushSint32(self._LastReceivedNumber) + msgout.pushSint32(self._AckBitMask) + + numPacked = 0 + + for block in self._Actions: + if block.Cycle == 0: + break + + if block.FirstPacket == 0: + block.FirstPacket = self._CurrentSendNumber; + + block.serial(message) + numPacked += 1 + if message.getPosInBit() > 480*8: # easy version + break + + self._sock.sendto(msgout.toBytes(), self.frontend) + + self._LastSendTime = int(time.clock_gettime(1)*1000) + self._PacketStamps.append( TStampQueue(self._CurrentSendNumber, self._UpdateTime) ) + self._CurrentSendNumber += 1 + def readDelta(self, msg): propertyCount = msg.readUint16('propertyCount') self.log.debug("propertyCount:%d" % propertyCount) @@ -2879,7 +2948,16 @@ class ClientNetworkConnection: self.sendSystemAckSync() def decodeVisualProperties(self, msgin): - self.log.debug("TODO") + ''' + khanat-opennel-code/code/ryzom/client/src/network_connection.cpp # void CNetworkConnection::decodeVisualProperties( CBitMemStream& msgin ) + ''' + while True: + if msgin.getPosInBit() + 8*8 > len(msgin)*8: + return + slot = msgin.readUint8('slot') + associationBits = msgin.readUint32('associationBits') + self.log.debug("TODO") + return def receiveNormalMessage(self, msgin): self.log.debug("received normal message Packet (%d) %s" % (msgin.needRead(), msgin.showLastData() )) @@ -2890,12 +2968,42 @@ class ClientNetworkConnection: self.log.debug('actions: None') self.log.debug("Message not read (%d) %s" % (msgin.needRead(), msgin.showLastData() )) - # remove all old action that are acked + # remove all old actions that are acked while self._Actions and self._Actions[0].FirstPacket != 0 and self._Actions[0].FirstPacket : + self.log.debug("remove old action") self._Actions.pop(0) self._CurrentServerTick = self._CurrentReceivedNumber * 2 + self._Synchronize + # remove useless stamps in queue + while len(self._PacketStamps) != 0 and self._LastReceivedAck > self._PacketStamps[0].first: + self._PacketStamps.pop(0) + + # Statistique ! + if len(self._PacketStamps) == 0 or self._PacketStamps[0].first > self._LastReceivedAck: + pass + else: + ackedPacketTime = self._PacketStamps[0].second + ping = self._UpdateTime - ackedPacketTime + self._InstantPing = ping + if ping < self._BestPing: + self._BestPing = ping + earliest = ackedPacketTime + self._BestPing//2 + latest = self._UpdateTime - self._BestPing//2 + + numStepTick = self._CurrentServerTick - self._CurrentClientTick + if numStepTick > 0 and earliest > self._CurrentClientTime and latest > self._CurrentClientTime: + if self._CurrentClientTime + self._MsPerTick * numStepTick < earliest: + self._MsPerTick = (earliest - self._CurrentClientTime)//numStepTick + if (self._CurrentClientTime + self._MsPerTick * numStepTick) > latest: + self._MsPerTick = (latest - self._CurrentClientTime)//numStepTick + if self._MsPerTick == 0: + self.log.warning("_MsPerTick is 0 because server tick is too big %d compare to the client tick is %d" %(self._CurrentServerTick, self._CurrentClientTick)) + self._MsPerTick = 1 + elif numStepTick <= 0: + self._MsPerTick = self._LCT + + ## remove useless stamps in queue #while self._PacketStamps and self._LastReceivedAck > self._PacketStamps[0].first: # self._PacketStamps.pop(0) @@ -2918,7 +3026,7 @@ class ClientNetworkConnection: # Decode the visual properties self.decodeVisualProperties( msgin ); - self._LastReceivedNormalTime = self._UpdateTime; + self._LastReceivedNormalTime = int(time.clock_gettime(1)*1000) def receiveSystemAckQuit(self, msgin): self.log.debug("received ACK_QUIT") @@ -3157,6 +3265,10 @@ class ClientNetworkConnection: if counterLoop > 10: break + def send(self): + if self._ConnectionState == TConnectionState.Connected and self._LastSendTime > 100: + self.sendNormalMessage() + def EmulateFirst(self, msgRawXml, databaseRawXml): self.msgXml = ET.fromstring(msgRawXml) #ET.dump(msgXml) @@ -3173,9 +3285,13 @@ class ClientNetworkConnection: self.sendSystemLogin() self.log.info("Receive Message") - for i in range(0, 2): # while True: - self.log.debug('loop %d' % i) + i = 0 + for _ in range(0, 50): + #while True: + self.log.debug("%s [%s: %d] %s" % ("*" * 40, "Loop", i,"*" * 40)) self.update() + self.send() + i += 1 self.log.info("Client Quit") self.sendSystemQuit()