Updated chat handler to use the MessageType enum values instead of numbers

Added local_id tracking for the packet service
Added mob spawning packet in response to game logic events (only for a NearbyUpdate event right now)
This commit is contained in:
2025-07-22 00:23:56 -04:00
parent da6d7518e5
commit 9fcd1741de
4 changed files with 73 additions and 16 deletions

View File

@@ -13,8 +13,9 @@ pub struct ConnectionState {
pub character_id: Option<i8>, pub character_id: Option<i8>,
pub character_name: Option<String>, pub character_name: Option<String>,
pub character_list: Option<Vec<u32>>, pub character_list: Option<Vec<u32>>,
pub additional_data: HashMap<String, String>, // Flexible data storage pub additional_data: HashMap<String, String>,
pub client_id: u16, pub client_id: u16,
pub local_id: u16, // Local connection ID for packet routing
pub chat_handler: Option<Arc<ChatClientHandler>>, pub chat_handler: Option<Arc<ChatClientHandler>>,
pub writer: Option<Arc<tokio::sync::Mutex<WriteHalf<TcpStream>>>>, pub writer: Option<Arc<tokio::sync::Mutex<WriteHalf<TcpStream>>>>,
} }
@@ -29,6 +30,7 @@ impl ConnectionState {
character_list: None, character_list: None,
additional_data: HashMap::new(), additional_data: HashMap::new(),
client_id: 0, client_id: 0,
local_id: 0,
chat_handler: None, chat_handler: None,
writer: None, writer: None,
} }

View File

