1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-07-17 10:47:44 +00:00

Fix various issues with the Lobby packets

Everything should be more consistent now, in regards to "tickets"
and actor ids.
This commit is contained in:
Joshua Goins 2025-07-13 09:42:27 -04:00
parent 822f693f8c
commit c339c89c41
11 changed files with 42 additions and 23 deletions

View file

@ -303,7 +303,8 @@ async fn main() {
..
} => {
connection.selected_service_account = Some(
connection.service_accounts[*account_index as usize].id,
connection.service_accounts[*account_index as usize].id
as u32,
);
connection.send_lobby_info(*sequence).await
}

View file

@ -154,9 +154,9 @@ async fn client_loop(
for segment in &segments {
match &segment.data {
SegmentData::None() => {},
SegmentData::Setup { ticket } => {
SegmentData::Setup { actor_id } => {
// for some reason they send a string representation
let actor_id = ticket.parse::<u32>().unwrap();
let actor_id = actor_id.parse::<u32>().unwrap();
// initialize player data if it doesn't exist'
if connection.player_data.actor_id == 0 {
@ -193,7 +193,7 @@ async fn client_loop(
connection.send_chat_segment(PacketSegment {
segment_type: SegmentType::Initialize,
data: SegmentData::Initialize {
player_id: connection.player_data.actor_id,
actor_id: connection.player_data.actor_id,
timestamp: timestamp_secs(),
},
..Default::default()

View file

@ -6,8 +6,7 @@ use crate::common::{read_string, write_string};
#[binrw]
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct ServiceAccount {
pub id: u32,
pub unk1: u32,
pub id: u64,
pub index: u32,
#[bw(pad_size_to = 0x44)]
#[br(count = 0x44)]

View file

@ -103,7 +103,8 @@ pub enum ClientLobbyIpcData {
unk1: u8,
unk2: u16,
unk3: u32, // TODO: probably multiple params
account_id: u64,
account_id: u32,
unk4: u32,
},
/// Sent by the client when it requests to enter a world.
#[br(pre_assert(*magic == ClientLobbyIpcType::GameLogin))]
@ -111,8 +112,10 @@ pub enum ClientLobbyIpcData {
sequence: u64,
content_id: u64,
// TODO: what else is in here?
unk1: u64,
unk2: u64,
unk1: u32,
unk2: u32,
unk3: u32,
unk4: u32,
},
/// Sent by the client after exchanging encryption information with the lobby server.
#[br(pre_assert(*magic == ClientLobbyIpcType::LoginEx))]
@ -304,6 +307,7 @@ mod tests {
unk2: 0,
account_id: 0,
unk3: 0,
unk4: 0,
},
),
(
@ -313,6 +317,8 @@ mod tests {
content_id: 0,
unk1: 0,
unk2: 0,
unk3: 0,
unk4: 0,
},
),
(

View file

@ -36,8 +36,7 @@ impl Default for CharacterFlag {
#[binrw]
#[derive(Debug, Clone, Default)]
pub struct CharacterDetails {
#[brw(pad_after = 4)]
pub actor_id: u32,
pub player_id: u64,
pub content_id: u64,
pub index: u8,
pub flags: CharacterFlag,

View file

@ -128,7 +128,10 @@ impl Default for ClientZoneIpcSegment {
op_code: ClientZoneIpcType::InitRequest,
option: 0,
timestamp: 0,
data: ClientZoneIpcData::InitRequest { unk: [0; 120] },
data: ClientZoneIpcData::InitRequest {
unk1: String::default(),
unk2: String::default(),
},
}
}
}
@ -472,8 +475,17 @@ pub enum ClientZoneIpcData {
/// Sent by the client when they successfully initialize with the server, and they need several bits of information (e.g. what zone to load)
#[br(pre_assert(*magic == ClientZoneIpcType::InitRequest))]
InitRequest {
// TODO: full of possibly interesting information
unk: [u8; 120],
#[brw(pad_before = 40)] // seems to be empty?
#[brw(pad_size_to = 32)]
#[br(count = 32)]
#[br(map = read_string)]
#[bw(map = write_string)]
unk1: String,
#[br(count = 48)]
#[brw(pad_size_to = 48)]
#[br(map = read_string)]
#[bw(map = write_string)]
unk2: String,
},
/// Sent by the client when they're done loading and they need to be spawned in
#[br(pre_assert(*magic == ClientZoneIpcType::FinishLoading))]
@ -952,7 +964,10 @@ mod tests {
let ipc_types = [
(
ClientZoneIpcType::InitRequest,
ClientZoneIpcData::InitRequest { unk: [0; 120] },
ClientZoneIpcData::InitRequest {
unk1: String::default(),
unk2: String::default(),
},
),
(
ClientZoneIpcType::FinishLoading,

View file

@ -412,7 +412,7 @@ impl LobbyConnection {
unk2: 0x1,
action: LobbyCharacterActionKind::Create,
details: CharacterDetails {
actor_id: our_actor_id,
player_id: our_actor_id as u64, // TODO: not correct
content_id: our_content_id,
character_name: character_action.name.clone(),
origin_server_name: self.world_name.clone(),
@ -458,7 +458,7 @@ impl LobbyConnection {
unk2: 0x1,
action: LobbyCharacterActionKind::Delete,
details: CharacterDetails {
actor_id: 0, // TODO: fill maybe?
player_id: 0, // TODO: fill maybe?
content_id: character_action.content_id,
character_name: character_action.name.clone(),
origin_server_name: self.world_name.clone(),
@ -506,7 +506,7 @@ impl LobbyConnection {
unk2: 0x1,
action: LobbyCharacterActionKind::RemakeChara,
details: CharacterDetails {
actor_id: 0, // TODO: fill maybe?
player_id: 0, // TODO: fill maybe?
content_id: character_action.content_id,
character_name: character_action.name.clone(),
origin_server_name: self.world_name.clone(),

View file

@ -166,7 +166,6 @@ impl LoginDatabase {
for (index, id) in accounts.enumerate() {
service_accounts.push(ServiceAccount {
id: id.unwrap(),
unk1: 0,
index: index as u32,
name: format!("FINAL FANTASY XIV {}", index + 1), // TODO: don't add the "1" if you only have one service account
});

View file

@ -57,11 +57,11 @@ pub enum SegmentData<T: ReadWriteIpcSegment> {
#[br(count = 36)]
#[br(map = read_string)]
#[bw(map = write_string)]
ticket: String, // square enix in their infinite wisdom has this as a STRING REPRESENTATION of an integer. what
actor_id: String, // square enix in their infinite wisdom has this as a STRING REPRESENTATION of an integer. what
},
#[br(pre_assert(kind == SegmentType::Initialize))]
Initialize {
player_id: u32,
actor_id: u32,
#[brw(pad_after = 32)]
timestamp: u32,
},

View file

@ -199,7 +199,7 @@ impl ZoneConnection {
self.send_segment(PacketSegment {
segment_type: SegmentType::Initialize,
data: SegmentData::Initialize {
player_id: self.player_data.actor_id,
actor_id: self.player_data.actor_id,
timestamp: timestamp_secs(),
},
..Default::default()

View file

@ -447,7 +447,7 @@ impl WorldDatabase {
};
characters.push(CharacterDetails {
actor_id: *actor_id,
player_id: *actor_id as u64, // TODO: not correct
content_id: *content_id as u64,
index: index as u8,
flags: CharacterFlag::NONE,