mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-25 16:27:46 +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:
parent
45be3835bb
commit
4d4720b192
2 changed files with 100 additions and 19 deletions
|
@ -4,7 +4,10 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||
use kawari::blowfish::Blowfish;
|
||||
use kawari::client_select_data::{ClientCustomizeData, ClientSelectData};
|
||||
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::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;
|
||||
}
|
||||
IPCStructData::LobbyCharacterAction { .. } => tracing::info!(
|
||||
"Client is doing a character-related action in the lobby, but we don't support any yet! Ignoring..."
|
||||
),
|
||||
IPCStructData::LobbyCharacterAction {
|
||||
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 {
|
||||
sequence,
|
||||
lookup_id,
|
||||
|
|
55
src/ipc.rs
55
src/ipc.rs
|
@ -171,21 +171,32 @@ pub struct CharacterDetails {
|
|||
}
|
||||
|
||||
#[binrw]
|
||||
#[brw(repr = u8)]
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum LobbyCharacterAction {
|
||||
ReserveName = 0x1,
|
||||
Create = 0x2,
|
||||
Rename = 0x3,
|
||||
Delete = 0x4,
|
||||
Move = 0x5,
|
||||
RemakeRetainer = 0x6,
|
||||
RemakeChara = 0x7,
|
||||
SettingsUploadBegin = 0x8,
|
||||
SettingsUpload = 0xC,
|
||||
WorldVisit = 0xE,
|
||||
DataCenterToken = 0xF,
|
||||
Request = 0x15,
|
||||
#[brw(magic = 0x1u8)]
|
||||
ReserveName,
|
||||
#[brw(magic = 0x2u8)]
|
||||
Create,
|
||||
#[brw(magic = 0x3u8)]
|
||||
Rename,
|
||||
#[brw(magic = 0x4u8)]
|
||||
Delete,
|
||||
#[brw(magic = 0x5u8)]
|
||||
Move,
|
||||
#[brw(magic = 0x6u8)]
|
||||
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]
|
||||
|
@ -235,8 +246,11 @@ pub enum IPCStructData {
|
|||
#[br(map = read_string)]
|
||||
#[bw(map = write_string)]
|
||||
name: String,
|
||||
// TODO: what else is in here?
|
||||
// according to TemporalStatis, chara make data? (probably op specific)
|
||||
#[bw(pad_size_to = 436)]
|
||||
#[br(count = 436)]
|
||||
#[br(map = read_string)]
|
||||
#[bw(map = write_string)]
|
||||
json: String,
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::RequestEnterWorld))]
|
||||
RequestEnterWorld {
|
||||
|
@ -469,6 +483,16 @@ pub enum IPCStructData {
|
|||
#[brw(pad_after = 24)] // empty bytes
|
||||
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]
|
||||
|
@ -533,6 +557,7 @@ impl IPCSegment {
|
|||
IPCStructData::Unk9 { .. } => 24,
|
||||
IPCStructData::Unk10 { .. } => 8,
|
||||
IPCStructData::Unk11 { .. } => 32,
|
||||
IPCStructData::NameRejection { .. } => 536,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue