def parse_frame(self, netstream, objects, propertymapper): self.current = reverse_bytewise(netstream.read('bits:32')).floatle self.delta = reverse_bytewise(netstream.read('bits:32')).floatle if self.current < 0.001 or self.delta < 0.001: raise FrameParsingError("Last Frame caused some offset. Nextbits: %s" % netstream.read('bits:64').hex) self.actors = self._parse_actors(netstream, objects, propertymapper)
def _read_unique_id(bitstream): system = _read_byte(bitstream) if system == 0: # Splitscreen uid = reverse_bytewise(bitstream.read('bits:24')).uintle elif system == 1: # STEAM uid = reverse_bytewise(bitstream.read('bits:64')).uintle elif system == 2: # PS4 uid = reverse_bytewise(bitstream.read('bits:256')).hex else: raise PropertyParsingError('Unknown System ID') splitscreen_id = _read_byte(bitstream) return system, uid, splitscreen_id
def _read_string(bitstream): # This should be in utils. But its only needed here, so yeah length = _read_int(bitstream)*8 if length < 0: length *= -2 return reverse_bytewise(bitstream.read('bits:'+str(length))).bytes[:-2].decode('utf-16') reversed_bytes = reverse_bytewise(bitstream.read('bits:'+str(length))).bytes[:-1] try: return reversed_bytes.decode('utf-8') except UnicodeDecodeError: return reversed_bytes.decode('latin-1')
def _read_reservations(bitstream): unknown = reverse_bytewise(bitstream.read('bits:3')).hex system, uid, playernum = _read_unique_id(bitstream) name = "Not Set" if system != 0: name = _read_string(bitstream) flag_1 = _read_bool(bitstream) flag_2 = _read_bool(bitstream) return unknown, name, flag_1, flag_2
def parse_netstream(self, qout=None, ev=None): try: self._netstream_raw = reverse_bytewise(self._netstream_raw) self.netstream = self._parse_frames(qout, ev) except Exception as e: if qout: qout.put('exception') qout.put(e) else: raise e
def _parse_actors(self, netstream, objects, propertymapper): actors = OrderedDict() # Ordered Dict to reflect order of appearance in json output while True: startpos = netstream.pos actor_present = netstream.read(BOOL) if not actor_present: break actorid = reverse_bytewise(netstream.read('bits:10')).uintle channel = netstream.read(BOOL) if not channel: try: shorttype = str(actorid) + 'd' + '_' shorttype += self._actor_alive[actorid].split('.')[-1].split(':')[-1] actors[shorttype] = {'startpos': startpos, 'actor_id': actorid, 'actor_type': self._actor_alive[actorid], 'open': channel} del self._actor_alive[actorid] except KeyError: raise FrameParsingError("Tried to delete non existent actor", actors) continue new = netstream.read(BOOL) try: if new: type_name, data = self._parse_new_actor(netstream, objects) self._actor_alive[actorid] = type_name else: data = self._parse_existing_actor(netstream, self._actor_alive[actorid], objects, propertymapper) except (PropertyParsingError, KeyError) as e: e.args += ({'CurrFrameActors': actors},) try: e.args += ({'ErrorActorType': self._actor_alive[actorid], 'ErrorActorId': actorid, 'ErrorActorData': data},) except KeyError: pass raise e if new: shorttype = str(actorid) + 'n' + '_' shorttype += self._actor_alive[actorid].split('.')[-1].split(':')[-1] else: shorttype = str(actorid) + 'e' + '_' shorttype += self._actor_alive[actorid].split('.')[-1].split(':')[-1] actors[shorttype] = { 'startpos': startpos, 'actor_id': actorid, 'actor_type': self._actor_alive[actorid], 'new': new, 'data': data} return actors
def _parse_new_actor(self, netstream, objects): actor = {} actor['flag'] = netstream.read(BOOL) type_id = reverse_bytewise(netstream.read('bits:32')).uintle type_name = objects[type_id] if 'TheWorld' in type_name: # World types are Vector Less return type_name, actor actor['vector'] = read_serialized_vector(netstream) if 'Ball_Default' in type_name or 'Car_Default' in type_name: actor['rotation'] = read_byte_vector(netstream) return type_name, actor
def _read_enum(bitstream): # What? O_o it seems right, but why 11? Like...what? return reverse_bytewise(bitstream.read('bits:11')).hex
def _read_string(bitstream): # This should be in utils. But its only needed here, so yeah length = _read_int(bitstream)*8 if length < 0: length *= -2 return reverse_bytewise(bitstream.read('bits:'+str(length))).bytes[:-2].decode('utf-16') return reverse_bytewise(bitstream.read('bits:'+str(length))).bytes[:-1].decode('utf-8')
def _read_float(bitstream): return reverse_bytewise(bitstream.read('bits:32')).floatle
def _read_byte(bitstream): return reverse_bytewise(bitstream.read('bits:8')).uintle
def _read_int(bitstream): return reverse_bytewise(bitstream.read('bits:32')).intle
def _parse_actors(self, netstream, objects, propertymapper): actors = OrderedDict( ) # Ordered Dict to reflect order of appearance in json output while True: startpos = netstream.pos actor_present = netstream.read(BOOL) if not actor_present: break actorid = reverse_bytewise(netstream.read('bits:10')).uintle channel = netstream.read(BOOL) if not channel: try: shorttype = str(actorid) + 'd' + '_' shorttype += self._actor_alive[actorid].split( '.')[-1].split(':')[-1] actors[shorttype] = { 'startpos': startpos, 'actor_id': actorid, 'actor_type': self._actor_alive[actorid], 'open': channel } del self._actor_alive[actorid] except KeyError: raise FrameParsingError( "Tried to delete non existent actor", actors) continue new = netstream.read(BOOL) if new: type_name, data = self._parse_new_actor(netstream, objects) self._actor_alive[actorid] = type_name else: try: data = self._parse_existing_actor( netstream, self._actor_alive[actorid], objects, propertymapper) except PropertyParsingError as e: e.args += ({ 'CurrFrameActors': actors }, { 'ErrorActorType': self._actor_alive[actorid], 'ErrorActorId': actorid }) raise e if new: shorttype = str(actorid) + 'n' + '_' shorttype += self._actor_alive[actorid].split('.')[-1].split( ':')[-1] else: shorttype = str(actorid) + 'e' + '_' shorttype += self._actor_alive[actorid].split('.')[-1].split( ':')[-1] actors[shorttype] = { 'startpos': startpos, 'actor_id': actorid, 'actor_type': self._actor_alive[actorid], 'new': new, 'data': data } return actors