mirror of
https://github.com/redstrate/Kawari.git
synced 2025-07-17 10:47:44 +00:00
Add support for sending the title list, when requested
This doesn't allow you to set them yet, just show them in the menu.
This commit is contained in:
parent
c339c89c41
commit
8be1fefa53
5 changed files with 49 additions and 3 deletions
|
@ -279,6 +279,11 @@
|
||||||
"name": "FreeCompanyInfo",
|
"name": "FreeCompanyInfo",
|
||||||
"opcode": 892,
|
"opcode": 892,
|
||||||
"size": 80
|
"size": 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TitleList",
|
||||||
|
"opcode": 731,
|
||||||
|
"size": 112
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ClientZoneIpcType": [
|
"ClientZoneIpcType": [
|
||||||
|
|
|
@ -2,7 +2,6 @@ use std::net::SocketAddr;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use kawari::RECEIVE_BUFFER_SIZE;
|
|
||||||
use kawari::common::Position;
|
use kawari::common::Position;
|
||||||
use kawari::common::{GameData, timestamp_secs};
|
use kawari::common::{GameData, timestamp_secs};
|
||||||
use kawari::config::get_config;
|
use kawari::config::get_config;
|
||||||
|
@ -27,6 +26,7 @@ use kawari::world::{
|
||||||
ClientHandle, Event, FromServer, LuaPlayer, PlayerData, ServerHandle, StatusEffects, ToServer,
|
ClientHandle, Event, FromServer, LuaPlayer, PlayerData, ServerHandle, StatusEffects, ToServer,
|
||||||
WorldDatabase, handle_custom_ipc, server_main_loop,
|
WorldDatabase, handle_custom_ipc, server_main_loop,
|
||||||
};
|
};
|
||||||
|
use kawari::{RECEIVE_BUFFER_SIZE, TITLE_UNLOCK_BITMASK_SIZE};
|
||||||
|
|
||||||
use mlua::{Function, Lua};
|
use mlua::{Function, Lua};
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
@ -415,8 +415,33 @@ async fn client_loop(
|
||||||
connection.player_data.teleport_query.aetheryte_id = aetheryte_id as u16;
|
connection.player_data.teleport_query.aetheryte_id = aetheryte_id as u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
// inform the server of our trigger, it will handle sending it to other clients
|
match trigger.trigger {
|
||||||
connection.handle.send(ToServer::ClientTrigger(connection.id, connection.player_data.actor_id, trigger.clone())).await;
|
ClientTriggerCommand::RequestTitleList {} => {
|
||||||
|
// send full title list for now
|
||||||
|
|
||||||
|
let ipc = ServerZoneIpcSegment {
|
||||||
|
op_code: ServerZoneIpcType::TitleList,
|
||||||
|
timestamp: timestamp_secs(),
|
||||||
|
data: ServerZoneIpcData::TitleList {
|
||||||
|
unlock_bitmask: [0xFF; TITLE_UNLOCK_BITMASK_SIZE]
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
connection
|
||||||
|
.send_segment(PacketSegment {
|
||||||
|
source_actor: connection.player_data.actor_id,
|
||||||
|
target_actor: connection.player_data.actor_id,
|
||||||
|
segment_type: SegmentType::Ipc,
|
||||||
|
data: SegmentData::Ipc { data: ipc },
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
// inform the server of our trigger, it will handle sending it to other clients
|
||||||
|
connection.handle.send(ToServer::ClientTrigger(connection.id, connection.player_data.actor_id, trigger.clone())).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ClientZoneIpcData::Unk2 { .. } => {
|
ClientZoneIpcData::Unk2 { .. } => {
|
||||||
// no-op
|
// no-op
|
||||||
|
|
|
@ -59,6 +59,8 @@ pub enum ClientTriggerCommand {
|
||||||
unk3: u32,
|
unk3: u32,
|
||||||
unk4: u32,
|
unk4: u32,
|
||||||
},
|
},
|
||||||
|
#[brw(magic = 0x12Fu16)]
|
||||||
|
RequestTitleList {},
|
||||||
Unknown {
|
Unknown {
|
||||||
category: u16,
|
category: u16,
|
||||||
// seen in haircut event
|
// seen in haircut event
|
||||||
|
|
|
@ -92,6 +92,7 @@ mod object_spawn;
|
||||||
pub use object_spawn::ObjectSpawn;
|
pub use object_spawn::ObjectSpawn;
|
||||||
|
|
||||||
use crate::COMPLETED_QUEST_BITMASK_SIZE;
|
use crate::COMPLETED_QUEST_BITMASK_SIZE;
|
||||||
|
use crate::TITLE_UNLOCK_BITMASK_SIZE;
|
||||||
use crate::common::ObjectTypeId;
|
use crate::common::ObjectTypeId;
|
||||||
use crate::common::Position;
|
use crate::common::Position;
|
||||||
use crate::common::read_string;
|
use crate::common::read_string;
|
||||||
|
@ -462,6 +463,10 @@ pub enum ServerZoneIpcData {
|
||||||
},
|
},
|
||||||
#[br(pre_assert(*magic == ServerZoneIpcType::FreeCompanyInfo))]
|
#[br(pre_assert(*magic == ServerZoneIpcType::FreeCompanyInfo))]
|
||||||
FreeCompanyInfo { unk: [u8; 80] },
|
FreeCompanyInfo { unk: [u8; 80] },
|
||||||
|
#[br(pre_assert(*magic == ServerZoneIpcType::TitleList))]
|
||||||
|
TitleList {
|
||||||
|
unlock_bitmask: [u8; TITLE_UNLOCK_BITMASK_SIZE],
|
||||||
|
},
|
||||||
Unknown {
|
Unknown {
|
||||||
#[br(count = size - 32)]
|
#[br(count = size - 32)]
|
||||||
unk: Vec<u8>,
|
unk: Vec<u8>,
|
||||||
|
@ -928,6 +933,12 @@ mod tests {
|
||||||
message: String::default(),
|
message: String::default(),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
ServerZoneIpcType::TitleList,
|
||||||
|
ServerZoneIpcData::TitleList {
|
||||||
|
unlock_bitmask: [0; TITLE_UNLOCK_BITMASK_SIZE],
|
||||||
|
},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
ServerZoneIpcType::FreeCompanyInfo,
|
ServerZoneIpcType::FreeCompanyInfo,
|
||||||
ServerZoneIpcData::FreeCompanyInfo { unk: [0; 80] },
|
ServerZoneIpcData::FreeCompanyInfo { unk: [0; 80] },
|
||||||
|
|
|
@ -76,6 +76,9 @@ pub const AETHERYTE_UNLOCK_BITMASK_SIZE: usize = 30;
|
||||||
/// The size of the completed quest bitmask.
|
/// The size of the completed quest bitmask.
|
||||||
pub const COMPLETED_QUEST_BITMASK_SIZE: usize = 691;
|
pub const COMPLETED_QUEST_BITMASK_SIZE: usize = 691;
|
||||||
|
|
||||||
|
/// The size of the unlocked title bitmask.
|
||||||
|
pub const TITLE_UNLOCK_BITMASK_SIZE: usize = 112;
|
||||||
|
|
||||||
/// The size of various classjob arrays.
|
/// The size of various classjob arrays.
|
||||||
pub const CLASSJOB_ARRAY_SIZE: usize = 32;
|
pub const CLASSJOB_ARRAY_SIZE: usize = 32;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue