From 873d7f5951339b9398119b0f1404d4f7325c5528 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Mon, 5 May 2025 21:03:47 -0400 Subject: [PATCH] Move custom IPC handling to a separate file --- src/bin/kawari-web.rs | 4 +- src/bin/kawari-world.rs | 231 +------------------------------ src/world/custom_ipc_handler.rs | 237 ++++++++++++++++++++++++++++++++ src/world/mod.rs | 3 + 4 files changed, 248 insertions(+), 227 deletions(-) create mode 100644 src/world/custom_ipc_handler.rs diff --git a/src/bin/kawari-web.rs b/src/bin/kawari-web.rs index 219972b..c565e08 100644 --- a/src/bin/kawari-web.rs +++ b/src/bin/kawari-web.rs @@ -86,7 +86,7 @@ async fn world_status() -> Html { async fn setup() -> Html { let environment = setup_default_environment(); let template = environment.get_template("setup.html").unwrap(); - Html(template.render({}).unwrap()) + Html(template.render(()).unwrap()) } #[derive(Deserialize)] @@ -101,7 +101,7 @@ async fn launcher_config(Query(params): Query) -> String { let environment = setup_default_environment(); let template = environment.get_template("launchertweaks.toml").unwrap(); template - .render(context! { launcher_url => config.launcher.server_name, enable_webview2 => if params.r#type == "webview2" { false } else { true }, game_patch_server => config.patch.game_server_name, boot_patch_server => config.patch.boot_server_name, lobby_port => config.lobby.port }) + .render(context! { launcher_url => config.launcher.server_name, enable_webview2 => params.r#type != "webview2", game_patch_server => config.patch.game_server_name, boot_patch_server => config.patch.boot_server_name, lobby_port => config.lobby.port }) .unwrap() } diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index 2c5acc2..f1c641b 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -3,13 +3,11 @@ use std::net::SocketAddr; use std::sync::{Arc, Mutex}; use kawari::RECEIVE_BUFFER_SIZE; -use kawari::common::workdefinitions::{CharaMake, RemakeMode}; +use kawari::common::Position; use kawari::common::{GameData, ObjectId, timestamp_secs}; -use kawari::common::{Position, determine_initial_starting_zone}; use kawari::config::get_config; -use kawari::inventory::{Inventory, Item}; +use kawari::inventory::Item; use kawari::ipc::chat::{ServerChatIpcData, ServerChatIpcSegment}; -use kawari::ipc::kawari::{CustomIpcData, CustomIpcSegment, CustomIpcType}; use kawari::ipc::zone::{ ActionEffect, ActionResult, ClientZoneIpcData, EffectKind, EventStart, GameMasterCommandType, GameMasterRank, OnlineStatus, ServerZoneIpcData, ServerZoneIpcSegment, SocialListRequestType, @@ -20,12 +18,11 @@ use kawari::ipc::zone::{ use kawari::opcodes::{ServerChatIpcType, ServerZoneIpcType}; use kawari::packet::oodle::OodleNetwork; use kawari::packet::{ - CompressionType, ConnectionType, PacketSegment, PacketState, SegmentData, SegmentType, - send_keep_alive, send_packet, + ConnectionType, PacketSegment, PacketState, SegmentData, SegmentType, send_keep_alive, }; use kawari::world::{ Actor, ClientHandle, EffectsBuilder, FromServer, LuaPlayer, PlayerData, ServerHandle, - StatusEffects, ToServer, WorldDatabase, server_main_loop, + StatusEffects, ToServer, WorldDatabase, handle_custom_ipc, server_main_loop, }; use kawari::world::{ChatHandler, Zone, ZoneConnection}; @@ -759,7 +756,7 @@ async fn client_loop( let state = lua.app_data_ref::().unwrap(); if let Some(event_script) = - state.event_scripts.get(&event_id) + state.event_scripts.get(event_id) { // run script lua.scope(|scope| { @@ -856,223 +853,7 @@ async fn client_loop( SegmentData::KeepAliveResponse { .. } => { tracing::info!("Got keep alive response from client... cool..."); } - SegmentData::KawariIpc { data } => { - match &data.data { - CustomIpcData::RequestCreateCharacter { - service_account_id, - name, - chara_make_json, - } => { - tracing::info!("creating character from: {name} {chara_make_json}"); - - let chara_make = CharaMake::from_json(chara_make_json); - - let city_state; - { - let mut game_data = game_data.lock().unwrap(); - - city_state = - game_data.get_citystate(chara_make.classjob_id as u16); - } - - let mut inventory = Inventory::default(); - { - let mut game_data = game_data.lock().unwrap(); - - // fill inventory - inventory.equip_racial_items( - chara_make.customize.race, - chara_make.customize.gender, - &mut game_data, - ); - } - - let (content_id, actor_id) = database.create_player_data( - *service_account_id, - name, - chara_make_json, - city_state, - determine_initial_starting_zone(city_state), - inventory - ); - - tracing::info!("Created new player: {content_id} {actor_id}"); - - // send them the new actor and content id - { - connection - .send_segment(PacketSegment { - segment_type: SegmentType::KawariIpc, - data: SegmentData::KawariIpc { - data: CustomIpcSegment { - op_code: CustomIpcType::CharacterCreated, - data: CustomIpcData::CharacterCreated { - actor_id, - content_id, - }, - ..Default::default() - }, - }, - ..Default::default() - }) - .await; - } - } - CustomIpcData::GetActorId { content_id } => { - let actor_id = database.find_actor_id(*content_id); - - tracing::info!("We found an actor id: {actor_id}"); - - // send them the actor id - { - connection - .send_segment(PacketSegment { - segment_type: SegmentType::KawariIpc, - data: SegmentData::KawariIpc { - data: CustomIpcSegment { - op_code: CustomIpcType::ActorIdFound, - data: CustomIpcData::ActorIdFound { actor_id }, - ..Default::default() - }, - }, - ..Default::default() - }) - .await; - } - } - CustomIpcData::CheckNameIsAvailable { name } => { - let is_name_free = database.check_is_name_free(name); - - // send response - { - connection - .send_segment(PacketSegment { - segment_type: SegmentType::KawariIpc, - data: SegmentData::KawariIpc { - data: CustomIpcSegment { - op_code: CustomIpcType::NameIsAvailableResponse, - data: CustomIpcData::NameIsAvailableResponse { - free: is_name_free, - }, - ..Default::default() - }, - }, - ..Default::default() - }) - .await; - } - } - CustomIpcData::RequestCharacterList { service_account_id } => { - let config = get_config(); - - let world_name; - { - let mut game_data = game_data.lock().unwrap(); - world_name = game_data.get_world_name(config.world.world_id); - } - - let characters; - { - let mut game_data = game_data.lock().unwrap(); - - characters = database.get_character_list( - *service_account_id, - config.world.world_id, - &world_name, - &mut game_data, - ); - } - - // send response - { - send_packet::( - &mut connection.socket, - &mut connection.state, - ConnectionType::None, - CompressionType::Uncompressed, - &[PacketSegment { - segment_type: SegmentType::KawariIpc, - data: SegmentData::KawariIpc { - data: CustomIpcSegment { - op_code: CustomIpcType::RequestCharacterListRepsonse, - data: CustomIpcData::RequestCharacterListRepsonse { - characters - }, - ..Default::default() - }, - }, - ..Default::default() - }], - ) - .await; - } - } - CustomIpcData::DeleteCharacter { content_id } => { - database.delete_character(*content_id); - - // send response - { - send_packet::( - &mut connection.socket, - &mut connection.state, - ConnectionType::None, - CompressionType::Uncompressed, - &[PacketSegment { - segment_type: SegmentType::KawariIpc, - data: SegmentData::KawariIpc { - data: CustomIpcSegment { - op_code: CustomIpcType::CharacterDeleted, - data: CustomIpcData::CharacterDeleted { - deleted: 1, - }, - ..Default::default() - }, - }, - ..Default::default() - }], - ) - .await; - } - } - CustomIpcData::ImportCharacter { service_account_id, path } => { - database.import_character(*service_account_id, path); - } - CustomIpcData::RemakeCharacter { content_id, chara_make_json } => { - // overwrite it in the database - database.set_chara_make(*content_id, chara_make_json); - - // reset flag - database.set_remake_mode(*content_id, RemakeMode::None); - - // send response - { - send_packet::( - &mut connection.socket, - &mut connection.state, - ConnectionType::None, - CompressionType::Uncompressed, - &[PacketSegment { - segment_type: SegmentType::KawariIpc, - data: SegmentData::KawariIpc { - data: CustomIpcSegment { - op_code: CustomIpcType::CharacterRemade, - data: CustomIpcData::CharacterRemade { - content_id: *content_id, - }, - ..Default::default() - }, - }, - ..Default::default() - }], - ) - .await; - } - } - _ => { - panic!("The server is recieving a response or unknown custom IPC!") - } - } - } + SegmentData::KawariIpc { data } => handle_custom_ipc(&mut connection, data).await, _ => { panic!("The server is recieving a response or unknown packet!") } diff --git a/src/world/custom_ipc_handler.rs b/src/world/custom_ipc_handler.rs new file mode 100644 index 0000000..98cdb03 --- /dev/null +++ b/src/world/custom_ipc_handler.rs @@ -0,0 +1,237 @@ +use crate::{ + common::{ + determine_initial_starting_zone, + workdefinitions::{CharaMake, RemakeMode}, + }, + config::get_config, + inventory::Inventory, + ipc::kawari::{CustomIpcData, CustomIpcSegment, CustomIpcType}, + packet::{ + CompressionType, ConnectionType, PacketSegment, SegmentData, SegmentType, send_packet, + }, +}; + +use super::ZoneConnection; + +pub async fn handle_custom_ipc(connection: &mut ZoneConnection, data: &CustomIpcSegment) { + match &data.data { + CustomIpcData::RequestCreateCharacter { + service_account_id, + name, + chara_make_json, + } => { + tracing::info!("creating character from: {name} {chara_make_json}"); + + let chara_make = CharaMake::from_json(chara_make_json); + + let city_state; + { + let mut game_data = connection.gamedata.lock().unwrap(); + + city_state = game_data.get_citystate(chara_make.classjob_id as u16); + } + + let mut inventory = Inventory::default(); + { + let mut game_data = connection.gamedata.lock().unwrap(); + + // fill inventory + inventory.equip_racial_items( + chara_make.customize.race, + chara_make.customize.gender, + &mut game_data, + ); + } + + let (content_id, actor_id) = connection.database.create_player_data( + *service_account_id, + name, + chara_make_json, + city_state, + determine_initial_starting_zone(city_state), + inventory, + ); + + tracing::info!("Created new player: {content_id} {actor_id}"); + + // send them the new actor and content id + { + connection + .send_segment(PacketSegment { + segment_type: SegmentType::KawariIpc, + data: SegmentData::KawariIpc { + data: CustomIpcSegment { + op_code: CustomIpcType::CharacterCreated, + data: CustomIpcData::CharacterCreated { + actor_id, + content_id, + }, + ..Default::default() + }, + }, + ..Default::default() + }) + .await; + } + } + CustomIpcData::GetActorId { content_id } => { + let actor_id = connection.database.find_actor_id(*content_id); + + tracing::info!("We found an actor id: {actor_id}"); + + // send them the actor id + { + connection + .send_segment(PacketSegment { + segment_type: SegmentType::KawariIpc, + data: SegmentData::KawariIpc { + data: CustomIpcSegment { + op_code: CustomIpcType::ActorIdFound, + data: CustomIpcData::ActorIdFound { actor_id }, + ..Default::default() + }, + }, + ..Default::default() + }) + .await; + } + } + CustomIpcData::CheckNameIsAvailable { name } => { + let is_name_free = connection.database.check_is_name_free(name); + + // send response + { + connection + .send_segment(PacketSegment { + segment_type: SegmentType::KawariIpc, + data: SegmentData::KawariIpc { + data: CustomIpcSegment { + op_code: CustomIpcType::NameIsAvailableResponse, + data: CustomIpcData::NameIsAvailableResponse { free: is_name_free }, + ..Default::default() + }, + }, + ..Default::default() + }) + .await; + } + } + CustomIpcData::RequestCharacterList { service_account_id } => { + let config = get_config(); + + let world_name; + { + let mut game_data = connection.gamedata.lock().unwrap(); + world_name = game_data.get_world_name(config.world.world_id); + } + + let characters; + { + let mut game_data = connection.gamedata.lock().unwrap(); + + characters = connection.database.get_character_list( + *service_account_id, + config.world.world_id, + &world_name, + &mut game_data, + ); + } + + // send response + { + send_packet::( + &mut connection.socket, + &mut connection.state, + ConnectionType::None, + CompressionType::Uncompressed, + &[PacketSegment { + segment_type: SegmentType::KawariIpc, + data: SegmentData::KawariIpc { + data: CustomIpcSegment { + op_code: CustomIpcType::RequestCharacterListRepsonse, + data: CustomIpcData::RequestCharacterListRepsonse { characters }, + ..Default::default() + }, + }, + ..Default::default() + }], + ) + .await; + } + } + CustomIpcData::DeleteCharacter { content_id } => { + connection.database.delete_character(*content_id); + + // send response + { + send_packet::( + &mut connection.socket, + &mut connection.state, + ConnectionType::None, + CompressionType::Uncompressed, + &[PacketSegment { + segment_type: SegmentType::KawariIpc, + data: SegmentData::KawariIpc { + data: CustomIpcSegment { + op_code: CustomIpcType::CharacterDeleted, + data: CustomIpcData::CharacterDeleted { deleted: 1 }, + ..Default::default() + }, + }, + ..Default::default() + }], + ) + .await; + } + } + CustomIpcData::ImportCharacter { + service_account_id, + path, + } => { + connection + .database + .import_character(*service_account_id, path); + } + CustomIpcData::RemakeCharacter { + content_id, + chara_make_json, + } => { + // overwrite it in the database + connection + .database + .set_chara_make(*content_id, chara_make_json); + + // reset flag + connection + .database + .set_remake_mode(*content_id, RemakeMode::None); + + // send response + { + send_packet::( + &mut connection.socket, + &mut connection.state, + ConnectionType::None, + CompressionType::Uncompressed, + &[PacketSegment { + segment_type: SegmentType::KawariIpc, + data: SegmentData::KawariIpc { + data: CustomIpcSegment { + op_code: CustomIpcType::CharacterRemade, + data: CustomIpcData::CharacterRemade { + content_id: *content_id, + }, + ..Default::default() + }, + }, + ..Default::default() + }], + ) + .await; + } + } + _ => { + panic!("The server is recieving a response or unknown custom IPC!") + } + } +} diff --git a/src/world/mod.rs b/src/world/mod.rs index cbb0616..bc8cf0b 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -26,3 +26,6 @@ pub use status_effects::StatusEffects; mod server; pub use server::server_main_loop; + +mod custom_ipc_handler; +pub use custom_ipc_handler::handle_custom_ipc;