ttmp-rs/examples/repack.rs

75 lines
2.6 KiB
Rust

use std::fs::{File, OpenOptions};
use std::io::{BufReader, BufWriter, Cursor, Seek, SeekFrom, Write};
use zip::{CompressionMethod, ZipWriter};
use zip::write::FileOptions;
use ttmp::model::ManifestKind;
use ttmp::mpd_encoder::{FileInfo, MpdEncoder};
use ttmp::ttmp_extractor::TtmpExtractor;
fn main() {
let args: Vec<String> = std::env::args().skip(1).collect();
let ttmp_path = &args[0];
let file = BufReader::new(File::open(ttmp_path).unwrap());
let extractor = TtmpExtractor::new(file).unwrap();
let mut zip = extractor.zip().borrow_mut();
let mut data_file = zip.by_name("TTMPD.mpd").unwrap();
let temp_mpd = OpenOptions::new()
.create(true)
.write(true)
.read(true)
.open("temp.mpd")
.unwrap();
let mut encoder = MpdEncoder::new(temp_mpd, extractor.manifest().clone());
for file in extractor.all_files_sorted() {
let mut data = Cursor::new(Vec::new());
println!("extracting {}", file.file.full_path);
TtmpExtractor::extract_one_into(&file, &mut data_file, &mut data).unwrap();
data.set_position(0);
let file_info = FileInfo {
group: file.group.map(ToOwned::to_owned),
option: file.option.map(ToOwned::to_owned),
game_path: file.file.full_path.clone(),
};
println!("adding {}", file.file.full_path);
if file.file.full_path.ends_with(".mdl") {
encoder.add_model_file(file_info, data.get_ref().len(), &mut data).unwrap();
} else if file.file.full_path.ends_with(".atex") || file.file.full_path.ends_with(".tex") {
encoder.add_texture_file(file_info, data.get_ref().len(), &mut data).unwrap();
} else {
encoder.add_standard_file(file_info, data.get_ref().len(), &mut data).unwrap();
}
}
let (manifest, mut file) = encoder.finalize().unwrap();
file.seek(SeekFrom::Start(0)).unwrap();
let repacked = BufWriter::new(File::create("repacked.ttmp2").unwrap());
let mut zip = ZipWriter::new(repacked);
zip.start_file("TTMPD.mpd", FileOptions::default().compression_method(CompressionMethod::Stored)).unwrap();
std::io::copy(&mut file, &mut zip).unwrap();
zip.start_file("TTMPL.mpl", FileOptions::default().compression_method(CompressionMethod::Deflated)).unwrap();
match manifest {
ManifestKind::V1(mods) => {
for mod_ in mods {
serde_json::to_writer(&mut zip, &mod_).unwrap();
zip.write_all(b"\n").unwrap();
}
}
ManifestKind::V2(pack) => {
serde_json::to_writer(&mut zip, &pack).unwrap();
}
}
zip.finish().unwrap();
}