Beispiel #1
0
def pack_level(item):
    """
    Pack a level-related item to its binary representation readable by
    Elastomania.
    """

    if type(item).__name__ in packers:
        return packers[type(item).__name__](item)

    level = item
    polygon_checksum = sum([
        sum([point.x + point.y for point in polygon.points])
        for polygon in level.polygons
    ])
    object_checksum = sum(
        [obj.point.x + obj.point.y + obj.type for obj in level.objects])
    picture_checksum = sum(
        [picture.point.x + picture.point.y for picture in level.pictures])
    collected_checksum = 3247.764325643 * (polygon_checksum + object_checksum +
                                           picture_checksum)
    integrity_1 = collected_checksum
    integrity_2 = random.randint(0, 5871) + 11877 - collected_checksum
    integrity_3 = random.randint(0, 5871) + 11877 - collected_checksum
    integrity_4 = random.randint(0, 6102) + 12112 - collected_checksum
    assert ((integrity_3 - integrity_2) <= 5871)

    return b''.join([
        bytes('POT14', 'latin1'),
        struct.pack('H', level.level_id & 0xFFFF),
        struct.pack('I', level.level_id),
        struct.pack('d', integrity_1),
        struct.pack('d', integrity_2),
        struct.pack('d', integrity_3),
        struct.pack('d', integrity_4),
        null_padded(level.name, 51),
        null_padded(level.lgr, 16),
        null_padded(level.ground_texture, 10),
        null_padded(level.sky_texture, 10),
        struct.pack('d',
                    len(level.polygons) + 0.4643643),
    ] + [pack_level(polygon) for polygon in level.polygons] + [
        struct.pack('d',
                    len(level.objects) + 0.4643643),
    ] + [pack_level(obj) for obj in level.objects] + [
        struct.pack('d',
                    len(level.pictures) + 0.2345672),
    ] + [pack_level(picture) for picture in level.pictures] + [
        struct.pack('I', END_OF_DATA_MARKER),
    ] + [bytes(chr(c), 'latin1') for c in TOP10_SINGLEPLAYER] + [] +
                    [bytes(chr(c), 'latin1') for c in TOP10_MULTIPLAYER] + [
                        struct.pack('I', END_OF_FILE_MARKER),
                    ])
Beispiel #2
0
def pack_LGR(lgr):
    """
    Converts LGR object into its binary representation to be saved as an lgr
    file.
    """

    def to_int32(val):
        return struct.pack('<I', val)

    l = 0
    l_name = []
    l_image_type = []
    l_default_distance = []
    l_default_clipping = []
    l_transparency = []
    x = []
    for obj in lgr.images:
        if(obj.is_in_pictures_lst()):
            l = l+1
            l_name.extend([null_padded(obj.name, 8), b'\0\0'])
            l_image_type.append(to_int32(obj.image_type))
            l_default_distance.append(to_int32(obj.default_distance))
            l_default_clipping.append(to_int32(obj.default_clipping))
            l_transparency.append(to_int32(obj.transparency))
        with io.BytesIO() as f:
            obj.save_PCX(f)
            x_len = f.tell()
            f.seek(0)
            x.extend([
                null_padded('%s.pcx' % obj.name, 13),
                bytes(obj.padding),
                to_int32(x_len),
                f.read()])

    return b"".join([
        b'LGR12',
        to_int32(len(lgr.images)),
        to_int32(LGR_PICTURES_LST_ID),
        to_int32(l),
        b''.join(l_name),
        b''.join(l_image_type),
        b''.join(l_default_distance),
        b''.join(l_default_clipping),
        b''.join(l_transparency),
        b''.join(x),
        to_int32(LGR_END_OF_FILE)])
