Browse Source

Implement conversion for blocks into regular BlockEntity (using AsRef)

master
NGnius (Graham) 2 years ago
parent
commit
8e0a3e8b32
14 changed files with 148 additions and 16 deletions
  1. +12
    -0
      src/techblox/blocks/block_entity.rs
  2. +1
    -1
      src/techblox/blocks/common_components.rs
  3. +11
    -1
      src/techblox/blocks/engine.rs
  4. +11
    -1
      src/techblox/blocks/joint.rs
  5. +3
    -2
      src/techblox/blocks/lookup_tables.rs
  6. +1
    -1
      src/techblox/blocks/mod.rs
  7. +11
    -1
      src/techblox/blocks/passenger_seat.rs
  8. +11
    -1
      src/techblox/blocks/pilot_seat.rs
  9. +19
    -1
      src/techblox/blocks/spring.rs
  10. +11
    -1
      src/techblox/blocks/tyre.rs
  11. +19
    -1
      src/techblox/blocks/wheel_rig.rs
  12. +2
    -1
      src/techblox/entity_traits.rs
  13. +4
    -4
      src/techblox/gamesave.rs
  14. +32
    -0
      tests/techblox_parsing.rs

+ 12
- 0
src/techblox/blocks/block_entity.rs View File

@@ -1,3 +1,5 @@
use std::convert::AsRef;

use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent};
use crate::techblox::blocks::{DBEntityStruct, PositionEntityStruct, ScalingEntityStruct, RotationEntityStruct,
SkewComponent, GridRotationStruct, SerializedGridConnectionsEntityStruct, SerializedBlockPlacementInfoStruct,
@@ -75,3 +77,13 @@ impl SerializedEntityDescriptor for BlockEntity {
Self::hash("StandardBlockEntityDescriptorV4") // 1357220432
}
}

impl AsRef<BlockEntity> for BlockEntity {
fn as_ref(&self) -> &Self {
self
}
}

pub trait Block: SerializedEntityDescriptor + AsRef<BlockEntity> {}

impl Block for BlockEntity {}

+ 1
- 1
src/techblox/blocks/common_components.rs View File

@@ -106,7 +106,7 @@ impl SerializedEntityComponent for SerializedColourParameterEntityStruct {}
/// Block group component.
#[derive(Copy, Clone, Parsable)]
pub struct BlockGroupEntityComponent {
/// Index of colour in Techblox palette
/// Index of block in Techblox block groups (deserialized in earlier part of game save)
pub current_block_group: i32,
}



+ 11
- 1
src/techblox/blocks/engine.rs View File

@@ -1,5 +1,7 @@
use std::convert::AsRef;

use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent,
blocks::{BlockEntity}};
blocks::{BlockEntity, Block}};
use libfj_parsable_macro_derive::*;

/// Engine entity descriptor
@@ -33,6 +35,14 @@ impl SerializedEntityDescriptor for EngineBlockEntity {
}
}

impl AsRef<BlockEntity> for EngineBlockEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block
}
}

impl Block for EngineBlockEntity {}

/// Engine settings entity component.
#[derive(Copy, Clone, Parsable)]
pub struct EngineBlockTweakableComponent {


+ 11
- 1
src/techblox/blocks/joint.rs View File

@@ -1,5 +1,7 @@
use std::convert::AsRef;

use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent,
blocks::{BlockEntity}};
blocks::{BlockEntity, Block}};
use libfj_parsable_macro_derive::*;

/// Joint block entity descriptor
@@ -26,3 +28,11 @@ impl SerializedEntityDescriptor for JointBlockEntity {
Self::hash("JointBlockEntityDescriptorV3") // 3586818581
}
}

impl AsRef<BlockEntity> for JointBlockEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block
}
}

impl Block for JointBlockEntity {}

+ 3
- 2
src/techblox/blocks/lookup_tables.rs View File

@@ -1,6 +1,6 @@
use std::io::Read;

use crate::techblox::{Parsable, SerializedEntityDescriptor};
use crate::techblox::{Parsable};
use crate::techblox::blocks::*;

