Skip to content

Commit

Permalink
Test helicopter and hanging lamp objects. Implement write operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
Neloreck committed Feb 25, 2024
1 parent f8e94da commit 0d7bca0
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 3 deletions.
Binary file not shown.
Binary file not shown.
124 changes: 122 additions & 2 deletions crates/xray-db/src/data/alife/alife_object_hanging_lamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ use crate::data::alife::alife_object_inherited_reader::{
};
use crate::data::alife::alife_object_skeleton::AlifeObjectSkeleton;
use crate::data::alife::alife_object_visual::AlifeObjectVisual;
use byteorder::{ByteOrder, ReadBytesExt};
use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};
use std::io;

#[derive(Clone, Debug, PartialEq)]
pub struct AlifeObjectHangingLamp {
pub base: AlifeObjectVisual,
pub skeleton: AlifeObjectSkeleton,
Expand Down Expand Up @@ -35,6 +36,7 @@ pub struct AlifeObjectHangingLamp {
}

impl AlifeObjectInheritedReader<AlifeObjectHangingLamp> for AlifeObjectHangingLamp {
/// Read hanging lamp data from the chunk.
fn read_from_chunk<T: ByteOrder>(chunk: &mut Chunk) -> io::Result<AlifeObjectHangingLamp> {
let base: AlifeObjectVisual = AlifeObjectVisual::read_from_chunk::<T>(chunk)?;
let skeleton: AlifeObjectSkeleton = AlifeObjectSkeleton::read_from_chunk::<T>(chunk)?;
Expand Down Expand Up @@ -90,9 +92,127 @@ impl AlifeObjectInheritedReader<AlifeObjectHangingLamp> for AlifeObjectHangingLa
})
}

/// Write skeleton data into the writer.
fn write<T: ByteOrder>(&self, writer: &mut ChunkWriter) -> io::Result<()> {
todo!("Implement write operation");
self.base.write::<T>(writer)?;
self.skeleton.write::<T>(writer)?;

writer.write_u32::<T>(self.main_color)?;
writer.write_f32::<T>(self.main_brightness)?;
writer.write_null_terminated_string(&self.color_animator)?;
writer.write_f32::<T>(self.main_range)?;
writer.write_u16::<T>(self.light_flags)?;
writer.write_null_terminated_string(&self.startup_animation)?;
writer.write_null_terminated_string(&self.fixed_bones)?;
writer.write_f32::<T>(self.health)?;

writer.write_f32::<T>(self.virtual_size)?;
writer.write_f32::<T>(self.ambient_radius)?;
writer.write_f32::<T>(self.ambient_power)?;
writer.write_null_terminated_string(&self.ambient_texture)?;
writer.write_null_terminated_string(&self.light_texture)?;
writer.write_null_terminated_string(&self.light_bone)?;
writer.write_f32::<T>(self.spot_cone_angle)?;
writer.write_null_terminated_string(&self.glow_texture)?;
writer.write_f32::<T>(self.glow_radius)?;

writer.write_null_terminated_string(&self.light_ambient_bone)?;
writer.write_f32::<T>(self.volumetric_quality)?;
writer.write_f32::<T>(self.volumetric_intensity)?;
writer.write_f32::<T>(self.volumetric_distance)?;

Ok(())
}
}

impl AlifeObjectGeneric for AlifeObjectHangingLamp {}

#[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_hanging_lamp::AlifeObjectHangingLamp;
use crate::data::alife::alife_object_inherited_reader::AlifeObjectInheritedReader;
use crate::data::alife::alife_object_skeleton::AlifeObjectSkeleton;
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_hanging_lamp.chunk"));

let object: AlifeObjectHangingLamp = AlifeObjectHangingLamp {
base: AlifeObjectVisual {
base: AlifeObjectAbstract {
game_vertex_id: 15,
distance: 7634.124,
direct_control: 253,
level_vertex_id: 3456,
flags: 34,
custom_data: String::from("custom-data"),
story_id: 6987,
spawn_story_id: 3986,
},
visual_name: String::from("visual-name"),
visual_flags: 168,
},
skeleton: AlifeObjectSkeleton {
name: String::from("skeleton-name"),
flags: 0,
source_id: 978,
},
main_color: 52323,
main_brightness: 1.0,
color_animator: String::from("color-animator"),
main_range: 0.5,
light_flags: 425,
startup_animation: String::from("setup-animation"),
fixed_bones: String::from("fixed-bones"),
health: 1.0,
virtual_size: 0.7,
ambient_radius: 24.0,
ambient_power: 52.0,
ambient_texture: String::from("ambient-texture"),
light_texture: String::from("light-texture"),
light_bone: String::from("light-bone"),
spot_cone_angle: 5.23,
glow_texture: String::from("glow-texture"),
glow_radius: 15.43,
light_ambient_bone: String::from("light-ambient-bone"),
volumetric_quality: 1.3,
volumetric_intensity: 2.2,
volumetric_distance: 3.1,
};

