save/restore: WIP implementation

Currently working on implementing serialize/deserialize for structs for
use in saving/restoring.
This commit is contained in:
Stephen Seo 2024-02-14 19:07:17 +09:00
parent aa0a67637f
commit 74a9980ca1
2 changed files with 563 additions and 0 deletions

View file

@ -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<u8> {
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::<f32>() * 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::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
rect.y = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
rect.w = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
rect.h = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
Ok((rect, idx))
}
pub fn serialize(&self) -> Vec<u8> {
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::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
circle.y = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
circle.r = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
Ok((circle, idx))
}
pub fn serialize(&self) -> Vec<u8> {
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<Vector> 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::<f32>() {
return Err(());
}
vector.x = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
vector.y = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
Ok((vector, idx))
}
pub fn serialize(&self) -> Vec<u8> {
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 {

View file

@ -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::<f32>() {
return Err(());
}
particle.velx = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
particle.vely = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
particle.velr = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
particle.r = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
particle.lifetime = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
particle.life_timer = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
Ok((particle, idx))
}
pub fn serialize(&self) -> Vec<u8> {
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<Particle>,
@ -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::<usize>() {
return Err(());
}
let particles_len: usize = usize::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<usize>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<usize>();
let mut particles: Vec<Particle> = 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::<f32>() {
return Err(());
}
psystem.spawn_timer = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
psystem.spawn_time = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
psystem.lifetime = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
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::<f32>() {
return Err(());
}
psystem.opacity = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
psystem.vel_multiplier = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
Ok((psystem, idx))
}
pub fn serialize(&self) -> Vec<u8> {
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::<f32>() {
return Err(());
}
rpsystem.r = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
rpsystem.velr = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
if data.len() < offset + idx + std::mem::size_of::<f32>() {
return Err(());
}
rpsystem.offset = f32::from_be_bytes(
data[(offset + idx)..(offset + idx + std::mem::size_of::<f32>())]
.try_into()
.map_err(|_| ())?,
);
idx += std::mem::size_of::<f32>();
Ok((rpsystem, idx))
}
pub fn serialize(&self) -> Vec<u8> {
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<Planet, ()> {
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<SaveData, ()> {
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<u8> {
todo!();
}
}
enum SaveLoadNotification {
Save { text: Option<String>, timer: f32 },
Load { text: Option<String>, timer: f32 },