1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-04-26 00:37:44 +00:00

Add new character name rejection

Next is being able to create a new character (but not really, because there is
no persistent.) This is a good first step, though.
This commit is contained in:
Joshua Goins 2025-03-13 22:22:02 -04:00
parent 45be3835bb
commit 4d4720b192
2 changed files with 100 additions and 19 deletions

View file

@ -4,7 +4,10 @@ use std::time::{SystemTime, UNIX_EPOCH};
use kawari::blowfish::Blowfish; use kawari::blowfish::Blowfish;
use kawari::client_select_data::{ClientCustomizeData, ClientSelectData}; use kawari::client_select_data::{ClientCustomizeData, ClientSelectData};
use kawari::encryption::generate_encryption_key; use kawari::encryption::generate_encryption_key;
use kawari::ipc::{CharacterDetails, IPCOpCode, IPCSegment, IPCStructData, Server, ServiceAccount}; use kawari::ipc::{
CharacterDetails, IPCOpCode, IPCSegment, IPCStructData, LobbyCharacterAction, Server,
ServiceAccount,
};
use kawari::oodle::FFXIVOodle; use kawari::oodle::FFXIVOodle;
use kawari::packet::{ use kawari::packet::{
CompressionType, PacketSegment, SegmentType, State, parse_packet, send_keep_alive, send_packet, CompressionType, PacketSegment, SegmentType, State, parse_packet, send_keep_alive, send_packet,
@ -65,9 +68,62 @@ async fn main() {
send_lobby_info(&mut write, &mut state, *sequence).await; send_lobby_info(&mut write, &mut state, *sequence).await;
} }
IPCStructData::LobbyCharacterAction { .. } => tracing::info!( IPCStructData::LobbyCharacterAction {
"Client is doing a character-related action in the lobby, but we don't support any yet! Ignoring..." character_id,
), character_index,
action,
world_id,
name,
..
} => {
match action {
LobbyCharacterAction::ReserveName => {
tracing::info!(
"Player is requesting {name} as a new character name!"
);
// reject
{
let ipc = IPCSegment {
unk1: 0,
unk2: 0,
op_code: IPCOpCode::InitializeChat, // wrong but technically right
server_id: 0,
timestamp: 0,
data: IPCStructData::NameRejection {
unk1: 0x03,
unk2: 0x0bdb,
unk3: 0x000132cc,
},
};
let response_packet = PacketSegment {
source_actor: 0x0,
target_actor: 0x0,
segment_type: SegmentType::Ipc { data: ipc },
};
send_packet(
&mut write,
&[response_packet],
&mut state,
CompressionType::Uncompressed,
)
.await;
}
}
LobbyCharacterAction::Create => todo!(),
LobbyCharacterAction::Rename => todo!(),
LobbyCharacterAction::Delete => todo!(),
LobbyCharacterAction::Move => todo!(),
LobbyCharacterAction::RemakeRetainer => todo!(),
LobbyCharacterAction::RemakeChara => todo!(),
LobbyCharacterAction::SettingsUploadBegin => todo!(),
LobbyCharacterAction::SettingsUpload => todo!(),
LobbyCharacterAction::WorldVisit => todo!(),
LobbyCharacterAction::DataCenterToken => todo!(),
LobbyCharacterAction::Request => todo!(),
}
}
IPCStructData::RequestEnterWorld { IPCStructData::RequestEnterWorld {
sequence, sequence,
lookup_id, lookup_id,

View file

@ -171,21 +171,32 @@ pub struct CharacterDetails {
} }
#[binrw] #[binrw]
#[brw(repr = u8)]
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub enum LobbyCharacterAction { pub enum LobbyCharacterAction {
ReserveName = 0x1, #[brw(magic = 0x1u8)]
Create = 0x2, ReserveName,
Rename = 0x3, #[brw(magic = 0x2u8)]
Delete = 0x4, Create,
Move = 0x5, #[brw(magic = 0x3u8)]
RemakeRetainer = 0x6, Rename,
RemakeChara = 0x7, #[brw(magic = 0x4u8)]
SettingsUploadBegin = 0x8, Delete,
SettingsUpload = 0xC, #[brw(magic = 0x5u8)]
WorldVisit = 0xE, Move,
DataCenterToken = 0xF, #[brw(magic = 0x6u8)]
Request = 0x15, RemakeRetainer,
#[brw(magic = 0x7u8)]
RemakeChara,
#[brw(magic = 0x8u8)]
SettingsUploadBegin,
#[brw(magic = 0xCu8)]
SettingsUpload,
#[brw(magic = 0xEu8)]
WorldVisit,
#[brw(magic = 0xFu8)]
DataCenterToken,
#[brw(magic = 0x15u8)]
Request,
} }
#[binrw] #[binrw]
@ -235,8 +246,11 @@ pub enum IPCStructData {
#[br(map = read_string)] #[br(map = read_string)]
#[bw(map = write_string)] #[bw(map = write_string)]
name: String, name: String,
// TODO: what else is in here? #[bw(pad_size_to = 436)]
// according to TemporalStatis, chara make data? (probably op specific) #[br(count = 436)]
#[br(map = read_string)]
#[bw(map = write_string)]
json: String,
}, },
#[br(pre_assert(*magic == IPCOpCode::RequestEnterWorld))] #[br(pre_assert(*magic == IPCOpCode::RequestEnterWorld))]
RequestEnterWorld { RequestEnterWorld {
@ -469,6 +483,16 @@ pub enum IPCStructData {
#[brw(pad_after = 24)] // empty bytes #[brw(pad_after = 24)] // empty bytes
unk: u32, unk: u32,
}, },
#[br(pre_assert(false))]
NameRejection {
// FIXME: This is opcode 0x2, which is InitializeChat. We need to separate the lobby/zone IPC codes.
unk1: u8,
#[brw(pad_before = 7)] // empty
unk2: u16,
#[brw(pad_before = 6)] // empty
#[brw(pad_after = 516)] // mostly empty
unk3: u32,
},
} }
#[binrw] #[binrw]
@ -533,6 +557,7 @@ impl IPCSegment {
IPCStructData::Unk9 { .. } => 24, IPCStructData::Unk9 { .. } => 24,
IPCStructData::Unk10 { .. } => 8, IPCStructData::Unk10 { .. } => 8,
IPCStructData::Unk11 { .. } => 32, IPCStructData::Unk11 { .. } => 32,
IPCStructData::NameRejection { .. } => 536,
} }
} }
} }