Beispiel #3
0
def pack_LGR(lgr: LGR) -> bytes:
    """
    Converts LGR object into its binary representation to be saved as an lgr
    file.
    """
    def to_int32(val: int) -> bytes:
        return struct.pack('<I', val)

    n_pics = 0
    l_name = []
    l_image_type = []
    l_default_distance = []
    l_default_clipping = []
    l_transparency = []
    x = []
    for obj in lgr.images:
        if obj.is_in_pictures_lst():
            n_pics = n_pics + 1
            l_name.extend([null_padded(obj.name, 8), b'\0\0'])
            l_image_type.append(to_int32(obj.image_type))
            l_default_distance.append(to_int32(obj.default_distance))
            l_default_clipping.append(to_int32(obj.default_clipping))
            l_transparency.append(to_int32(obj.transparency))
        with io.BytesIO() as f:
            obj.save_PCX(f)
            x_len = f.tell()
            f.seek(0)
            x.extend([
                null_padded('%s.pcx' % obj.name, 13),
                bytes(obj.padding),
                to_int32(x_len),
                f.read()
            ])

    return b"".join([
        b'LGR12',
        to_int32(len(lgr.images)),
        to_int32(LGR_PICTURES_LST_ID),
        to_int32(n_pics), b''.join(l_name), b''.join(l_image_type),
        b''.join(l_default_distance), b''.join(l_default_clipping),
        b''.join(l_transparency), b''.join(x),
        to_int32(LGR_END_OF_FILE)
    ])
Beispiel #4
0
 def to_buffer(self) -> bytes:
     self.sort()
     return b''.join([
         struct.pack('I', len(self.single)),
         b''.join([struct.pack('I', t.time) for t in self.single]),
         b''.join([struct.pack('I', 0)
                   for _ in range(10 - len(self.single))]),
         b''.join([null_padded(t.kuski, 15) for t in self.single]),
         b''.join([null_padded('', 15)
                   for _ in range(10 - len(self.single))]),
         b''.join([null_padded(t.kuski2, 15) for t in self.single]),
         b''.join([null_padded('', 15)
                   for _ in range(10 - len(self.single))]),
         struct.pack('I', len(self.multi)),
         b''.join([struct.pack('I', t.time) for t in self.multi]),
         b''.join([struct.pack('I', 0)
                   for _ in range(10 - len(self.multi))]),
         b''.join([null_padded(t.kuski, 15) for t in self.multi]),
         b''.join([null_padded('', 15)
                   for _ in range(10 - len(self.multi))]),
         b''.join([null_padded(t.kuski2, 15) for t in self.multi]),
         b''.join([null_padded('', 15)
                   for _ in range(10 - len(self.multi))]),
     ])
Beispiel #5
0
def pack_level(item: LevelItem, is_elma: bool = True) -> bytes:
    """
    Pack a level-related item to its binary representation readable by
    Elasto Mania.
    """

    if not is_elma and type(item).__name__ in ['Polygon', 'Obj']:
        packer_name = 'Across' + type(item).__name__
    else:
        packer_name = type(item).__name__
    if packer_name in packers:
        return packers[packer_name](item)

    if isinstance(item, elma.models.Level):
        level = item
    else:
        raise NotImplementedError(
            f"Packing not implemented for type {type(item)}.")
    if is_elma:
        assert (level.version == VERSION_ELMA)
    else:
        assert (level.version == VERSION_ACROSS)

    polygon_checksum = sum([
        sum([point.x + point.y for point in polygon.points])
        for polygon in level.polygons
    ])
    object_checksum = sum(
        [obj.point.x + obj.point.y + obj.type for obj in level.objects])
    picture_checksum = sum(
        [picture.point.x + picture.point.y
         for picture in level.pictures]) if is_elma else 0
    collected_checksum = 3247.764325643 * (polygon_checksum + object_checksum +
                                           picture_checksum)
    if level.preserve_integrity_values:
        integrity_1, integrity_2, integrity_3, integrity_4 = level.integrity
    else:
        integrity_1 = collected_checksum
        integrity_2 = random.randint(0, 5871) + 11877 - collected_checksum
        integrity_3 = random.randint(0, 5871) + 11877 - collected_checksum
        integrity_4 = random.randint(0, 6102) + 12112 - collected_checksum
    assert ((integrity_3 - integrity_2) <= 5871)

    if is_elma:
        return b''.join([
            bytes(level.version, 'latin1'),
            struct.pack('H', level.level_id & 0xFFFF),
            struct.pack('I', level.level_id),
            struct.pack('d', integrity_1),
            struct.pack('d', integrity_2),
            struct.pack('d', integrity_3),
            struct.pack('d', integrity_4),
            null_padded(level.name, 51),
            null_padded(level.lgr, 16),
            null_padded(level.ground_texture, 10),
            null_padded(level.sky_texture, 10),
            struct.pack('d',
                        len(level.polygons) + 0.4643643),
        ] + [pack_level(polygon) for polygon in level.polygons] + [
            struct.pack('d',
                        len(level.objects) + 0.4643643),
        ] + [pack_level(obj) for obj in level.objects] + [
            struct.pack('d',
                        len(level.pictures) + 0.2345672),
        ] + [pack_level(picture) for picture in level.pictures] + [
            struct.pack('I', END_OF_DATA_MARKER),
        ] + [
            bytes(chr(c), 'latin1')
            for c in crypt_top10(level.top10.to_buffer())
        ] + [
            struct.pack('I', END_OF_FILE_MARKER),
        ])
    else:
        level_data = [
            bytes(level.version, 'latin1'),
            struct.pack('I', level.level_id),
            struct.pack('d', integrity_1),
            struct.pack('d', integrity_2),
            struct.pack('d', integrity_3),
            struct.pack('d', integrity_4),
            null_padded(level.name, 15),
            null_padded('', 44),
            struct.pack('d',
                        len(level.polygons) + 0.4643643),
        ] + [pack_level(polygon, False) for polygon in level.polygons] + [
            struct.pack('d',
                        len(level.objects) + 0.4643643),
        ] + [pack_level(obj, False) for obj in level.objects]

        if len(level.top10.single) > 0 or len(level.top10.multi) > 0:
            level_data += [
                struct.pack('I', END_OF_DATA_MARKER),
            ] + [
                bytes(chr(c), 'latin1')
                for c in crypt_top10(level.top10.to_buffer())
            ] + [
                struct.pack('I', END_OF_FILE_MARKER),
            ]
        return b''.join(level_data)
