def _debug_byte_structure_to_file( self, filename, trail_generator: IncrementalGenerator = None, commit=False): """ Used for debugging - Writes structure from read file to the filesystem in a easily readable manner. """ if commit and hasattr(self, '_object_manager'): self._object_manager.reconstruct() s_print("\nWriting structure to file...", final=True) with open(filename, 'w', encoding="utf-8") as f: result = [] for section in self.sections.values(): result.append(self._retrieve_byte_structure(section)) if trail_generator is not None: s_print("\tWriting trail...") trail = trail_generator.get_remaining_bytes() result.append(f"\n\n{'#' * 27} TRAIL ({len(trail)})\n\n") result.append( create_textual_hex(trail.hex(), space_distance=2, enter_distance=24)) s_print("\tWriting trail finished successfully.", final=True) f.write(''.join(result)) s_print("Writing structure to file finished successfully.", final=True)
def _load_content_sections(self, raw_file_igenerator: IncrementalGenerator): data_igenerator = IncrementalGenerator( name='Scenario Data', file_content=decompress_bytes( raw_file_igenerator.get_remaining_bytes())) for section_name in self.structure.keys(): if section_name == "FileHeader": continue try: section = self._create_and_load_section( section_name, data_igenerator) self._add_to_sections(section) except (ValueError, TypeError) as e: print( f"\n[{e.__class__.__name__}] AoE2Scenario.parse_file: \n\tSection: {section_name}\n" ) self.write_error_file(trail_generator=data_igenerator) raise e
def retrieve_bytes(igenerator: IncrementalGenerator, retriever) -> List[bytes]: """ Retrieves the bytes belonging to this retriever. Args: igenerator (IncrementalGenerator): The generator to return the bytes from retriever (Retriever): The retriever holding the bytes Returns: The corresponding bytes in a list. When 4 int8s need to retrieved, the list will have a length of 4 where each entry is 1 byte each. """ var_type, var_len = retriever.datatype.type_and_length retrieved_bytes = [] try: for i in range(retriever.datatype.repeat): if var_type != "str": # (Signed) ints, floats, chars, plain bytes etc. retrieved_bytes.append(igenerator.get_bytes(var_len)) else: # String, Stored as: (signed int (n), string (string_length = n)) int_bytes = igenerator.get_bytes(var_len) string_length = bytes_to_int(int_bytes, signed=True) string_bytes = b'' if string_length == 0 else igenerator.get_bytes( string_length) retrieved_bytes.append(int_bytes + string_bytes) except EndOfFileError: if is_end_of_file_mark(retriever): retriever.datatype.repeat = 0 return [] except TypeError: print(retriever) print(retriever.datatype.repeat) exit() # If more bytes present in the file after END_OF_FILE_MARK handle_end_of_file_mark(igenerator, retriever) return retrieved_bytes
def from_file(cls, filename, game_version): print(f"\nReading file: '{filename}'") s_print("Reading scenario file...") igenerator = IncrementalGenerator.from_file(filename) s_print("Reading scenario file finished successfully.", final=True) scenario = cls() scenario.read_mode = "from_file" scenario.game_version = game_version scenario.scenario_version = get_file_version(igenerator) # Log game and scenario version print("\n############### Attributes ###############") print(f">>> Game version: '{scenario.game_version}'") print(f">>> Scenario version: {scenario.scenario_version}") print("##########################################") s_print(f"\nLoading scenario structure...") initialise_version_dependencies(scenario.game_version, scenario.scenario_version) scenario._load_structure() s_print(f"Loading scenario structure finished successfully.", final=True) # scenario._initialize(igenerator) s_print("Parsing scenario file...", final=True) scenario._load_header_section(igenerator) scenario._load_content_sections(igenerator) s_print(f"Parsing scenario file finished successfully.", final=True) scenario._object_manager = AoE2ObjectManager( sections=scenario.sections, game_version=scenario.game_version, scenario_version=scenario.scenario_version) scenario._object_manager.setup() return scenario
def get_file_version(generator: IncrementalGenerator): """Get first 4 bytes of a file, which contains the version of the scenario""" return generator.get_bytes(4, update_progress=False).decode('ASCII')