diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index 418091f..d4dc701 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -336,6 +336,12 @@ async fn client_loop( connection.send_inventory(false).await; connection.send_stats(&chara_details).await; + let online_status = if connection.player_data.gm_rank == GameMasterRank::NormalUser { + OnlineStatus::Online + } else { + OnlineStatus::GameMasterBlue + }; + // send player spawn { let ipc = ServerZoneIpcSegment { @@ -346,8 +352,8 @@ async fn client_loop( content_id: connection.player_data.content_id, current_world_id: config.world.world_id, home_world_id: config.world.world_id, - gm_rank: GameMasterRank::Debug, - online_status: OnlineStatus::GameMasterBlue, + gm_rank: connection.player_data.gm_rank, + online_status, common: common.clone(), ..Default::default() }), diff --git a/src/ipc/zone/common_spawn.rs b/src/ipc/zone/common_spawn.rs index 28b65be..e726b8b 100644 --- a/src/ipc/zone/common_spawn.rs +++ b/src/ipc/zone/common_spawn.rs @@ -104,7 +104,7 @@ pub enum OnlineStatus { #[binrw] #[brw(little)] #[brw(repr = u8)] -#[derive(Debug, Clone, Default, PartialEq)] +#[derive(Debug, Clone, Copy, Default, PartialEq)] pub enum GameMasterRank { #[default] NormalUser, @@ -116,6 +116,23 @@ pub enum GameMasterRank { Debug = 90, } +impl TryFrom for GameMasterRank { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(Self::NormalUser), + 1 => Ok(Self::GameMaster), + 3 => Ok(Self::EventJunior), + 4 => Ok(Self::EventSenior), + 5 => Ok(Self::Support), + 7 => Ok(Self::Senior), + 90 => Ok(Self::Debug), + _ => Err(()), + } + } +} + #[binrw] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct DisplayFlag(u32); diff --git a/src/world/connection.rs b/src/world/connection.rs index 763be05..d94eb94 100644 --- a/src/world/connection.rs +++ b/src/world/connection.rs @@ -15,9 +15,9 @@ use crate::{ chat::ServerChatIpcSegment, zone::{ ActorControl, ActorControlSelf, ActorControlTarget, ClientZoneIpcSegment, CommonSpawn, - ContainerInfo, DisplayFlag, Equip, InitZone, ItemInfo, Move, NpcSpawn, ObjectKind, - PlayerStats, PlayerSubKind, ServerZoneIpcData, ServerZoneIpcSegment, StatusEffect, - StatusEffectList, UpdateClassInfo, Warp, WeatherChange, + ContainerInfo, DisplayFlag, Equip, GameMasterRank, InitZone, ItemInfo, Move, NpcSpawn, + ObjectKind, PlayerStats, PlayerSubKind, ServerZoneIpcData, ServerZoneIpcSegment, + StatusEffect, StatusEffectList, UpdateClassInfo, Warp, WeatherChange, }, }, opcodes::ServerZoneIpcType, @@ -60,6 +60,7 @@ pub struct PlayerData { pub inventory: Inventory, pub teleport_query: TeleportQuery, + pub gm_rank: GameMasterRank, } /// Represents a single connection between an instance of the client and the world server diff --git a/src/world/database.rs b/src/world/database.rs index 09832c0..0488947 100644 --- a/src/world/database.rs +++ b/src/world/database.rs @@ -9,7 +9,10 @@ use crate::{ workdefinitions::{CharaMake, ClientSelectData, RemakeMode}, }, inventory::Inventory, - ipc::lobby::{CharacterDetails, CharacterFlag}, + ipc::{ + lobby::{CharacterDetails, CharacterFlag}, + zone::GameMasterRank, + }, }; use super::PlayerData; @@ -44,7 +47,7 @@ impl WorldDatabase { // Create characters data table { - let query = "CREATE TABLE IF NOT EXISTS character_data (content_id INTEGER PRIMARY KEY, name STRING, chara_make STRING, city_state INTEGER, zone_id INTEGER, pos_x REAL, pos_y REAL, pos_z REAL, rotation REAL, inventory STRING, remake_mode INTEGER);"; + let query = "CREATE TABLE IF NOT EXISTS character_data (content_id INTEGER PRIMARY KEY, name STRING, chara_make STRING, city_state INTEGER, zone_id INTEGER, pos_x REAL, pos_y REAL, pos_z REAL, rotation REAL, inventory STRING, remake_mode INTEGER, gm_rank INTEGER);"; connection.execute(query, ()).unwrap(); } @@ -139,15 +142,16 @@ impl WorldDatabase { .unwrap(); stmt = connection - .prepare("SELECT pos_x, pos_y, pos_z, rotation, zone_id, inventory FROM character_data WHERE content_id = ?1") + .prepare("SELECT pos_x, pos_y, pos_z, rotation, zone_id, inventory, gm_rank FROM character_data WHERE content_id = ?1") .unwrap(); - let (pos_x, pos_y, pos_z, rotation, zone_id, inventory_json): ( + let (pos_x, pos_y, pos_z, rotation, zone_id, inventory_json, gm_rank): ( f32, f32, f32, f32, u16, String, + u8, ) = stmt .query_row((content_id,), |row| { Ok(( @@ -157,6 +161,7 @@ impl WorldDatabase { row.get(3)?, row.get(4)?, row.get(5)?, + row.get(6)?, )) }) .unwrap(); @@ -175,6 +180,7 @@ impl WorldDatabase { rotation, zone_id, inventory, + gm_rank: GameMasterRank::try_from(gm_rank).unwrap(), ..Default::default() } } @@ -344,7 +350,7 @@ impl WorldDatabase { // insert char data connection .execute( - "INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0, 0.0, ?6, 0);", + "INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0, 0.0, ?6, 0, 0);", ( content_id, name,