コード例 #1
0
ファイル: luzreader.py プロジェクト: luxaritas/PyLUS
    def __init__(self, file, conn=None):
        self.conn = conn or sqlite3.connect('client_assets/cdclient.sqlite')
        self.scenes = []

        with open(file, 'rb') as file:
            self.data = file.read()
            self.size = len(self.data)
            self.stream = ReadStream(self.data, unlocked=True)

        self.version = self.stream.read(c_uint)
        assert self.version == 41, self.version
        self.unknown1 = self.stream.read(c_uint)
        self.world_id = self.stream.read(c_uint)

        self.spawnpoint = Vector3(self.stream.read(c_float), self.stream.read(c_float), self.stream.read(c_float))
        self.spawnpoint_rot = Vector4(self.stream.read(c_float), self.stream.read(c_float), self.stream.read(c_float),
                                      self.stream.read(c_float))

        self.num_scenes = self.stream.read(c_uint)

        for _ in range(self.num_scenes):
            filename = self.stream.read(bytes, length_type=c_ubyte).decode('latin1')
            scene_id = self.stream.read(c_uint64)
            scene_name = self.stream.read(bytes, length_type=c_ubyte).decode('latin1')
            assert self.stream.read(bytes, length=3)
            pth = os.path.join('client_assets', 'luz', filename)

            if os.path.exists(pth):
                with open(pth, 'rb') as file:
                    objects = self.get_lvl_objects(ReadStream(file.read(), unlocked=True))
                    self.scenes.append(LUScene(scene_id, scene_name, objects))
            else:
                self.scenes.append(LUScene(scene_id, scene_name))
コード例 #2
0
ファイル: sessions.py プロジェクト: luxaritas/PyLUS
 def deserialize(cls, stream: ReadStream):
     """
     Deserializes the packet
     """
     return cls(username=stream.read(str, allocated_length=33),
                session_key=stream.read(str, allocated_length=33),
                unknown=stream.read(bytes, length=33))
コード例 #3
0
    def mission_accept(self, packet, conn: Connection, stream: ReadStream):
        """
        Handles the mission dialogue ok game message
        """
        complete = stream.read(c_bit)
        state = stream.read(c_int)
        mission_id = stream.read(c_int)
        responder_objid = stream.read(c_int64)

        print(f'Mission {mission_id} accepted')
        print(f'Complete: {complete}')
        print(f'State: {state}')
        print(f'Responder: {responder_objid}')

        session = self.server.handle_until_return('session:get_session',
                                                  conn.get_address())
        char = self.server.handle_until_return(
            'char:characters',
            session.account.user.id)[session.account.front_character]

        if complete:
            self.server.handle('char:complete_mission', char.pk, mission_id)

            wstr = WriteStream()
            wstr.write(c_int(mission_id))
            wstr.write(c_int(8))
            wstr.write(c_bit(False))

            msg = ServerGameMessage(responder_objid,
                                    GameMessageID.NOTIFY_MISSION, wstr)
        else:

            self.server.handle('char:activate_mission', char.pk, mission_id)

            # tasks = self.server.handle_until_return('world:get_mission_tasks', mission_id)

            # for task in tasks:
            #     wstr = WriteStream()
            #     wstr.write(c_int(mission_id))
            #     wstr.write(c_int(1 << (task[2] + 1)))
            #     wstr.write(c_uint8(0))

            #     msg = ServerGameMessage(packet.objid, GameMessageID.NOTIFY_MISSION_TASK, wstr)
            #     conn.send(msg)

            wstr = WriteStream()
            wstr.write(c_int(mission_id))
            wstr.write(c_int(2))
            wstr.write(c_bit(False))

            msg = ServerGameMessage(responder_objid,
                                    GameMessageID.NOTIFY_MISSION, wstr)

        conn.send(msg)
コード例 #4
0
    def request_linked_mission(self, packet, conn: Connection,
                               stream: ReadStream):
        """
        Handles the request linked mission game message
        """
        objid = stream.read(c_int64)
        mission = stream.read(c_int)
        offered = stream.read(c_bit)

        print(f'Request for linked mission {mission}')
        print(f'Object ID: {objid}')
        print(f'Offered: {offered}')
