use std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
time::{Duration, Instant},
};
use rand::Rng;
use serde::{Deserialize, Serialize};
use warqueen::{
ClientOnServerDisconnectionDetails, ClientOnServerEvent, NetReceive, NetSend,
ServerListenerNetworking,
};
#[derive(Deserialize, NetReceive)]
enum MessageClientToServer {
String(String),
}
#[derive(Serialize, NetSend)]
enum MessageServerToClient {
String(String),
}
fn main() {
let desired_port = 21001;
let server_listener = ServerListenerNetworking::new(Some(desired_port), None, None);
let actual_port = server_listener.server_port();
println!("Opened on port {actual_port}");
let mut clients = vec![];
let mut next_client_id = 0;
let mut last_sent_time = Instant::now();
let halt = Arc::new(AtomicBool::new(false));
let halt_cloned = Arc::clone(&halt);
ctrlc::set_handler(move || {
println!();
halt_cloned.store(true, Ordering::Relaxed);
})
.unwrap();
loop {
while let Some(new_client) = server_listener.poll_client() {
let address = new_client.client_address();
let client_id = next_client_id;
next_client_id += 1;
println!("Connected to client at {address}, given id {client_id}");
clients.push((new_client, client_id));
}
let mut disconnected_ids = vec![];
for (client, client_id) in clients.iter() {
while let Some(event) = client.poll_event_from_client() {
match event {
ClientOnServerEvent::Message(message) => match message {
MessageClientToServer::String(content) => {
println!("Client {client_id} says \"{content}\"");
}
},
ClientOnServerEvent::Disconnected(details) => {
match details {
ClientOnServerDisconnectionDetails::None => {
println!("Client {client_id} disconnected")
}
ClientOnServerDisconnectionDetails::Timeout => {
println!("Client {client_id} timed out")
}
}
disconnected_ids.push(*client_id);
}
}
}
}
clients.retain(|(_client, client_id)| !disconnected_ids.contains(client_id));
if last_sent_time.elapsed() > Duration::from_millis(2500) && !clients.is_empty() {
last_sent_time = Instant::now();
let random_client_index = rand::rng().random_range(0..clients.len());
let (client, client_id) = &clients[random_client_index];
println!("We say \"uwu\" to the client {client_id}");
let message = MessageServerToClient::String("uwu".to_string());
client.send_message_to_client(message);
}
if halt.load(Ordering::Relaxed) {
println!("Let's disconnect everyone");
for (client, client_id) in clients {
println!("Disconnecting client {client_id}");
client.disconnect().wait_for_proper_disconnection();
}
return;
}
std::thread::sleep(Duration::from_millis(10));
}
}