Beispiel #6
0
def pack_replay(item: Union[elma.models.Event, elma.models.Replay]) -> bytes:
    """
    Pack a replay-related item to its binary representation readable by
    Elasto Mania.
    """

    if isinstance(item, elma.models.ObjectTouchEvent):
        return (struct.pack('d', item.time) +
                struct.pack('I', item.object_number) + struct.pack('f', 0))

    if isinstance(item, elma.models.TurnEvent):
        return (struct.pack('d', item.time) + struct.pack('h', -1) +
                struct.pack('h', 5) + struct.pack('f', 0.99))

    if isinstance(item, elma.models.LeftVoltEvent):
        return (struct.pack('d', item.time) + struct.pack('h', -1) +
                struct.pack('h', 7) + struct.pack('f', 0.99))

    if isinstance(item, elma.models.RightVoltEvent):
        return (struct.pack('d', item.time) + struct.pack('h', -1) +
                struct.pack('h', 6) + struct.pack('f', 0.99))

    if isinstance(item, elma.models.GroundTouchEvent):
        return (struct.pack('d', item.time) + struct.pack('h', -1) +
                struct.pack('h', 1) +
                struct.pack('f', item.event_sound_volume))

    if isinstance(item, elma.models.AppleTouchEvent):
        return (struct.pack('d', item.time) + struct.pack('h', -1) +
                struct.pack('h', 4) + struct.pack('f', 0.99))
    if isinstance(item, elma.models.Replay):
        replay = item
    else:
        raise NotImplementedError(
            f"Packing not implemented for type {type(item)}")

    name = null_padded(replay.level_name, 12)
    return b''.join([
        struct.pack('i', len(replay.frames)),
        struct.pack('i', 0x83),
        struct.pack('i', replay.is_multi),
        struct.pack('i', replay.is_flagtag),
        struct.pack('I', replay.level_id),
        name,
        struct.pack('i', 0),
        b''.join(
            [struct.pack('f', frame.position.x) for frame in replay.frames]),
        b''.join(
            [struct.pack('f', frame.position.y) for frame in replay.frames]),
        b''.join([
            struct.pack('h', frame.left_wheel_position.x)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.left_wheel_position.y)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.right_wheel_position.x)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.right_wheel_position.y)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.head_position.x) for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.head_position.y) for frame in replay.frames
        ]),
        b''.join([struct.pack('h', frame.rotation)
                  for frame in replay.frames]),
        b''.join([
            struct.pack('B', frame.left_wheel_rotation)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('B', frame.right_wheel_rotation)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack(
                'B', frame._gas_and_turn_state & 0b11111100 |
                (frame.is_turned_right << 1) | frame.is_gasing)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.spring_sound_effect_volume)
            for frame in replay.frames
        ]),
        struct.pack('I', len(replay.events)),
        b''.join([pack_replay(event) for event in replay.events]),
        struct.pack('I', END_OF_REPLAY_FILE_MARKER),
    ])
