You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
4.4 KiB
Rust

use crate::server_info::events::{FullPlayerEvent, PlayerPositionEvent, WebsocketEvent};
use crate::server_info::player_details::Player;
use futures_util::SinkExt;
use std::collections::HashMap;
use std::future::Future;
use std::os::raw::c_ushort;
use std::sync::Arc;
use tokio::runtime::{Handle, Runtime};
use tokio::sync::{Mutex, RwLock};
use warp::ws::{Message, WebSocket};
#[derive(Default, Debug)]
pub struct ServerInfo {
pub players: HashMap<c_ushort, Player>,
}
#[derive(Default, Debug)]
pub struct ServerLogic {
pub web_sockets: HashMap<u64, WebSocket>,
}
type SyncMutex<T> = std::sync::Mutex<T>;
#[derive(Clone, Debug)]
pub struct ServerInfoHandle {
pub info: Arc<RwLock<ServerInfo>>,
pub logic: Arc<Mutex<ServerLogic>>,
pub runtime: Arc<SyncMutex<Runtime>>,
pub handle: Arc<Handle>,
}
impl ServerInfoHandle {
pub fn new() -> Self {
let runtime = Runtime::new().unwrap();
let handle = runtime.handle().clone();
ServerInfoHandle {
info: Arc::new(RwLock::new(ServerInfo::default())),
logic: Arc::new(Mutex::new(ServerLogic::default())),
runtime: Arc::new(SyncMutex::new(runtime)),
handle: Arc::new(handle),
}
}
pub async fn publish_event(&self, event: WebsocketEvent) {
let logic = self.logic.clone();
self.handle.spawn(async move {
let mut logic = logic.lock().await;
let json = serde_json::to_string(&event).unwrap();
let mut to_remove = vec![];
for (id, web_socket) in &mut logic.web_sockets {
if web_socket.send(Message::text(&json)).await.is_err() {
to_remove.push(*id);
}
}
for id in to_remove {
logic.web_sockets.remove(&id).map(|x| x.close());
}
});
}
pub async fn gui_action(&self, player_id: u16, _message_box_id: i32, _data: Option<&str>) {
let mut info = self.info.write().await;
if let Some(player) = info.players.get_mut(&player_id) {
if !player.logged_in {
player.logged_in = true;
player.on_login();
}
}
}
pub async fn update_players(&self, low_freq: bool) {
let mut info = self.info.write().await;
for (_, player) in &mut info.players {
if !player.logged_in {
continue;
}
player.update();
if low_freq {
player.low_frequency_update();
}
}
if info.players.len() == 0 {
return;
}
let players = info.players.clone();
self.publish_event(if low_freq {
WebsocketEvent::FullPlayer(FullPlayerEvent {
players: players
.values()
.filter(|p| p.logged_in)
.map(|p| p.clone())
.collect::<Vec<Player>>(),
})
} else {
WebsocketEvent::PlayerPosition(PlayerPositionEvent {
positions: players
.values()
.filter(|p| p.logged_in)
.map(|p| p.get_player_position())
.collect(),
})
})
.await;
}
pub async fn add_player(&self, player_id: c_ushort) {
let mut info = self.info.write().await;
info.players.insert(player_id, Player::new(player_id));
}
pub async fn remove_player(&self, player: c_ushort) {
let mut info = self.info.write().await;
info.players.remove(&player);
if info.players.len() == 0 {
self.publish_event(WebsocketEvent::FullPlayer(FullPlayerEvent {
players: vec![],
}))
.await;
}
}
pub async fn get_players(&self) -> Vec<Player> {
let info = self.info.read().await;
info.players.iter().map(|p| (*p.1).clone()).collect()
}
pub async fn add_websocket(&self, ws: WebSocket) {
let mut logic = self.logic.lock().await;
let new_id = logic
.web_sockets
.keys()
.max()
.map(|x| x + 1)
.unwrap_or_default();
println!("Added websocket ({})", new_id);
logic.web_sockets.insert(new_id, ws);
}
pub fn block_on<F: Future>(&mut self, task: F) -> F::Output {
self.runtime.lock().unwrap().block_on(task)
}
}