mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-25 08:27:44 +00:00
Send ActorControl and StatusEffectList packets in vain
This was hopefully supposed to show the player spawned by !spawnactor, but it still doesn't work...
This commit is contained in:
parent
da0860cdd7
commit
4927fa9119
8 changed files with 126 additions and 27 deletions
|
@ -7,7 +7,7 @@ use kawari::world::ipc::{
|
|||
use kawari::world::{
|
||||
ChatHandler, Zone, ZoneConnection,
|
||||
ipc::{
|
||||
ActorControlSelf, ActorControlType, PlayerEntry, PlayerSetup, PlayerSpawn, PlayerStats,
|
||||
ActorControlCategory, ActorControlSelf, PlayerEntry, PlayerSetup, PlayerSpawn, PlayerStats,
|
||||
Position, SocialList,
|
||||
},
|
||||
};
|
||||
|
@ -171,7 +171,7 @@ async fn main() {
|
|||
data: ServerZoneIpcData::ActorControlSelf(
|
||||
ActorControlSelf {
|
||||
category:
|
||||
ActorControlType::SetCharaGearParamUI,
|
||||
ActorControlCategory::SetCharaGearParamUI,
|
||||
param1: 1,
|
||||
param2: 1,
|
||||
param3: 0,
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
|
||||
use crate::{
|
||||
CHAR_NAME, CUSTOMIZE_DATA, INVALID_OBJECT_ID, WORLD_ID,
|
||||
common::timestamp_secs,
|
||||
packet::{PacketSegment, SegmentType},
|
||||
world::ipc::{
|
||||
CommonSpawn, NpcSpawn, ObjectKind, PlayerSpawn, ServerZoneIpcData, ServerZoneIpcSegment,
|
||||
ServerZoneIpcType,
|
||||
ActorControl, ActorControlCategory, CommonSpawn, NpcSpawn, ObjectKind, PlayerSpawn,
|
||||
ServerZoneIpcData, ServerZoneIpcSegment, ServerZoneIpcType, StatusEffectList,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -37,6 +38,35 @@ impl ChatHandler {
|
|||
"!spawnactor" => {
|
||||
tracing::info!("Spawning actor...");
|
||||
|
||||
// status effect
|
||||
{
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
unk1: 20,
|
||||
unk2: 0,
|
||||
op_code: ServerZoneIpcType::StatusEffectList,
|
||||
server_id: 0,
|
||||
timestamp: timestamp_secs(),
|
||||
data: ServerZoneIpcData::StatusEffectList(StatusEffectList {
|
||||
classjob_id: 3,
|
||||
level: 10,
|
||||
unk1: 10,
|
||||
curr_hp: 241,
|
||||
max_hp: 241,
|
||||
curr_mp: 10000,
|
||||
max_mp: 10000,
|
||||
..Default::default()
|
||||
}),
|
||||
};
|
||||
|
||||
connection
|
||||
.send_segment(PacketSegment {
|
||||
source_actor: 0x106ad804,
|
||||
target_actor: connection.player_id,
|
||||
segment_type: SegmentType::Ipc { data: ipc },
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
// send player spawn
|
||||
{
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
|
@ -63,6 +93,7 @@ impl ChatHandler {
|
|||
spawn_index: connection.get_free_spawn_index(),
|
||||
look: CUSTOMIZE_DATA,
|
||||
fc_tag: "LOCAL".to_string(),
|
||||
subtype: 4,
|
||||
models: [
|
||||
0, // head
|
||||
89, // body
|
||||
|
@ -90,6 +121,29 @@ impl ChatHandler {
|
|||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
// zone in
|
||||
{
|
||||
let ipc = ServerZoneIpcSegment {
|
||||
unk1: 20,
|
||||
unk2: 0,
|
||||
op_code: ServerZoneIpcType::ActorControl,
|
||||
server_id: 0,
|
||||
timestamp: timestamp_secs(),
|
||||
data: ServerZoneIpcData::ActorControl(ActorControl {
|
||||
category: ActorControlCategory::ZoneIn,
|
||||
..Default::default()
|
||||
}),
|
||||
};
|
||||
|
||||
connection
|
||||
.send_segment(PacketSegment {
|
||||
source_actor: 0x106ad804,
|
||||
target_actor: connection.player_id,
|
||||
segment_type: SegmentType::Ipc { data: ipc },
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
"!spawnnpc" => {
|
||||
// spawn another one of us
|
||||
|
|
23
src/world/ipc/actor_control.rs
Normal file
23
src/world/ipc/actor_control.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use binrw::binrw;
|
||||
|
||||
// See https://github.com/awgil/ffxiv_reverse/blob/f35b6226c1478234ca2b7149f82d251cffca2f56/vnetlog/vnetlog/ServerIPC.cs#L266 for a REALLY useful list of known values
|
||||
#[binrw]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Default)]
|
||||
#[brw(repr = u16)]
|
||||
pub enum ActorControlCategory {
|
||||
#[default]
|
||||
ZoneIn = 0xC8,
|
||||
SetCharaGearParamUI = 0x260,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ActorControl {
|
||||
#[brw(pad_after = 2)]
|
||||
pub category: ActorControlCategory,
|
||||
pub param1: u32,
|
||||
pub param2: u32,
|
||||
pub param3: u32,
|
||||
#[brw(pad_after = 4)] // maybe not always empty?
|
||||
pub param4: u32,
|
||||
}
|
|
@ -1,18 +1,12 @@
|
|||
use binrw::binrw;
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Default)]
|
||||
#[brw(repr = u16)]
|
||||
pub enum ActorControlType {
|
||||
#[default]
|
||||
SetCharaGearParamUI = 0x260,
|
||||
}
|
||||
use super::ActorControlCategory;
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ActorControlSelf {
|
||||
#[brw(pad_after = 2)]
|
||||
pub category: ActorControlType,
|
||||
pub category: ActorControlCategory,
|
||||
pub param1: u32,
|
||||
pub param2: u32,
|
||||
pub param3: u32,
|
||||
|
|
|
@ -28,7 +28,9 @@ pub use player_stats::PlayerStats;
|
|||
|
||||
mod actor_control_self;
|
||||
pub use actor_control_self::ActorControlSelf;
|
||||
pub use actor_control_self::ActorControlType;
|
||||
|
||||
mod actor_control;
|
||||
pub use actor_control::{ActorControl, ActorControlCategory};
|
||||
|
||||
mod init_zone;
|
||||
pub use init_zone::InitZone;
|
||||
|
@ -39,6 +41,9 @@ pub use npc_spawn::NpcSpawn;
|
|||
mod common_spawn;
|
||||
pub use common_spawn::{CharacterMode, CommonSpawn, ObjectKind};
|
||||
|
||||
mod status_effect_list;
|
||||
pub use status_effect_list::StatusEffectList;
|
||||
|
||||
use crate::common::read_string;
|
||||
use crate::common::write_string;
|
||||
use crate::packet::IpcSegment;
|
||||
|
@ -92,6 +97,7 @@ impl ReadWriteIpcSegment for ServerZoneIpcSegment {
|
|||
ServerZoneIpcType::SocialList => 1136,
|
||||
ServerZoneIpcType::PrepareZoning => 16,
|
||||
ServerZoneIpcType::NpcSpawn => 648,
|
||||
ServerZoneIpcType::StatusEffectList => 384,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +177,7 @@ pub enum ServerZoneIpcType {
|
|||
// Sent by the server before init zone???
|
||||
Unk16 = 0x3AB,
|
||||
// Sent by the server
|
||||
ActorControl = 0x1B9,
|
||||
ActorControl = 0x38E,
|
||||
// Sent by the server
|
||||
ActorMove = 0x3D8,
|
||||
// Sent by the server
|
||||
|
@ -180,6 +186,8 @@ pub enum ServerZoneIpcType {
|
|||
SocialList = 0x36C,
|
||||
// Sent by the server to spawn an NPC
|
||||
NpcSpawn = 0x100,
|
||||
// Sent by the server to update an actor's status effect list
|
||||
StatusEffectList = 0xBB,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
@ -283,10 +291,7 @@ pub enum ServerZoneIpcData {
|
|||
Unk16 {
|
||||
unk: [u8; 136],
|
||||
},
|
||||
ActorControl {
|
||||
#[brw(pad_after = 20)] // empty
|
||||
unk: u32,
|
||||
},
|
||||
ActorControl(ActorControl),
|
||||
ActorMove {
|
||||
#[brw(pad_after = 4)] // empty
|
||||
pos: Position,
|
||||
|
@ -296,6 +301,7 @@ pub enum ServerZoneIpcData {
|
|||
},
|
||||
SocialList(SocialList),
|
||||
NpcSpawn(NpcSpawn),
|
||||
StatusEffectList(StatusEffectList),
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
@ -442,6 +448,14 @@ mod tests {
|
|||
ServerZoneIpcType::NpcSpawn,
|
||||
ServerZoneIpcData::NpcSpawn(NpcSpawn::default()),
|
||||
),
|
||||
(
|
||||
ServerZoneIpcType::ActorControl,
|
||||
ServerZoneIpcData::ActorControl(ActorControl::default()),
|
||||
),
|
||||
(
|
||||
ServerZoneIpcType::StatusEffectList,
|
||||
ServerZoneIpcData::StatusEffectList(StatusEffectList::default()),
|
||||
),
|
||||
];
|
||||
|
||||
for (opcode, data) in &ipc_types {
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use binrw::binrw;
|
||||
|
||||
use crate::CHAR_NAME_MAX_LENGTH;
|
||||
use crate::common::{CustomizeData, read_string, write_string};
|
||||
|
||||
use super::position::Position;
|
||||
use super::{CharacterMode, CommonSpawn, ObjectKind, StatusEffect};
|
||||
use super::CommonSpawn;
|
||||
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
use binrw::binrw;
|
||||
|
||||
use crate::CHAR_NAME_MAX_LENGTH;
|
||||
use crate::common::{CustomizeData, read_string, write_string};
|
||||
|
||||
use super::position::Position;
|
||||
use super::status_effect::StatusEffect;
|
||||
use super::{CommonSpawn, ObjectKind};
|
||||
use super::CommonSpawn;
|
||||
|
||||
#[binrw]
|
||||
#[brw(little)]
|
||||
|
@ -63,5 +59,6 @@ mod tests {
|
|||
assert_eq!(player_spawn.common.subtype, 4);
|
||||
assert_eq!(player_spawn.common.model_chara, 0);
|
||||
assert_eq!(player_spawn.common.object_kind, ObjectKind::Player);
|
||||
assert_eq!(player_spawn.common.display_flags, 262144);
|
||||
}
|
||||
}
|
||||
|
|
20
src/world/ipc/status_effect_list.rs
Normal file
20
src/world/ipc/status_effect_list.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
use binrw::binrw;
|
||||
|
||||
use super::StatusEffect;
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct StatusEffectList {
|
||||
pub classjob_id: u8,
|
||||
pub level: u8,
|
||||
pub unk1: u8,
|
||||
pub unk2: u8,
|
||||
pub curr_hp: u32,
|
||||
pub max_hp: u32,
|
||||
pub curr_mp: u16,
|
||||
pub max_mp: u16,
|
||||
pub shield: u16,
|
||||
pub unk3: u16,
|
||||
pub statues: [StatusEffect; 30],
|
||||
pub unk4: u32,
|
||||
}
|
Loading…
Add table
Reference in a new issue