Updated handlers by spliting the TcpStream in half to allow reading and writing data at the same time.
This fixes an issue where you are unable to get chat messages until the client sends a packet to the server

Fixed client id's by adding the id manager
Added shout chat handling
This commit is contained in:
2025-06-07 00:36:02 -04:00
parent d4dadf5170
commit aa2be43f4e
17 changed files with 480 additions and 157 deletions

View File

@@ -8,15 +8,21 @@ pub struct GuildChat;
impl ChatChannel for GuildChat {
fn handle_message(&self, message: ChatMessage, sender_id: &str, clients: &Clients) {
// This is a placeholder. In a real implementation, verify
// guild membership by consulting your Character or Guild service.
let clients_lock = clients.lock().unwrap();
for (id, tx) in clients_lock.iter() {
// For demonstration, send only to clients whose IDs contain
// "guild". Replace this logic with your actual membership check.
if id != sender_id && id.contains("guild") {
let _ = tx.try_send(message.clone());
}
}
//TODO: Make sure the clients actually are apart of the same guild.
let new_message = ChatMessage {
client_id: sender_id.to_string(),
r#type: message.r#type,
message: message.message,
target_id: message.target_id,
sender: message.sender,
};
// let clients_lock = clients.lock().unwrap();
// for (id, tx) in clients_lock.iter() {
// if id != sender_id && id.contains("guild") {
// let _ = tx.try_send(new_message.clone());
// }
// }
}
}

View File

@@ -9,14 +9,18 @@ pub struct LocalChat;
impl ChatChannel for LocalChat {
fn handle_message(&self, message: ChatMessage, sender_id: &str, clients: &Clients) {
// In a full implementation, you might query for nearby clients.
// For demo purposes, we simply broadcast to all clients except the sender.
debug!("LocalChat::handle_message: {:?}", message);
let new_message = ChatMessage {
client_id: sender_id.to_string(), // Make sure the client isn't attempting bad things
r#type: message.r#type,
message: message.message,
target_id: message.target_id,
sender: message.sender,
};
let clients_lock = clients.lock().unwrap();
for (id, tx) in clients_lock.iter() {
// if id != sender_id {
let _ = tx.try_send(message.clone());
// }
let _ = tx.try_send(new_message.clone());
}
}
}

View File

@@ -8,13 +8,17 @@ pub struct ShoutChat;
impl ChatChannel for ShoutChat {
fn handle_message(&self, message: ChatMessage, sender_id: &str, clients: &Clients) {
// For demo purposes, we simply broadcast to all clients except the sender.
// TODO: make sure the clients are on the same map
let new_message = ChatMessage {
client_id: sender_id.to_string(),
r#type: message.r#type,
message: message.message,
target_id: message.target_id,
sender: message.sender,
};
let clients_lock = clients.lock().unwrap();
for (id, tx) in clients_lock.iter() {
if id != sender_id {
let _ = tx.try_send(message.clone());
}
let _ = tx.try_send(new_message.clone());
}
}
}

View File

@@ -3,6 +3,7 @@ use std::collections::HashMap;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use tonic::{Request, Response, Status};
use tonic::metadata::MetadataMap;
use tracing::debug;
pub mod common {
@@ -37,6 +38,18 @@ impl MyChatService {
}
}
fn get_authenticated_id(metadata: &MetadataMap) -> Result<String, Status> {
if let Some(client_id_val) = metadata.get("x-client-id") {
// Convert the header to a string.
client_id_val
.to_str()
.map(ToString::to_string)
.map_err(|_| Status::unauthenticated("Invalid client ID header"))
} else {
Err(Status::unauthenticated("Missing client ID header"))
}
}
#[tonic::async_trait]
impl ChatService for MyChatService {
type ChatStreamStream =
@@ -48,11 +61,9 @@ impl ChatService for MyChatService {
) -> Result<Response<Self::ChatStreamStream>, Status> {
debug!("New chat client connected");
debug!("request: {:?}", request);
let mut inbound = request.into_inner();
// Create a new client ID. In production, use authenticated IDs.
let client_id = format!("client-{}", uuid::Uuid::new_v4());
let client_id = get_authenticated_id(request.metadata())?;
let mut inbound = request.into_inner();
// Create a channel for sending outbound messages to this client.
let (tx, rx) = tokio::sync::mpsc::channel(32);