127 lines
3.2 KiB
Rust
127 lines
3.2 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use std::sync::Arc;
|
|
use tokio::sync::Mutex;
|
|
use tokio::sync::mpsc;
|
|
use uuid::Uuid;
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct Step {
|
|
pub from: String,
|
|
pub to: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
#[serde(tag = "type")]
|
|
pub enum ClientEvent {
|
|
Join { username: String },
|
|
FindMatch,
|
|
Move { from: String, to: String },
|
|
Resign,
|
|
Chat { text: String },
|
|
RequestLegalMoves { fen: String },
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum ServerEvent {
|
|
PlayerJoined(Uuid, String),
|
|
PlayerLeft(Uuid),
|
|
PlayerJoinedQueue(Uuid),
|
|
PlayerJoinedMatch(Uuid, Uuid), // player_id, match_id
|
|
PlayerMove(Uuid, Step),
|
|
PlayerResigned(Uuid),
|
|
MatchCreated(Uuid, Uuid, Uuid), // match_id, white_id, black_id
|
|
}
|
|
|
|
pub struct EventSystem {
|
|
sender: mpsc::UnboundedSender<(Uuid, ClientEvent)>,
|
|
receiver: Arc<Mutex<mpsc::UnboundedReceiver<(Uuid, ClientEvent)>>>,
|
|
}
|
|
|
|
impl Clone for EventSystem {
|
|
fn clone(&self) -> Self {
|
|
Self {
|
|
sender: self.sender.clone(),
|
|
receiver: Arc::clone(&self.receiver),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EventSystem {
|
|
pub fn new() -> Self {
|
|
let (sender, receiver) = mpsc::unbounded_channel();
|
|
Self {
|
|
sender,
|
|
receiver: Arc::new(Mutex::new(receiver)),
|
|
}
|
|
}
|
|
|
|
pub async fn send_event(
|
|
&self,
|
|
player_id: Uuid,
|
|
event: ClientEvent,
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
self.sender.send((player_id, event))?;
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn next_event(&self) -> Option<(Uuid, ClientEvent)> {
|
|
let mut receiver = self.receiver.lock().await;
|
|
receiver.recv().await
|
|
}
|
|
}
|
|
|
|
impl Default for EventSystem {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use uuid::Uuid;
|
|
|
|
#[tokio::test]
|
|
async fn test_event_system_send_and_receive() {
|
|
let event_system = EventSystem::new();
|
|
let player_id = Uuid::new_v4();
|
|
|
|
let join_event = ClientEvent::Join {
|
|
username: "test_user".to_string(),
|
|
};
|
|
|
|
let send_result = event_system.send_event(player_id, join_event).await;
|
|
assert!(send_result.is_ok(), "Should send event successfully");
|
|
|
|
let received = event_system.next_event().await;
|
|
assert!(received.is_some(), "Should receive sent event");
|
|
|
|
let (received_id, received_event) = received.unwrap();
|
|
assert_eq!(received_id, player_id, "Should receive correct player ID");
|
|
|
|
match received_event {
|
|
ClientEvent::Join { username } => {
|
|
assert_eq!(username, "test_user", "Should receive correct username");
|
|
}
|
|
_ => panic!("Should receive Join event"),
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_event_system_clone() {
|
|
let event_system1 = EventSystem::new();
|
|
let event_system2 = event_system1.clone();
|
|
|
|
let player_id = Uuid::new_v4();
|
|
let event = ClientEvent::FindMatch;
|
|
|
|
event_system1.send_event(player_id, event).await.unwrap();
|
|
|
|
let received = event_system2.next_event().await;
|
|
assert!(
|
|
received.is_some(),
|
|
"Cloned event system should receive events"
|
|
);
|
|
}
|
|
}
|