コード例 #5
0
ファイル: sessions.py プロジェクト: luxaritas/PyLUS
    def allow_packet(self, data: ReadStream, conn: Connection):
        """
        Allows a packet
        """
        packet = Packet.deserialize(ReadStream(data), self.server.packets)

        if not getattr(packet,
                       'allow_without_session') and not self.get_session(
                           conn.get_address()):
            self.destroy_session(conn)
コード例 #6
0
    def deserialize(cls, stream: ReadStream, packet_types):
        """
        Deserialize the packet
        """
        header = LUHeader.deserialize(stream)
        packet = packet_types.get(getattr(header, 'packet_name', None))

        if packet:
            return packet.deserialize(stream)

        return cls(header=header, data=stream.read_remaining())
コード例 #7
0
    def __init__(self, file, server_zone):
        self.conn = sqlite3.connect('client_assets/cdclient.sqlite')
        self.scenes = []

        with open(file, 'rb') as file:
            self.data = file.read()
            self.size = len(self.data)
            self.stream = ReadStream(self.data, unlocked=True)

        self.version = self.stream.read(c_uint)
        assert self.version in (36, 38, 39, 40, 41), 'Unknown LUZ version ' + self.version
        self.unknown1 = self.stream.read(c_uint)
        self.world_id = self.stream.read(c_uint)

        if self.version >= 38:
            self.spawnpoint = Vector3(self.stream.read(c_float), self.stream.read(c_float), self.stream.read(c_float))
            self.spawnpoint_rot = LVLVector4(self.stream.read(c_float), self.stream.read(c_float), self.stream.read(c_float),
                                          self.stream.read(c_float))
        else:
            # TODO: Verify what should actually happen in versions < 38
            self.spawnpoint = Vector3(0,0,0)
            self.spawnpoint_rot = Vector4(0,0,0,0)

        if self.version >= 37:
            self.num_scenes = self.stream.read(c_uint)
        else:
            self.num_scenes = self.stream.read(c_ubyte)

        for _ in range(self.num_scenes):
            filename = self.stream.read(bytes, length_type=c_ubyte).decode('latin1')
            scene_id = self.stream.read(c_uint64)
            scene_name = self.stream.read(bytes, length_type=c_ubyte).decode('latin1')
            assert self.stream.read(bytes, length=3)
            lvl_path = os.path.join('client_assets', 'lvl', server_zone, filename)

            if os.path.exists(lvl_path):
                with open(lvl_path, 'rb') as file:
                    objects = self.get_lvl_objects(ReadStream(file.read(), unlocked=True))
                    self.scenes.append(LUScene(scene_id, scene_name, objects))
            else:
                self.scenes.append(LUScene(scene_id, scene_name))
コード例 #8
0
ファイル: lu_packet.py プロジェクト: luxaritas/PyLUS
    def on_packet(self, data: ReadStream, conn: Connection):
        """
        Packet handler
        """
        packet = Packet.deserialize(ReadStream(data), self.server.packets)

        if not getattr(packet.header, 'packet_name', None):
            self.server.handle('pkt:unknown_packet', packet)
        else:
            log.debug(
                f'[{self.server.type}] Recieved LU Packet {packet.header.packet_name}'
            )
            self.server.handle(f'pkt:{packet.header.packet_name}', packet,
                               conn)
コード例 #9
0
    def collected(self, packet, conn: Connection, stream: ReadStream):
        """
        Handles the has been collected game message
        """

        objid = stream.read(c_int64)

        print(f'Collected object')
        print(f'ID: {packet.objid}')
        print(f'Player: {objid}')

        session = self.server.handle_until_return('session:get_session',
                                                  conn.get_address())
        char = self.server.handle_until_return(
            'char:characters',
            session.account.user.id)[session.account.front_character]
        clone = self.server.handle_until_return('world:get_clone',
                                                session.clone)
        char_missions = self.server.handle_until_return(
            'char:get_missions', char.pk)

        objs = [x for x in clone.objects if x.objid == packet.objid]

        if objs:
            obj = objs[0]

            for char_mission in [x for x in char_missions if x.state == 2]:
                tasks = self.server.handle_until_return(
                    'world:get_mission_tasks', char_mission.mission)

                for task in tasks:
                    if task[3] == obj.lot and task[2] == 3:
                        char_mission.progress += 1
                        char_mission.save()

                        wstr = WriteStream()

                        wstr.write(c_int(char_mission.mission))
                        wstr.write(c_int(1 << (tasks.index(task) + 1)))
                        wstr.write(c_uint8(1))
                        wstr.write(
                            c_float(char_mission.progress + (clone.zone << 8)))

                        msg = ServerGameMessage(
                            objid, GameMessageID.NOTIFY_MISSION_TASK, wstr)

                        conn.send(msg)

                        return
