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 = 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(); }