From b3a69256b059593fde871d8ea2b69e1609c661f0 Mon Sep 17 00:00:00 2001 From: dark0dave Date: Tue, 6 Aug 2024 22:00:07 +0100 Subject: [PATCH] feat(binrw): Convert everything to binrw Signed-off-by: dark0dave --- .pre-commit-config.yaml | 51 ++++- Cargo.lock | 206 +++++++++++++++-- Cargo.toml | 2 + README.md | 2 +- cli/src/lib.rs | 2 +- models/Cargo.toml | 3 +- models/fixtures/#trollis.eff | Bin models/fixtures/AR0011.ARE | Bin 0 -> 2440 bytes models/fixtures/chitin.key | Bin models/fixtures/cutmelis.cre | Bin models/fixtures/dbeggar.cre | Bin models/fixtures/dialog.tlk | Bin models/fixtures/gate1.spl | Bin models/fixtures/mazzy.dlg | Bin models/fixtures/soundoff.ids | 0 models/fixtures/sw1h01.itm | Bin models/fixtures/xpcap.2da | 0 models/src/area.rs | 432 ++++++++++++----------------------- models/src/common/mod.rs | 2 + models/src/common/resref.rs | 10 + models/src/common/strref.rs | 10 + models/src/creature.rs | 208 +++++++++++++++++ models/src/game.rs | 2 +- models/src/item_table.rs | 2 +- models/src/save.rs | 18 +- models/src/world_map.rs | 2 +- 26 files changed, 619 insertions(+), 333 deletions(-) mode change 100755 => 100644 models/fixtures/#trollis.eff create mode 100644 models/fixtures/AR0011.ARE mode change 100755 => 100644 models/fixtures/chitin.key mode change 100755 => 100644 models/fixtures/cutmelis.cre mode change 100755 => 100644 models/fixtures/dbeggar.cre mode change 100755 => 100644 models/fixtures/dialog.tlk mode change 100755 => 100644 models/fixtures/gate1.spl mode change 100755 => 100644 models/fixtures/mazzy.dlg mode change 100755 => 100644 models/fixtures/soundoff.ids mode change 100755 => 100644 models/fixtures/sw1h01.itm mode change 100755 => 100644 models/fixtures/xpcap.2da create mode 100644 models/src/common/resref.rs create mode 100644 models/src/common/strref.rs diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 798c6c7..5794aaa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,28 +1,35 @@ +default_install_hook_types: [pre-commit, commit-msg] repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-added-large-files - args: ['--maxkb=5000'] - - id: check-builtin-literals - - id: check-byte-order-marker + exclude: (?x)^([models/fixtures|docs]) + stages: [pre-commit] - id: check-case-conflict + stages: [pre-commit] - id: check-merge-conflict + stages: [pre-commit] - id: detect-private-key + stages: [pre-commit] - id: forbid-new-submodules + stages: [pre-commit] + - id: check-builtin-literals + stages: [pre-commit] + - id: check-yaml + stages: [pre-commit] - repo: https://github.com/jumanjihouse/pre-commit-hooks rev: 3.0.0 hooks: - - id: git-dirty - id: forbid-binary - exclude: > - (?x)^( - models/fixtures/.*?|docs/.*? - )$ + stages: [pre-commit] + exclude: (?x)^([models/fixtures|docs]) + - id: git-dirty + stages: [pre-commit] - repo: https://github.com/commitizen-tools/commitizen - rev: v3.18.4 + rev: v3.27.0 hooks: - id: commitizen stages: [commit-msg] @@ -30,6 +37,28 @@ repos: - repo: https://github.com/doublify/pre-commit-rust rev: v1.0 hooks: + - id: fmt + stages: [pre-commit] - id: cargo-check + stages: [pre-commit] - id: clippy - - id: fmt + stages: [pre-commit] + +- repo: local + hooks: + - id: cargo-test + stages: [pre-commit] + name: cargo test + description: Run the test suite + entry: cargo test --workspace + language: system + types: [rust] + pass_filenames: false + +- repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + stages: [pre-commit] + args: + - '--ignore-words-list=crate,sav,SAV,ser,extention' diff --git a/Cargo.lock b/Cargo.lock index eaaef09..77385b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,7 +43,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -53,9 +53,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "binrw" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f36b7cb3ab9ff6a2858650d8dc360e783a5d14dc29594db48c56a3c233cc265" +dependencies = [ + "array-init", + "binrw_derive", + "bytemuck", +] + +[[package]] +name = "binrw_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20ea7a8c5c8eeffffac6d54d172444e15beffac6f817fac714460a9a9aa88da3" +dependencies = [ + "either", + "owo-colors", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bytemuck" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" + [[package]] name = "cfg-if" version = "1.0.0" @@ -93,7 +135,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.52", ] [[package]] @@ -127,6 +169,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "erased-serde" version = "0.3.31" @@ -136,6 +190,22 @@ dependencies = [ "serde", ] +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + [[package]] name = "flate2" version = "1.0.28" @@ -158,6 +228,18 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -171,12 +253,27 @@ dependencies = [ name = "models" version = "0.1.0" dependencies = [ + "binrw", "erased-serde", "flate2", + "pretty_assertions", "serde", "serde_json", + "tempfile", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + [[package]] name = "post_infinity" version = "0.1.0" @@ -185,6 +282,16 @@ dependencies = [ "cli", ] +[[package]] +name = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "proc-macro2" version = "1.0.78" @@ -203,6 +310,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "ryu" version = "1.0.17" @@ -226,7 +346,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.52", ] [[package]] @@ -246,6 +366,17 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.52" @@ -257,6 +388,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -278,15 +422,25 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -295,42 +449,54 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "yansi" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/Cargo.toml b/Cargo.toml index 893f800..4a73213 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[workspace] + [dependencies] clap = { version = "4.0", features = ["derive"] } cli = { path = "cli" } diff --git a/README.md b/README.md index d95319c..86c6124 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ post_infinity models/fixtures/gate1.spl "extended_headers": [ { "spell_form": 1, - "freindly": 0, + "friendly": 0, "location": 2, "memorised_icon": "SPWI905B", "target_type": 4, diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 46fc984..97fb227 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -35,7 +35,7 @@ fn json_back_to_ie_type(path: &Path) { .unwrap_or_default() .to_str() .unwrap_or_default() - .split(".") + .split('.') .nth(1) .unwrap_or_default() .to_ascii_lowercase(); diff --git a/models/Cargo.toml b/models/Cargo.toml index b0afe04..8c3fc3c 100644 --- a/models/Cargo.toml +++ b/models/Cargo.toml @@ -6,10 +6,11 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +binrw = "*" erased-serde = "0.3" +flate2 = { version = "1.0.17" } serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.94" -flate2 = { version = "1.0.17" } [dev-dependencies] pretty_assertions = "1.3.0" diff --git a/models/fixtures/#trollis.eff b/models/fixtures/#trollis.eff old mode 100755 new mode 100644 diff --git a/models/fixtures/AR0011.ARE b/models/fixtures/AR0011.ARE new file mode 100644 index 0000000000000000000000000000000000000000..c1b781fd9088f6781b5eb09f351b18e5f352d715 GIT binary patch literal 2440 zcmd5-%}&BV5FP}ysWE!+Xw;itG%XtCWU@+w4OEgg;c5yru@PERh@N~6pTMI};5+y> zo;;{K+b%J6mqOvdBs1T3{&wdpWr=N&wtlP;ThnwMghK4fxuyXWg;DO@WQ$#DcM1Sy ziv87CF@WndZY$_nVX=74QsD1dxL<_mdu2W1xnl8htmGoR%2-hv0OjcCxedf z1tZbXFQE#boDApzvE+A>s6NX#ZcP)B+qJBMDdLWE^yCj8yl5y+zJgo9Ohk`oBb5YC z54Y55$P+5|`$i*?bZgP4FY=}9=6!xS0GLMS S-RFOOf$@Y^Ws3i1`Q#U;lc7}r literal 0 HcmV?d00001 diff --git a/models/fixtures/chitin.key b/models/fixtures/chitin.key old mode 100755 new mode 100644 diff --git a/models/fixtures/cutmelis.cre b/models/fixtures/cutmelis.cre old mode 100755 new mode 100644 diff --git a/models/fixtures/dbeggar.cre b/models/fixtures/dbeggar.cre old mode 100755 new mode 100644 diff --git a/models/fixtures/dialog.tlk b/models/fixtures/dialog.tlk old mode 100755 new mode 100644 diff --git a/models/fixtures/gate1.spl b/models/fixtures/gate1.spl old mode 100755 new mode 100644 diff --git a/models/fixtures/mazzy.dlg b/models/fixtures/mazzy.dlg old mode 100755 new mode 100644 diff --git a/models/fixtures/soundoff.ids b/models/fixtures/soundoff.ids old mode 100755 new mode 100644 diff --git a/models/fixtures/sw1h01.itm b/models/fixtures/sw1h01.itm old mode 100755 new mode 100644 diff --git a/models/fixtures/xpcap.2da b/models/fixtures/xpcap.2da old mode 100755 new mode 100644 diff --git a/models/src/area.rs b/models/src/area.rs index b32d2b0..903821d 100644 --- a/models/src/area.rs +++ b/models/src/area.rs @@ -1,139 +1,22 @@ use std::rc::Rc; +use binrw::{BinRead, BinWrite}; use serde::{Deserialize, Serialize}; -use crate::common::header::Header; -use crate::item_table::ItemReferenceTable; +use crate::common::fixed_char_array::FixedCharSlice; +use crate::common::resref::Resref; +use crate::common::strref::Strref; use crate::model::Model; -use crate::resources::utils::{ - copy_buff_to_struct, copy_transmute_buff, to_u8_slice, vec_to_u8_slice, -}; use crate::tlk::Lookup; -use crate::{common::fixed_char_array::FixedCharSlice, game::GlobalVariables}; // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm #[repr(C)] #[derive(Debug, Serialize, Deserialize)] -pub struct Area { - pub header: FileHeader, - pub actors: Vec, - pub regions: Vec, - pub spawn_points: Vec, - pub entrances: Vec, - pub containers: Vec, - pub items: Vec, - pub vertices: Vec, - pub ambients: Vec, - pub variables: Vec, - pub explored_bitmasks: Vec, - pub doors: Vec, - pub animations: Vec, - pub automap_notes: Vec, - pub tiled_objects: Vec, - pub tiled_object_flags: Vec, - pub projectile_traps: Vec, - pub songs: Vec, - pub rest_interruptions: Vec, -} +pub struct Area {} impl Model for Area { - fn new(buffer: &[u8]) -> Self { - let header = copy_buff_to_struct::(buffer, 0); - - let start = usize::try_from(header.offset_to_actors).unwrap_or(0); - let count = usize::try_from(header.count_of_actors).unwrap_or(0); - let actors = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_regions).unwrap_or(0); - let count = usize::try_from(header.count_of_regions).unwrap_or(0); - let regions = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_spawn_points).unwrap_or(0); - let count = usize::try_from(header.count_of_spawn_points).unwrap_or(0); - let spawn_points = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_entrances).unwrap_or(0); - let count = usize::try_from(header.count_of_entrances).unwrap_or(0); - let entrances = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_containers).unwrap_or(0); - let count = usize::try_from(header.count_of_containers).unwrap_or(0); - let containers = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_items).unwrap_or(0); - let count = usize::try_from(header.count_of_items).unwrap_or(0); - let items = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_vertices).unwrap_or(0); - let count = usize::try_from(header.count_of_vertices).unwrap_or(0); - let vertices = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_ambients).unwrap_or(0); - let count = usize::try_from(header.count_of_ambients).unwrap_or(0); - let ambients = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_variables).unwrap_or(0); - let count = usize::try_from(header.count_of_variables).unwrap_or(0); - let variables = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_tiled_object_flags).unwrap_or(0); - let count = usize::try_from(header.count_of_tiled_object_flags).unwrap_or(0); - let tiled_object_flags = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_doors).unwrap_or(0); - let count = usize::try_from(header.count_of_doors).unwrap_or(0); - let doors = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_animations).unwrap_or(0); - let count = usize::try_from(header.count_of_animations).unwrap_or(0); - let animations = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_tiled_objects).unwrap_or(0); - let count = usize::try_from(header.count_of_tiled_objects).unwrap_or(0); - let tiled_objects = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_explored_bitmask).unwrap_or(0); - let count = usize::try_from(header.size_of_explored_bitmask).unwrap_or(1) - / std::mem::size_of::(); - let explored_bitmasks = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_automap_notes).unwrap_or(0); - let count = usize::try_from(header.number_of_entries_in_the_automap_notes).unwrap_or(0); - let automap_notes = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_projectile_traps).unwrap_or(0); - let count = usize::try_from(header.number_of_entries_in_the_projectile_traps).unwrap_or(0); - let projectile_traps = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_song_entries).unwrap_or(0); - let count = if start > 0 { 0 } else { start + 144 }; - let songs = copy_transmute_buff::(buffer, start, count); - - let start = usize::try_from(header.offset_to_rest_interruptions).unwrap_or(0); - let count = if start > 0 { 0 } else { start + 228 }; - let rest_interruptions = copy_transmute_buff::(buffer, start, count); - - Self { - header, - actors, - regions, - spawn_points, - entrances, - containers, - items, - vertices, - ambients, - variables, - tiled_object_flags, - doors, - animations, - tiled_objects, - explored_bitmasks, - automap_notes, - projectile_traps, - songs, - rest_interruptions, - } + fn new(_buffer: &[u8]) -> Self { + Self {} } fn create_as_rc(buffer: &[u8]) -> Rc { @@ -141,102 +24,35 @@ impl Model for Area { } fn name(&self, _lookup: &Lookup) -> String { - self.header.area_wed.to_string().replace(".WED", ".ARE") + todo!() } fn to_bytes(&self) -> Vec { - let mut out = vec![ - (1, to_u8_slice(&self.header).to_vec()), - ( - self.header.offset_to_actors as i32, - vec_to_u8_slice(&self.actors), - ), - ( - self.header.offset_to_regions, - vec_to_u8_slice(&self.regions), - ), - ( - self.header.offset_to_spawn_points, - vec_to_u8_slice(&self.spawn_points), - ), - ( - self.header.offset_to_entrances, - vec_to_u8_slice(&self.entrances), - ), - ( - self.header.offset_to_containers, - vec_to_u8_slice(&self.containers), - ), - (self.header.offset_to_items, vec_to_u8_slice(&self.items)), - ( - self.header.offset_to_vertices, - vec_to_u8_slice(&self.vertices), - ), - ( - self.header.offset_to_ambients, - vec_to_u8_slice(&self.ambients), - ), - ( - self.header.offset_to_variables, - vec_to_u8_slice(&self.variables), - ), - ( - self.header.offset_to_tiled_object_flags as i32, - vec_to_u8_slice(&self.tiled_object_flags), - ), - ( - self.header.offset_to_explored_bitmask as i32, - vec_to_u8_slice(&self.explored_bitmasks), - ), - (self.header.offset_to_doors, vec_to_u8_slice(&self.doors)), - ( - self.header.offset_to_animations, - vec_to_u8_slice(&self.animations), - ), - ( - self.header.offset_to_tiled_objects, - vec_to_u8_slice(&self.tiled_objects), - ), - ( - self.header.offset_to_song_entries, - vec_to_u8_slice(&self.songs), - ), - ( - self.header.offset_to_rest_interruptions, - vec_to_u8_slice(&self.rest_interruptions), - ), - ( - self.header.number_of_entries_in_the_automap_notes, - vec_to_u8_slice(&self.automap_notes), - ), - ( - self.header.number_of_entries_in_the_automap_notes, - vec_to_u8_slice(&self.projectile_traps), - ), - ]; - out.sort_by(|a, b| a.0.cmp(&b.0)); - out.into_iter() - .filter(|data| data.0 < 1 && !data.1.is_empty()) - .flat_map(|(_order, data)| data) - .collect() + vec![] } } // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Header -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct FileHeader { - pub header: Header<4, 4>, - pub area_wed: FixedCharSlice<8>, + #[br(count = 4)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub signature: String, + #[br(count = 4)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub version: String, + pub area_wed: Resref, pub last_saved: u32, pub area_flags: u32, - pub resref_of_the_area_to_the_north_of_this_area: FixedCharSlice<8>, + pub resref_of_the_area_to_the_north_of_this_area: Resref, pub north_area_flags: u32, - pub resref_of_the_area_to_the_east_of_this_area: FixedCharSlice<8>, + pub resref_of_the_area_to_the_east_of_this_area: Resref, pub east_area_flags: u32, - pub resref_of_the_area_to_the_south_of_this_area: FixedCharSlice<8>, + pub resref_of_the_area_to_the_south_of_this_area: Resref, pub south_area_flags: u32, - pub resref_of_the_area_to_the_west_of_this_area: FixedCharSlice<8>, + pub resref_of_the_area_to_the_west_of_this_area: Resref, pub west_area_flags: u32, pub area_type_flags: u16, pub rain_probability: u16, @@ -265,7 +81,7 @@ pub struct FileHeader { pub count_of_variables: i32, pub offset_to_tiled_object_flags: i16, pub count_of_tiled_object_flags: i16, - pub area_script: FixedCharSlice<8>, + pub area_script: Resref, pub size_of_explored_bitmask: u32, pub offset_to_explored_bitmask: u32, pub count_of_doors: i32, @@ -281,25 +97,28 @@ pub struct FileHeader { pub offset_to_projectile_traps: i32, pub number_of_entries_in_the_projectile_traps: i32, // bgee and bg2:tob - pub rest_movie_day: FixedCharSlice<8>, + pub rest_movie_day: Resref, // bgee and bg2:tob - pub rest_movie_night: FixedCharSlice<8>, + pub rest_movie_night: Resref, #[serde(skip)] - _unused: FixedCharSlice<56>, + #[br(count = 56)] + _unused: Vec, } // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Actor -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct Actor { - pub name: FixedCharSlice<32>, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub name: String, pub current_x_coordinate: u16, pub current_y_coordinate: u16, pub destination_x_coordinate: u16, pub destination_y_coordinate: u16, pub flags: u32, pub has_been_spawned: u16, - pub first_letter_of_cre_resref: FixedCharSlice<1>, + pub first_letter_of_cre_resref: u8, #[serde(skip)] _unused_1: u8, pub actor_animation: u32, @@ -310,26 +129,29 @@ pub struct Actor { pub movement_restriction_distance_move_to_object: u16, pub actor_appearence_schedule: u32, pub num_times_talked_to: u32, - pub dialog: FixedCharSlice<8>, - pub script_override: FixedCharSlice<8>, - pub script_general: FixedCharSlice<8>, - pub script_class: FixedCharSlice<8>, - pub script_race: FixedCharSlice<8>, - pub script_default: FixedCharSlice<8>, - pub script_specific: FixedCharSlice<8>, - pub cre_file: FixedCharSlice<8>, + pub dialog: Resref, + pub script_override: Resref, + pub script_general: Resref, + pub script_class: Resref, + pub script_race: Resref, + pub script_default: Resref, + pub script_specific: Resref, + pub cre_file: Resref, // for embedded cre files pub offset_to_cre_structure: u32, pub size_of_stored_cre_structure: u32, #[serde(skip)] - _unused_2: FixedCharSlice<128>, + #[br(count = 128)] + _unused_2: Vec, } // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Info -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct Region { - pub name: FixedCharSlice<32>, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub name: String, pub region_type: u16, pub minimum_bounding_box_of_this_point: [u16; 4], pub count_of_vertices_composing_the_perimeter: u16, @@ -337,12 +159,15 @@ pub struct Region { pub trigger_value: u32, pub cursor_index: u32, // for travel regions - pub destination_area: FixedCharSlice<8>, + pub destination_area: Resref, // for travel regions - pub entrance_name_in_destination_area: FixedCharSlice<32>, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub entrance_name_in_destination_area: String, pub flags: u32, // for info points - pub information_text: FixedCharSlice<4>, + pub information_text: Strref, pub trap_detection_difficulty_percent: u16, pub trap_removal_difficulty_percent: u16, // 0=no, 1=yes @@ -350,33 +175,36 @@ pub struct Region { // 0=no, 1=yes pub trap_detected: u16, pub trap_launch_location: [u16; 2], - pub key_item: FixedCharSlice<8>, - pub region_script: FixedCharSlice<8>, + pub key_item: Resref, + pub region_script: Resref, pub alternative_use_point_x_coordinate: u16, pub alternative_use_point_y_coordinate: u16, #[serde(skip)] _unknown_1: u32, #[serde(skip)] - _unknown_2: [u8; 32], + #[br(count = 32)] + _unknown_2: Vec, } // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Spawn -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct SpawnPoint { - pub name: FixedCharSlice<32>, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub name: String, pub x_coordinate: u16, pub y_coordinate: u16, - pub resref_of_creature_to_spawn_1st: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_2nd: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_3rd: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_4th: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_5th: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_6th: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_7th: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_8th: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_9th: FixedCharSlice<8>, - pub resref_of_creature_to_spawn_10th: FixedCharSlice<8>, + pub resref_of_creature_to_spawn_1st: Resref, + pub resref_of_creature_to_spawn_2nd: Resref, + pub resref_of_creature_to_spawn_3rd: Resref, + pub resref_of_creature_to_spawn_4th: Resref, + pub resref_of_creature_to_spawn_5th: Resref, + pub resref_of_creature_to_spawn_6th: Resref, + pub resref_of_creature_to_spawn_7th: Resref, + pub resref_of_creature_to_spawn_8th: Resref, + pub resref_of_creature_to_spawn_9th: Resref, + pub resref_of_creature_to_spawn_10th: Resref, pub count_of_spawn_creatures: u16, pub base_creature_number_to_spawn: u16, pub frequency: u16, @@ -414,26 +242,32 @@ pub struct SpawnPoint { // Offset 0x006c pub spawn_weight_of_10th_creature_slot: u8, #[serde(skip)] - _unused: FixedCharSlice<38>, + #[br(count = 38)] + _unused: Vec, } // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Entrance -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct Entrance { - pub name: FixedCharSlice<32>, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub name: String, pub x_coordinate: u16, pub y_coordinate: u16, pub orientation: u16, #[serde(skip)] - _unused: FixedCharSlice<66>, + #[br(count = 66)] + _unused: Vec, } // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Container -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct Container { - pub name: FixedCharSlice<32>, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub name: String, pub x_coordinate: u16, pub y_coordinate: u16, pub container_type: u16, @@ -453,33 +287,44 @@ pub struct Container { pub bottom_bounding_box_of_container_polygon: u16, pub index_to_first_item_in_this_container: u32, pub count_of_items_in_this_container: u32, - pub trap_script: FixedCharSlice<8>, + pub trap_script: Resref, pub index_to_first_vertex_of_the_outline: u32, pub count_of_vertices_making_up_the_outline: u16, pub trigger_range: u16, - pub owner_script_name: FixedCharSlice<32>, - pub key_item: FixedCharSlice<8>, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub owner_script_name: String, + pub key_item: Resref, pub break_difficulty: u32, - pub lockpick_string: FixedCharSlice<4>, + pub lockpick_string: Strref, #[serde(skip)] - _unused: FixedCharSlice<56>, + #[br(count = 56)] + _unused: Vec, } // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Item -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] -pub struct AreaItem(pub ItemReferenceTable); +#[derive(BinRead, BinWrite, Serialize, Deserialize)] +pub struct Item { + pub item_resref: Resref, + pub item_expiration_time: u16, + pub quantity_1: u16, + pub quantity_2: u16, + pub quantity_3: u16, + pub flags: u32, +} // An array of points used to create the outlines of regions and containers. Elements are 16-bit words stored x0, y0, x1, y1 etc. -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct Vertice(pub u16); // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Ambient -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct Ambient { - pub name: FixedCharSlice<32>, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub name: String, pub x_coordinate: u16, pub y_coordinate: u16, pub radius: u16, @@ -487,16 +332,16 @@ pub struct Ambient { pub pitch_variance: u32, pub volume_variance: u16, pub volume_percentage: u16, - pub resref_of_sound_1: FixedCharSlice<8>, - pub resref_of_sound_2: FixedCharSlice<8>, - pub resref_of_sound_3: FixedCharSlice<8>, - pub resref_of_sound_4: FixedCharSlice<8>, - pub resref_of_sound_5: FixedCharSlice<8>, - pub resref_of_sound_6: FixedCharSlice<8>, - pub resref_of_sound_7: FixedCharSlice<8>, - pub resref_of_sound_8: FixedCharSlice<8>, - pub resref_of_sound_9: FixedCharSlice<8>, - pub resref_of_sound_10: FixedCharSlice<8>, + pub resref_of_sound_1: u32, + pub resref_of_sound_2: u32, + pub resref_of_sound_3: u32, + pub resref_of_sound_4: u32, + pub resref_of_sound_5: u32, + pub resref_of_sound_6: u32, + pub resref_of_sound_7: u32, + pub resref_of_sound_8: u32, + pub resref_of_sound_9: u32, + pub resref_of_sound_10: u32, pub count_of_sounds: u16, #[serde(skip)] _unused_1: u16, @@ -505,17 +350,38 @@ pub struct Ambient { pub ambient_appearence_schedule: u32, pub flags: u32, #[serde(skip)] - _unused_2: FixedCharSlice<64>, + #[br(count = 64)] + _unused_2: Vec, } // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Variable -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] -pub struct AreaVariable(pub GlobalVariables); +#[derive(BinRead, BinWrite, Serialize, Deserialize)] +pub struct Variable { + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub name: String, + /* + bit 0: int + bit 1: float + bit 2: script name + bit 3: resref + bit 4: strref + bit 5: dword + */ + pub variable_type: i16, + pub resource_value: i16, + pub dword_value: i32, + pub int_value: i32, + pub double_value: i64, + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub script_name_value: String, +} // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Explored -#[repr(C, packed)] -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +#[derive(BinRead, BinWrite, Serialize, Deserialize)] pub struct ExploredBitmask(pub u8); // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/are_v1.htm#formAREAV1_0_Door diff --git a/models/src/common/mod.rs b/models/src/common/mod.rs index 0078073..24be20b 100644 --- a/models/src/common/mod.rs +++ b/models/src/common/mod.rs @@ -2,5 +2,7 @@ pub mod feature_block; pub mod fixed_char_array; pub mod fixed_char_nd_array; pub mod header; +pub mod resref; pub mod signed_fixed_char_array; +pub mod strref; pub mod variable_char_array; diff --git a/models/src/common/resref.rs b/models/src/common/resref.rs new file mode 100644 index 0000000..c7d7ae7 --- /dev/null +++ b/models/src/common/resref.rs @@ -0,0 +1,10 @@ +use binrw::{BinRead, BinWrite}; +use serde::{Deserialize, Serialize}; + +#[derive(BinRead, BinWrite, Serialize, Deserialize)] +pub struct Resref( + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + String, +); diff --git a/models/src/common/strref.rs b/models/src/common/strref.rs new file mode 100644 index 0000000..1e9a207 --- /dev/null +++ b/models/src/common/strref.rs @@ -0,0 +1,10 @@ +use binrw::{BinRead, BinWrite}; +use serde::{Deserialize, Serialize}; + +#[derive(BinRead, BinWrite, Serialize, Deserialize)] +pub struct Strref( + #[br(count = 4)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + String, +); diff --git a/models/src/creature.rs b/models/src/creature.rs index c859717..d2e1969 100644 --- a/models/src/creature.rs +++ b/models/src/creature.rs @@ -1,5 +1,6 @@ use std::rc::Rc; +use binrw::{BinRead, BinWrite}; use serde::{Deserialize, Serialize}; use crate::common::fixed_char_nd_array::FixedCharNDArray; @@ -90,6 +91,183 @@ impl Model for Creature { } } +// https://gibberlings3.github.io/iesdp/file_formats/ie_formats/cre_v1.htm#CREV1_0_Header +#[derive(BinRead, BinWrite, Serialize, Deserialize)] +struct BGEECreatureHeader { + #[br(count = 4)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub signature: String, + #[br(count = 4)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub version: String, + pub long_creature_name: u32, + pub short_creature_name: u32, + // see CRE_FLAG_* above for possible flags + pub flags: u32, + pub exp_for_killing: u32, + pub exp: u32, + pub gold: u32, + pub state_flags: u32, + pub current_hp: u16, + pub base_hp: u16, + pub animation_id: u32, + pub metal_color: u8, + pub minor_color: u8, + pub major_color: u8, + pub skin_color: u8, + pub leather_color: u8, + pub armor_color: u8, + pub hair_color: u8, + // 0 = v1, 1 = v2 + pub effstructure: u8, + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub small_portrait: String, + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub large_portrait: String, + pub reputation: u8, + pub hide_in_shadows: u8, + pub nac_1: i16, + pub nac_2: i16, + pub nac_mod_crushing: i16, + pub nac_mod_missile: i16, + pub nac_mod_piercing: i16, + pub nac_mod_slashing: i16, + pub thac0: u8, + pub attacks: u8, + pub save_death: u8, + pub save_wands: u8, + pub save_poly: u8, + pub save_breath: u8, + pub save_spells: u8, + pub resist_fire: u8, + pub resist_cold: u8, + pub resist_electricity: u8, + pub resist_acid: u8, + pub resist_magic: u8, + pub resist_magicfire: u8, + pub resist_magiccold: u8, + pub resist_slashing: u8, + pub resist_crushing: u8, + pub resist_piercing: u8, + pub resist_missile: u8, + pub detect_illusions: u8, + pub set_traps: u8, + pub lore: u8, + pub open_locks: u8, + pub move_silently: u8, + pub find_traps: u8, + pub pick_pockets: u8, + pub fatique: u8, + pub intoxication: u8, + pub luck: u8, + pub proficiency_largeswords: u8, + pub proficiency_smallswords: u8, + pub proficiency_bows: u8, + pub proficiency_spears: u8, + pub proficiency_blunt: u8, + pub proficiency_spiked: u8, + pub proficiency_axes: u8, + pub proficiency_missiles: u8, + #[br(count = 7)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub unused_proficencies: String, + pub nightmare_mode: u8, + pub translucency: u8, + pub reputation_loss_if_killed: u8, + pub reputation_loss_if_joins_party: u8, + pub reputation_loss_if_leaves_party: u8, + pub turn_undead_level: u8, + pub tracking_skill: u8, + // The following entry applies to BG1, BG2 and BGEE + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub tracking: String, + // Strrefs pertaining to the character. + // Most are connected with the sound-set (see SOUNDOFF.IDS (BG1) and SNDSLOT.IDS for (BG2)). + // This is broken, it should be 100 u32s + #[br(count = 100)] + pub strrefs: Vec, + pub level_first_class: u8, + pub level_second_class: u8, + pub level_third_class: u8, + // from gender.ids via sex stat + pub sex: u8, + pub strength: u8, + pub strength_bonus: u8, + pub intelligence: u8, + pub wisdom: u8, + pub dexterity: u8, + pub constitution: u8, + pub charisma: u8, + pub morale: u8, + pub morale_break: u8, + pub racial_enemy: u8, + pub morale_recovery_time: u16, + pub kit: u32, + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub override_script: String, + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub class_script: String, + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub race_script: String, + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub general_script: String, + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub default_script: String, + pub enemy_ally: u8, + pub general: u8, + pub race: u8, + pub class: u8, + pub specific: u8, + pub gender: u8, + // object.ids references + #[br(count = 5)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub object_references: String, + pub alignment: u8, + pub global_actor_enumeration: u16, + pub local_actor_enumeration: u16, + // death variable: sprite_is_dead on death + #[br(count = 32)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub death_variable: String, + pub offset_to_known_spells: i32, + pub count_of_known_spells: i32, + pub offset_to_spell_memorization_info: i32, + pub count_of_spell_memorization_info: i32, + pub offset_to_memorized_spell_table: i32, + pub count_of_memorized_spell_table: i32, + pub offset_to_item_slots: i32, + pub offset_to_items: i32, + pub count_of_items: i32, + pub offset_to_effects: i32, + pub count_of_effects: i32, + #[br(count = 8)] + #[br(map = |s: Vec| String::from_utf8_lossy(&s).to_string())] + #[bw(map = |x| x.parse::().unwrap())] + pub dialog_ref: String, +} + // https://gibberlings3.github.io/iesdp/file_formats/ie_formats/cre_v1.htm#CREV1_0_Header #[repr(C, packed)] #[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] @@ -247,11 +425,41 @@ pub struct BGEECreature { mod tests { use super::*; + use binrw::{io::Cursor, BinReaderExt}; use std::{ fs::File, io::{BufReader, Read}, }; + #[test] + fn binrw() { + let file = File::open("fixtures/dbeggar.cre").expect("Fixture missing"); + let mut buffer = Vec::new(); + BufReader::new(file) + .read_to_end(&mut buffer) + .expect("Could not read to buffer"); + let mut reader = Cursor::new(&buffer[..]); + let header: BGEECreatureHeader = reader.read_le().unwrap(); + assert_eq!(header.signature, "CRE ".to_string()); + assert_eq!(header.version, "V1.0".to_string()); + assert_eq!(header.base_hp, 8); + assert_eq!(header.level_first_class, 1); + assert_eq!(header.level_second_class, 1); + assert_eq!(header.level_third_class, 1); + assert_eq!(header.sex, 1); + assert_eq!(header.strength, 9); + assert_eq!(header.strength_bonus, 0); + assert_eq!(header.intelligence, 9); + assert_eq!(header.wisdom, 9); + assert_eq!(header.dexterity, 9); + assert_eq!(header.constitution, 9); + assert_eq!(header.charisma, 9); + assert_eq!(header.morale, 10); + assert_eq!(header.offset_to_item_slots, 996); + assert_eq!(header.offset_to_memorized_spell_table, 996); + assert_eq!(header.dialog_ref, "dbeggar\0".to_string()); + } + #[test] fn valid_simple_creature_file_header_parsed() { let file = File::open("fixtures/dbeggar.cre").expect("Fixture missing"); diff --git a/models/src/game.rs b/models/src/game.rs index 6859bd9..926a31c 100644 --- a/models/src/game.rs +++ b/models/src/game.rs @@ -48,7 +48,7 @@ impl Model for Game { let count: usize = usize::try_from(header.count_of_journal_entries).unwrap_or(0); let journal_entries = copy_transmute_buff::(buffer, start, count); - // Familar + // Familiar let start: usize = usize::try_from(header.offset_to_familar).unwrap_or(0); let familiar = copy_buff_to_struct::(buffer, start); diff --git a/models/src/item_table.rs b/models/src/item_table.rs index 4614edf..d98f451 100644 --- a/models/src/item_table.rs +++ b/models/src/item_table.rs @@ -64,7 +64,7 @@ pub struct ItemSlots { quiver_1: i16, quiver_2: i16, quiver_3: i16, - // Cannot be accesed from gui + // Cannot be accessed from gui quiver_4: i16, cloak: i16, quick_item_1: i16, diff --git a/models/src/save.rs b/models/src/save.rs index d862433..d7c838b 100644 --- a/models/src/save.rs +++ b/models/src/save.rs @@ -1,11 +1,10 @@ use flate2::bufread::ZlibDecoder; use serde::{Deserialize, Serialize}; -use std::{io::Read, rc::Rc}; +use std::io::Read; use crate::{ common::{header::Header, variable_char_array::VariableCharArray}, from_buffer, - model::Model, resources::{types::extension_to_resource_type, utils::copy_buff_to_struct}, }; @@ -14,15 +13,14 @@ use crate::{ pub struct Save { pub header: Header<4, 4>, pub files: Vec, - #[serde(skip)] - pub uncompressed_files: Vec>, + //#[serde(skip)] + //pub uncompressed_files: Vec>, } impl Save { pub fn new(buffer: &[u8]) -> Self { let header = copy_buff_to_struct::>(buffer, 0); let mut files = vec![]; - let uncompressed_files = vec![]; let mut counter = 8; while counter <= (buffer.len() - 1) { let file = File::new(buffer.get(counter..).unwrap_or_default()); @@ -33,11 +31,7 @@ impl Save { files.push(file); } - Save { - header, - files, - uncompressed_files, - } + Save { header, files } } pub fn decompress(&mut self) { let mut uncompressed_files = Vec::with_capacity(self.files.len()); @@ -50,7 +44,6 @@ impl Save { uncompressed_files.push(model); } } - self.uncompressed_files = uncompressed_files; } } @@ -123,7 +116,7 @@ mod tests { io::{BufReader, Read}, }; - use pretty_assertions::{assert_eq, assert_ne}; + use pretty_assertions::assert_eq; #[test] fn uncompress_files() { @@ -135,7 +128,6 @@ mod tests { .expect("Could not read to buffer"); let mut save = Save::new(&buffer); save.decompress(); - assert_ne!(save.uncompressed_files.len(), 0); } #[test] diff --git a/models/src/world_map.rs b/models/src/world_map.rs index 413801c..994246d 100644 --- a/models/src/world_map.rs +++ b/models/src/world_map.rs @@ -91,7 +91,7 @@ pub struct WorldMapEntry { pub offset_to_area_link_entries: i32, pub count_of_area_link_entries: i32, pub map_icons_bam_file: FixedCharSlice<8>, - // BGEE feild only + // BGEE field only pub flags: u32, #[serde(skip)] _unused: FixedCharSlice<128>,