pub struct ModuleFile {
pub header: ModuleHeader,
pub files: Vec<ModuleFileEntry>,
pub resource_indices: Vec<u32>,
blocks: Vec<ModuleBlockEntry>,
file_data_offset: u64,
module_file: Option<BufReader<File>>,
hd1_file: Option<BufReader<File>>,
pub use_hd1: bool,
}
Expand description
Module structure which contains the layout of the entire module file.
Fields§
§header: ModuleHeader
Information relating to how the other fields should be read.
files: Vec<ModuleFileEntry>
Metadata regarding compression and layout of files (tags).
resource_indices: Vec<u32>
Indices of resource files present in the module.
blocks: Vec<ModuleBlockEntry>
Uncompressed/compressed blocks making up a file.
file_data_offset: u64
Offset in BufReader
where file data starts.
module_file: Option<BufReader<File>>
Reference to the module file buffer.
hd1_file: Option<BufReader<File>>
Reference to HD1 buffer if it exists.
use_hd1: bool
Whether to use the HD1 module or not.
Implementations§
Source§impl ModuleFile
impl ModuleFile
Sourcepub fn from_path<T: AsRef<Path>>(file_path: T) -> Result<Self>
pub fn from_path<T: AsRef<Path>>(file_path: T) -> Result<Self>
Instantiates a ModuleFile
object from the given file path.
Examples found in repository?
21fn load_modules<R: AsRef<Path>>(deploy_path: R) -> Result<Vec<ModuleFile>> {
22 let mut modules = Vec::new();
23 for entry in walkdir::WalkDir::new(deploy_path)
24 .into_iter()
25 .filter_map(|e| e.ok())
26 {
27 if entry.file_type().is_file() {
28 let file_path = entry.path().to_str().unwrap();
29 if file_path.ends_with(".module") {
30 let module = ModuleFile::from_path(file_path)?;
31 modules.push(module);
32 }
33 }
34 }
35 Ok(modules)
36}
More examples
11fn load_modules<R: AsRef<Path>>(deploy_path: R) -> Result<Vec<ModuleFile>> {
12 let mut modules = Vec::new();
13 for entry in walkdir::WalkDir::new(deploy_path)
14 .into_iter()
15 .filter_map(|e| e.ok())
16 {
17 if entry.file_type().is_file() {
18 let file_path = entry.path().to_str().unwrap();
19 if file_path.ends_with(".module") {
20 let module = ModuleFile::from_path(file_path)?;
21 modules.push(module);
22 }
23 }
24 }
25 Ok(modules)
26}
23fn main() -> Result<()> {
24 let mut module = ModuleFile::from_path(DEPLOY_PATH)?;
25 for idx in 0..module.files.len() {
26 if module.files[idx].tag_group == SCRIPT_GROUP {
27 let tag = module.read_tag(idx as u32)?;
28 if let Some(tag) = tag {
29 let mut source = HsSourceFileTag::default();
30 tag.read_metadata(&mut source)?;
31
32 let server_buf = source.server.data;
33 let client_buf = source.client.data;
34
35 let server_file = File::create(format!("{SAVE_PATH}/{}_server.luac", tag.tag_id))?;
36 let mut bw = BufWriter::new(server_file);
37 bw.write_all(&server_buf)?;
38
39 let client_file = File::create(format!("{SAVE_PATH}/{}_client.luac", tag.tag_id))?;
40 let mut bw = BufWriter::new(client_file);
41 bw.write_all(&client_buf)?;
42 }
43 }
44 }
45 Ok(())
46}
Sourcepub fn read<T: AsRef<Path>>(&mut self, file_path: T) -> Result<()>
pub fn read<T: AsRef<Path>>(&mut self, file_path: T) -> Result<()>
Reads the module file from the given file path. This function reads the entire structure of the module file. It also calculates and stores important offsets within the file.
§Arguments
file_path
- A reference to a type that implementsPath
that holds the path to the module file.
§Errors
- If the reader fails to read the exact number of bytes
ReadError
- If the string table has invalid UTF-8
Utf8ReadingError
Sourcefn open_hd1<T: AsRef<Path>>(&mut self, file_path: T) -> Result<()>
fn open_hd1<T: AsRef<Path>>(&mut self, file_path: T) -> Result<()>
Opens the HD1 file if it exists.
Sourcefn get_tag_path(&self, index: usize, depth: usize) -> Result<String>
fn get_tag_path(&self, index: usize, depth: usize) -> Result<String>
Gets the tag path of a file entry.
This function returns the tag path of a file entry based on the provided index. For file entries that have a parent, the function recursively gets the tag path of the parent and appends the child index to the path.
§Arguments
index
- The index of the file entry to get the tag path from.depth
- The depth of the recursion. This is used to prevent infinite recursion.
§Returns
Returns the tag path of the file entry if the operation is successful.
Sourcepub fn read_tag(&mut self, index: u32) -> Result<Option<&mut ModuleFileEntry>>
pub fn read_tag(&mut self, index: u32) -> Result<Option<&mut ModuleFileEntry>>
Reads a specific tag from the module file.
This function reads a specific tag from the module file based on the provided index.
It also utilizes the HD1 stream if the file entry has the flag set for it and the stream is loaded, and returns None
if the tag offset is invalid.
§Arguments
index
- The index of the file entry to read the tag from. This index corresponds to the position of the file entry in thefiles
vector.
§Returns
Returns a mutable reference to the file if the read operation is successful, or an Error
, a None
if the file was not read (if tag offset is specified as invalid) or the containing the I/O error if any reading operation fails.
Examples found in repository?
148fn main() -> Result<()> {
149 let mut modules = load_modules(String::from("C:/XboxGames/Halo Infinite/Content/deploy/"))?;
150
151 for module in &mut modules {
152 for index in 0..module.files.len() {
153 let tag = module.read_tag(index as u32)?;
154 if let Some(tag) = tag {
155 if tag.tag_group == "mat " {
156 let mut mat = MaterialTag::default();
157 tag.read_metadata(&mut mat)?;
158 }
159 // explicitly drop buffer to free up memory
160 // normally, can take 50+ GBs of RAM
161 module.files[index].data_stream = None
162 }
163 }
164 }
165 Ok(())
166}
More examples
23fn main() -> Result<()> {
24 let mut module = ModuleFile::from_path(DEPLOY_PATH)?;
25 for idx in 0..module.files.len() {
26 if module.files[idx].tag_group == SCRIPT_GROUP {
27 let tag = module.read_tag(idx as u32)?;
28 if let Some(tag) = tag {
29 let mut source = HsSourceFileTag::default();
30 tag.read_metadata(&mut source)?;
31
32 let server_buf = source.server.data;
33 let client_buf = source.client.data;
34
35 let server_file = File::create(format!("{SAVE_PATH}/{}_server.luac", tag.tag_id))?;
36 let mut bw = BufWriter::new(server_file);
37 bw.write_all(&server_buf)?;
38
39 let client_file = File::create(format!("{SAVE_PATH}/{}_client.luac", tag.tag_id))?;
40 let mut bw = BufWriter::new(client_file);
41 bw.write_all(&client_buf)?;
42 }
43 }
44 }
45 Ok(())
46}
38fn main() -> Result<()> {
39 let args: InfiniteExtract = argh::from_env();
40 let mut modules = load_modules(args.deploy_path)?;
41 for module in &mut modules {
42 for idx in 0..module.files.len() {
43 module.read_tag(idx as u32)?;
44 }
45
46 for file in &mut module.files {
47 let mut buffer = Vec::with_capacity(file.total_uncompressed_size as usize);
48 if let Some(stream) = file.data_stream.as_mut() {
49 stream.rewind()?;
50 stream.read_to_end(&mut buffer)?;
51 }
52 let tag_path = file
53 .tag_name
54 .replace(" ", "_")
55 .replace("*", "_")
56 .replace(r"\", "/")
57 .replace(":", "_");
58 let path = PathBuf::from(&args.output_path).join(tag_path);
59 create_dir_all(path.parent().unwrap())?;
60 let filee = File::create(path)?;
61 let mut bw = BufWriter::new(&filee);
62 bw.write_all(&buffer)?;
63 }
64 }
65 Ok(())
66}
Sourcepub fn read_tag_from_id(
&mut self,
global_id: i32,
) -> Result<Option<&mut ModuleFileEntry>>
pub fn read_tag_from_id( &mut self, global_id: i32, ) -> Result<Option<&mut ModuleFileEntry>>
Searches for the index of the tag given the global_id
.
This function searches for the index of a tag in the files
vector using the provided
global_id
. If the tag is found, it reads the tag using the read_tag
function and
stores it in the index.
§Arguments
global_id
- The global tag ID of the file to find. This ID is used to identify the specific tag within the module file.
§Returns
Returns a mutable reference to the file if successful. If the tag is not
found or couldn’t be read, it returns None
. Any I/O error encountered during the operation is also returned
if it occurs.