use crate::types::{ClientId, ComponentKind, NetworkId};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum GameEvent {
AsteroidDepleted {
network_id: NetworkId,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FragmentedEvent {
pub message_id: u32,
pub fragment_index: u16,
pub total_fragments: u16,
#[serde(with = "serde_bytes")]
pub payload: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ReplicationEvent {
pub network_id: NetworkId,
pub component_kind: ComponentKind,
#[serde(with = "serde_bytes")]
pub payload: Vec<u8>,
pub tick: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ComponentUpdate {
pub network_id: NetworkId,
pub component_kind: ComponentKind,
#[serde(with = "serde_bytes")]
pub payload: Vec<u8>,
pub tick: u64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum NetworkEvent {
ClientConnected(ClientId),
ClientDisconnected(ClientId),
UnreliableMessage {
client_id: ClientId,
#[serde(with = "serde_bytes")]
data: Vec<u8>,
},
ReliableMessage {
client_id: ClientId,
#[serde(with = "serde_bytes")]
data: Vec<u8>,
},
Ping {
client_id: ClientId,
tick: u64,
},
Pong {
tick: u64,
},
Auth {
session_token: String,
},
SessionClosed(ClientId),
StreamReset(ClientId),
Fragment {
client_id: ClientId,
fragment: FragmentedEvent,
},
StressTest {
client_id: ClientId,
count: u16,
rotate: bool,
},
Spawn {
client_id: ClientId,
entity_type: u16,
x: f32,
y: f32,
rot: f32,
},
ClearWorld {
client_id: ClientId,
},
Disconnected(ClientId),
GameEvent {
client_id: ClientId,
event: GameEvent,
},
}
impl NetworkEvent {
#[must_use]
pub const fn is_wire(&self) -> bool {
match self {
Self::Ping { .. }
| Self::Pong { .. }
| Self::Auth { .. }
| Self::Fragment { .. }
| Self::StressTest { .. }
| Self::Spawn { .. }
| Self::ClearWorld { .. }
| Self::GameEvent { .. } => true,
Self::ClientConnected(_)
| Self::ClientDisconnected(_)
| Self::UnreliableMessage { .. }
| Self::ReliableMessage { .. }
| Self::SessionClosed(_)
| Self::StreamReset(_)
| Self::Disconnected(_) => false,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum WireEvent {
Ping {
tick: u64,
},
Pong {
tick: u64,
},
Auth {
session_token: String,
},
Fragment(FragmentedEvent),
StressTest {
count: u16,
rotate: bool,
},
Spawn {
entity_type: u16,
x: f32,
y: f32,
rot: f32,
},
ClearWorld,
GameEvent(GameEvent),
}
impl WireEvent {
#[must_use]
pub fn into_network_event(self, client_id: crate::types::ClientId) -> NetworkEvent {
match self {
Self::Ping { tick } => NetworkEvent::Ping { client_id, tick },
Self::Pong { tick } => NetworkEvent::Pong { tick },
Self::Auth { session_token } => NetworkEvent::Auth { session_token },
Self::Fragment(fragment) => NetworkEvent::Fragment {
client_id,
fragment,
},
Self::StressTest { count, rotate } => NetworkEvent::StressTest {
client_id,
count,
rotate,
},
Self::Spawn {
entity_type,
x,
y,
rot,
} => NetworkEvent::Spawn {
client_id,
entity_type,
x,
y,
rot,
},
Self::ClearWorld => NetworkEvent::ClearWorld { client_id },
Self::GameEvent(event) => NetworkEvent::GameEvent { client_id, event },
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_network_event_is_wire() {
assert!(
NetworkEvent::Ping {
client_id: ClientId(1),
tick: 100
}
.is_wire()
);
assert!(
NetworkEvent::GameEvent {
client_id: ClientId(1),
event: GameEvent::AsteroidDepleted {
network_id: NetworkId(1)
}
}
.is_wire()
);
assert!(!NetworkEvent::ClientConnected(ClientId(1)).is_wire());
assert!(!NetworkEvent::ClientDisconnected(ClientId(1)).is_wire());
}
#[test]
fn test_wire_event_conversion_roundtrip() {
let wire = WireEvent::GameEvent(GameEvent::AsteroidDepleted {
network_id: NetworkId(42),
});
let client_id = ClientId(7);
let network = wire.clone().into_network_event(client_id);
if let NetworkEvent::GameEvent {
client_id: cid,
event,
} = network
{
assert_eq!(cid, client_id);
assert_eq!(
event,
GameEvent::AsteroidDepleted {
network_id: NetworkId(42)
}
);
} else {
panic!("Conversion failed to preserve GameEvent variant");
}
}
}