1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-07-01 04:07:45 +00:00
kawari/src/world/common.rs
Joshua Goins 58e4e89765 Support toggling displaying your weapon and other flags
This is now networked and shown both to you and other players. This
still needs to be persisted for other player spawns.
2025-06-25 21:30:14 -04:00

124 lines
3.5 KiB
Rust

use std::{
net::SocketAddr,
sync::{
Arc,
atomic::{AtomicUsize, Ordering},
},
};
use tokio::sync::mpsc::Sender;
use crate::{
common::Position,
ipc::zone::{
ActionRequest, ActorControl, ActorControlSelf, ActorControlTarget, ClientTrigger,
CommonSpawn, Config, 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),
/// Action has completed and needs to be executed
ActionComplete(ActionRequest),
/// Action has been cancelled
ActionCancelled(),
/// Update an actor's equip display flags.
UpdateConfig(u32, Config),
}
#[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),
/// Spawn a debug clone.
DebugSpawnClone(ClientId, u32),
/// Request to perform an action
ActionRequest(ClientId, u32, ActionRequest),
/// We want to update our own equip display flags.
Config(ClientId, u32, Config),
}
#[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)
}
}