@@ -92,10 +92,10 @@ pub(crate) async fn handle_join_server_req(
return Err("Session not valid".into()); return Err("Session not valid".into());
} }
let client_id = state.client_id.clone(); let local_id = state.local_id.clone();
let data = SrvJoinServerReply { let data = SrvJoinServerReply {
result: srv_join_server_reply::Result::Ok, result: srv_join_server_reply::Result::Ok,
id: client_id as u32, id: local_id as u32,
pay_flag: 0, pay_flag: 0,
}; };
let response_packet = Packet::new(PacketType::PakscJoinServerReply, &data)?; let response_packet = Packet::new(PacketType::PakscJoinServerReply, &data)?;
@@ -170,12 +170,12 @@ pub(crate) async fn handle_login_req(
} else { } else {
debug!("Successfully logged in"); debug!("Successfully logged in");
let mut client_id = 0; let mut local_id = 0;
if let Some(mut state) = connection_service.get_connection_mut(&connection_id) { if let Some(mut state) = connection_service.get_connection_mut(&connection_id) {
state.user_id = Some(response.user_id); state.user_id = Some(response.user_id);
state.session_id = Some(response.session_id.clone()); state.session_id = Some(response.session_id.clone());
client_id = connection_service.next_id(); local_id = connection_service.next_id();
state.client_id = client_id; state.local_id = local_id;
} }
let chat_url = format!( let chat_url = format!(
@@ -187,7 +187,7 @@ pub(crate) async fn handle_login_req(
.unwrap() .unwrap()
); );
let handler = ChatClientHandler::new(chat_url, client_id.to_string(), response.session_id.clone()).await?; let handler = ChatClientHandler::new(chat_url, local_id.to_string(), response.session_id.clone()).await?;
let chat_handler = Arc::new(handler); let chat_handler = Arc::new(handler);
if let Some(mut state) = connection_service.get_connection_mut(&connection_id) { if let Some(mut state) = connection_service.get_connection_mut(&connection_id) {

View File

@@ -9,7 +9,7 @@ use tokio::io::WriteHalf;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tonic::transport::Channel; use tonic::transport::Channel;
use tracing::{debug, error}; use tracing::{debug, error, warn};
use utils::null_string::NullTerminatedString; use utils::null_string::NullTerminatedString;
use utils::service_discovery::get_kube_service_endpoints_by_dns; use utils::service_discovery::get_kube_service_endpoints_by_dns;
use crate::handlers::chat_client::chat::{ChatMessage, MessageType}; use crate::handlers::chat_client::chat::{ChatMessage, MessageType};
@@ -25,6 +25,7 @@ pub async fn create_chat_client_handler(
use crate::packets::srv_whisper_chat::SrvWhisperChat; use crate::packets::srv_whisper_chat::SrvWhisperChat;
use crate::packets::srv_clan_chat::SrvClanChat; use crate::packets::srv_clan_chat::SrvClanChat;
use crate::packets::srv_allied_chat::SrvAlliedChat; use crate::packets::srv_allied_chat::SrvAlliedChat;
use crate::handlers::chat_client::chat::MessageType;
tokio::spawn({ tokio::spawn({
async move { async move {
debug!("Spawning chat handler task"); debug!("Spawning chat handler task");
@@ -32,8 +33,8 @@ pub async fn create_chat_client_handler(
let mut rx = task_chat_handler.inbound_rx.lock().await; let mut rx = task_chat_handler.inbound_rx.lock().await;
while let Some(chat_msg) = rx.recv().await { while let Some(chat_msg) = rx.recv().await {
debug!("Packet-Service received chat message: {} (client_id: {}, type {})", chat_msg.message, chat_msg.client_id, chat_msg.r#type); debug!("Packet-Service received chat message: {} (client_id: {}, type {})", chat_msg.message, chat_msg.client_id, chat_msg.r#type);
match chat_msg.r#type { match MessageType::try_from(chat_msg.r#type).unwrap_or(MessageType::Normal) {
1 => { MessageType::Normal => {
// Normal Chat // Normal Chat
let data = SrvNormalChat { let data = SrvNormalChat {
char_id: chat_msg.client_id.parse().unwrap(), char_id: chat_msg.client_id.parse().unwrap(),
@@ -51,7 +52,7 @@ pub async fn create_chat_client_handler(
error!("unable to send normal chat: {:?}", e); error!("unable to send normal chat: {:?}", e);
} }
} }
2 => { MessageType::Shout => {
// Shout Chat // Shout Chat
let data = SrvShoutChat { let data = SrvShoutChat {
sender: NullTerminatedString(chat_msg.sender), sender: NullTerminatedString(chat_msg.sender),
@@ -67,7 +68,7 @@ pub async fn create_chat_client_handler(
error!("unable to send shout chat: {:?}", e); error!("unable to send shout chat: {:?}", e);
} }
} }
3 => { MessageType::Party => {
// Party Chat // Party Chat
let data = SrvPartyChat { let data = SrvPartyChat {
char_id: chat_msg.client_id.parse().unwrap(), char_id: chat_msg.client_id.parse().unwrap(),
@@ -83,7 +84,7 @@ pub async fn create_chat_client_handler(
error!("unable to send party chat: {:?}", e); error!("unable to send party chat: {:?}", e);
} }
} }
4 => { MessageType::Whisper => {
// Whisper Chat // Whisper Chat
let data = SrvWhisperChat { let data = SrvWhisperChat {
sender: NullTerminatedString(chat_msg.sender), sender: NullTerminatedString(chat_msg.sender),
@@ -99,7 +100,7 @@ pub async fn create_chat_client_handler(
error!("unable to send whisper chat: {:?}", e); error!("unable to send whisper chat: {:?}", e);
} }
} }
5 => { MessageType::Clan => {
// Clan Chat // Clan Chat
let data = SrvClanChat { let data = SrvClanChat {
sender: NullTerminatedString(chat_msg.sender), sender: NullTerminatedString(chat_msg.sender),
@@ -115,7 +116,7 @@ pub async fn create_chat_client_handler(
error!("unable to send clan chat: {:?}", e); error!("unable to send clan chat: {:?}", e);
} }
} }
6 => { MessageType::Allied => {
// Allied Chat // Allied Chat
let data = SrvAlliedChat { let data = SrvAlliedChat {
team: 0, team: 0,
@@ -131,7 +132,8 @@ pub async fn create_chat_client_handler(
error!("unable to send allied chat: {:?}", e); error!("unable to send allied chat: {:?}", e);
} }
} }
_ => { MessageType::Unspecified => {
warn!("Unspecified chat type, defaulting to normal chat");
// Normal Chat // Normal Chat
let data = SrvNormalChat { let data = SrvNormalChat {
char_id: chat_msg.client_id.parse().unwrap(), char_id: chat_msg.client_id.parse().unwrap(),

View File

@@ -11,6 +11,7 @@ use tokio::sync::Mutex;
use tonic::transport::Channel; use tonic::transport::Channel;
use tracing::{debug, error, info, warn}; use tracing::{debug, error, info, warn};
use utils::service_discovery::get_kube_service_endpoints_by_dns; use utils::service_discovery::get_kube_service_endpoints_by_dns;
use crate::world_client::world::WorldObject;
fn distance(x1: f64, y1: f64, x2: f64, y2: f64) -> u16 { fn distance(x1: f64, y1: f64, x2: f64, y2: f64) -> u16 {
let dist = ((x2 - x1).powi(2) + (y2 - y1).powi(2)).sqrt(); let dist = ((x2 - x1).powi(2) + (y2 - y1).powi(2)).sqrt();
@@ -220,6 +221,50 @@ pub(crate) async fn handle_set_animation_req(
// World service integration - movement events // World service integration - movement events
pub(crate) async fn spawn_mob(
mob: &WorldObject,
connection_service: Arc<ConnectionService>,
session_id: String
) -> Result<(), Box<dyn Error + Send + Sync>> {
use crate::packets::srv_mob_char::SrvMobChar;
let data = SrvMobChar {
id: mob.id as u16,
x: mob.x,
y: mob.y,
dest_x: 0.0,
dest_y: 0.0,
command: 0,
target_id: 0,
move_mode: 0,
hp: mob.hp,
team_id: 0,
status_flag: 0,
npc_id: mob.id as u16,
quest_id: 0,
};
let response_packet = Packet::new(PacketType::PakwcMobChar, &data)?;
if let Some(mut state) = connection_service.get_connection_mut(&session_id) {
let writer_clone = state.writer.clone().unwrap();
let mut locked_stream = writer_clone.lock().await;
send_packet(&mut locked_stream, &response_packet).await?;
}
Ok(())
}
pub(crate) async fn spawn_mobs(
mobs: Vec<&WorldObject>,
connection_service: Arc<ConnectionService>,
session_id: String
) {
for mob in mobs {
let result = spawn_mob(mob, connection_service.clone(), session_id.clone()).await;
if let Err(e) = result {
error!("Failed to spawn mob for session {}: {}", session_id, e);
}
}
}
async fn handle_world_events( async fn handle_world_events(
world_client_manager: Arc<WorldClientManager>, world_client_manager: Arc<WorldClientManager>,
connection_service: Arc<ConnectionService>, connection_service: Arc<ConnectionService>,
@@ -258,6 +303,14 @@ async fn handle_world_events(
debug!("Nearby npcs: {:?}", npcs); debug!("Nearby npcs: {:?}", npcs);
debug!("Nearby mobs: {:?}", mobs); debug!("Nearby mobs: {:?}", mobs);
// if !npcs.is_empty() {
// spawn_npcs(npcs, connection_service.clone(), session_id.clone()).await;
// }
if !mobs.is_empty() {
spawn_mobs(mobs, connection_service.clone(), session_id.clone()).await;
}
// if !npcs.is_empty() { // if !npcs.is_empty() {
// // Send all nearby npcs in a single batch update // // Send all nearby npcs in a single batch update
// let batch_event = SrvNpcChar { // let batch_event = SrvNpcChar {