const HASHNAMES: &[&str] = &[
@@ -70,7 +70,8 @@ const HASHNAMES: &[&str] = &[
"CharacterCameraEntityDescriptorV1",
];

pub fn lookup_hashname(hash: u32, data: &mut dyn Read) -> std::io::Result<Box<dyn SerializedEntityDescriptor>> {
pub fn lookup_hashname(hash: u32, data: &mut dyn Read) ->
std::io::Result<Box<dyn Block>> {
Ok(match hash {
1357220432 /*StandardBlockEntityDescriptorV4*/ => Box::new(BlockEntity::parse(data)?),
2281299333 /*PilotSeatEntityDescriptorV4*/ => Box::new(PilotSeatEntity::parse(data)?),


+ 1
- 1
src/techblox/blocks/mod.rs View File

@@ -12,7 +12,7 @@ mod tyre;
mod wheel_rig;
mod wire_entity;

pub use block_entity::{BlockEntity};
pub use block_entity::{BlockEntity, Block};
pub use common_components::{DBEntityStruct, PositionEntityStruct, ScalingEntityStruct, RotationEntityStruct,
SkewComponent, GridRotationStruct, SerializedGridConnectionsEntityStruct, SerializedBlockPlacementInfoStruct,
SerializedCubeMaterialStruct, SerializedUniformBlockScaleEntityStruct, SerializedColourParameterEntityStruct,


+ 11
- 1
src/techblox/blocks/passenger_seat.rs View File

@@ -1,5 +1,7 @@
use std::convert::AsRef;

use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent,
blocks::{BlockEntity, SeatFollowCamComponent}};
blocks::{BlockEntity, SeatFollowCamComponent, Block}};
use libfj_parsable_macro_derive::*;

/// Passenger seat entity descriptor (V4)
@@ -32,3 +34,11 @@ impl SerializedEntityDescriptor for PassengerSeatEntity {
Self::hash("PassengerSeatEntityDescriptorV4") // 1360086092
}
}

impl AsRef<BlockEntity> for PassengerSeatEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block
}
}

impl Block for PassengerSeatEntity {}

+ 11
- 1
src/techblox/blocks/pilot_seat.rs View File

@@ -1,4 +1,6 @@
use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent, blocks::BlockEntity};
use std::convert::AsRef;

use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent, blocks::{BlockEntity, Block}};
use libfj_parsable_macro_derive::*;

/// Pilot seat entity descriptor (V4)
@@ -32,6 +34,14 @@ impl SerializedEntityDescriptor for PilotSeatEntity {
}
}

impl AsRef<BlockEntity> for PilotSeatEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block
}
}

impl Block for PilotSeatEntity {}

/// Seat settings entity component.
#[derive(Copy, Clone, Parsable)]
pub struct SeatFollowCamComponent {


+ 19
- 1
src/techblox/blocks/spring.rs View File

@@ -1,5 +1,7 @@
use std::convert::AsRef;

use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent,
blocks::{BlockEntity}};
blocks::{BlockEntity, Block}};
use libfj_parsable_macro_derive::*;

/// Damped angular spring entity descriptor
@@ -37,6 +39,14 @@ impl SerializedEntityDescriptor for DampedAngularSpringEntity {
}
}

impl AsRef<BlockEntity> for DampedAngularSpringEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block
}
}

impl Block for DampedAngularSpringEntity {}

/// Damped spring entity descriptor
#[derive(Copy, Clone, Parsable)]
pub struct DampedSpringEntity {
@@ -72,6 +82,14 @@ impl SerializedEntityDescriptor for DampedSpringEntity {
}
}

impl AsRef<BlockEntity> for DampedSpringEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block
}
}

impl Block for DampedSpringEntity {}

/// Joint settings entity component.
#[derive(Copy, Clone, Parsable)]
pub struct TweakableJointDampingComponent {


+ 11
- 1
src/techblox/blocks/tyre.rs View File

@@ -1,5 +1,7 @@
use std::convert::AsRef;

use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent,
blocks::{BlockEntity}};
blocks::{BlockEntity, Block}};
use libfj_parsable_macro_derive::*;

/// Tire entity descriptor
@@ -26,3 +28,11 @@ impl SerializedEntityDescriptor for TyreEntity {
Self::hash("TyreEntityDescriptorV1") // 1517625162
}
}

impl AsRef<BlockEntity> for TyreEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block
}
}

impl Block for TyreEntity {}

+ 19
- 1
src/techblox/blocks/wheel_rig.rs View File

@@ -1,5 +1,7 @@
use std::convert::AsRef;

use crate::techblox::{SerializedEntityDescriptor, Parsable, SerializedEntityComponent,
blocks::{BlockEntity, TweakableJointDampingComponent}};
blocks::{BlockEntity, TweakableJointDampingComponent, Block}};
use libfj_parsable_macro_derive::*;

/// Wheel rig entity descriptor
@@ -37,6 +39,14 @@ impl SerializedEntityDescriptor for WheelRigEntity {
}
}

impl AsRef<BlockEntity> for WheelRigEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block
}
}

impl Block for WheelRigEntity {}

/// Wheel rig entity descriptor
#[derive(Copy, Clone, Parsable)]
pub struct WheelRigSteerableEntity {
@@ -68,6 +78,14 @@ impl SerializedEntityDescriptor for WheelRigSteerableEntity {
}
}

impl AsRef<BlockEntity> for WheelRigSteerableEntity {
fn as_ref(&self) -> &BlockEntity {
&self.block.as_ref()
}
}

impl Block for WheelRigSteerableEntity {}