Beispiel #7
0
    lambda polygon: b''.join([
        struct.pack('I', len(polygon.points)),
    ] + [pack_level(point) for point in polygon.points]),
    'Obj':
    lambda obj: b''.join([
        pack_level(obj.point),
        struct.pack('I', obj.type),
        struct.pack('I', obj.gravity),
        struct.pack('I', obj.animation_number - 1)
    ]),
    'AcrossObj':
    lambda obj: b''.join([pack_level(obj.point),
                          struct.pack('I', obj.type)]),
    'Picture':
    lambda picture: b''.join([
        null_padded(picture.picture_name, 10),
        null_padded(picture.texture_name, 10),
        null_padded(picture.mask_name, 10),
        pack_level(picture.point),
        struct.pack('I', picture.distance),
        struct.pack('I', picture.clipping)
    ])
}


def pack_level(item: LevelItem, is_elma: bool = True) -> bytes:
    """
    Pack a level-related item to its binary representation readable by
    Elasto Mania.
    """
Beispiel #8
0
def pack_replay(item):
    """
    Pack a replay-related item to its binary representation readable by
    Elastomania.
    """

    if isinstance(item, ObjectTouchEvent):
        return (struct.pack('d', item.time) +
                struct.pack('I', item.object_number) + struct.pack('I', 0))

    if isinstance(item, TurnEvent):
        return (struct.pack('d', item.time) + struct.pack('I', 393215) +
                struct.pack('I', 1065185444))

    if isinstance(item, LeftVoltEvent):
        return (struct.pack('d', item.time) + struct.pack('I', 524287) +
                struct.pack('I', 1065185444))

    if isinstance(item, RightVoltEvent):
        return (struct.pack('d', item.time) + struct.pack('I', 458751) +
                struct.pack('I', 1065185444))

    if isinstance(item, GroundTouchAEvent):
        return (struct.pack('d', item.time) + struct.pack('I', 131071) +
                struct.pack('I', item.value))

    if isinstance(item, GroundTouchBEvent):
        return (struct.pack('d', item.time) + struct.pack('I', 327679) +
                struct.pack('I', item.value))

    replay = item
    if PY_VERSION == 2:
        name = null_padded(replay.level_name, 12)
    else:
        name = null_padded(replay.level_name.decode('latin1'), 12)
    return b''.join([
        struct.pack('i', len(replay.frames)),
        struct.pack('i', 0x83),
        struct.pack('i', replay.is_multi),
        struct.pack('i', replay.is_flagtag),
        struct.pack('I', replay.level_id),
        name,
        struct.pack('i', 0),
        b''.join(
            [struct.pack('f', frame.position.x) for frame in replay.frames]),
        b''.join(
            [struct.pack('f', frame.position.y) for frame in replay.frames]),
        b''.join([
            struct.pack('h', frame.left_wheel_position.x)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.left_wheel_position.y)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.right_wheel_position.x)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.right_wheel_position.y)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.head_position.x) for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.head_position.y) for frame in replay.frames
        ]),
        b''.join([struct.pack('h', frame.rotation)
                  for frame in replay.frames]),
        b''.join([
            struct.pack('B', frame.left_wheel_rotation)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('B', frame.right_wheel_rotation)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack(
                'B', frame._gas_and_turn_state & 0b11111100 |
                (frame.is_turned_right << 1) | frame.is_gasing)
            for frame in replay.frames
        ]),
        b''.join([
            struct.pack('h', frame.spring_sound_effect_volume)
            for frame in replay.frames
        ]),
        struct.pack('I', len(replay.events)),
        b''.join([pack_replay(event) for event in replay.events]),
        struct.pack('I', END_OF_REPLAY_FILE_MARKER),
    ])