use chrono::{naive::NaiveDate, Datelike};
use std::io::{Read, Write};
use crate::techblox::{EntityHeader, BlockGroupEntity, parse_i64, parse_u32, Parsable,
SerializedFlyCamEntity, SerializedPhysicsCameraEntity};
use crate::techblox::blocks::{lookup_hashname, SerializedWireEntity, SerializedGlobalWireSettingsEntity, Block};
pub struct GameSave {
pub version: NaiveDate,
pub ticks: i64,
pub cube_len: u32,
pub max_entity_id: u32,
pub group_len: u32,
pub group_headers: Vec<EntityHeader>,
pub cube_groups: Vec<BlockGroupEntity>,
pub cube_headers: Vec<EntityHeader>,
pub cube_entities: Vec<Box<dyn Block>>,
pub wire_len: u32,
pub wire_headers: Vec<EntityHeader>,
pub wire_entities: Vec<SerializedWireEntity>,
pub wire_settings_header: EntityHeader,
pub wire_settings_entity: SerializedGlobalWireSettingsEntity,
pub flycam_header: EntityHeader,
pub flycam_entity: SerializedFlyCamEntity,
pub phycam_header: EntityHeader,
pub phycam_entity: SerializedPhysicsCameraEntity,
}
impl Parsable for GameSave {
fn parse(data: &mut dyn Read) -> std::io::Result<Self> {
let year = parse_u32(data)?; let month = parse_u32(data)?;
let day = parse_u32(data)?;
let date = NaiveDate::from_ymd_opt(year as i32, month, day).unwrap();
let ticks = parse_i64(data)?; let cube_count = parse_u32(data)?; let max_e_id = parse_u32(data)?; let group_count = parse_u32(data)?; let mut groups_h = Vec::<EntityHeader>::with_capacity(group_count as usize);
let mut groups_e = Vec::<BlockGroupEntity>::with_capacity(group_count as usize);
for _i in 0..group_count {
groups_h.push(EntityHeader::parse(data)?);
groups_e.push(BlockGroupEntity::parse(data)?);
}
let mut cubes_h = Vec::<EntityHeader>::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;
cubes_h.push(header);
cubes_e.push(lookup_hashname(hash, data)?);
}
let wire_count = parse_u32(data)?;
let mut wires_h = Vec::<EntityHeader>::with_capacity(wire_count as usize);
let mut wires_e = Vec::<SerializedWireEntity>::with_capacity(wire_count as usize);
for _i in 0..wire_count {
wires_h.push(EntityHeader::parse(data)?);
wires_e.push(SerializedWireEntity::parse(data)?);
}
let wire_settings_h = EntityHeader::parse(data)?;
let wire_settings_e = SerializedGlobalWireSettingsEntity::parse(data)?;
let flycam_h = EntityHeader::parse(data)?;
let flycam_e = SerializedFlyCamEntity::parse(data)?;
let phycam_h = EntityHeader::parse(data)?;
let phycam_e = SerializedPhysicsCameraEntity::parse(data)?;
Ok(Self {
version: date,
ticks: ticks,
cube_len: cube_count,
max_entity_id: max_e_id,
group_len: group_count,
group_headers: groups_h,
cube_groups: groups_e,
cube_headers: cubes_h,
cube_entities: cubes_e,
wire_len: wire_count,
wire_headers: wires_h,
wire_entities: wires_e,
wire_settings_header: wire_settings_h,
wire_settings_entity: wire_settings_e,
flycam_header: flycam_h,
flycam_entity: flycam_e,
phycam_header: phycam_h,
phycam_entity: phycam_e,
})
}
fn dump(&self, writer: &mut dyn Write) -> std::io::Result<usize> {
let mut write_count: usize = 0;
write_count += self.version.year().dump(writer)?;
write_count += self.version.month().dump(writer)?;
write_count += self.version.day().dump(writer)?;
write_count += self.ticks.dump(writer)?;
write_count += self.cube_len.dump(writer)?;
write_count += self.max_entity_id.dump(writer)?;
write_count += self.group_len.dump(writer)?;
for i in 0..self.group_len as usize {
write_count += self.group_headers[i].dump(writer)?;
write_count += self.cube_groups[i].dump(writer)?;
}
for i in 0..self.cube_len as usize {
write_count += self.cube_headers[i].dump(writer)?;
write_count += self.cube_entities[i].dump(writer)?;
}
write_count += self.wire_len.dump(writer)?;
for i in 0..self.wire_len as usize {
write_count += self.wire_headers[i].dump(writer)?;
write_count += self.wire_entities[i].dump(writer)?;
}
write_count += self.wire_settings_header.dump(writer)?;
write_count += self.wire_settings_entity.dump(writer)?;
write_count += self.flycam_header.dump(writer)?;
write_count += self.flycam_entity.dump(writer)?;
write_count += self.phycam_header.dump(writer)?;
write_count += self.phycam_entity.dump(writer)?;
Ok(write_count)
}
}
impl std::string::ToString for GameSave {
fn to_string(&self) -> String {
format!("{}g {}c {}w (v{})", self.group_len, self.cube_len, self.wire_len, self.version)
}
}