コード例 #10
0
    def client_game_message(self, packet: ClientGameMessage, conn: Connection):
        """
        Handles the game messages
        """
        if packet.extra_data:
            stream = ReadStream(packet.extra_data)

        if packet.message_id == GameMessageID.REQUEST_USE:
            self.request_use(packet, conn, stream)
        elif packet.message_id == GameMessageID.MISSION_DIALOGUE_OK:
            self.mission_accept(packet, conn, stream)
        elif packet.message_id == GameMessageID.REQUEST_LINKED_MISSION:
            self.request_linked_mission(packet, conn, stream)
        elif packet.message_id == GameMessageID.HAS_BEEN_COLLECTED:
            self.collected(packet, conn, stream)
        elif packet.message_id == 888:
            pass
        else:
            print(f'Unhandled game message: {packet.message_id}')
コード例 #11
0
 def deserialize(cls, stream: ReadStream):
     """
     Deserializes the packet
     """
     return cls(username=stream.read(str, allocated_length=33),
                password=stream.read(str, allocated_length=41),
                language_id=stream.read(c_uint16),
                unknown=stream.read(c_uint8),
                process_memory_info=stream.read(str, allocated_length=256),
                graphics_driver_info=stream.read(str, allocated_length=128),
                processor_count=stream.read(c_uint32),
                processor_type=stream.read(c_uint32),
                processor_level=stream.read(c_uint16),
                processor_revision=stream.read(c_uint16),
                unknown1=stream.read(c_uint32),
                os_major_version=stream.read(c_uint32),
                os_minor_version=stream.read(c_uint32),
                os_build_number=stream.read(c_uint32),
                os_platform_id=stream.read(c_uint32))
コード例 #12
0
 def deserialize(cls, stream: ReadStream):
     """
     Deserializes the game version
     """
     return cls(stream.read(c_uint16), stream.read(c_uint16), stream.read(c_uint16))
コード例 #13
0
ファイル: world_redirect.py プロジェクト: luxaritas/PyLUS
 def deserialize(cls, stream: ReadStream):
     """
     Deserializes the packet
     """
     char_id = stream.read(c_int64)
     return cls(char_id)
コード例 #14
0
    def request_use(self, packet, conn: Connection, stream: ReadStream):
        """
        Handles the request use game message
        """
        session = self.server.handle_until_return('session:get_session',
                                                  conn.get_address())
        clone = self.server.handle_until_return('world:get_clone',
                                                session.clone)
        char = self.server.handle_until_return(
            'char:front_char', session.account.character_set.all())
        char_missions = self.server.handle_until_return(
            'char:get_missions', char.pk)

        multiinteract = stream.read(c_bit)
        multiinteract_id = stream.read(c_uint32)
        multiinteract_type = stream.read(c_int)
        objid = stream.read(c_int64)
        secondary = stream.read(c_bit)

        print(f'Multi interact: {multiinteract}')
        print(f'Multi interact ID: {multiinteract_id}')
        print(f'Multi interact type: {multiinteract_type}')
        print(f'Object ID: {objid}')
        print(f'Secondary: {secondary}')

        objs = [x for x in clone.objects if x.objid == objid]

        if objs:
            obj = objs[0]

            if char_missions:
                missions = self.server.handle_until_return(
                    'world:missions_for_lot_target', obj.lot)

                for char_mission in [x for x in char_missions if x.state == 2]:
                    missions2 = [
                        x for x in missions if x[0] == char_mission.mission
                    ]

                    if missions2:
                        mission = missions2[0]

                        self.server.handle('char:complete_mission', char.pk,
                                           mission[0])

                        msg = ServerGameMessage(
                            packet.objid, GameMessageID.OFFER_MISSION,
                            c_int(mission[0]) + c_int64(objid))
                        conn.send(msg)

                        return

            missions = self.server.handle_until_return(
                'world:missions_for_lot', obj.lot)
            missions = [
                x for x in missions if x[0] not in
                [y.mission for y in char_missions if y.state == 8]
            ]

            if missions:
                mission = missions[0]

                msg = ServerGameMessage(packet.objid,
                                        GameMessageID.OFFER_MISSION,
                                        c_int(mission[0]) + c_int64(objid))

                conn.send(msg)
