mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-27 00:47:45 +00:00
Fix a few problems with ClientSelectData, use the same character in both servers
I apparently had a few fields missing here. Also just some general clean up, make it the same looking character in both the Lobby and World server. I also chose Gridania as the test zone.
This commit is contained in:
parent
5c22532474
commit
640aeb797c
7 changed files with 122 additions and 149 deletions
|
@ -13,7 +13,7 @@ use kawari::oodle::FFXIVOodle;
|
|||
use kawari::packet::{
|
||||
CompressionType, PacketSegment, SegmentType, State, parse_packet, send_keep_alive, send_packet,
|
||||
};
|
||||
use kawari::{CONTENT_ID, WORLD_ID, WORLD_NAME, ZONE_ID};
|
||||
use kawari::{CHAR_NAME, CONTENT_ID, CUSTOMIZE_DATA, WORLD_ID, WORLD_NAME, ZONE_ID};
|
||||
use tokio::io::{AsyncReadExt, WriteHalf};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
|
@ -396,33 +396,7 @@ async fn send_lobby_info(socket: &mut WriteHalf<TcpStream>, state: &mut State, s
|
|||
unk9: 0,
|
||||
zone_id: ZONE_ID as i32,
|
||||
unk11: 0,
|
||||
customize: ClientCustomizeData {
|
||||
race: 3,
|
||||
gender: 1,
|
||||
height: 0,
|
||||
subrace: 0,
|
||||
face: 1,
|
||||
hair: 1,
|
||||
enable_highlights: 1,
|
||||
skin_tone: 1,
|
||||
right_eye_color: 1,
|
||||
hair_tone: 1,
|
||||
highlights: 1,
|
||||
facial_features: 1,
|
||||
facial_feature_color: 1,
|
||||
eyebrows: 1,
|
||||
left_eye_color: 1,
|
||||
eyes: 1,
|
||||
nose: 1,
|
||||
jaw: 1,
|
||||
mouth: 1,
|
||||
lips_tone_fur_pattern: 1,
|
||||
race_feature_size: 1,
|
||||
race_feature_type: 1,
|
||||
bust: 0,
|
||||
face_paint: 1,
|
||||
face_paint_color: 0,
|
||||
},
|
||||
customize: CUSTOMIZE_DATA,
|
||||
unk12: 0,
|
||||
unk13: 0,
|
||||
unk14: [0; 10],
|
||||
|
@ -432,7 +406,7 @@ async fn send_lobby_info(socket: &mut WriteHalf<TcpStream>, state: &mut State, s
|
|||
unk18: 0,
|
||||
unk19: 0,
|
||||
unk20: 0,
|
||||
unk21: "hello".to_string(),
|
||||
unk21: String::new(),
|
||||
unk22: 0,
|
||||
unk23: 0,
|
||||
};
|
||||
|
@ -444,7 +418,7 @@ async fn send_lobby_info(socket: &mut WriteHalf<TcpStream>, state: &mut State, s
|
|||
unk1: [0; 16],
|
||||
origin_server_id: WORLD_ID,
|
||||
current_server_id: WORLD_ID,
|
||||
character_name: "test".to_string(),
|
||||
character_name: CHAR_NAME.to_string(),
|
||||
origin_server_name: WORLD_NAME.to_string(),
|
||||
current_server_name: WORLD_NAME.to_string(),
|
||||
character_detail_json: select_data.to_json(),
|
||||
|
|
|
@ -7,10 +7,10 @@ use kawari::packet::{
|
|||
CompressionType, PacketSegment, SegmentType, State, parse_packet, send_keep_alive, send_packet,
|
||||
};
|
||||
use kawari::world::{
|
||||
ActorControlSelf, ActorControlType, CustomizeData, InitZone, PlayerSetup, PlayerSpawn,
|
||||
PlayerStats, Position, UpdateClassInfo,
|
||||
ActorControlSelf, ActorControlType, InitZone, PlayerSetup, PlayerSpawn, PlayerStats, Position,
|
||||
UpdateClassInfo,
|
||||
};
|
||||
use kawari::{CONTENT_ID, WORLD_ID, ZONE_ID};
|
||||
use kawari::{CHAR_NAME, CONTENT_ID, CUSTOMIZE_DATA, WORLD_ID, ZONE_ID};
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
|
@ -268,7 +268,7 @@ async fn main() {
|
|||
content_id: CONTENT_ID,
|
||||
exp: [10000; 32],
|
||||
levels: [100; 32],
|
||||
name: "KAWARI".to_string(),
|
||||
name: CHAR_NAME.to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
};
|
||||
|
@ -499,7 +499,7 @@ async fn main() {
|
|||
home_world_id: WORLD_ID,
|
||||
title: 1,
|
||||
class_job: 35,
|
||||
name: "Test".to_string(),
|
||||
name: CHAR_NAME.to_string(),
|
||||
hp_curr: 100,
|
||||
hp_max: 100,
|
||||
mp_curr: 100,
|
||||
|
@ -508,35 +508,20 @@ async fn main() {
|
|||
spawn_index: 1,
|
||||
state: 1,
|
||||
gm_rank: 3,
|
||||
look: CustomizeData {
|
||||
race: 3,
|
||||
age: 0,
|
||||
gender: 1,
|
||||
height: 5,
|
||||
subrace: 0,
|
||||
face: 1,
|
||||
hair: 2,
|
||||
enable_highlights: 0,
|
||||
skin_tone: 4,
|
||||
right_eye_color: 5,
|
||||
hair_tone: 2,
|
||||
highlights: 7,
|
||||
facial_features: 1,
|
||||
facial_feature_color: 1,
|
||||
eyebrows: 2,
|
||||
left_eye_color: 1,
|
||||
eyes: 1,
|
||||
nose: 0,
|
||||
jaw: 1,
|
||||
mouth: 0,
|
||||
lips_tone_fur_pattern: 1,
|
||||
race_feature_size: 1,
|
||||
race_feature_type: 1,
|
||||
bust: 0,
|
||||
face_paint: 1,
|
||||
face_paint_color: 1,
|
||||
},
|
||||
look: CUSTOMIZE_DATA,
|
||||
fc_tag: "LOCAL".to_string(),
|
||||
models: [
|
||||
0, // head
|
||||
89, // body
|
||||
89, // hands
|
||||
89, // legs
|
||||
89, // feet
|
||||
0, // ears
|
||||
0, // neck
|
||||
0, // wrists
|
||||
0, // left finger
|
||||
0, // right finger
|
||||
],
|
||||
..Default::default()
|
||||
}),
|
||||
};
|
||||
|
@ -731,6 +716,9 @@ async fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
IPCStructData::Unk12 { .. } => {
|
||||
tracing::info!("Recieved Unk12!");
|
||||
}
|
||||
_ => panic!(
|
||||
"The server is recieving a IPC response or unknown packet!"
|
||||
),
|
||||
|
|
|
@ -4,31 +4,32 @@ use serde_json::{Value, json};
|
|||
#[binrw]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ClientCustomizeData {
|
||||
pub race: i32,
|
||||
pub gender: i32,
|
||||
pub height: i32,
|
||||
pub subrace: i32,
|
||||
pub face: i32,
|
||||
pub hair: i32,
|
||||
pub enable_highlights: i32,
|
||||
pub skin_tone: i32,
|
||||
pub right_eye_color: i32,
|
||||
pub hair_tone: i32,
|
||||
pub highlights: i32,
|
||||
pub facial_features: i32,
|
||||
pub facial_feature_color: i32,
|
||||
pub eyebrows: i32,
|
||||
pub left_eye_color: i32,
|
||||
pub eyes: i32,
|
||||
pub nose: i32,
|
||||
pub jaw: i32,
|
||||
pub mouth: i32,
|
||||
pub lips_tone_fur_pattern: i32,
|
||||
pub race_feature_size: i32,
|
||||
pub race_feature_type: i32,
|
||||
pub bust: i32,
|
||||
pub face_paint: i32,
|
||||
pub face_paint_color: i32,
|
||||
pub race: u8,
|
||||
pub gender: u8,
|
||||
pub age: u8,
|
||||
pub height: u8,
|
||||
pub subrace: u8,
|
||||
pub face: u8,
|
||||
pub hair: u8,
|
||||
pub enable_highlights: u8,
|
||||
pub skin_tone: u8,
|
||||
pub right_eye_color: u8,
|
||||
pub hair_tone: u8,
|
||||
pub highlights: u8,
|
||||
pub facial_features: u8,
|
||||
pub facial_feature_color: u8,
|
||||
pub eyebrows: u8,
|
||||
pub left_eye_color: u8,
|
||||
pub eyes: u8,
|
||||
pub nose: u8,
|
||||
pub jaw: u8,
|
||||
pub mouth: u8,
|
||||
pub lips_tone_fur_pattern: u8,
|
||||
pub race_feature_size: u8,
|
||||
pub race_feature_type: u8,
|
||||
pub bust: u8,
|
||||
pub face_paint: u8,
|
||||
pub face_paint_color: u8,
|
||||
}
|
||||
|
||||
impl ClientCustomizeData {
|
||||
|
@ -36,9 +37,11 @@ impl ClientCustomizeData {
|
|||
json!([
|
||||
self.race.to_string(),
|
||||
self.gender.to_string(),
|
||||
self.age.to_string(),
|
||||
self.height.to_string(),
|
||||
self.subrace.to_string(),
|
||||
self.face.to_string(),
|
||||
self.hair.to_string(),
|
||||
self.enable_highlights.to_string(),
|
||||
self.skin_tone.to_string(),
|
||||
self.right_eye_color.to_string(),
|
||||
|
@ -63,31 +66,32 @@ impl ClientCustomizeData {
|
|||
|
||||
pub fn from_json(json: &Value) -> Self {
|
||||
Self {
|
||||
race: json[0].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
gender: json[1].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
height: json[2].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
subrace: json[3].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
face: json[4].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
hair: json[5].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
enable_highlights: json[6].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
skin_tone: json[7].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
right_eye_color: json[8].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
hair_tone: json[9].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
highlights: json[10].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
facial_features: json[11].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
facial_feature_color: json[12].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
eyebrows: json[13].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
left_eye_color: json[14].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
eyes: json[15].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
nose: json[16].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
jaw: json[17].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
mouth: json[18].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
lips_tone_fur_pattern: json[19].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
race_feature_size: json[20].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
race_feature_type: json[21].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
bust: json[22].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
face_paint: json[23].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
face_paint_color: json[24].as_str().unwrap().parse::<i32>().unwrap(),
|
||||
race: json[0].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
gender: json[1].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
height: json[2].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
subrace: json[3].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
face: json[4].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
hair: json[5].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
enable_highlights: json[6].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
skin_tone: json[7].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
right_eye_color: json[8].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
hair_tone: json[9].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
highlights: json[10].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
facial_features: json[11].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
facial_feature_color: json[12].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
eyebrows: json[13].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
left_eye_color: json[14].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
eyes: json[15].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
nose: json[16].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
jaw: json[17].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
mouth: json[18].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
lips_tone_fur_pattern: json[19].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
race_feature_size: json[20].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
race_feature_type: json[21].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
bust: json[22].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
face_paint: json[23].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
face_paint_color: json[24].as_str().unwrap().parse::<u8>().unwrap(),
|
||||
age: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +113,7 @@ pub struct ClientSelectData {
|
|||
pub customize: ClientCustomizeData,
|
||||
pub unk12: i32,
|
||||
pub unk13: i32,
|
||||
pub unk14: [i32; 10],
|
||||
pub unk14: [i32; 10], // probably model ids
|
||||
pub unk15: i32,
|
||||
pub unk16: i32,
|
||||
/// If set to 1, the user is granted one opportunity to edit their character and are prompted to re-choose their class.
|
||||
|
@ -159,6 +163,6 @@ impl ClientSelectData {
|
|||
"classid": 116,
|
||||
});
|
||||
|
||||
serde_json::to_string_pretty(&obj).unwrap()
|
||||
serde_json::to_string(&obj).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,6 +98,8 @@ pub enum IPCOpCode {
|
|||
Unk11 = 0x156,
|
||||
// Assumed what this is, but probably incorrect
|
||||
CharacterCreated = 0xE,
|
||||
// Unknown, client sends this for ???
|
||||
Unk12 = 0x0E9,
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
|
@ -357,6 +359,10 @@ pub enum IPCStructData {
|
|||
#[br(dbg)]
|
||||
unk: [u8; 24],
|
||||
},
|
||||
#[br(pre_assert(*magic == IPCOpCode::Unk12))]
|
||||
Unk12 {
|
||||
unk: [u8; 8], // TODO: unknown
|
||||
},
|
||||
|
||||
// Server->Client IPC
|
||||
#[br(pre_assert(false))]
|
||||
|
@ -571,6 +577,7 @@ impl IPCSegment {
|
|||
IPCStructData::Unk11 { .. } => 32,
|
||||
IPCStructData::NameRejection { .. } => 536,
|
||||
IPCStructData::CharacterCreated { .. } => 2568,
|
||||
IPCStructData::Unk12 { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
34
src/lib.rs
34
src/lib.rs
|
@ -1,3 +1,4 @@
|
|||
use client_select_data::ClientCustomizeData;
|
||||
use minijinja::Environment;
|
||||
use rand::Rng;
|
||||
use rand::distributions::Alphanumeric;
|
||||
|
@ -20,13 +21,44 @@ pub mod world;
|
|||
pub const WORLD_ID: u16 = 63;
|
||||
pub const WORLD_NAME: &str = "KAWARI";
|
||||
|
||||
pub const ZONE_ID: u16 = 1255;
|
||||
pub const ZONE_ID: u16 = 132;
|
||||
|
||||
pub const CONTENT_ID: u64 = 11111111111111111;
|
||||
|
||||
pub const CUSTOMIZE_DATA: ClientCustomizeData = ClientCustomizeData {
|
||||
race: 4,
|
||||
gender: 1,
|
||||
age: 1,
|
||||
height: 50,
|
||||
subrace: 7,
|
||||
face: 3,
|
||||
hair: 5,
|
||||
enable_highlights: 0,
|
||||
skin_tone: 10,
|
||||
right_eye_color: 75,
|
||||
hair_tone: 50,
|
||||
highlights: 0,
|
||||
facial_features: 1,
|
||||
facial_feature_color: 19,
|
||||
eyebrows: 1,
|
||||
left_eye_color: 75,
|
||||
eyes: 1,
|
||||
nose: 0,
|
||||
jaw: 1,
|
||||
mouth: 1,
|
||||
lips_tone_fur_pattern: 169,
|
||||
race_feature_size: 100,
|
||||
race_feature_type: 1,
|
||||
bust: 100,
|
||||
face_paint: 0,
|
||||
face_paint_color: 167,
|
||||
};
|
||||
|
||||
/// Maxmimum length of a character's name.
|
||||
pub const CHAR_NAME_MAX_LENGTH: usize = 32;
|
||||
|
||||
pub const CHAR_NAME: &str = "Test User";
|
||||
|
||||
pub fn generate_sid() -> String {
|
||||
let random_id: String = rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
mod player_spawn;
|
||||
pub use player_spawn::CustomizeData;
|
||||
pub use player_spawn::PlayerSpawn;
|
||||
|
||||
mod position;
|
||||
|
|
|
@ -88,7 +88,7 @@ pub struct PlayerSpawn {
|
|||
#[br(map = read_string)]
|
||||
#[bw(map = write_string)]
|
||||
pub name: String,
|
||||
pub look: CustomizeData,
|
||||
pub look: ClientCustomizeData,
|
||||
#[br(count = 6)]
|
||||
#[bw(pad_size_to = 6)]
|
||||
#[br(map = read_string)]
|
||||
|
@ -97,37 +97,6 @@ pub struct PlayerSpawn {
|
|||
pub padding: [u8; 2],
|
||||
}
|
||||
|
||||
#[binrw]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct CustomizeData {
|
||||
pub race: u8,
|
||||
pub gender: u8,
|
||||
pub age: u8,
|
||||
pub height: u8,
|
||||
pub subrace: u8,
|
||||
pub face: u8,
|
||||
pub hair: u8,
|
||||
pub enable_highlights: u8,
|
||||
pub skin_tone: u8,
|
||||
pub right_eye_color: u8,
|
||||
pub hair_tone: u8,
|
||||
pub highlights: u8,
|
||||
pub facial_features: u8,
|
||||
pub facial_feature_color: u8,
|
||||
pub eyebrows: u8,
|
||||
pub left_eye_color: u8,
|
||||
pub eyes: u8,
|
||||
pub nose: u8,
|
||||
pub jaw: u8,
|
||||
pub mouth: u8,
|
||||
pub lips_tone_fur_pattern: u8,
|
||||
pub race_feature_size: u8,
|
||||
pub race_feature_type: u8,
|
||||
pub bust: u8,
|
||||
pub face_paint: u8,
|
||||
pub face_paint_color: u8,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{fs::read, io::Cursor, path::PathBuf};
|
||||
|
|
Loading…
Add table
Reference in a new issue