use serde::{Deserialize, Serialize};
use crate::snapshot::RemoteEntity;
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug, Default)]
#[serde(rename_all = "kebab-case")]
pub enum PieMode {
#[default]
Play,
EditorPreview,
}
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug)]
pub enum PieChannel {
Reliable,
Unreliable,
Frames,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub enum StateEvent {
EntitySpawned {
entity: RemoteEntity,
},
ComponentChanged {
entity: u64,
type_path: String,
value: serde_json::Value,
},
EntityDespawned {
entity: u64,
},
Status {
mode: PieMode,
ready: bool,
},
Log {
level: String,
message: String,
},
CursorState {
grabbed: bool,
visible: bool,
},
PickResult {
entity: Option<u64>,
},
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub enum ControlEvent {
Pause,
Resume,
Stop,
SetComponent {
entity: u64,
type_path: String,
value: serde_json::Value,
},
AddComponent {
entity: u64,
type_path: String,
value: serde_json::Value,
},
RemoveComponent {
entity: u64,
type_path: String,
},
StartFrameStream {
width: u32,
height: u32,
},
StopFrameStream,
Input(crate::input::PieInputEvent),
Pick,
Highlight {
entity: Option<u64>,
},
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub enum PieEvent {
State(StateEvent),
Control(ControlEvent),
}
pub fn to_bytes<T: Serialize>(value: &T) -> Result<Vec<u8>, serde_json::Error> {
serde_json::to_vec(value)
}
pub fn from_bytes<T: for<'de> Deserialize<'de>>(bytes: &[u8]) -> Result<T, serde_json::Error> {
serde_json::from_slice(bytes)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn control_event_round_trips_through_bytes() {
let ev = ControlEvent::Pause;
let bytes = to_bytes(&ev).unwrap();
let back: ControlEvent = from_bytes(&bytes).unwrap();
assert_eq!(back, ControlEvent::Pause);
}
#[test]
fn state_event_status_round_trips() {
let ev = StateEvent::Status {
mode: PieMode::Play,
ready: true,
};
let bytes = to_bytes(&ev).unwrap();
let back: StateEvent = from_bytes(&bytes).unwrap();
assert_eq!(back, ev);
}
#[test]
fn input_event_round_trips() {
use crate::input::PieInputEvent;
use bevy::input::keyboard::{Key, KeyCode};
let ev = ControlEvent::Input(PieInputEvent::Key {
key: KeyCode::KeyW,
logical: Key::Character("w".into()),
pressed: true,
repeat: false,
});
let bytes = to_bytes(&ev).unwrap();
assert_eq!(from_bytes::<ControlEvent>(&bytes).unwrap(), ev);
let ev = ControlEvent::Input(PieInputEvent::CursorMoved {
position: bevy::math::Vec2::new(640.5, 360.0),
});
let bytes = to_bytes(&ev).unwrap();
assert_eq!(from_bytes::<ControlEvent>(&bytes).unwrap(), ev);
}
#[test]
fn cursor_state_round_trips() {
let ev = StateEvent::CursorState {
grabbed: true,
visible: false,
};
let bytes = to_bytes(&ev).unwrap();
assert_eq!(from_bytes::<StateEvent>(&bytes).unwrap(), ev);
}
#[test]
fn pick_events_round_trip() {
let ev = ControlEvent::Pick;
let bytes = to_bytes(&ev).unwrap();
assert_eq!(from_bytes::<ControlEvent>(&bytes).unwrap(), ev);
let ev = StateEvent::PickResult { entity: Some(42) };
let bytes = to_bytes(&ev).unwrap();
assert_eq!(from_bytes::<StateEvent>(&bytes).unwrap(), ev);
let ev = StateEvent::PickResult { entity: None };
let bytes = to_bytes(&ev).unwrap();
assert_eq!(from_bytes::<StateEvent>(&bytes).unwrap(), ev);
}
#[test]
fn highlight_events_round_trip() {
let ev = ControlEvent::Highlight { entity: Some(7) };
let bytes = to_bytes(&ev).unwrap();
assert_eq!(from_bytes::<ControlEvent>(&bytes).unwrap(), ev);
let ev = ControlEvent::Highlight { entity: None };
let bytes = to_bytes(&ev).unwrap();
assert_eq!(from_bytes::<ControlEvent>(&bytes).unwrap(), ev);
}
}