object.write::<SpawnByteOrder>(&mut writer)?;

assert_eq!(writer.bytes_written(), 234);

let bytes_written: usize = writer.flush_chunk_into_file::<SpawnByteOrder>(
&mut overwrite_test_resource_as_file(&filename)?,
0,
)?;

assert_eq!(bytes_written, 234);

let file: FileSlice = open_test_resource_as_slice(&filename)?;

assert_eq!(file.bytes_remaining(), 234 + 8);

let mut chunk: Chunk = Chunk::from_file(file)?.read_child_by_index(0)?;
let read_object: AlifeObjectHangingLamp =
AlifeObjectHangingLamp::read_from_chunk::<SpawnByteOrder>(&mut chunk)?;

assert_eq!(read_object, object);

Ok(())
}
}
87 changes: 86 additions & 1 deletion crates/xray-db/src/data/alife/alife_object_helicopter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::data::alife::alife_object_visual::AlifeObjectVisual;
use byteorder::ByteOrder;
use std::io;

#[derive(Clone, Debug, PartialEq)]
pub struct AlifeObjectHelicopter {
pub base: AlifeObjectVisual,
pub skeleton: AlifeObjectSkeleton,
Expand All @@ -18,6 +19,7 @@ pub struct AlifeObjectHelicopter {
}

impl AlifeObjectInheritedReader<AlifeObjectHelicopter> for AlifeObjectHelicopter {
/// Read helicopter data from the chunk.
fn read_from_chunk<T: ByteOrder>(chunk: &mut Chunk) -> io::Result<AlifeObjectHelicopter> {
let base: AlifeObjectVisual = AlifeObjectVisual::read_from_chunk::<T>(chunk)?;
let motion: AlifeObjectMotion = AlifeObjectMotion::read_from_chunk::<T>(chunk)?;
Expand All @@ -35,9 +37,92 @@ impl AlifeObjectInheritedReader<AlifeObjectHelicopter> for AlifeObjectHelicopter
})
}

/// Write helicopter data into the chunk.
fn write<T: ByteOrder>(&self, writer: &mut ChunkWriter) -> io::Result<()> {
todo!("Implement write operation");
self.base.write::<T>(writer)?;
self.motion.write::<T>(writer)?;
self.skeleton.write::<T>(writer)?;

writer.write_null_terminated_string(&self.startup_animation)?;
writer.write_null_terminated_string(&self.engine_sound)?;

Ok(())
}
}

impl AlifeObjectGeneric for AlifeObjectHelicopter {}

#[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_helicopter::AlifeObjectHelicopter;
use crate::data::alife::alife_object_inherited_reader::AlifeObjectInheritedReader;
use crate::data::alife::alife_object_motion::AlifeObjectMotion;
use crate::data::alife::alife_object_skeleton::AlifeObjectSkeleton;
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_helicopter.chunk"));

let object: AlifeObjectHelicopter = AlifeObjectHelicopter {
base: AlifeObjectVisual {
base: AlifeObjectAbstract {
game_vertex_id: 6432,
distance: 243.53,
direct_control: 25364,
level_vertex_id: 3541,
flags: 43,
custom_data: String::from("custom-data"),
story_id: 64353,
spawn_story_id: 2533,
},
visual_name: String::from("visual-name"),
visual_flags: 43,
},
skeleton: AlifeObjectSkeleton {
name: String::from("skeleton-name"),
flags: 0,
source_id: 235,
},
motion: AlifeObjectMotion {
motion_name: String::from("motion-name"),
},
startup_animation: String::from("startup-animation"),
engine_sound: String::from("engine-sound"),
};

object.write::<SpawnByteOrder>(&mut writer)?;

assert_eq!(writer.bytes_written(), 111);

let bytes_written: usize = writer.flush_chunk_into_file::<SpawnByteOrder>(
&mut overwrite_test_resource_as_file(&filename)?,
0,
)?;

assert_eq!(bytes_written, 111);

let file: FileSlice = open_test_resource_as_slice(&filename)?;

assert_eq!(file.bytes_remaining(), 111 + 8);

let mut chunk: Chunk = Chunk::from_file(file)?.read_child_by_index(0)?;
let read_object: AlifeObjectHelicopter =
AlifeObjectHelicopter::read_from_chunk::<SpawnByteOrder>(&mut chunk)?;

assert_eq!(read_object, object);

Ok(())
}
}

0 comments on commit 0d7bca0

Please sign in to comment.