1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-05-20 09:47:44 +00:00
kawari/src/world/server.rs

128 lines
4 KiB
Rust
Raw Normal View History

use std::collections::HashMap;
use tokio::sync::mpsc::Receiver;
use crate::{common::ObjectId, ipc::zone::CommonSpawn};
use super::{Actor, ClientHandle, ClientId, FromServer, ToServer};
#[derive(Default, Debug)]
struct WorldServer {
clients: HashMap<ClientId, ClientHandle>,
// structure temporary, of course
actors: HashMap<ObjectId, CommonSpawn>,
}
pub async fn server_main_loop(mut recv: Receiver<ToServer>) -> Result<(), std::io::Error> {
let mut data = WorldServer::default();
let mut to_remove = Vec::new();
while let Some(msg) = recv.recv().await {
match msg {
ToServer::NewClient(handle) => {
data.clients.insert(handle.id, handle);
}
ToServer::ZoneLoaded(from_id) => {
for (id, handle) in &mut data.clients {
let id = *id;
if id == from_id {
// send existing player data
for (id, common) in &data.actors {
let msg = FromServer::ActorSpawn(
Actor {
id: *id,
hp: 100,
spawn_index: 0,
},
common.clone(),
);
handle.send(msg).unwrap();
}
break;
}
}
}
ToServer::Message(from_id, msg) => {
for (id, handle) in &mut data.clients {
let id = *id;
if id == from_id {
continue;
}
let msg = FromServer::Message(msg.clone());
if handle.send(msg).is_err() {
to_remove.push(id);
}
}
}
ToServer::ActorSpawned(from_id, actor, common) => {
data.actors.insert(actor.id, common.clone());
for (id, handle) in &mut data.clients {
let id = *id;
if id == from_id {
continue;
}
let msg = FromServer::ActorSpawn(actor, common.clone());
if handle.send(msg).is_err() {
to_remove.push(id);
}
}
}
ToServer::ActorDespawned(_from_id, actor_id) => {
data.actors.remove(&ObjectId(actor_id));
for (id, handle) in &mut data.clients {
let id = *id;
let msg = FromServer::ActorDespawn(actor_id);
if handle.send(msg).is_err() {
to_remove.push(id);
}
}
}
ToServer::ActorMoved(from_id, actor_id, position, rotation) => {
if let Some((_, common)) = data
.actors
.iter_mut()
.find(|actor| *actor.0 == ObjectId(actor_id))
{
common.pos = position;
common.rotation = rotation;
}
for (id, handle) in &mut data.clients {
let id = *id;
if id == from_id {
continue;
}
let msg = FromServer::ActorMove(actor_id, position, rotation);
if handle.send(msg).is_err() {
to_remove.push(id);
}
}
}
ToServer::Disconnected(from_id) => {
to_remove.push(from_id);
}
ToServer::FatalError(err) => return Err(err),
}
}
// Remove any clients that errored out
for id in to_remove {
data.clients.remove(&id);
}
Ok(())
}