From 74a9980ca15cfbb0c55a3825b4f0825089a0f0b5 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Wed, 14 Feb 2024 19:07:17 +0900 Subject: [PATCH] save/restore: WIP implementation Currently working on implementing serialize/deserialize for structs for use in saving/restoring. --- src/faux_quicksilver.rs | 188 ++++++++++++++++++++ src/original_impl.rs | 375 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 563 insertions(+) diff --git a/src/faux_quicksilver.rs b/src/faux_quicksilver.rs index 33fd4a4..beffb5a 100644 --- a/src/faux_quicksilver.rs +++ b/src/faux_quicksilver.rs @@ -14,6 +14,12 @@ pub struct Color { pub a: u8, } +impl Default for Color { + fn default() -> Self { + Self::WHITE + } +} + impl Color { pub const WHITE: Self = Self { r: 255, @@ -39,6 +45,32 @@ impl Color { pub fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self { Self { r, g, b, a } } + + pub fn deserialize(data: &[u8], offset: usize) -> Result<(Color, usize), ()> { + if data.len() < offset + 4 { + Err(()) + } else { + let mut color = Color::WHITE; + + color.r = data[offset]; + color.g = data[offset + 1]; + color.b = data[offset + 2]; + color.a = data[offset + 3]; + + Ok((color, 4)) + } + } + + pub fn serialize(&self) -> Vec { + let mut bytes = Vec::new(); + + bytes.push(self.r); + bytes.push(self.g); + bytes.push(self.b); + bytes.push(self.a); + + bytes + } } #[derive(Copy, Clone, Debug, PartialEq)] @@ -58,6 +90,61 @@ impl Rectangle { self.x += v.x; self.y += v.y; } + + pub fn deserialize(data: &[u8], offset: usize) -> Result<(Rectangle, usize), ()> { + if data.len() < offset + std::mem::size_of::() * 4 { + return Err(()); + } + + let mut idx: usize = 0; + let mut rect = Rectangle::new(0.0, 0.0, 0.0, 0.0); + + rect.x = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + rect.y = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + rect.w = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + rect.h = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + Ok((rect, idx)) + } + + pub fn serialize(&self) -> Vec { + let mut bytes = Vec::new(); + + for byte in self.x.to_be_bytes() { + bytes.push(byte); + } + for byte in self.y.to_be_bytes() { + bytes.push(byte); + } + for byte in self.w.to_be_bytes() { + bytes.push(byte); + } + for byte in self.h.to_be_bytes() { + bytes.push(byte); + } + + bytes + } } impl Default for Rectangle { @@ -78,6 +165,16 @@ pub struct Circle { pub r: f32, } +impl Default for Circle { + fn default() -> Self { + Self { + x: 0.0, + y: 0.0, + r: 1.0, + } + } +} + impl Circle { pub fn new(x: f32, y: f32, r: f32) -> Self { Self { x, y, r } @@ -87,6 +184,54 @@ impl Circle { self.x += v.x; self.y += v.y; } + + pub fn deserialize(data: &[u8], offset: usize) -> Result<(Circle, usize), ()> { + if data.len() < 12 + offset { + return Err(()); + } + + let mut idx: usize = 0; + let mut circle = Circle::new(0.0, 0.0, 1.0); + + circle.x = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + circle.y = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + circle.r = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + Ok((circle, idx)) + } + + pub fn serialize(&self) -> Vec { + let mut bytes = Vec::new(); + + for byte in self.x.to_be_bytes() { + bytes.push(byte); + } + for byte in self.y.to_be_bytes() { + bytes.push(byte); + } + for byte in self.r.to_be_bytes() { + bytes.push(byte); + } + + bytes + } } #[derive(Copy, Clone, Debug, PartialEq)] @@ -95,6 +240,12 @@ pub struct Vector { pub y: f32, } +impl Default for Vector { + fn default() -> Self { + Self { x: 1.0, y: 1.0 } + } +} + impl Add for Vector { type Output = Vector; @@ -146,6 +297,43 @@ impl Vector { pub fn new(x: f32, y: f32) -> Self { Self { x, y } } + + pub fn deserialize(data: &[u8], offset: usize) -> Result<(Vector, usize), ()> { + let mut idx: usize = 0; + let mut vector = Vector::new(0.0, 0.0); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + vector.x = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + vector.y = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + Ok((vector, idx)) + } + + pub fn serialize(&self) -> Vec { + let mut bytes = Vec::new(); + + for byte in self.x.to_be_bytes() { + bytes.push(byte); + } + for byte in self.y.to_be_bytes() { + bytes.push(byte); + } + + bytes + } } impl From<(f32, f32)> for Vector { diff --git a/src/original_impl.rs b/src/original_impl.rs index 7f6f4c9..faacb9f 100644 --- a/src/original_impl.rs +++ b/src/original_impl.rs @@ -535,6 +535,121 @@ struct Particle { life_timer: f32, } +impl Default for Particle { + fn default() -> Self { + Self { + rect: Rectangle::new(0.0, 0.0, 1.0, 1.0), + circle: Circle::new(0.0, 0.0, 1.0), + is_rect: true, + velx: 0.0, + vely: 0.0, + velr: 0.0, + r: 1.0, + lifetime: 1.0, + life_timer: 0.0, + } + } +} + +impl Particle { + pub fn deserialize(data: &[u8], offset: usize) -> Result<(Particle, usize), ()> { + let mut idx: usize = 0; + let mut particle = Particle::default(); + + let (rect, rect_size) = Rectangle::deserialize(data, offset + idx)?; + particle.rect = rect; + idx += rect_size; + + let (circle, circle_size) = Circle::deserialize(data, offset + idx)?; + particle.circle = circle; + idx += circle_size; + + if data.len() < offset + idx + 1 { + return Err(()); + } + particle.is_rect = data[offset + idx] != 0; + idx += 1; + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + particle.velx = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + particle.vely = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + particle.velr = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + particle.r = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + particle.lifetime = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + particle.life_timer = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + Ok((particle, idx)) + } + + pub fn serialize(&self) -> Vec { + let mut bytes = Vec::new(); + + bytes.append(&mut self.rect.serialize()); + bytes.append(&mut self.circle.serialize()); + bytes.push(if self.is_rect { 1 } else { 0 }); + bytes.append(&mut self.velx.to_be_bytes().into()); + bytes.append(&mut self.vely.to_be_bytes().into()); + bytes.append(&mut self.velr.to_be_bytes().into()); + bytes.append(&mut self.r.to_be_bytes().into()); + bytes.append(&mut self.lifetime.to_be_bytes().into()); + bytes.append(&mut self.life_timer.to_be_bytes().into()); + + bytes + } +} + #[derive(Clone)] struct ParticleSystem { particles: Vec, @@ -550,6 +665,24 @@ struct ParticleSystem { vel_multiplier: f32, } +impl Default for ParticleSystem { + fn default() -> Self { + Self { + particles: Vec::new(), + spawn_timer: 0.0, + spawn_time: 1.0, + lifetime: 1.0, + host_rect: Rectangle::default(), + host_circle: Circle::default(), + is_rect: true, + direction: Vector::default(), + color: Color::default(), + opacity: 1.0, + vel_multiplier: 1.0, + } + } +} + impl ParticleSystem { fn new( spawn_time: f32, @@ -684,6 +817,113 @@ impl ParticleSystem { }); } } + + pub fn deserialize(data: &[u8], offset: usize) -> Result<(Self, usize), ()> { + let mut idx: usize = 0; + let mut psystem = ParticleSystem::default(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + let particles_len: usize = usize::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + let mut particles: Vec = Vec::new(); + for _ in 0..particles_len { + let (particle, particle_size) = Particle::deserialize(data, offset + idx)?; + particles.push(particle); + idx += particle_size; + } + psystem.particles = particles; + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + psystem.spawn_timer = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + psystem.spawn_time = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + psystem.lifetime = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + let (rect, rect_size) = Rectangle::deserialize(data, offset + idx)?; + psystem.host_rect = rect; + idx += rect_size; + + let (circle, circle_size) = Circle::deserialize(data, offset + idx)?; + psystem.host_circle = circle; + idx += circle_size; + + if data.len() < offset + idx + 1 { + return Err(()); + } + psystem.is_rect = data[offset + idx] != 0; + idx += 1; + + let (vector, vector_size) = Vector::deserialize(data, offset + idx)?; + psystem.direction = vector; + idx += vector_size; + + let (color, color_size) = Color::deserialize(data, offset + idx)?; + psystem.color = color; + idx += color_size; + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + psystem.opacity = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + psystem.vel_multiplier = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + Ok((psystem, idx)) + } + + pub fn serialize(&self) -> Vec { + let mut bytes = Vec::new(); + + let particle_count: usize = self.particles.len(); + bytes.append(&mut particle_count.to_be_bytes().into()); + todo!(); + + bytes + } } #[derive(Clone)] @@ -694,6 +934,17 @@ struct RotatingParticleSystem { offset: f32, } +impl Default for RotatingParticleSystem { + fn default() -> Self { + Self { + particle_system: ParticleSystem::default(), + r: 0.0, + velr: 0.2, + offset: 0.0, + } + } +} + impl RotatingParticleSystem { fn new( spawn_time: f32, @@ -789,6 +1040,55 @@ impl RotatingParticleSystem { .ok(); } } + + pub fn deserialize(data: &[u8], offset: usize) -> Result<(Self, usize), ()> { + let mut idx: usize = 0; + let mut rpsystem = RotatingParticleSystem::default(); + + let (psystem, psystem_size) = ParticleSystem::deserialize(data, offset + idx)?; + rpsystem.particle_system = psystem; + idx += psystem_size; + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + rpsystem.r = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + rpsystem.velr = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + if data.len() < offset + idx + std::mem::size_of::() { + return Err(()); + } + rpsystem.offset = f32::from_be_bytes( + data[(offset + idx)..(offset + idx + std::mem::size_of::())] + .try_into() + .map_err(|_| ())?, + ); + idx += std::mem::size_of::(); + + Ok((rpsystem, idx)) + } + + pub fn serialize(&self) -> Vec { + let mut bytes = Vec::new(); + + todo!(); + + bytes + } } struct ExplConvCircleParticle { @@ -968,6 +1268,26 @@ impl Planet { moon.draw(window, transform); } } + + pub fn deserialize(data: &[u8], offset: usize) -> Result { + let mut idx: usize = 0; + let mut planet = Planet::new(Circle::new(0.0, 0.0, 1.0), Color::WHITE); + + let (circle, circle_size) = Circle::deserialize(data, offset + idx)?; + planet.circle = circle; + idx += circle_size; + + let (color, color_size) = Color::deserialize(data, offset + idx)?; + planet.color = color; + idx += color_size; + + let (psystem, psystem_size) = ParticleSystem::deserialize(data, offset + idx)?; + planet.particle_system = psystem; + idx += psystem_size; + + todo!("deserialize rotatingparticlesystem"); + Err(()) + } } #[derive(Clone)] @@ -1180,6 +1500,61 @@ struct SaveData { joining_particles: RotatingParticleSystem, } +const SAVE_DATA_IDENTIFIER: [u8; 4] = [0x53, 0x41, 0x56, 0x45]; +#[derive(Copy, Clone)] +enum SaveDataDeserializeState { + GET_IDENTIFIER, + GET_PLANETS, +} + +impl SaveData { + pub fn deserialize(data: &[u8]) -> Result { + let mut idx: usize = 0; + let mut save_data = SaveData { + planets: Vec::new(), + stars: Vec::new(), + fishes: Vec::new(), + player: Rectangle::new(0.0, 0.0, 0.0, 0.0), + joining_particles: RotatingParticleSystem::new( + PP_GEN_RATE, + 1.0, + Rectangle::new(400.0, 300.0, 16.0, 16.0), + Circle::new(100.0, 100.0, 32.0), + true, + Vector::new(0.0, 0.0), + Color::GREEN, + 0.0, + 0.0, + 0.1, + JOINING_FAR_DIST, + 1.0, + ), + }; + let mut state = SaveDataDeserializeState::GET_IDENTIFIER; + + while idx < data.len() { + match state { + SaveDataDeserializeState::GET_IDENTIFIER => { + for i in 0..SAVE_DATA_IDENTIFIER.len() { + if data[idx + i] != SAVE_DATA_IDENTIFIER[i] { + return Err(()); + } + } + idx += SAVE_DATA_IDENTIFIER.len(); + state = SaveDataDeserializeState::GET_PLANETS; + } + SaveDataDeserializeState::GET_PLANETS => todo!(), + } + } + + Err(()) + } + + pub fn serialize(&self) -> Vec { + todo!(); + } +} + enum SaveLoadNotification { Save { text: Option, timer: f32 }, Load { text: Option, timer: f32 },