mirror of
https://github.com/G2-Games/lbee-utils.git
synced 2025-04-19 07:12:55 -05:00
Made code more maintainable, fixed bugs
This commit is contained in:
parent
1a9a05b004
commit
9e49b22b23
2 changed files with 75 additions and 52 deletions
|
@ -257,7 +257,7 @@ impl Pak {
|
|||
debug!("remainder {}", remainder);
|
||||
debug!("block_offset {} - expected offset {}", block_offset, entry.offset);
|
||||
output.write_all(&entry.data)?;
|
||||
output.write_all(&vec![0u8; remainder as usize])?;
|
||||
output.write_all(&vec![0u8; remainder])?;
|
||||
block_offset += block_size as u32;
|
||||
}
|
||||
|
||||
|
@ -331,6 +331,23 @@ impl Pak {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn replace_by_id(
|
||||
&mut self,
|
||||
id: u32,
|
||||
replacement_bytes: &[u8],
|
||||
) -> Result<(), PakError> {
|
||||
let entry = self.get_entry_by_id(id);
|
||||
let index = if let Some(entry) = entry {
|
||||
entry.index
|
||||
} else {
|
||||
return Err(PakError::IndexError)
|
||||
};
|
||||
|
||||
self.replace(index, replacement_bytes)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the header information from the PAK
|
||||
pub fn header(&self) -> &Header {
|
||||
&self.header
|
||||
|
@ -350,7 +367,7 @@ impl Pak {
|
|||
self.entries
|
||||
.iter_mut()
|
||||
.find(|e|
|
||||
e.name.as_ref().is_some_and(|n| n == &name)
|
||||
e.name.as_ref().is_some_and(|n| n == name)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -364,6 +381,6 @@ impl Pak {
|
|||
self.entries
|
||||
.iter()
|
||||
.any(|e| e.name.as_ref()
|
||||
.is_some_and(|n| n == &name))
|
||||
.is_some_and(|n| n == name))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::{fs, path::PathBuf};
|
||||
use clap::{error::ErrorKind, Error, Parser, Subcommand};
|
||||
use clap::{error::{Error, ErrorKind}, Parser, Subcommand};
|
||||
use luca_pak::Pak;
|
||||
|
||||
#[derive(Parser)]
|
||||
|
@ -31,10 +31,16 @@ enum Commands {
|
|||
|
||||
/// The name of the file within the PAK you wish to replace.
|
||||
/// If not provided, the filename will be used.
|
||||
/// Icompatible with batch mode.
|
||||
/// Incompatible with batch mode, and ID.
|
||||
#[arg(short, long)]
|
||||
name: Option<String>,
|
||||
|
||||
/// The ID of the file within the PAK you wish to replace.
|
||||
/// If not provided, the filename will be used.
|
||||
/// Incompatible with batch mode, and name.
|
||||
#[arg(short, long)]
|
||||
id: Option<u32>,
|
||||
|
||||
/// File or folder to use as a replacement
|
||||
#[arg(value_name = "REPLACEMENT")]
|
||||
replacement: PathBuf,
|
||||
|
@ -48,44 +54,34 @@ enum Commands {
|
|||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
|
||||
if !cli.input.is_file() {
|
||||
Error::raw(ErrorKind::ValueValidation,
|
||||
"The input file/folder provided is not a file\n",
|
||||
).exit()
|
||||
}
|
||||
|
||||
let mut pak = Pak::open(&cli.input).unwrap();
|
||||
let mut pak = match Pak::open(&cli.input) {
|
||||
Ok(pak) => pak,
|
||||
Err(err) => fmt_error(&format!("Could not open PAK file: {}", err)).exit()
|
||||
};
|
||||
|
||||
match cli.command {
|
||||
Commands::Extract { output } => {
|
||||
if !output.is_dir() {
|
||||
Error::raw(ErrorKind::ValueValidation,
|
||||
"The output given was not a directory\n",
|
||||
).exit()
|
||||
if output.exists() && !output.is_dir() {
|
||||
fmt_error("The output given was not a directory").exit()
|
||||
} else if !output.exists() {
|
||||
fs::create_dir(&output).unwrap();
|
||||
}
|
||||
|
||||
for entry in pak.entries() {
|
||||
entry.save(&output).unwrap();
|
||||
}
|
||||
},
|
||||
Commands::Replace { batch, name, replacement, output } => {
|
||||
if !output.is_file() {
|
||||
Error::raw(ErrorKind::ValueValidation,
|
||||
"Replacement output must be a file\n",
|
||||
).exit()
|
||||
Commands::Replace { batch, name, id, replacement, output } => {
|
||||
if id.is_some() && name.is_some() {
|
||||
fmt_error("Cannot use ID and name together").exit()
|
||||
}
|
||||
|
||||
if batch {
|
||||
if name.is_some() {
|
||||
Error::raw(ErrorKind::ValueValidation,
|
||||
"Cannot use name with batch\n",
|
||||
).exit()
|
||||
if name.is_some() || id.is_some() {
|
||||
fmt_error("Cannot use name or ID with batch").exit()
|
||||
}
|
||||
|
||||
if !replacement.is_dir() {
|
||||
Error::raw(ErrorKind::ValueValidation,
|
||||
"Batch replacement must be a directory\n",
|
||||
).exit()
|
||||
fmt_error("Batch replacement must be a directory").exit()
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(replacement).unwrap() {
|
||||
|
@ -97,23 +93,21 @@ fn main() {
|
|||
.to_string_lossy()
|
||||
.into();
|
||||
|
||||
dbg!(&search_name);
|
||||
let parsed_id: Option<u32> = search_name.parse().ok();
|
||||
|
||||
// Read in the replacement file to a vec
|
||||
let rep_data: Vec<u8> = std::fs::read(entry.path()).unwrap();
|
||||
if let Err(err) = pak.replace_by_name(search_name, &rep_data) {
|
||||
Error::raw(ErrorKind::ValueValidation,
|
||||
format!("Failed to replace file in PAK: {}\n", err),
|
||||
).exit()
|
||||
}
|
||||
}
|
||||
|
||||
pak.save(&output).unwrap();
|
||||
// Try replacing by name, if that fails, replace by parsed ID
|
||||
if pak.replace_by_name(search_name, &rep_data).is_err() {
|
||||
fmt_error("Could not replace entry in PAK: Could not find name").print().unwrap()
|
||||
} else if parsed_id.is_some() && pak.replace_by_id(parsed_id.unwrap(), &rep_data).is_err() {
|
||||
fmt_error("Could not replace entry in PAK: ID is invalid").print().unwrap()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !replacement.is_file() {
|
||||
Error::raw(ErrorKind::ValueValidation,
|
||||
"Replacement input must be a file\n",
|
||||
).exit()
|
||||
fmt_error("Replacement input must be a file").exit()
|
||||
}
|
||||
|
||||
let search_name = if let Some(name) = name {
|
||||
|
@ -126,24 +120,36 @@ fn main() {
|
|||
.into()
|
||||
};
|
||||
|
||||
let search_id = if id.is_some() {
|
||||
id
|
||||
} else if let Ok(id) = search_name.parse::<u32>() {
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Read in the replacement file to a vec
|
||||
let rep_data: Vec<u8> = std::fs::read(replacement).unwrap();
|
||||
if let Err(err) = pak.replace_by_name(search_name, &rep_data) {
|
||||
Error::raw(ErrorKind::ValueValidation,
|
||||
format!("Failed to replace file in PAK: {}\n", err),
|
||||
).exit()
|
||||
if id.is_some() {
|
||||
if pak.replace_by_id(search_id.unwrap(), &rep_data).is_err() {
|
||||
fmt_error("Could not replace entry in PAK: ID is invalid").exit()
|
||||
}
|
||||
} else if pak.replace_by_name(search_name, &rep_data).is_err() {
|
||||
fmt_error("Could not replace entry in PAK: Could not find name").exit()
|
||||
}
|
||||
|
||||
pak.save(&output).unwrap();
|
||||
}
|
||||
},
|
||||
|
||||
pak.save(&output).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
let rep_cz_data: Vec<u8> = std::fs::read("en_manual01_Linkto_2_6.cz1").unwrap();
|
||||
pak.replace(4, &rep_cz_data).unwrap();
|
||||
|
||||
let mut output = BufWriter::new(File::create("MANUAL-modified.PAK").unwrap());
|
||||
pak.encode(&mut output).unwrap();
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn fmt_error(message: &str) -> Error {
|
||||
Error::raw(
|
||||
ErrorKind::ValueValidation,
|
||||
format!("{}\n", message),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue