implement basic CLI with clap, list-entities and find-entities
This commit is contained in:
parent
7c2fbba153
commit
6030fc29ce
7 changed files with 341 additions and 52 deletions
214
Cargo.lock
generated
214
Cargo.lock
generated
|
|
@ -8,6 +8,54 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
|
@ -20,6 +68,52 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "1.0.0"
|
||||
|
|
@ -49,6 +143,7 @@ name = "fot-save-edit"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"clap",
|
||||
"deflate",
|
||||
"encoding_rs",
|
||||
"indexmap",
|
||||
|
|
@ -62,6 +157,12 @@ version = "0.14.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.0.0"
|
||||
|
|
@ -86,3 +187,116 @@ name = "memmem"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
|
|
|||
|
|
@ -2,11 +2,14 @@
|
|||
name = "fot-save-edit"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
auhtors = ["mykola2312", "puuuuh"]
|
||||
repository = "https://github.com/mykola2312/fot-save-edit/"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.4.3"
|
||||
clap = { version = "4.4.2", features = ["derive"] }
|
||||
deflate = "1.0.0"
|
||||
encoding_rs = "0.8.33"
|
||||
indexmap = "2.0.0"
|
||||
|
|
|
|||
26
src/fot.rs
26
src/fot.rs
|
|
@ -1,14 +1,14 @@
|
|||
mod attributes;
|
||||
mod decoder;
|
||||
mod entity;
|
||||
mod entitylist;
|
||||
mod esh;
|
||||
mod ferror;
|
||||
mod fstring;
|
||||
mod raw;
|
||||
pub mod attributes;
|
||||
pub mod decoder;
|
||||
pub mod entity;
|
||||
pub mod entitylist;
|
||||
pub mod esh;
|
||||
pub mod ferror;
|
||||
pub mod fstring;
|
||||
pub mod raw;
|
||||
pub mod save;
|
||||
mod sgd;
|
||||
mod ssg;
|
||||
mod stream;
|
||||
mod tag;
|
||||
mod world;
|
||||
pub mod sgd;
|
||||
pub mod ssg;
|
||||
pub mod stream;
|
||||
pub mod tag;
|
||||
pub mod world;
|
||||
|
|
|
|||
|
|
@ -267,12 +267,12 @@ impl ESH {
|
|||
pub fn get_nested(&self, name: &str) -> Result<ESH, FE> {
|
||||
let value = match self.get(name) {
|
||||
Some(value) => value,
|
||||
None => return Err(FE::NoESHValue)
|
||||
None => return Err(FE::NoESHValue),
|
||||
};
|
||||
|
||||
if let ESHValue::Binary(bin) = value {
|
||||
let mut rd = ReadStream::new(bin, 0);
|
||||
|
||||
|
||||
let _ = rd.read_u32()?;
|
||||
rd.read::<ESH>()
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub enum FError {
|
|||
NoESHValue,
|
||||
ESHValueNonBinary,
|
||||
AttributesNonBinary,
|
||||
ValueNoESBIN
|
||||
ValueNoESBIN,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for FError {
|
||||
|
|
@ -35,7 +35,7 @@ impl std::fmt::Display for FError {
|
|||
FE::NoESHValue => write!(f, "Entity has no specific ESH value"),
|
||||
FE::ESHValueNonBinary => write!(f, "ESH value is not binary"),
|
||||
FE::AttributesNonBinary => write!(f, "Attributes Binary != true"),
|
||||
FE::ValueNoESBIN => write!(f, "Value has no esbin")
|
||||
FE::ValueNoESBIN => write!(f, "Value has no esbin"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use super::decoder::DecoderCtx;
|
||||
use super::entitylist::{EntityEncoding, EntityList};
|
||||
use super::esh::ESHValue;
|
||||
use super::ferror::FError as FE;
|
||||
use super::fstring::FString;
|
||||
use super::sgd::SGD;
|
||||
|
|
@ -28,30 +27,6 @@ pub struct World {
|
|||
|
||||
impl World {
|
||||
const WORLD_HDR_LEN: usize = 0x13;
|
||||
|
||||
pub fn test(&mut self) -> Result<(), FE> {
|
||||
//let actor_type = self.entlist.get_type_idx("Actor").unwrap();
|
||||
//let ent = self.entlist.get_entity_mut(2122);
|
||||
let ent = self.entlist.get_entity_mut(2122);
|
||||
let esh = ent.get_esh_mut()?;
|
||||
for (name, value) in &esh.props {
|
||||
println!("{} {}", name, value);
|
||||
}
|
||||
//self.entlist.dump_to_entfile(ent, Path::new("D:\\actor.ent"))?;
|
||||
|
||||
println!("");
|
||||
let mut attribs = esh.get_nested("Current Attributes")?;
|
||||
for (name, value) in &attribs.props {
|
||||
println!("{} {}", name, value);
|
||||
}
|
||||
|
||||
attribs.set("hitPoints", ESHValue::Int(999));
|
||||
attribs.set("poisonPoints", ESHValue::Int(0));
|
||||
|
||||
esh.set_nested("Current Attributes", attribs)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub type WorldOffsetSize = (usize, usize);
|
||||
|
|
|
|||
117
src/main.rs
117
src/main.rs
|
|
@ -1,19 +1,116 @@
|
|||
#![deny(rust_2018_idioms)]
|
||||
use std::env;
|
||||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
use std::collections::HashMap;
|
||||
use std::io::{stdout, BufWriter, Write};
|
||||
use std::path::Path;
|
||||
|
||||
mod fot;
|
||||
use fot::attributes::*;
|
||||
use fot::entitylist::EntityList;
|
||||
use fot::save::Save;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<_> = env::args().collect();
|
||||
let save_path = args.get(1).unwrap();
|
||||
let out_path = match args.get(2) {
|
||||
Some(path) => path,
|
||||
None => "out.sav"
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
/// Input file path (.sav or .ent)
|
||||
#[arg(short, long)]
|
||||
input: String,
|
||||
|
||||
// Specify save file or ent file type
|
||||
#[arg(value_enum)]
|
||||
kind: Kind,
|
||||
|
||||
/// Output file path
|
||||
#[arg(short, long)]
|
||||
output: String,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
||||
enum Kind {
|
||||
Save,
|
||||
Ent,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum Commands {
|
||||
ListEntities,
|
||||
/// Find entities, kv = key1=value,key2=value2
|
||||
FindEntities {
|
||||
kv: String,
|
||||
},
|
||||
}
|
||||
|
||||
fn list_entities(entlist: &EntityList) {
|
||||
let mut bf = BufWriter::new(stdout().lock());
|
||||
for (id, ent) in entlist {
|
||||
let type_name = if ent.type_idx != 0xFFFF {
|
||||
entlist.get_type_name(ent.type_idx).str.as_str()
|
||||
} else {
|
||||
"<no type>"
|
||||
};
|
||||
write!(bf, "{}\t{}\n", id, type_name).expect("failed to write stdout");
|
||||
}
|
||||
}
|
||||
|
||||
fn find_entities(entlist: &EntityList, line: String) {
|
||||
let kv = line
|
||||
.split(",")
|
||||
.map(|kv| kv.split_once("="))
|
||||
.collect::<Option<HashMap<&str, &str>>>()
|
||||
.unwrap();
|
||||
|
||||
let mut bf = BufWriter::new(stdout().lock());
|
||||
for (id, ent) in entlist {
|
||||
let type_name = if ent.type_idx != 0xFFFF {
|
||||
entlist.get_type_name(ent.type_idx).str.as_str()
|
||||
} else {
|
||||
"<no type>"
|
||||
};
|
||||
|
||||
let esh = match &ent.esh {
|
||||
Some(esh) => esh,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
for (name, value) in &esh.props {
|
||||
let key = name.str.as_str();
|
||||
if kv.contains_key(key) {
|
||||
let svalue = value.to_string();
|
||||
if svalue == kv[key] {
|
||||
write!(bf, "{}\t{}\n", id, type_name).expect("failed to write stdout");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_save(cli: Cli) {
|
||||
let mut save = match Save::load(Path::new(cli.input.as_str())) {
|
||||
Ok(save) => save,
|
||||
Err(fe) => panic!("{}", fe),
|
||||
};
|
||||
|
||||
let mut save = Save::load(Path::new(save_path)).expect("load save");
|
||||
save.world.test().expect("test");
|
||||
save.save(Path::new(out_path)).expect("failed to save");
|
||||
match cli.command {
|
||||
Commands::ListEntities => {
|
||||
list_entities(&save.world.entlist);
|
||||
},
|
||||
Commands::FindEntities { kv } => {
|
||||
find_entities(&save.world.entlist, kv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.kind {
|
||||
Kind::Save => do_save(cli),
|
||||
Kind::Ent => todo!(),
|
||||
}
|
||||
|
||||
//let mut save = Save::load(Path::new(save_path)).expect("load save");
|
||||
//save.save(Path::new(out_path)).expect("failed to save");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue