mirror of
https://github.com/redstrate/Kawari.git
synced 2025-07-01 20:27:46 +00:00
I don't know why I created a new message kind just for spawning NPCs when ActorSpawn does this just fine. But what this actually means is that the debug NPCs can now be spawned more than once.
111 lines
3 KiB
Rust
111 lines
3 KiB
Rust
use std::{
|
|
net::SocketAddr,
|
|
sync::{
|
|
Arc,
|
|
atomic::{AtomicUsize, Ordering},
|
|
},
|
|
};
|
|
|
|
use tokio::sync::mpsc::Sender;
|
|
|
|
use crate::{
|
|
common::Position,
|
|
ipc::zone::{
|
|
ActorControl, ActorControlSelf, ActorControlTarget, ClientTrigger, CommonSpawn, NpcSpawn,
|
|
},
|
|
};
|
|
|
|
use super::Actor;
|
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
|
pub struct ClientId(usize);
|
|
|
|
pub enum FromServer {
|
|
/// A chat message.
|
|
Message(String),
|
|
/// An actor has been spawned.
|
|
ActorSpawn(Actor, NpcSpawn),
|
|
/// An actor moved to a new position.
|
|
ActorMove(u32, Position, f32),
|
|
// An actor has despawned.
|
|
ActorDespawn(u32),
|
|
/// We need to update an actor
|
|
ActorControl(u32, ActorControl),
|
|
/// We need to update an actor's target
|
|
ActorControlTarget(u32, ActorControlTarget),
|
|
/// We need to update the player actor
|
|
ActorControlSelf(ActorControlSelf),
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct ClientHandle {
|
|
pub id: ClientId,
|
|
pub ip: SocketAddr,
|
|
pub channel: Sender<FromServer>,
|
|
pub actor_id: u32,
|
|
pub common: CommonSpawn,
|
|
}
|
|
|
|
impl ClientHandle {
|
|
/// Send a message to this client actor. Will emit an error if sending does
|
|
/// not succeed immediately, as this means that forwarding messages to the
|
|
/// tcp connection cannot keep up.
|
|
pub fn send(&mut self, msg: FromServer) -> Result<(), std::io::Error> {
|
|
if self.channel.try_send(msg).is_err() {
|
|
Err(std::io::Error::new(
|
|
std::io::ErrorKind::BrokenPipe,
|
|
"Can't keep up or dead",
|
|
))
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Kill the actor.
|
|
pub fn kill(self) {
|
|
// run the destructor
|
|
drop(self);
|
|
}
|
|
}
|
|
|
|
pub enum ToServer {
|
|
/// A new connection has started.
|
|
NewClient(ClientHandle),
|
|
/// The connection sent a message.
|
|
Message(ClientId, String),
|
|
/// The connection's player moved.
|
|
ActorMoved(ClientId, u32, Position, f32),
|
|
/// The connection has recieved a client trigger.
|
|
ClientTrigger(ClientId, u32, ClientTrigger),
|
|
/// The connection loaded into a zone.
|
|
// TODO: the connection should not be in charge and telling the global server what zone they just loaded in! but this will work for now
|
|
ZoneLoaded(ClientId, u16),
|
|
/// The connection left a zone.
|
|
LeftZone(ClientId, u32, u16),
|
|
/// The connection disconnected.
|
|
Disconnected(ClientId),
|
|
/// A fatal error occured.
|
|
FatalError(std::io::Error),
|
|
/// Spawn a friendly debug NPC.
|
|
DebugNewNpc(ClientId, u32),
|
|
/// Spawn an enemy debug NPC.
|
|
DebugNewEnemy(ClientId, u32),
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct ServerHandle {
|
|
pub chan: Sender<ToServer>,
|
|
pub next_id: Arc<AtomicUsize>,
|
|
}
|
|
|
|
impl ServerHandle {
|
|
pub async fn send(&mut self, msg: ToServer) {
|
|
if self.chan.send(msg).await.is_err() {
|
|
panic!("Main loop has shut down.");
|
|
}
|
|
}
|
|
pub fn next_id(&self) -> ClientId {
|
|
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
|
|
ClientId(id)
|
|
}
|
|
}
|