From 5b7e07642ae0f325a8484d5687b1787cae6e7733 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Sat, 29 Mar 2025 00:15:29 -0400 Subject: [PATCH] Commit dynamic character values back to the database This now saves the current zone id, position and the rotation of your character to the database when you log out. This isn't restored yet though. --- src/bin/kawari-world.rs | 7 +++++-- src/world/chat_handler.rs | 6 +++--- src/world/connection.rs | 9 +++++++- src/world/database.rs | 44 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index 1efb82a..dcf5633 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -73,7 +73,6 @@ async fn main() { player_data: PlayerData::default(), spawn_index: 0, zone: None, - position: Position::default(), inventory: Inventory::new(), status_effects: StatusEffects::default(), event: None, @@ -544,11 +543,15 @@ async fn main() { rotation.to_degrees() ); - connection.position = *position; + connection.player_data.rotation = *rotation; + connection.player_data.position = *position; } ClientZoneIpcData::LogOut { .. } => { tracing::info!("Recieved log out from client!"); + // write the player back to the database + database.commit_player_data(&connection.player_data); + // tell the client to disconnect { let ipc = ServerZoneIpcSegment { diff --git a/src/world/chat_handler.rs b/src/world/chat_handler.rs index af12c14..b3522be 100644 --- a/src/world/chat_handler.rs +++ b/src/world/chat_handler.rs @@ -114,7 +114,7 @@ impl ChatHandler { 0, // left finger 0, // right finger ], - pos: connection.position, + pos: connection.player_data.position, ..Default::default() }, ..Default::default() @@ -218,7 +218,7 @@ impl ChatHandler { 0, // left finger 0, // right finger ], - pos: connection.position, + pos: connection.player_data.position, ..Default::default() }, ..Default::default() @@ -257,7 +257,7 @@ impl ChatHandler { level: 1, battalion: 4, model_chara: 297, - pos: connection.position, + pos: connection.player_data.position, ..Default::default() }, ..Default::default() diff --git a/src/world/connection.rs b/src/world/connection.rs index 92257f4..9d18f14 100644 --- a/src/world/connection.rs +++ b/src/world/connection.rs @@ -20,9 +20,16 @@ use super::{ #[derive(Debug, Default, Clone, Copy)] pub struct PlayerData { + // Static data pub actor_id: u32, pub content_id: u64, pub account_id: u32, + + // Dynamic data + pub position: Position, + /// In radians. + pub rotation: f32, + pub zone_id: u16, } #[derive(Debug, Default, Clone)] @@ -66,7 +73,6 @@ pub struct ZoneConnection { pub zone: Option, pub spawn_index: u8, - pub position: Position, pub inventory: Inventory, pub status_effects: StatusEffects, @@ -117,6 +123,7 @@ impl ZoneConnection { pub async fn change_zone(&mut self, new_zone_id: u16) { self.zone = Some(Zone::load(new_zone_id)); + self.player_data.zone_id = new_zone_id; // Player Class Info { diff --git a/src/world/database.rs b/src/world/database.rs index b866ed2..c5e81d1 100644 --- a/src/world/database.rs +++ b/src/world/database.rs @@ -39,7 +39,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);"; + 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);"; connection.execute(query, ()).unwrap(); } @@ -58,13 +58,53 @@ impl WorldDatabase { .query_row((actor_id,), |row| Ok((row.get(0)?, row.get(1)?))) .unwrap(); + stmt = connection + .prepare("SELECT pos_x, pos_y, pos_z, rotation, zone_id FROM character_data WHERE content_id = ?1") + .unwrap(); + let (pos_x, pos_y, pos_z, rotation, zone_id) = stmt + .query_row((content_id,), |row| { + Ok(( + row.get(0)?, + row.get(1)?, + row.get(2)?, + row.get(3)?, + row.get(4)?, + )) + }) + .unwrap(); + PlayerData { actor_id, content_id, account_id, + position: Position { + x: pos_x, + y: pos_y, + z: pos_z, + }, + rotation, + zone_id, } } + /// Commit the dynamic player data back to the database + pub fn commit_player_data(&self, data: &PlayerData) { + let connection = self.connection.lock().unwrap(); + + let mut stmt = connection + .prepare("UPDATE character_data SET zone_id=?1, pos_x=?2, pos_y=?3, pos_z=?4, rotation=?5 WHERE content_id = ?6") + .unwrap(); + stmt.execute(( + data.zone_id, + data.position.x, + data.position.y, + data.position.z, + data.rotation, + data.content_id, + )) + .unwrap(); + } + // TODO: from/to sql int pub fn find_actor_id(&self, content_id: u64) -> u32 { @@ -199,7 +239,7 @@ impl WorldDatabase { // insert char data connection .execute( - "INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0);", + "INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0, 0.0);", (content_id, name, chara_make, city_state, zone_id), ) .unwrap();