/// Wheel rig settings entity component.
#[derive(Copy, Clone, Parsable)]
pub struct WheelRigTweakableStruct {


+ 2
- 1
src/techblox/entity_traits.rs View File

@@ -1,4 +1,5 @@
use std::io::{Read, Write};
use std::any::Any;

/// Standard trait for parsing Techblox game save data.
pub trait Parsable {
@@ -26,7 +27,7 @@ pub trait SerializedEntityDescriptor: Parsable {

/// Serializable entity component.
/// Components are the atomic unit of entities.
pub trait SerializedEntityComponent: Parsable {
pub trait SerializedEntityComponent: Parsable + Any {
/// Raw size of struct, in bytes.
fn size() -> usize where Self: Sized {
std::mem::size_of::<Self>()


+ 4
- 4
src/techblox/gamesave.rs View File

@@ -1,9 +1,9 @@
use chrono::{naive::NaiveDate, Datelike};
use std::io::{Read, Write};

use crate::techblox::{EntityHeader, BlockGroupEntity, parse_i64, parse_u32, Parsable, SerializedEntityDescriptor,
use crate::techblox::{EntityHeader, BlockGroupEntity, parse_i64, parse_u32, Parsable,
SerializedFlyCamEntity, SerializedPhysicsCameraEntity};
use crate::techblox::blocks::{lookup_hashname, SerializedWireEntity, SerializedGlobalWireSettingsEntity};
use crate::techblox::blocks::{lookup_hashname, SerializedWireEntity, SerializedGlobalWireSettingsEntity, Block};

/// A collection of cubes and other data from a GameSave.techblox file
//#[derive(Clone)]
@@ -37,7 +37,7 @@ pub struct GameSave {
pub cube_headers: Vec<EntityHeader>,

/// Blocks
pub cube_entities: Vec<Box<dyn SerializedEntityDescriptor>>,
pub cube_entities: Vec<Box<dyn Block>>,

/// Amount of wires in the save data, as claimed by the file.
pub wire_len: u32,
@@ -89,7 +89,7 @@ impl Parsable for GameSave {

// parse cube data
let mut cubes_h = Vec::<EntityHeader>::with_capacity(cube_count as usize);
let mut cubes_e = Vec::<Box<dyn SerializedEntityDescriptor>>::with_capacity(cube_count as usize);
let mut cubes_e = Vec::<Box<dyn Block>>::with_capacity(cube_count as usize);
for _i in 0..cube_count {
let header = EntityHeader::parse(data)?;
let hash = header.hash;


+ 32
- 0
tests/techblox_parsing.rs View File

@@ -6,6 +6,8 @@ use libfj::techblox::{SerializedEntityDescriptor, Parsable, blocks, EntityHeader
use std::io::{Read, Seek};
#[cfg(feature = "techblox")]
use std::fs::{File, OpenOptions};
#[cfg(feature = "techblox")]
use std::convert::AsRef;

#[cfg(feature = "techblox")]
const GAMESAVE_PATH: &str = "tests/GameSave.Techblox";
@@ -184,6 +186,10 @@ fn techblox_gamesave_parse_all() -> Result<(), ()> {
for i in 0..(gs.group_len as usize) {
assert_eq!(gs.group_headers[i].component_count, techblox::BlockGroupEntity::serialized_components());
assert_eq!(gs.group_headers[i].hash, gs.cube_groups[i].hash_name());
/*let pos = format!("({}, {}, {})", gs.cube_groups[i].block_group_transform.block_group_grid_position.x, gs.cube_groups[i].block_group_transform.block_group_grid_position.y, gs.cube_groups[i].block_group_transform.block_group_grid_position.z);
let rot = format!("({}, {}, {}, {})", gs.cube_groups[i].block_group_transform.block_group_grid_rotation.value.x, gs.cube_groups[i].block_group_transform.block_group_grid_rotation.value.y, gs.cube_groups[i].block_group_transform.block_group_grid_rotation.value.z,
gs.cube_groups[i].block_group_transform.block_group_grid_rotation.value.w);
println!("block id: {}, position: {}, rotation: {}", gs.cube_groups[i].saved_block_group_id.saved_block_group_id, pos, rot);*/
}
for i in 1..(gs.cube_len as usize) {
//assert_eq!(gs.cube_headers[i-1].hash, gs.cube_headers[i].hash);
@@ -221,3 +227,29 @@ fn techblox_gamesave_parse_all() -> Result<(), ()> {
assert_eq!(in_file.stream_position().unwrap(), out_file.stream_position().unwrap());
Ok(())
}

#[cfg(feature = "techblox")]
#[test]
fn techblox_gamesave_block_groups() -> Result<(), ()> {
let mut in_file = File::open(GAMESAVE_PATH_ALL).map_err(|_| ())?;
let mut buf = Vec::new();
in_file.read_to_end(&mut buf).map_err(|_| ())?;
let gs = techblox::GameSave::parse(&mut buf.as_slice()).map_err(|_| ())?;

for block_trait in &gs.cube_entities {
let block: &blocks::BlockEntity = block_trait.as_ref().as_ref();
//println!("Block @ ({}, {}, {})", block.pos_component.position.x, block.pos_component.position.y, block.pos_component.position.z);
assert!(is_in_block_groups(block.group_component.current_block_group, &gs.cube_groups));
}
Ok(())
}

#[cfg(feature = "techblox")]
fn is_in_block_groups(id: i32, block_groups: &Vec<techblox::BlockGroupEntity>) -> bool {
for bg in block_groups {
if bg.saved_block_group_id.saved_block_group_id == id {
return true;
}
}
false
}

Loading…
Cancel
Save