1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-06-30 11:47:45 +00:00

Store classjob EXP

This isn't sent in the PlayerStatus packet *yet*, only on
UpdateClassInfo. For some reason, passing it makes the client freak
out and I'm not sure why yet.
This commit is contained in:
Joshua Goins 2025-06-28 14:56:45 -04:00
parent 0a740198f8
commit f46b62ad9e
3 changed files with 21 additions and 8 deletions

View file

@ -276,7 +276,8 @@ async fn client_loop(
timestamp: timestamp_secs(), timestamp: timestamp_secs(),
data: ServerZoneIpcData::PlayerStatus(PlayerStatus { data: ServerZoneIpcData::PlayerStatus(PlayerStatus {
content_id: connection.player_data.content_id, content_id: connection.player_data.content_id,
exp: connection.player_data.classjob_exp, // for some reason the client really doesn't like us setting this?
//exp: connection.player_data.classjob_exp,
name: chara_details.name, name: chara_details.name,
char_id: connection.player_data.actor_id, char_id: connection.player_data.actor_id,
race: chara_details.chara_make.customize.race, race: chara_details.chara_make.customize.race,

View file

@ -191,7 +191,7 @@ mod tests {
assert_eq!(player_setup.max_level, 100); assert_eq!(player_setup.max_level, 100);
assert_eq!(player_setup.gender, 1); assert_eq!(player_setup.gender, 1);
assert_eq!(player_setup.race, 1); assert_eq!(player_setup.race, 1);
assert_eq!(player_setup.tribe, 2); assert_eq!(player_setup.tribe, 3);
assert_eq!(player_setup.expansion, 5); assert_eq!(player_setup.expansion, 5);
assert_eq!(player_setup.current_job, 1); // gladiator assert_eq!(player_setup.current_job, 1); // gladiator
assert_eq!(player_setup.current_class, 1); // ditto assert_eq!(player_setup.current_class, 1); // ditto

View file

@ -48,7 +48,7 @@ impl WorldDatabase {
// Create characters data table // 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, gm_rank INTEGER, classjob_id INTEGER, classjob_levels STRING, unlocks STRING, aetherytes STRING);"; 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, classjob_id INTEGER, classjob_levels STRING, classjob_exp STRING, unlocks STRING, aetherytes STRING);";
connection.execute(query, ()).unwrap(); connection.execute(query, ()).unwrap();
} }
@ -278,7 +278,7 @@ impl WorldDatabase {
.unwrap(); .unwrap();
stmt = connection stmt = connection
.prepare("SELECT pos_x, pos_y, pos_z, rotation, zone_id, inventory, gm_rank, classjob_id, classjob_levels, unlocks, aetherytes FROM character_data WHERE content_id = ?1") .prepare("SELECT pos_x, pos_y, pos_z, rotation, zone_id, inventory, gm_rank, classjob_id, classjob_levels, classjob_exp, unlocks, aetherytes FROM character_data WHERE content_id = ?1")
.unwrap(); .unwrap();
let ( let (
pos_x, pos_x,
@ -290,6 +290,7 @@ impl WorldDatabase {
gm_rank, gm_rank,
classjob_id, classjob_id,
classjob_levels, classjob_levels,
classjob_exp,
unlocks, unlocks,
aetherytes, aetherytes,
): ( ): (
@ -304,6 +305,7 @@ impl WorldDatabase {
String, String,
String, String,
String, String,
String,
) = stmt ) = stmt
.query_row((content_id,), |row| { .query_row((content_id,), |row| {
Ok(( Ok((
@ -318,13 +320,14 @@ impl WorldDatabase {
row.get(8)?, row.get(8)?,
row.get(9)?, row.get(9)?,
row.get(10)?, row.get(10)?,
row.get(11)?,
)) ))
}) })
.unwrap(); .unwrap();
let inventory = serde_json::from_str(&inventory_json).unwrap(); let inventory = serde_json::from_str(&inventory_json).unwrap();
PlayerData { let data = PlayerData {
actor_id, actor_id,
content_id, content_id,
account_id, account_id,
@ -339,10 +342,15 @@ impl WorldDatabase {
gm_rank: GameMasterRank::try_from(gm_rank).unwrap(), gm_rank: GameMasterRank::try_from(gm_rank).unwrap(),
classjob_id: classjob_id as u8, classjob_id: classjob_id as u8,
classjob_levels: serde_json::from_str(&classjob_levels).unwrap(), classjob_levels: serde_json::from_str(&classjob_levels).unwrap(),
classjob_exp: serde_json::from_str(&classjob_exp).unwrap(),
unlocks: serde_json::from_str(&unlocks).unwrap(), unlocks: serde_json::from_str(&unlocks).unwrap(),
aetherytes: serde_json::from_str(&aetherytes).unwrap(), aetherytes: serde_json::from_str(&aetherytes).unwrap(),
..Default::default() ..Default::default()
} };
dbg!(&data);
data
} }
/// Commit the dynamic player data back to the database /// Commit the dynamic player data back to the database
@ -350,7 +358,7 @@ impl WorldDatabase {
let connection = self.connection.lock().unwrap(); let connection = self.connection.lock().unwrap();
let mut stmt = connection let mut stmt = connection
.prepare("UPDATE character_data SET zone_id=?1, pos_x=?2, pos_y=?3, pos_z=?4, rotation=?5, inventory=?6, classjob_id=?7, classjob_levels=?8, unlocks=?9, aetherytes=?10 WHERE content_id = ?11") .prepare("UPDATE character_data SET zone_id=?1, pos_x=?2, pos_y=?3, pos_z=?4, rotation=?5, inventory=?6, classjob_id=?7, classjob_levels=?8, classjob_exp=?9, unlocks=?10, aetherytes=?11 WHERE content_id = ?12")
.unwrap(); .unwrap();
stmt.execute(( stmt.execute((
data.zone_id, data.zone_id,
@ -361,6 +369,7 @@ impl WorldDatabase {
serde_json::to_string(&data.inventory).unwrap(), serde_json::to_string(&data.inventory).unwrap(),
data.classjob_id, data.classjob_id,
serde_json::to_string(&data.classjob_levels).unwrap(), serde_json::to_string(&data.classjob_levels).unwrap(),
serde_json::to_string(&data.classjob_exp).unwrap(),
serde_json::to_string(&data.unlocks).unwrap(), serde_json::to_string(&data.unlocks).unwrap(),
serde_json::to_string(&data.aetherytes).unwrap(), serde_json::to_string(&data.aetherytes).unwrap(),
data.content_id, data.content_id,
@ -521,6 +530,8 @@ impl WorldDatabase {
let mut classjob_levels = [0i32; 32]; let mut classjob_levels = [0i32; 32];
classjob_levels[chara_make.classjob_id as usize] = 1; // inital level classjob_levels[chara_make.classjob_id as usize] = 1; // inital level
let classjob_exp = [0u32; 32];
// fill out initial unlocks // fill out initial unlocks
let unlocks = vec![0u8; UNLOCK_BITMASK_SIZE]; let unlocks = vec![0u8; UNLOCK_BITMASK_SIZE];
@ -538,7 +549,7 @@ impl WorldDatabase {
// insert char data // insert char data
connection connection
.execute( .execute(
"INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0, 0.0, ?6, 0, 90, ?7, ?8, ?9, ?10);", "INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0, 0.0, ?6, 0, 90, ?7, ?8, ?9, ?10, ?11);",
( (
content_id, content_id,
name, name,
@ -548,6 +559,7 @@ impl WorldDatabase {
serde_json::to_string(&inventory).unwrap(), serde_json::to_string(&inventory).unwrap(),
chara_make.classjob_id, chara_make.classjob_id,
serde_json::to_string(&classjob_levels).unwrap(), serde_json::to_string(&classjob_levels).unwrap(),
serde_json::to_string(&classjob_exp).unwrap(),
serde_json::to_string(&unlocks).unwrap(), serde_json::to_string(&unlocks).unwrap(),
serde_json::to_string(&aetherytes).unwrap(), serde_json::to_string(&aetherytes).unwrap(),
), ),