コード例 #15
0
ファイル: luzreader.py プロジェクト: luxaritas/PyLUS
class LUZReader:
    """
    LEGO Universe Zone file reader
    """
    def __init__(self, file, conn=None):
        self.conn = conn or sqlite3.connect('client_assets/cdclient.sqlite')
        self.scenes = []

        with open(file, 'rb') as file:
            self.data = file.read()
            self.size = len(self.data)
            self.stream = ReadStream(self.data, unlocked=True)

        self.version = self.stream.read(c_uint)
        assert self.version == 41, self.version
        self.unknown1 = self.stream.read(c_uint)
        self.world_id = self.stream.read(c_uint)

        self.spawnpoint = Vector3(self.stream.read(c_float), self.stream.read(c_float), self.stream.read(c_float))
        self.spawnpoint_rot = Vector4(self.stream.read(c_float), self.stream.read(c_float), self.stream.read(c_float),
                                      self.stream.read(c_float))

        self.num_scenes = self.stream.read(c_uint)

        for _ in range(self.num_scenes):
            filename = self.stream.read(bytes, length_type=c_ubyte).decode('latin1')
            scene_id = self.stream.read(c_uint64)
            scene_name = self.stream.read(bytes, length_type=c_ubyte).decode('latin1')
            assert self.stream.read(bytes, length=3)
            pth = os.path.join('client_assets', 'luz', filename)

            if os.path.exists(pth):
                with open(pth, 'rb') as file:
                    objects = self.get_lvl_objects(ReadStream(file.read(), unlocked=True))
                    self.scenes.append(LUScene(scene_id, scene_name, objects))
            else:
                self.scenes.append(LUScene(scene_id, scene_name))

    def get_lvl_objects(self, stream):
        """
        Parses a level file and returns its objects
        """
        header = stream.read(bytes, length=4)
        objects = []

        stream.read_offset = 0

        if header == b'CHNK':
            while not stream.all_read():
                assert stream.read_offset // 8 % 16 == 0
                start_pos = stream.read_offset // 8
                assert stream.read(bytes, length=4) == b'CHNK'

                chunk_type = stream.read(c_uint)
                assert stream.read(c_ushort) == 1
                assert stream.read(c_ushort) in (1, 2)
                chunk_len = stream.read(c_uint)
                data_pos = stream.read(c_uint)
                stream.read_offset = data_pos * 8
                assert stream.read_offset // 8 % 16 == 0

                if chunk_type == 1000:
                    pass
                elif chunk_type == 2000:
                    pass
                elif chunk_type == 2001:
                    objects = self.parse_chunk_2001(stream)
                elif chunk_type == 2002:
                    pass

                stream.read_offset = (start_pos + chunk_len) * 8

        return objects

    def parse_chunk_2001(self, stream):
        """
        Parses chunk 2001
        """
        objects = []

        for _ in range(stream.read(c_uint)):
            objid = stream.read(c_int64)
            lot = stream.read(c_uint)
            unknown1 = stream.read(c_uint)
            unknown2 = stream.read(c_uint)
            position = Vector3(stream.read(c_float), stream.read(c_float), stream.read(c_float))

            rot_w = stream.read(c_float)
            rot_z = stream.read(c_float)
            rot_y = stream.read(c_float)
            rot_x = stream.read(c_float)

            rotation = Vector4(rot_x, rot_y, rot_z, rot_w)
            scale = stream.read(c_float)
            config_data = parse_ldf(stream.read(str, length_type=c_uint))

            assert stream.read(c_uint) == 0

            if config_data.get('renderDisabled'):
                continue

            if lot == 176:
                lot = config_data['spawntemplate']

            # if lot == 4638:
            #     continue

            obj = LUObject(objid, lot, position, rotation, scale, config_data, self.conn)
            objects.append(obj)

        return objects
