From f8e94dac675a314b66d3e360ce6c9e544b53e6db Mon Sep 17 00:00:00 2001 From: Neloreck Date: Sun, 25 Feb 2024 05:41:30 +0200 Subject: [PATCH] Write operation implementation for weapon objects. --- .../alife_object_inventory_box.chunk | Bin 0 -> 40 bytes .../alife_object_item_weapon_magazined.chunk | Bin 0 -> 75 bytes ...ife_object_item_weapon_magazined_wgl.chunk | Bin 0 -> 75 bytes .../alife_object_item_weapon_shotgun.chunk | Bin 0 -> 75 bytes .../data/alife/alife_object_inventory_box.rs | 78 ++++++++++++++- .../alife_object_item_weapon_magazined.rs | 89 +++++++++++++++++- .../alife_object_item_weapon_magazined_wgl.rs | 89 +++++++++++++++++- .../alife/alife_object_item_weapon_shotgun.rs | 86 ++++++++++++++++- 8 files changed, 337 insertions(+), 5 deletions(-) create mode 100644 crates/xray-db/resources/tests/chunks/alife_object_inventory_box/alife_object_inventory_box.chunk create mode 100644 crates/xray-db/resources/tests/chunks/alife_object_item_weapon_magazined/alife_object_item_weapon_magazined.chunk create mode 100644 crates/xray-db/resources/tests/chunks/alife_object_item_weapon_magazined_wgl/alife_object_item_weapon_magazined_wgl.chunk create mode 100644 crates/xray-db/resources/tests/chunks/alife_object_item_weapon_shotgun/alife_object_item_weapon_shotgun.chunk diff --git a/crates/xray-db/resources/tests/chunks/alife_object_inventory_box/alife_object_inventory_box.chunk b/crates/xray-db/resources/tests/chunks/alife_object_inventory_box/alife_object_inventory_box.chunk new file mode 100644 index 0000000000000000000000000000000000000000..460cd9b83fb0fce20b6622d592d211a2f4c6d132 GIT binary patch literal 40 PcmZQzU|>)HVnP4_1gHQZ literal 0 HcmV?d00001 diff --git a/crates/xray-db/resources/tests/chunks/alife_object_item_weapon_magazined/alife_object_item_weapon_magazined.chunk b/crates/xray-db/resources/tests/chunks/alife_object_item_weapon_magazined/alife_object_item_weapon_magazined.chunk new file mode 100644 index 0000000000000000000000000000000000000000..a41a32a5120426d55544b860f3e3157adab3ebc5 GIT binary patch literal 75 zcmZQzU|?_t;sOz~nh+-t>tPZDg94CFE-fy}&(%#yEJ>KH^AxEL5285sadr4G{o literal 0 HcmV?d00001 diff --git a/crates/xray-db/resources/tests/chunks/alife_object_item_weapon_shotgun/alife_object_item_weapon_shotgun.chunk b/crates/xray-db/resources/tests/chunks/alife_object_item_weapon_shotgun/alife_object_item_weapon_shotgun.chunk new file mode 100644 index 0000000000000000000000000000000000000000..13903f3acd6c0fe05a706a1fba68fe1eec9373cf GIT binary patch literal 75 zcmZQzU|?_tVy`~!_6Vn)j0_AnqZt?!fg;JJ#U=T>KH^AxEPpK7#RVI8xV;A literal 0 HcmV?d00001 diff --git a/crates/xray-db/src/data/alife/alife_object_inventory_box.rs b/crates/xray-db/src/data/alife/alife_object_inventory_box.rs index 02ec5f6..fda947c 100644 --- a/crates/xray-db/src/data/alife/alife_object_inventory_box.rs +++ b/crates/xray-db/src/data/alife/alife_object_inventory_box.rs @@ -4,7 +4,7 @@ use crate::data::alife::alife_object_inherited_reader::{ AlifeObjectGeneric, AlifeObjectInheritedReader, }; use crate::data::alife::alife_object_visual::AlifeObjectVisual; -use byteorder::{ByteOrder, ReadBytesExt}; +use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt}; use std::io; #[derive(Clone, Debug, PartialEq)] @@ -16,6 +16,7 @@ pub struct AlifeObjectInventoryBox { } impl AlifeObjectInheritedReader for AlifeObjectInventoryBox { + /// Read inventory object data from the chunk. fn read_from_chunk(chunk: &mut Chunk) -> io::Result { let base: AlifeObjectVisual = AlifeObjectVisual::read_from_chunk::(chunk)?; @@ -31,9 +32,82 @@ impl AlifeObjectInheritedReader for AlifeObjectInventor }) } + /// Write inventory object data into the writer. fn write(&self, writer: &mut ChunkWriter) -> io::Result<()> { - todo!("Implement write operation"); + self.base.write::(writer)?; + + writer.write_u8(self.can_take)?; + writer.write_u8(self.is_closed)?; + writer.write_null_terminated_string(&self.tip)?; + + Ok(()) } } impl AlifeObjectGeneric for AlifeObjectInventoryBox {} + +#[cfg(test)] +mod tests { + use crate::chunk::chunk::Chunk; + use crate::chunk::writer::ChunkWriter; + use crate::data::alife::alife_object_abstract::AlifeObjectAbstract; + use crate::data::alife::alife_object_inherited_reader::AlifeObjectInheritedReader; + use crate::data::alife::alife_object_inventory_box::AlifeObjectInventoryBox; + use crate::data::alife::alife_object_visual::AlifeObjectVisual; + use crate::test::utils::{ + get_test_chunk_file_sub_dir, open_test_resource_as_slice, overwrite_test_resource_as_file, + }; + use crate::types::SpawnByteOrder; + use fileslice::FileSlice; + use std::io; + + #[test] + fn test_read_write_object() -> io::Result<()> { + let mut writer: ChunkWriter = ChunkWriter::new(); + let filename: String = + get_test_chunk_file_sub_dir(file!(), &String::from("alife_object_inventory_box.chunk")); + + let object: AlifeObjectInventoryBox = AlifeObjectInventoryBox { + base: AlifeObjectVisual { + base: AlifeObjectAbstract { + game_vertex_id: 0, + distance: 0.0, + direct_control: 0, + level_vertex_id: 0, + flags: 0, + custom_data: "".to_string(), + story_id: 0, + spawn_story_id: 0, + }, + visual_name: "".to_string(), + visual_flags: 0, + }, + can_take: 0, + is_closed: 0, + tip: "".to_string(), + }; + + object.write::(&mut writer)?; + + assert_eq!(writer.bytes_written(), 32); + + let bytes_written: usize = writer.flush_chunk_into_file::( + &mut overwrite_test_resource_as_file(&filename)?, + 0, + )?; + + assert_eq!(bytes_written, 32); + + let file: FileSlice = open_test_resource_as_slice(&filename)?; + + assert_eq!(file.bytes_remaining(), 32 + 8); + + let mut chunk: Chunk = Chunk::from_file(file)?.read_child_by_index(0)?; + let read_object: AlifeObjectInventoryBox = + AlifeObjectInventoryBox::read_from_chunk::(&mut chunk)?; + + assert_eq!(read_object, object); + + Ok(()) + } +} diff --git a/crates/xray-db/src/data/alife/alife_object_item_weapon_magazined.rs b/crates/xray-db/src/data/alife/alife_object_item_weapon_magazined.rs index 11f5a3e..6e1b146 100644 --- a/crates/xray-db/src/data/alife/alife_object_item_weapon_magazined.rs +++ b/crates/xray-db/src/data/alife/alife_object_item_weapon_magazined.rs @@ -7,11 +7,13 @@ use crate::data::alife::alife_object_item_weapon::AlifeObjectItemWeapon; use byteorder::ByteOrder; use std::io; +#[derive(Clone, Debug, PartialEq)] pub struct AlifeObjectItemWeaponMagazined { pub base: AlifeObjectItemWeapon, } impl AlifeObjectInheritedReader for AlifeObjectItemWeaponMagazined { + /// Read magazined weapon data from the chunk. fn read_from_chunk( chunk: &mut Chunk, ) -> io::Result { @@ -20,9 +22,94 @@ impl AlifeObjectInheritedReader for AlifeObjectI Ok(AlifeObjectItemWeaponMagazined { base }) } + /// Write magazined weapon item into the writer. fn write(&self, writer: &mut ChunkWriter) -> io::Result<()> { - todo!("Implement write operation"); + self.base.write::(writer)?; + + Ok(()) } } impl AlifeObjectGeneric for AlifeObjectItemWeaponMagazined {} + +#[cfg(test)] +mod tests { + use crate::chunk::chunk::Chunk; + use crate::chunk::writer::ChunkWriter; + use crate::data::alife::alife_object_abstract::AlifeObjectAbstract; + use crate::data::alife::alife_object_inherited_reader::AlifeObjectInheritedReader; + use crate::data::alife::alife_object_item::AlifeObjectItem; + use crate::data::alife::alife_object_item_weapon::AlifeObjectItemWeapon; + use crate::data::alife::alife_object_item_weapon_magazined::AlifeObjectItemWeaponMagazined; + use crate::data::alife::alife_object_item_weapon_magazined_wgl::AlifeObjectItemWeaponMagazinedWgl; + use crate::data::alife::alife_object_visual::AlifeObjectVisual; + use crate::test::utils::{ + get_test_chunk_file_sub_dir, open_test_resource_as_slice, overwrite_test_resource_as_file, + }; + use crate::types::SpawnByteOrder; + use fileslice::FileSlice; + use std::io; + + #[test] + fn test_read_write_object() -> io::Result<()> { + let mut writer: ChunkWriter = ChunkWriter::new(); + let filename: String = get_test_chunk_file_sub_dir( + file!(), + &String::from("alife_object_item_weapon_magazined.chunk"), + ); + + let object: AlifeObjectItemWeaponMagazinedWgl = AlifeObjectItemWeaponMagazinedWgl { + base: AlifeObjectItemWeaponMagazined { + base: AlifeObjectItemWeapon { + base: AlifeObjectItem { + base: AlifeObjectVisual { + base: AlifeObjectAbstract { + game_vertex_id: 5232, + distance: 53.1213, + direct_control: 67, + level_vertex_id: 25313, + flags: 32, + custom_data: String::from("custom-data"), + story_id: 3486, + spawn_story_id: 37663, + }, + visual_name: String::from("visual-name"), + visual_flags: 33, + }, + condition: 1.0, + upgrades_count: 0, + }, + ammo_current: 20, + ammo_elapsed: 10, + weapon_state: 1, + addon_flags: 1, + ammo_type: 1, + elapsed_grenades: 0, + }, + }, + }; + + object.write::(&mut writer)?; + + assert_eq!(writer.bytes_written(), 67); + + let bytes_written: usize = writer.flush_chunk_into_file::( + &mut overwrite_test_resource_as_file(&filename)?, + 0, + )?; + + assert_eq!(bytes_written, 67); + + let file: FileSlice = open_test_resource_as_slice(&filename)?; + + assert_eq!(file.bytes_remaining(), 67 + 8); + + let mut chunk: Chunk = Chunk::from_file(file)?.read_child_by_index(0)?; + let read_object: AlifeObjectItemWeaponMagazinedWgl = + AlifeObjectItemWeaponMagazinedWgl::read_from_chunk::(&mut chunk)?; + + assert_eq!(read_object, object); + + Ok(()) + } +} diff --git a/crates/xray-db/src/data/alife/alife_object_item_weapon_magazined_wgl.rs b/crates/xray-db/src/data/alife/alife_object_item_weapon_magazined_wgl.rs index daa3683..82122c6 100644 --- a/crates/xray-db/src/data/alife/alife_object_item_weapon_magazined_wgl.rs +++ b/crates/xray-db/src/data/alife/alife_object_item_weapon_magazined_wgl.rs @@ -7,6 +7,7 @@ use crate::data::alife::alife_object_item_weapon_magazined::AlifeObjectItemWeapo use byteorder::ByteOrder; use std::io; +#[derive(Clone, Debug, PartialEq)] pub struct AlifeObjectItemWeaponMagazinedWgl { pub base: AlifeObjectItemWeaponMagazined, } @@ -14,6 +15,7 @@ pub struct AlifeObjectItemWeaponMagazinedWgl { impl AlifeObjectInheritedReader for AlifeObjectItemWeaponMagazinedWgl { + /// Read magazined weapon with launcher from the chunk. fn read_from_chunk( chunk: &mut Chunk, ) -> io::Result { @@ -23,9 +25,94 @@ impl AlifeObjectInheritedReader Ok(AlifeObjectItemWeaponMagazinedWgl { base }) } + /// Write magazined weapon with launcher data into the writer. fn write(&self, writer: &mut ChunkWriter) -> io::Result<()> { - todo!("Implement write operation"); + self.base.write::(writer)?; + + Ok(()) } } impl AlifeObjectGeneric for AlifeObjectItemWeaponMagazinedWgl {} + +#[cfg(test)] +mod tests { + use crate::chunk::chunk::Chunk; + use crate::chunk::writer::ChunkWriter; + use crate::data::alife::alife_object_abstract::AlifeObjectAbstract; + use crate::data::alife::alife_object_inherited_reader::AlifeObjectInheritedReader; + use crate::data::alife::alife_object_item::AlifeObjectItem; + use crate::data::alife::alife_object_item_weapon::AlifeObjectItemWeapon; + use crate::data::alife::alife_object_item_weapon_magazined::AlifeObjectItemWeaponMagazined; + use crate::data::alife::alife_object_item_weapon_magazined_wgl::AlifeObjectItemWeaponMagazinedWgl; + use crate::data::alife::alife_object_visual::AlifeObjectVisual; + use crate::test::utils::{ + get_test_chunk_file_sub_dir, open_test_resource_as_slice, overwrite_test_resource_as_file, + }; + use crate::types::SpawnByteOrder; + use fileslice::FileSlice; + use std::io; + + #[test] + fn test_read_write_object() -> io::Result<()> { + let mut writer: ChunkWriter = ChunkWriter::new(); + let filename: String = get_test_chunk_file_sub_dir( + file!(), + &String::from("alife_object_item_weapon_magazined_wgl.chunk"), + ); + + let object: AlifeObjectItemWeaponMagazinedWgl = AlifeObjectItemWeaponMagazinedWgl { + base: AlifeObjectItemWeaponMagazined { + base: AlifeObjectItemWeapon { + base: AlifeObjectItem { + base: AlifeObjectVisual { + base: AlifeObjectAbstract { + game_vertex_id: 2413, + distance: 53.1213, + direct_control: 3643, + level_vertex_id: 25313, + flags: 32, + custom_data: String::from("custom-data"), + story_id: 3486, + spawn_story_id: 37663, + }, + visual_name: String::from("visual-name"), + visual_flags: 36, + }, + condition: 1.0, + upgrades_count: 0, + }, + ammo_current: 20, + ammo_elapsed: 10, + weapon_state: 1, + addon_flags: 1, + ammo_type: 1, + elapsed_grenades: 0, + }, + }, + }; + + object.write::(&mut writer)?; + + assert_eq!(writer.bytes_written(), 67); + + let bytes_written: usize = writer.flush_chunk_into_file::( + &mut overwrite_test_resource_as_file(&filename)?, + 0, + )?; + + assert_eq!(bytes_written, 67); + + let file: FileSlice = open_test_resource_as_slice(&filename)?; + + assert_eq!(file.bytes_remaining(), 67 + 8); + + let mut chunk: Chunk = Chunk::from_file(file)?.read_child_by_index(0)?; + let read_object: AlifeObjectItemWeaponMagazinedWgl = + AlifeObjectItemWeaponMagazinedWgl::read_from_chunk::(&mut chunk)?; + + assert_eq!(read_object, object); + + Ok(()) + } +} diff --git a/crates/xray-db/src/data/alife/alife_object_item_weapon_shotgun.rs b/crates/xray-db/src/data/alife/alife_object_item_weapon_shotgun.rs index 7ebf8f8..f1dcddf 100644 --- a/crates/xray-db/src/data/alife/alife_object_item_weapon_shotgun.rs +++ b/crates/xray-db/src/data/alife/alife_object_item_weapon_shotgun.rs @@ -7,20 +7,104 @@ use crate::data::alife::alife_object_item_weapon::AlifeObjectItemWeapon; use byteorder::ByteOrder; use std::io; +#[derive(Clone, Debug, PartialEq)] pub struct AlifeObjectItemWeaponShotgun { pub base: AlifeObjectItemWeapon, } impl AlifeObjectInheritedReader for AlifeObjectItemWeaponShotgun { + /// Read shotgun object data from the chunk. fn read_from_chunk(chunk: &mut Chunk) -> io::Result { let base: AlifeObjectItemWeapon = AlifeObjectItemWeapon::read_from_chunk::(chunk)?; Ok(AlifeObjectItemWeaponShotgun { base }) } + /// Write shotgun object data into the writer. fn write(&self, writer: &mut ChunkWriter) -> io::Result<()> { - todo!("Implement write operation"); + self.base.write::(writer)?; + + Ok(()) } } impl AlifeObjectGeneric for AlifeObjectItemWeaponShotgun {} + +#[cfg(test)] +mod tests { + use crate::chunk::chunk::Chunk; + use crate::chunk::writer::ChunkWriter; + use crate::data::alife::alife_object_abstract::AlifeObjectAbstract; + use crate::data::alife::alife_object_inherited_reader::AlifeObjectInheritedReader; + use crate::data::alife::alife_object_item::AlifeObjectItem; + use crate::data::alife::alife_object_item_weapon::AlifeObjectItemWeapon; + use crate::data::alife::alife_object_item_weapon_shotgun::AlifeObjectItemWeaponShotgun; + use crate::data::alife::alife_object_visual::AlifeObjectVisual; + use crate::test::utils::{ + get_test_chunk_file_sub_dir, open_test_resource_as_slice, overwrite_test_resource_as_file, + }; + use crate::types::SpawnByteOrder; + use fileslice::FileSlice; + use std::io; + + #[test] + fn test_read_write_object() -> io::Result<()> { + let mut writer: ChunkWriter = ChunkWriter::new(); + let filename: String = get_test_chunk_file_sub_dir( + file!(), + &String::from("alife_object_item_weapon_shotgun.chunk"), + ); + + let object: AlifeObjectItemWeaponShotgun = AlifeObjectItemWeaponShotgun { + base: AlifeObjectItemWeapon { + base: AlifeObjectItem { + base: AlifeObjectVisual { + base: AlifeObjectAbstract { + game_vertex_id: 36426, + distance: 54.132, + direct_control: 441, + level_vertex_id: 23513, + flags: 33, + custom_data: String::from("custom-data"), + story_id: 35426, + spawn_story_id: 267845, + }, + visual_name: String::from("visual-name"), + visual_flags: 253, + }, + condition: 1.0, + upgrades_count: 0, + }, + ammo_current: 20, + ammo_elapsed: 10, + weapon_state: 3, + addon_flags: 36, + ammo_type: 1, + elapsed_grenades: 1, + }, + }; + + object.write::(&mut writer)?; + + assert_eq!(writer.bytes_written(), 67); + + let bytes_written: usize = writer.flush_chunk_into_file::( + &mut overwrite_test_resource_as_file(&filename)?, + 0, + )?; + + assert_eq!(bytes_written, 67); + + let file: FileSlice = open_test_resource_as_slice(&filename)?; + + assert_eq!(file.bytes_remaining(), 67 + 8); + + let mut chunk: Chunk = Chunk::from_file(file)?.read_child_by_index(0)?; + let read_object: AlifeObjectItemWeaponShotgun = + AlifeObjectItemWeaponShotgun::read_from_chunk::(&mut chunk)?; + + assert_eq!(read_object, object); + + Ok(()) + } +}