1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-04-21 15:07:45 +00:00

Implement basic support for actions

This only works for sprint, and it adds 30 sprint buffs. It also regularly
crashes the server afterwards usually.
This commit is contained in:
Joshua Goins 2025-03-19 00:28:47 -04:00
parent 3947eebb44
commit f4536f2cb7
4 changed files with 91 additions and 5 deletions

View file

@ -1,8 +1,9 @@
use kawari::config::get_config;
use kawari::oodle::OodleNetwork;
use kawari::packet::{ConnectionType, PacketSegment, PacketState, SegmentType, send_keep_alive};
use kawari::world::ipc::{
ClientZoneIpcData, CommonSpawn, GameMasterCommandType, ObjectKind, ServerZoneIpcData,
ServerZoneIpcSegment, ServerZoneIpcType, SocialListRequestType,
ServerZoneIpcSegment, ServerZoneIpcType, SocialListRequestType, StatusEffect,
};
use kawari::world::{
ChatHandler, Zone, ZoneConnection,
@ -15,6 +16,8 @@ use kawari::{
CHAR_NAME, CITY_STATE, CONTENT_ID, CUSTOMIZE_DATA, DEITY, NAMEDAY_DAY, NAMEDAY_MONTH, WORLD_ID,
ZONE_ID, common::timestamp_secs,
};
use physis::common::{Language, Platform};
use physis::gamedata::GameData;
use tokio::io::AsyncReadExt;
use tokio::net::TcpListener;
@ -594,6 +597,58 @@ async fn main() {
ClientZoneIpcData::Unk14 { .. } => {
tracing::info!("Recieved Unk14!");
}
ClientZoneIpcData::ActionRequest(request) => {
tracing::info!("Recieved action request: {:#?}!", request);
let config = get_config();
let mut game_data = GameData::from_existing(
Platform::Win32,
&config.game_location,
)
.unwrap();
let exh =
game_data.read_excel_sheet_header("Action").unwrap();
let exd = game_data
.read_excel_sheet("Action", &exh, Language::English, 0)
.unwrap();
let action_row = &exd
.read_row(&exh, request.action_id as u32)
.unwrap()[0];
println!("Found action: {:#?}", action_row);
// send new status list
{
let ipc = ServerZoneIpcSegment {
op_code: ServerZoneIpcType::StatusEffectList,
timestamp: timestamp_secs(),
data: ServerZoneIpcData::StatusEffectList(
kawari::world::ipc::StatusEffectList {
statues: [StatusEffect {
effect_id: 50,
param: 0,
duration: 50.0,
source_actor_id: connection.player_id,
};
30],
..Default::default()
},
),
..Default::default()
};
connection
.send_segment(PacketSegment {
source_actor: connection.player_id,
target_actor: connection.player_id,
segment_type: SegmentType::Ipc { data: ipc },
})
.await;
}
}
}
}
SegmentType::KeepAlive { id, timestamp } => {

View file

@ -0,0 +1,24 @@
use binrw::binrw;
#[binrw]
#[derive(Debug, Eq, PartialEq, Clone, Default)]
#[brw(repr = u8)]
pub enum ActionKind {
#[default]
Nothing = 0x0,
Normal = 0x1,
}
#[binrw]
#[derive(Debug, Clone, Default)]
pub struct ActionRequest {
pub exec_proc: u8, // what?
pub action_kind: ActionKind,
#[brw(pad_before = 2)] // this ISNT empty
pub action_id: u32, // See Action Excel sheet
pub request_id: u32,
pub dir: u16,
pub dir_target: u16,
pub target: u64,
pub arg: u32,
}

View file

@ -47,6 +47,9 @@ pub use status_effect_list::StatusEffectList;
mod weather_change;
pub use weather_change::WeatherChange;
mod action_request;
pub use action_request::ActionRequest;
use crate::common::read_string;
use crate::common::write_string;
use crate::packet::IpcSegment;
@ -234,6 +237,8 @@ pub enum ClientZoneIpcType {
Unk13 = 0x2EE,
// Sent by the client for unknown reasons
Unk14 = 0x87,
// Sent by the client when a character performs an action
ActionRequest = 0x213,
}
#[binrw]
@ -403,6 +408,8 @@ pub enum ClientZoneIpcData {
Unk14 {
unk: [u8; 8], // TODO: unknown
},
#[br(pre_assert(*magic == ClientZoneIpcType::ActionRequest))]
ActionRequest(ActionRequest),
}
#[cfg(test)]

View file

@ -3,8 +3,8 @@ use binrw::binrw;
#[binrw]
#[derive(Debug, Clone, Copy, Default)]
pub struct StatusEffect {
effect_id: u16,
param: u16,
duration: f32,
source_actor_id: u32,
pub effect_id: u16,
pub param: u16,
pub duration: f32,
pub source_actor_id: u32,
}