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), ])
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)])
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) ])
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))]), ])
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)
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), ])
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. """
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), ])