mirror of
https://github.com/redstrate/Kawari.git
synced 2025-06-30 11:47:45 +00:00
Make the current classjob persistent, and your levels too
This requires another database wipe, or if you're savvy enough a few schema edits.
This commit is contained in:
parent
a24e0a5658
commit
2a1491c8f9
3 changed files with 63 additions and 29 deletions
|
@ -587,7 +587,7 @@ async fn client_loop(
|
|||
|
||||
match &command {
|
||||
GameMasterCommandType::SetLevel => {
|
||||
connection.player_data.level = *arg0 as u8;
|
||||
connection.player_data.set_current_level(*arg0 as i32);
|
||||
connection.update_class_info().await;
|
||||
}
|
||||
GameMasterCommandType::ChangeWeather => {
|
||||
|
|
|
@ -46,7 +46,7 @@ pub struct PlayerData {
|
|||
pub account_id: u32,
|
||||
|
||||
pub classjob_id: u8,
|
||||
pub level: u8,
|
||||
pub classjob_levels: [i32; 32],
|
||||
pub curr_hp: u32,
|
||||
pub max_hp: u32,
|
||||
pub curr_mp: u16,
|
||||
|
@ -64,6 +64,16 @@ pub struct PlayerData {
|
|||
pub gm_invisible: bool,
|
||||
}
|
||||
|
||||
impl PlayerData {
|
||||
pub fn current_level(&self) -> i32 {
|
||||
self.classjob_levels[self.classjob_id as usize]
|
||||
}
|
||||
|
||||
pub fn set_current_level(&mut self, level: i32) {
|
||||
self.classjob_levels[self.classjob_id as usize] = level;
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a single connection between an instance of the client and the world server
|
||||
pub struct ZoneConnection {
|
||||
pub config: WorldConfig,
|
||||
|
@ -137,8 +147,6 @@ impl ZoneConnection {
|
|||
|
||||
pub async fn initialize(&mut self, actor_id: u32) {
|
||||
// some still hardcoded values
|
||||
self.player_data.classjob_id = 1;
|
||||
self.player_data.level = 5;
|
||||
self.player_data.curr_hp = 100;
|
||||
self.player_data.max_hp = 100;
|
||||
self.player_data.curr_mp = 10000;
|
||||
|
@ -282,8 +290,8 @@ impl ZoneConnection {
|
|||
data: ServerZoneIpcData::UpdateClassInfo(UpdateClassInfo {
|
||||
class_id: self.player_data.classjob_id as u16,
|
||||
unknown: 1,
|
||||
synced_level: self.player_data.level as u16,
|
||||
class_level: self.player_data.level as u16,
|
||||
synced_level: self.player_data.current_level() as u16,
|
||||
class_level: self.player_data.current_level() as u16,
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
|
@ -658,7 +666,7 @@ impl ZoneConnection {
|
|||
data: ServerZoneIpcData::StatusEffectList(StatusEffectList {
|
||||
statues: list,
|
||||
classjob_id: self.player_data.classjob_id,
|
||||
level: self.player_data.level,
|
||||
level: self.player_data.current_level() as u8,
|
||||
curr_hp: self.player_data.curr_hp,
|
||||
max_hp: self.player_data.max_hp,
|
||||
curr_mp: self.player_data.curr_mp,
|
||||
|
@ -779,7 +787,7 @@ impl ZoneConnection {
|
|||
hp_max: self.player_data.max_hp,
|
||||
mp_curr: self.player_data.curr_mp,
|
||||
mp_max: self.player_data.max_mp,
|
||||
level: self.player_data.level,
|
||||
level: self.player_data.current_level() as u8,
|
||||
object_kind: ObjectKind::Player(PlayerSubKind::Player),
|
||||
look: chara_details.chara_make.customize,
|
||||
display_flags: DisplayFlag::UNK,
|
||||
|
|
|
@ -47,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, gm_rank 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, classjob_id INTEGER, classjob_levels STRING);";
|
||||
connection.execute(query, ()).unwrap();
|
||||
}
|
||||
|
||||
|
@ -142,17 +142,19 @@ impl WorldDatabase {
|
|||
.unwrap();
|
||||
|
||||
stmt = connection
|
||||
.prepare("SELECT pos_x, pos_y, pos_z, rotation, zone_id, inventory, gm_rank 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 FROM character_data WHERE content_id = ?1")
|
||||
.unwrap();
|
||||
let (pos_x, pos_y, pos_z, rotation, zone_id, inventory_json, gm_rank): (
|
||||
f32,
|
||||
f32,
|
||||
f32,
|
||||
f32,
|
||||
u16,
|
||||
String,
|
||||
u8,
|
||||
) = stmt
|
||||
let (
|
||||
pos_x,
|
||||
pos_y,
|
||||
pos_z,
|
||||
rotation,
|
||||
zone_id,
|
||||
inventory_json,
|
||||
gm_rank,
|
||||
classjob_id,
|
||||
classjob_levels,
|
||||
): (f32, f32, f32, f32, u16, String, u8, i32, String) = stmt
|
||||
.query_row((content_id,), |row| {
|
||||
Ok((
|
||||
row.get(0)?,
|
||||
|
@ -162,6 +164,8 @@ impl WorldDatabase {
|
|||
row.get(4)?,
|
||||
row.get(5)?,
|
||||
row.get(6)?,
|
||||
row.get(7)?,
|
||||
row.get(8)?,
|
||||
))
|
||||
})
|
||||
.unwrap();
|
||||
|
@ -181,6 +185,8 @@ impl WorldDatabase {
|
|||
zone_id,
|
||||
inventory,
|
||||
gm_rank: GameMasterRank::try_from(gm_rank).unwrap(),
|
||||
classjob_id: classjob_id as u8,
|
||||
classjob_levels: serde_json::from_str(&classjob_levels).unwrap(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +196,7 @@ impl WorldDatabase {
|
|||
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, inventory=?6 WHERE content_id = ?7")
|
||||
.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 WHERE content_id = ?9")
|
||||
.unwrap();
|
||||
stmt.execute((
|
||||
data.zone_id,
|
||||
|
@ -199,6 +205,8 @@ impl WorldDatabase {
|
|||
data.position.z,
|
||||
data.rotation,
|
||||
serde_json::to_string(&data.inventory).unwrap(),
|
||||
data.classjob_id,
|
||||
serde_json::to_string(&data.classjob_levels).unwrap(),
|
||||
data.content_id,
|
||||
))
|
||||
.unwrap();
|
||||
|
@ -247,30 +255,41 @@ impl WorldDatabase {
|
|||
for (index, (content_id, actor_id)) in content_actor_ids.iter().enumerate() {
|
||||
let mut stmt = connection
|
||||
.prepare(
|
||||
"SELECT name, chara_make, zone_id, inventory, remake_mode FROM character_data WHERE content_id = ?1",
|
||||
"SELECT name, chara_make, zone_id, inventory, remake_mode, classjob_id, classjob_levels FROM character_data WHERE content_id = ?1",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let result: Result<(String, String, u16, String, i32), rusqlite::Error> = stmt
|
||||
.query_row((content_id,), |row| {
|
||||
let result: Result<(String, String, u16, String, i32, i32, String), rusqlite::Error> =
|
||||
stmt.query_row((content_id,), |row| {
|
||||
Ok((
|
||||
row.get(0)?,
|
||||
row.get(1)?,
|
||||
row.get(2)?,
|
||||
row.get(3)?,
|
||||
row.get(4)?,
|
||||
row.get(5)?,
|
||||
row.get(6)?,
|
||||
))
|
||||
});
|
||||
|
||||
if let Ok((name, chara_make, zone_id, inventory_json, remake_mode)) = result {
|
||||
if let Ok((
|
||||
name,
|
||||
chara_make,
|
||||
zone_id,
|
||||
inventory_json,
|
||||
remake_mode,
|
||||
classjob_id,
|
||||
classjob_levels,
|
||||
)) = result
|
||||
{
|
||||
let chara_make = CharaMake::from_json(&chara_make);
|
||||
|
||||
let inventory: Inventory = serde_json::from_str(&inventory_json).unwrap();
|
||||
|
||||
let select_data = ClientSelectData {
|
||||
character_name: name.clone(),
|
||||
current_class: 2,
|
||||
class_levels: [5; 32],
|
||||
current_class: classjob_id,
|
||||
class_levels: serde_json::from_str(&classjob_levels).unwrap(),
|
||||
race: chara_make.customize.race as i32,
|
||||
subrace: chara_make.customize.subrace as i32,
|
||||
gender: chara_make.customize.gender as i32,
|
||||
|
@ -331,7 +350,7 @@ impl WorldDatabase {
|
|||
&self,
|
||||
service_account_id: u32,
|
||||
name: &str,
|
||||
chara_make: &str,
|
||||
chara_make_str: &str,
|
||||
city_state: u8,
|
||||
zone_id: u16,
|
||||
inventory: Inventory,
|
||||
|
@ -341,6 +360,11 @@ impl WorldDatabase {
|
|||
|
||||
let connection = self.connection.lock().unwrap();
|
||||
|
||||
// fill out the initial classjob
|
||||
let chara_make = CharaMake::from_json(chara_make_str);
|
||||
let mut classjob_levels = [0i32; 32];
|
||||
classjob_levels[chara_make.classjob_id as usize] = 1; // inital level
|
||||
|
||||
// insert ids
|
||||
connection
|
||||
.execute(
|
||||
|
@ -352,14 +376,16 @@ 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, 90);",
|
||||
"INSERT INTO character_data VALUES (?1, ?2, ?3, ?4, ?5, 0.0, 0.0, 0.0, 0.0, ?6, 0, 90, ?7, ?8);",
|
||||
(
|
||||
content_id,
|
||||
name,
|
||||
chara_make,
|
||||
chara_make_str,
|
||||
city_state,
|
||||
zone_id,
|
||||
serde_json::to_string(&inventory).unwrap(),
|
||||
chara_make.classjob_id,
|
||||
serde_json::to_string(&classjob_levels).unwrap(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
|
Loading…
Add table
Reference in a new issue