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 {
|
match &command {
|
||||||
GameMasterCommandType::SetLevel => {
|
GameMasterCommandType::SetLevel => {
|
||||||
connection.player_data.level = *arg0 as u8;
|
connection.player_data.set_current_level(*arg0 as i32);
|
||||||
connection.update_class_info().await;
|
connection.update_class_info().await;
|
||||||
}
|
}
|
||||||
GameMasterCommandType::ChangeWeather => {
|
GameMasterCommandType::ChangeWeather => {
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub struct PlayerData {
|
||||||
pub account_id: u32,
|
pub account_id: u32,
|
||||||
|
|
||||||
pub classjob_id: u8,
|
pub classjob_id: u8,
|
||||||
pub level: u8,
|
pub classjob_levels: [i32; 32],
|
||||||
pub curr_hp: u32,
|
pub curr_hp: u32,
|
||||||
pub max_hp: u32,
|
pub max_hp: u32,
|
||||||
pub curr_mp: u16,
|
pub curr_mp: u16,
|
||||||
|
@ -64,6 +64,16 @@ pub struct PlayerData {
|
||||||
pub gm_invisible: bool,
|
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
|
/// Represents a single connection between an instance of the client and the world server
|
||||||
pub struct ZoneConnection {
|
pub struct ZoneConnection {
|
||||||
pub config: WorldConfig,
|
pub config: WorldConfig,
|
||||||
|
@ -137,8 +147,6 @@ impl ZoneConnection {
|
||||||
|
|
||||||
pub async fn initialize(&mut self, actor_id: u32) {
|
pub async fn initialize(&mut self, actor_id: u32) {
|
||||||
// some still hardcoded values
|
// some still hardcoded values
|
||||||
self.player_data.classjob_id = 1;
|
|
||||||
self.player_data.level = 5;
|
|
||||||
self.player_data.curr_hp = 100;
|
self.player_data.curr_hp = 100;
|
||||||
self.player_data.max_hp = 100;
|
self.player_data.max_hp = 100;
|
||||||
self.player_data.curr_mp = 10000;
|
self.player_data.curr_mp = 10000;
|
||||||
|
@ -282,8 +290,8 @@ impl ZoneConnection {
|
||||||
data: ServerZoneIpcData::UpdateClassInfo(UpdateClassInfo {
|
data: ServerZoneIpcData::UpdateClassInfo(UpdateClassInfo {
|
||||||
class_id: self.player_data.classjob_id as u16,
|
class_id: self.player_data.classjob_id as u16,
|
||||||
unknown: 1,
|
unknown: 1,
|
||||||
synced_level: self.player_data.level as u16,
|
synced_level: self.player_data.current_level() as u16,
|
||||||
class_level: self.player_data.level as u16,
|
class_level: self.player_data.current_level() as u16,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -658,7 +666,7 @@ impl ZoneConnection {
|
||||||
data: ServerZoneIpcData::StatusEffectList(StatusEffectList {
|
data: ServerZoneIpcData::StatusEffectList(StatusEffectList {
|
||||||
statues: list,
|
statues: list,
|
||||||
classjob_id: self.player_data.classjob_id,
|
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,
|
curr_hp: self.player_data.curr_hp,
|
||||||
max_hp: self.player_data.max_hp,
|
max_hp: self.player_data.max_hp,
|
||||||
curr_mp: self.player_data.curr_mp,
|
curr_mp: self.player_data.curr_mp,
|
||||||
|
@ -779,7 +787,7 @@ impl ZoneConnection {
|
||||||
hp_max: self.player_data.max_hp,
|
hp_max: self.player_data.max_hp,
|
||||||
mp_curr: self.player_data.curr_mp,
|
mp_curr: self.player_data.curr_mp,
|
||||||
mp_max: self.player_data.max_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),
|
object_kind: ObjectKind::Player(PlayerSubKind::Player),
|
||||||
look: chara_details.chara_make.customize,
|
look: chara_details.chara_make.customize,
|
||||||
display_flags: DisplayFlag::UNK,
|
display_flags: DisplayFlag::UNK,
|
||||||
|
|
|
@ -47,7 +47,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);";
|
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();
|
connection.execute(query, ()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,17 +142,19 @@ impl WorldDatabase {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
stmt = connection
|
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();
|
.unwrap();
|
||||||
let (pos_x, pos_y, pos_z, rotation, zone_id, inventory_json, gm_rank): (
|
let (
|
||||||
f32,
|
pos_x,
|
||||||
f32,
|
pos_y,
|
||||||
f32,
|
pos_z,
|
||||||
f32,
|
rotation,
|
||||||
u16,
|
zone_id,
|
||||||
String,
|
inventory_json,
|
||||||
u8,
|
gm_rank,
|
||||||
) = stmt
|
classjob_id,
|
||||||
|
classjob_levels,
|
||||||
|
): (f32, f32, f32, f32, u16, String, u8, i32, String) = stmt
|
||||||
.query_row((content_id,), |row| {
|
.query_row((content_id,), |row| {
|
||||||
Ok((
|
Ok((
|
||||||
row.get(0)?,
|
row.get(0)?,
|
||||||
|
@ -162,6 +164,8 @@ impl WorldDatabase {
|
||||||
row.get(4)?,
|
row.get(4)?,
|
||||||
row.get(5)?,
|
row.get(5)?,
|
||||||
row.get(6)?,
|
row.get(6)?,
|
||||||
|
row.get(7)?,
|
||||||
|
row.get(8)?,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -181,6 +185,8 @@ impl WorldDatabase {
|
||||||
zone_id,
|
zone_id,
|
||||||
inventory,
|
inventory,
|
||||||
gm_rank: GameMasterRank::try_from(gm_rank).unwrap(),
|
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()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +196,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 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();
|
.unwrap();
|
||||||
stmt.execute((
|
stmt.execute((
|
||||||
data.zone_id,
|
data.zone_id,
|
||||||
|
@ -199,6 +205,8 @@ impl WorldDatabase {
|
||||||
data.position.z,
|
data.position.z,
|
||||||
data.rotation,
|
data.rotation,
|
||||||
serde_json::to_string(&data.inventory).unwrap(),
|
serde_json::to_string(&data.inventory).unwrap(),
|
||||||
|
data.classjob_id,
|
||||||
|
serde_json::to_string(&data.classjob_levels).unwrap(),
|
||||||
data.content_id,
|
data.content_id,
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -247,30 +255,41 @@ impl WorldDatabase {
|
||||||
for (index, (content_id, actor_id)) in content_actor_ids.iter().enumerate() {
|
for (index, (content_id, actor_id)) in content_actor_ids.iter().enumerate() {
|
||||||
let mut stmt = connection
|
let mut stmt = connection
|
||||||
.prepare(
|
.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();
|
.unwrap();
|
||||||
|
|
||||||
let result: Result<(String, String, u16, String, i32), rusqlite::Error> = stmt
|
let result: Result<(String, String, u16, String, i32, i32, String), rusqlite::Error> =
|
||||||
.query_row((content_id,), |row| {
|
stmt.query_row((content_id,), |row| {
|
||||||
Ok((
|
Ok((
|
||||||
row.get(0)?,
|
row.get(0)?,
|
||||||
row.get(1)?,
|
row.get(1)?,
|
||||||
row.get(2)?,
|
row.get(2)?,
|
||||||
row.get(3)?,
|
row.get(3)?,
|
||||||
row.get(4)?,
|
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 chara_make = CharaMake::from_json(&chara_make);
|
||||||
|
|
||||||
let inventory: Inventory = serde_json::from_str(&inventory_json).unwrap();
|
let inventory: Inventory = serde_json::from_str(&inventory_json).unwrap();
|
||||||
|
|
||||||
let select_data = ClientSelectData {
|
let select_data = ClientSelectData {
|
||||||
character_name: name.clone(),
|
character_name: name.clone(),
|
||||||
current_class: 2,
|
current_class: classjob_id,
|
||||||
class_levels: [5; 32],
|
class_levels: serde_json::from_str(&classjob_levels).unwrap(),
|
||||||
race: chara_make.customize.race as i32,
|
race: chara_make.customize.race as i32,
|
||||||
subrace: chara_make.customize.subrace as i32,
|
subrace: chara_make.customize.subrace as i32,
|
||||||
gender: chara_make.customize.gender as i32,
|
gender: chara_make.customize.gender as i32,
|
||||||
|
@ -331,7 +350,7 @@ impl WorldDatabase {
|
||||||
&self,
|
&self,
|
||||||
service_account_id: u32,
|
service_account_id: u32,
|
||||||
name: &str,
|
name: &str,
|
||||||
chara_make: &str,
|
chara_make_str: &str,
|
||||||
city_state: u8,
|
city_state: u8,
|
||||||
zone_id: u16,
|
zone_id: u16,
|
||||||
inventory: Inventory,
|
inventory: Inventory,
|
||||||
|
@ -341,6 +360,11 @@ impl WorldDatabase {
|
||||||
|
|
||||||
let connection = self.connection.lock().unwrap();
|
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
|
// insert ids
|
||||||
connection
|
connection
|
||||||
.execute(
|
.execute(
|
||||||
|
@ -352,14 +376,16 @@ 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);",
|
"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,
|
content_id,
|
||||||
name,
|
name,
|
||||||
chara_make,
|
chara_make_str,
|
||||||
city_state,
|
city_state,
|
||||||
zone_id,
|
zone_id,
|
||||||
serde_json::to_string(&inventory).unwrap(),
|
serde_json::to_string(&inventory).unwrap(),
|
||||||
|
chara_make.classjob_id,
|
||||||
|
serde_json::to_string(&classjob_levels).unwrap(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Add table
Reference in a new issue