def decode(file: Path, debug: bool = False) -> AMap: """ :raises ValueError: something failed """ with file.open("rb") as reader: data = reader.read() identifier = data[0:11].decode("utf-8") if debug: utils.debug_print(data[0:11], "identifier", identifier, 0) offset = 11 if identifier == MapType.CMAP.value: version = utils.unpack_from('<B', data, offset, ("version", ), debug)[0] offset += 1 if version == 0: return CMap_0.decode(data, offset, debug) elif version == 1: return CMap_1.decode(data, offset, debug) else: raise ValueError( f"reading .cmap version {version} is not supported") elif identifier == MapType.ECMAP.value: version = utils.unpack_from('<B', data, offset, ("version", ), debug)[0] offset += 1 if version == 0: return ECMap_0.decode(data, offset, debug) elif version == 1: return ECMap_1.decode(data, offset, debug) elif version == 2: return ECMap_2.decode(data, offset, debug) else: raise ValueError( f"reading .ecmap version {version} is not supported") else: raise ValueError("given data is not a .cmap or .ecmap")
def decode(file: Path, debug: bool = False) -> AMap: """ :raises ValueError: something failed """ with file.open("rb") as reader: data = reader.read() identifier = data[0:11].decode("utf-8") if debug: utils.debug_print(data[0:11], "identifier", identifier, 0) offset = 11 if identifier != MapType.CMAP.value and identifier != MapType.ECMAP.value: raise ValueError("given data is not a .cmap or .ecmap") version = utils.unpack_from('<B', data, offset, ("version", ), debug)[0] offset += 1 map_cls = _TYPE_MAP.get((MapType(identifier), version), None) if map_cls is None: raise ValueError( f"reading {identifier} version {version} is not supported") return map_cls.decode(data, offset, debug)
def decode(cls, data: bytes, offset: int, debug: bool = False) -> CMap_2: cmap = CMap_2() name_len = utils.unpack_from('<B', data, offset, ("name length", ), debug)[0] offset += 1 cmap.name = data[offset:offset + name_len].decode("utf-8") if debug: utils.debug_print(data[offset:offset + name_len], "name", cmap.name, offset) offset += name_len utils.unpack_from('<?', data, offset, ("unused (gamemode)", ), debug) offset += 1 cmap.sun_rotation_hor = utils.unpack_from( '<f', data, offset, ("sun rotation horizontal", ), debug)[0] offset += 4 cmap.sun_rotation_ver = utils.unpack_from('<f', data, offset, ("sun rotation vertical", ), debug)[0] offset += 4 cmap.camera_pos = utils.unpack_from( '<ddd', data, offset, ("camera pos x", "camera pos y", "camera pos z"), debug) offset += 3 * 8 cmap.camera_look = utils.unpack_from( '<ddd', data, offset, ("camera look x", "camera look y", "camera look z"), debug) offset += 3 * 8 # entities processing ent_count = utils.unpack_from('<I', data, offset, ("entity count", ), debug)[0] offset += 4 ent_done = 0 while ent_done < ent_count: ent_type = utils.unpack_from('<B', data, offset, ("entity type", ), debug)[0] offset += 1 if ent_type == 0: cur_ent = Block_2.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 1: cur_ent = Sphere_2.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 2: cur_ent = PlayerStart_2.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 3: cur_ent = BarrierWall_2.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 4: cur_ent = BarrierFloor_2.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 128: cur_ent = Dummy_2.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size else: raise ValueError( f"Unknown entity type: {ent_type} at {offset - 1}") ent_done += 1 if debug: print(offset, " / ", len(data), " consumed") if offset != len(data): raise ValueError("Not all bytes were consumed") return cmap
def decode(cls, data: bytes, offset: int, debug: bool = False) -> CMap: cmap = CMap() name_len = utils.unpack_from('<B', data, offset, ("name length",), debug)[0] offset += 1 cmap.name = data[offset:offset + name_len].decode("utf-8") if debug: utils.debug_print(data[offset:offset + name_len], "name", cmap.name, offset) offset += name_len utils.unpack_from('<?', data, offset, ("unused (gamemode)",), debug) offset += 1 # checkpoint times cmap.checkpoint_times = decode_checkpoint_times(data, offset, debug) # checkpoint times count + 4 (platin, gold, silver, bronze) * checkpoint times * 4 bytes offset += 1 + 4 * len(cmap.checkpoint_times) * 4 cmap.sun_rotation = utils.unpack_from('<f', data, offset, ("sun rotation",), debug)[0] offset += 4 cmap.sun_angle = utils.unpack_from('<f', data, offset, ("sun angle",), debug)[0] offset += 4 cmap.camera_pos = utils.unpack_from('<ddd', data, offset, ("camera pos x", "camera pos y", "camera pos z"), debug) offset += 3 * 8 cmap.camera_look = utils.unpack_from('<ddd', data, offset, ("camera look x", "camera look y", "camera look z"), debug) offset += 3 * 8 # entities processing ent_count = utils.unpack_from('<I', data, offset, ("entity count",), debug)[0] offset += 4 ent_done = 0 while ent_done < ent_count: ent_type = utils.unpack_from('<B', data, offset, ("entity type",), debug)[0] offset += 1 if ent_type == 0: cur_ent = Block.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 1: cur_ent = Sphere.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 2: cur_ent = PlayerStart.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 128: cur_ent = Dummy.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size else: raise ValueError(f"Unknown entity type: {ent_type} at {offset - 1}") ent_done += 1 if debug: print(offset, " / ", len(data), " consumed") if offset != len(data): raise ValueError("Not all bytes were consumed") return cmap
def decode(cls, data: bytes, offset: int, debug: bool = False) -> 'ECMAP': cmap = CMap_0() name_len = utils.unpack_from('<B', data, offset, ("name length", ), debug)[0] offset += 1 cmap.name = data[offset:offset + name_len].decode("utf-8") if debug: utils.debug_print(data[offset:offset + name_len], "name", cmap.name, offset) offset += name_len cmap.timer_enabled = utils.unpack_from('<?', data, offset, ("timer enabled", ), debug) offset += 1 utils.unpack_from('<B', data, offset, ("unused", ), debug) offset += 1 cmap.sun_rotation = utils.unpack_from('<f', data, offset, ("sun rotation", ), debug)[0] offset += 4 cmap.sun_angle = utils.unpack_from('<f', data, offset, ("sun angle", ), debug)[0] offset += 4 cmap.camera_pos = utils.unpack_from( '<ddd', data, offset, ("camera pos x", "camera pos y", "camera pos z"), debug) offset += 3 * 8 cmap.camera_look = utils.unpack_from( '<ddd', data, offset, ("camera look x", "camera look y", "camera look z"), debug) offset += 3 * 8 # entities processing ent_count = utils.unpack_from('<I', data, offset, ("entity count", ), debug)[0] offset += 4 ent_done = 0 while ent_done < ent_count: ent_type = utils.unpack_from('<B', data, offset, ("entity type", ), debug)[0] offset += 1 if ent_type == 0: cur_ent = Block_0.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 1: cur_ent = Sphere_0.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 2: cur_ent = PlayerStart_0.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size elif ent_type == 128: cur_ent = Dummy_0.decode(data, offset, debug) cmap.entities.append(cur_ent) offset += cur_ent.byte_size else: raise ValueError( f"Unknown entity type: {ent_type} at {offset - 1}") ent_done += 1 if debug: print(offset, " / ", len(data), " consumed") if offset != len(data): raise ValueError("Not all bytes were consumed") ecmap = ECMap() ecmap.cmap = cmap return ecmap