コード例 #16
0
class LUZReader:
    """
    LEGO Universe Zone file reader
    """
    def __init__(self, file, server_zone):
        self.conn = sqlite3.connect('client_assets/cdclient.sqlite')
        self.scenes = []

        with open(file, 'rb') as file:
            self.data = file.read()
            self.size = len(self.data)
            self.stream = ReadStream(self.data, unlocked=True)

        self.version = self.stream.read(c_uint)
        assert self.version in (36, 38, 39, 40, 41), 'Unknown LUZ version ' + self.version
        self.unknown1 = self.stream.read(c_uint)
        self.world_id = self.stream.read(c_uint)

        if self.version >= 38:
            self.spawnpoint = Vector3(self.stream.read(c_float), self.stream.read(c_float), self.stream.read(c_float))
            self.spawnpoint_rot = LVLVector4(self.stream.read(c_float), self.stream.read(c_float), self.stream.read(c_float),
                                          self.stream.read(c_float))
        else:
            # TODO: Verify what should actually happen in versions < 38
            self.spawnpoint = Vector3(0,0,0)
            self.spawnpoint_rot = Vector4(0,0,0,0)

        if self.version >= 37:
            self.num_scenes = self.stream.read(c_uint)
        else:
            self.num_scenes = self.stream.read(c_ubyte)

        for _ in range(self.num_scenes):
            filename = self.stream.read(bytes, length_type=c_ubyte).decode('latin1')
            scene_id = self.stream.read(c_uint64)
            scene_name = self.stream.read(bytes, length_type=c_ubyte).decode('latin1')
            assert self.stream.read(bytes, length=3)
            lvl_path = os.path.join('client_assets', 'lvl', server_zone, filename)

            if os.path.exists(lvl_path):
                with open(lvl_path, 'rb') as file:
                    objects = self.get_lvl_objects(ReadStream(file.read(), unlocked=True))
                    self.scenes.append(LUScene(scene_id, scene_name, objects))
            else:
                self.scenes.append(LUScene(scene_id, scene_name))

    def get_lvl_objects(self, stream):
        """
        Parses a level file and returns its objects
        """
        header = stream.read(bytes, length=4)
        objects = []

        stream.read_offset = 0

        if header == b'CHNK':
            while not stream.all_read():
                assert stream.read_offset // 8 % 16 == 0, 'Invalid LVL chunk read offset'
                start_pos = stream.read_offset // 8
                assert stream.read(bytes, length=4) == b'CHNK'

                chunk_type = stream.read(c_uint)
                assert stream.read(c_ushort) == 1
                assert stream.read(c_ushort) in (1, 2)
                chunk_len = stream.read(c_uint)
                data_pos = stream.read(c_uint)
                stream.read_offset = data_pos * 8
                assert stream.read_offset // 8 % 16 == 0

                if chunk_type == 1000:
                    pass
                elif chunk_type == 2000:
                    pass
                elif chunk_type == 2001:
                    objects = self.parse_chunk_2001(stream)
                elif chunk_type == 2002:
                    pass

                stream.read_offset = (start_pos + chunk_len) * 8

        return objects

    def parse_chunk_2001(self, stream):
        """
        Parses chunk 2001
        """
        objects = []

        for _ in range(stream.read(c_uint)):
            objid = stream.read(c_int64)
            lot = stream.read(c_uint)
            unknown1 = stream.read(c_uint)
            unknown2 = stream.read(c_uint)

            position = stream.read(Vector3)
            rotation = stream.read(LVLVector4)
            scale = stream.read(c_float)

            config_data = parse_ldf(stream.read(str, length_type=c_uint))

            assert stream.read(c_uint) == 0

            if config_data.get('renderDisabled'):
                continue

            spawner=None
            if lot == 176:
                spawner=objid
                lot = config_data['spawntemplate']
                objid = random.randint(1000000000000000000, 1999999999999999999)

            obj = LUObject(objid, lot, position, rotation, scale, config_data, spawner, self.conn)
            objects.append(obj)

        return objects