mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added persistence for skill trees.
This commit is contained in:
parent
cc60ca58be
commit
69be3a3d93
@ -7,8 +7,8 @@ use common::{
|
|||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
span,
|
span,
|
||||||
};
|
};
|
||||||
|
use hashbrown::HashSet;
|
||||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
|
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
const ENERGY_REGEN_ACCEL: f32 = 10.0;
|
const ENERGY_REGEN_ACCEL: f32 = 10.0;
|
||||||
|
|
||||||
|
@ -28,9 +28,9 @@ use common_net::{
|
|||||||
};
|
};
|
||||||
use common_sys::state::BlockChange;
|
use common_sys::state::BlockChange;
|
||||||
use comp::item::Reagent;
|
use comp::item::Reagent;
|
||||||
|
use hashbrown::HashSet;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
|
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
|
||||||
use std::collections::HashSet;
|
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use vek::Vec3;
|
use vek::Vec3;
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ use crate::{
|
|||||||
convert_body_from_database, convert_body_to_database_json,
|
convert_body_from_database, convert_body_to_database_json,
|
||||||
convert_character_from_database, convert_inventory_from_database_items,
|
convert_character_from_database, convert_inventory_from_database_items,
|
||||||
convert_items_to_database_items, convert_loadout_from_database_items,
|
convert_items_to_database_items, convert_loadout_from_database_items,
|
||||||
|
convert_skill_groups_to_database, convert_skills_to_database,
|
||||||
convert_stats_from_database, convert_stats_to_database,
|
convert_stats_from_database, convert_stats_to_database,
|
||||||
convert_waypoint_from_database_json,
|
convert_waypoint_from_database_json,
|
||||||
},
|
},
|
||||||
@ -58,7 +59,9 @@ pub fn load_character_data(
|
|||||||
char_id: CharacterId,
|
char_id: CharacterId,
|
||||||
connection: VelorenTransaction,
|
connection: VelorenTransaction,
|
||||||
) -> CharacterDataResult {
|
) -> CharacterDataResult {
|
||||||
use schema::{body::dsl::*, character::dsl::*, item::dsl::*};
|
use schema::{
|
||||||
|
body::dsl::*, character::dsl::*, item::dsl::*, skill_group::dsl::*,
|
||||||
|
};
|
||||||
|
|
||||||
let character_containers = get_pseudo_containers(connection, char_id)?;
|
let character_containers = get_pseudo_containers(connection, char_id)?;
|
||||||
|
|
||||||
@ -100,9 +103,22 @@ pub fn load_character_data(
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let skill_data = schema::skill::dsl::skill
|
||||||
|
.filter(schema::skill::dsl::character_id.eq(char_id))
|
||||||
|
.load::<Skill>(&*connection)?;
|
||||||
|
|
||||||
|
let skill_group_data = skill_group
|
||||||
|
.filter(schema::skill_group::dsl::character_id.eq(char_id))
|
||||||
|
.load::<SkillGroup>(&*connection)?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
convert_body_from_database(&char_body)?,
|
convert_body_from_database(&char_body)?,
|
||||||
convert_stats_from_database(&stats_data, character_data.alias),
|
convert_stats_from_database(
|
||||||
|
&stats_data,
|
||||||
|
character_data.alias,
|
||||||
|
&skill_data,
|
||||||
|
&skill_group_data,
|
||||||
|
),
|
||||||
convert_inventory_from_database_items(&inventory_items, &loadout_items)?,
|
convert_inventory_from_database_items(&inventory_items, &loadout_items)?,
|
||||||
char_waypoint,
|
char_waypoint,
|
||||||
))
|
))
|
||||||
@ -172,7 +188,7 @@ pub fn create_character(
|
|||||||
|
|
||||||
check_character_limit(uuid, connection)?;
|
check_character_limit(uuid, connection)?;
|
||||||
|
|
||||||
use schema::{body, character};
|
use schema::{body, character, skill_group};
|
||||||
|
|
||||||
let (body, stats, inventory, waypoint) = persisted_components;
|
let (body, stats, inventory, waypoint) = persisted_components;
|
||||||
|
|
||||||
@ -218,6 +234,8 @@ pub fn create_character(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let skill_set = stats.skill_set.clone();
|
||||||
|
|
||||||
// Insert stats record
|
// Insert stats record
|
||||||
let db_stats = convert_stats_to_database(character_id, &stats, &waypoint)?;
|
let db_stats = convert_stats_to_database(character_id, &stats, &waypoint)?;
|
||||||
let stats_count = diesel::insert_into(schema::stats::table)
|
let stats_count = diesel::insert_into(schema::stats::table)
|
||||||
@ -266,6 +284,18 @@ pub fn create_character(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let db_skill_groups = convert_skill_groups_to_database(character_id, skill_set.skill_groups);
|
||||||
|
let skill_groups_count = diesel::insert_into(skill_group::table)
|
||||||
|
.values(&db_skill_groups)
|
||||||
|
.execute(&*connection)?;
|
||||||
|
|
||||||
|
if skill_groups_count != 1 {
|
||||||
|
return Err(Error::OtherError(format!(
|
||||||
|
"Error inserting into skill_group table for char_id {}",
|
||||||
|
character_id
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
// Insert default inventory and loadout item records
|
// Insert default inventory and loadout item records
|
||||||
let mut inserts = Vec::new();
|
let mut inserts = Vec::new();
|
||||||
|
|
||||||
@ -305,7 +335,9 @@ pub fn delete_character(
|
|||||||
char_id: CharacterId,
|
char_id: CharacterId,
|
||||||
connection: VelorenTransaction,
|
connection: VelorenTransaction,
|
||||||
) -> CharacterListResult {
|
) -> CharacterListResult {
|
||||||
use schema::{body::dsl::*, character::dsl::*, stats::dsl::*};
|
use schema::{
|
||||||
|
body::dsl::*, character::dsl::*, skill::dsl::*, skill_group::dsl::*, stats::dsl::*,
|
||||||
|
};
|
||||||
|
|
||||||
// Load the character to delete - ensures that the requesting player
|
// Load the character to delete - ensures that the requesting player
|
||||||
// owns the character
|
// owns the character
|
||||||
@ -317,6 +349,13 @@ pub fn delete_character(
|
|||||||
)
|
)
|
||||||
.first::<Character>(&*connection)?;
|
.first::<Character>(&*connection)?;
|
||||||
|
|
||||||
|
// Delete skills
|
||||||
|
diesel::delete(skill_group.filter(schema::skill_group::dsl::character_id.eq(char_id)))
|
||||||
|
.execute(&*connection)?;
|
||||||
|
|
||||||
|
diesel::delete(skill.filter(schema::skill::dsl::character_id.eq(char_id)))
|
||||||
|
.execute(&*connection)?;
|
||||||
|
|
||||||
// Delete character
|
// Delete character
|
||||||
let character_count = diesel::delete(
|
let character_count = diesel::delete(
|
||||||
character
|
character
|
||||||
@ -529,7 +568,7 @@ pub fn update(
|
|||||||
char_waypoint: Option<comp::Waypoint>,
|
char_waypoint: Option<comp::Waypoint>,
|
||||||
connection: VelorenTransaction,
|
connection: VelorenTransaction,
|
||||||
) -> Result<Vec<Arc<common::comp::item::ItemId>>, Error> {
|
) -> Result<Vec<Arc<common::comp::item::ItemId>>, Error> {
|
||||||
use super::schema::item::dsl::*;
|
use super::schema::{item::dsl::*, skill_group::dsl::*};
|
||||||
|
|
||||||
let pseudo_containers = get_pseudo_containers(connection, char_id)?;
|
let pseudo_containers = get_pseudo_containers(connection, char_id)?;
|
||||||
|
|
||||||
@ -591,6 +630,20 @@ pub fn update(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let char_skill_set = char_stats.skill_set.clone();
|
||||||
|
|
||||||
|
let db_skill_groups = convert_skill_groups_to_database(char_id, char_skill_set.skill_groups);
|
||||||
|
|
||||||
|
diesel::replace_into(skill_group)
|
||||||
|
.values(&db_skill_groups)
|
||||||
|
.execute(&*connection)?;
|
||||||
|
|
||||||
|
let db_skills = convert_skills_to_database(char_id, char_skill_set.skills);
|
||||||
|
|
||||||
|
diesel::replace_into(schema::skill::dsl::skill)
|
||||||
|
.values(&db_skills)
|
||||||
|
.execute(&*connection)?;
|
||||||
|
|
||||||
let db_stats = convert_stats_to_database(char_id, &char_stats, &char_waypoint)?;
|
let db_stats = convert_stats_to_database(char_id, &char_stats, &char_waypoint)?;
|
||||||
let stats_count =
|
let stats_count =
|
||||||
diesel::update(schema::stats::dsl::stats.filter(schema::stats::dsl::stats_id.eq(char_id)))
|
diesel::update(schema::stats::dsl::stats.filter(schema::stats::dsl::stats_id.eq(char_id)))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::persistence::{
|
use crate::persistence::{
|
||||||
character::EntityId,
|
character::EntityId,
|
||||||
models::{Body, Character, Item, Stats},
|
models::{Body, Character, Item, Skill, SkillGroup, Stats},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::persistence::{
|
use crate::persistence::{
|
||||||
@ -15,11 +15,13 @@ use common::{
|
|||||||
loadout_builder::LoadoutBuilder,
|
loadout_builder::LoadoutBuilder,
|
||||||
slot::InvSlotId,
|
slot::InvSlotId,
|
||||||
},
|
},
|
||||||
|
skills,
|
||||||
Body as CompBody, Waypoint, *,
|
Body as CompBody, Waypoint, *,
|
||||||
},
|
},
|
||||||
resources::Time,
|
resources::Time,
|
||||||
};
|
};
|
||||||
use core::{convert::TryFrom, num::NonZeroU64};
|
use core::{convert::TryFrom, num::NonZeroU64};
|
||||||
|
use hashbrown::HashMap;
|
||||||
use itertools::{Either, Itertools};
|
use itertools::{Either, Itertools};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -342,7 +344,12 @@ pub fn convert_character_from_database(character: &Character) -> common::charact
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_stats_from_database(stats: &Stats, alias: String) -> common::comp::Stats {
|
pub fn convert_stats_from_database(
|
||||||
|
stats: &Stats,
|
||||||
|
alias: String,
|
||||||
|
skills: &[Skill],
|
||||||
|
skill_groups: &[SkillGroup],
|
||||||
|
) -> common::comp::Stats {
|
||||||
let mut new_stats = common::comp::Stats::empty();
|
let mut new_stats = common::comp::Stats::empty();
|
||||||
new_stats.name = alias;
|
new_stats.name = alias;
|
||||||
new_stats.level.set_level(stats.level as u32);
|
new_stats.level.set_level(stats.level as u32);
|
||||||
@ -356,6 +363,10 @@ pub fn convert_stats_from_database(stats: &Stats, alias: String) -> common::comp
|
|||||||
new_stats.endurance = stats.endurance as u32;
|
new_stats.endurance = stats.endurance as u32;
|
||||||
new_stats.fitness = stats.fitness as u32;
|
new_stats.fitness = stats.fitness as u32;
|
||||||
new_stats.willpower = stats.willpower as u32;
|
new_stats.willpower = stats.willpower as u32;
|
||||||
|
new_stats.skill_set = skills::SkillSet {
|
||||||
|
skill_groups: convert_skill_groups_from_database(skill_groups),
|
||||||
|
skills: convert_skills_from_database(skills),
|
||||||
|
};
|
||||||
|
|
||||||
new_stats
|
new_stats
|
||||||
}
|
}
|
||||||
@ -369,3 +380,72 @@ fn get_item_from_asset(item_definition_id: &str) -> Result<common::comp::Item, E
|
|||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_skill_groups_from_database(skill_groups: &[SkillGroup]) -> Vec<skills::SkillGroup> {
|
||||||
|
let mut new_skill_groups = Vec::new();
|
||||||
|
for skill_group in skill_groups.iter() {
|
||||||
|
let skill_group_type =
|
||||||
|
serde_json::de::from_str::<skills::SkillGroupType>(&skill_group.skill_group_type)
|
||||||
|
.map_err(|err| {
|
||||||
|
Error::ConversionError(format!(
|
||||||
|
"Error de-serializing skill group: {} err: {}",
|
||||||
|
skill_group.skill_group_type, err
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let new_skill_group = skills::SkillGroup {
|
||||||
|
skill_group_type,
|
||||||
|
exp: skill_group.exp as u16,
|
||||||
|
available_sp: skill_group.available_sp as u16,
|
||||||
|
};
|
||||||
|
new_skill_groups.push(new_skill_group);
|
||||||
|
}
|
||||||
|
new_skill_groups
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_skills_from_database(skills: &[Skill]) -> HashMap<skills::Skill, skills::Level> {
|
||||||
|
let mut new_skills = HashMap::new();
|
||||||
|
for skill in skills.iter() {
|
||||||
|
let new_skill = serde_json::de::from_str::<skills::Skill>(&skill.skill_type)
|
||||||
|
.map_err(|err| {
|
||||||
|
Error::ConversionError(format!(
|
||||||
|
"Error de-serializing skill: {} err: {}",
|
||||||
|
skill.skill_type, err
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
new_skills.insert(new_skill, skill.level.map(|l| l as u16));
|
||||||
|
}
|
||||||
|
new_skills
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_skill_groups_to_database(
|
||||||
|
character_id: CharacterId,
|
||||||
|
skill_groups: Vec<skills::SkillGroup>,
|
||||||
|
) -> Vec<SkillGroup> {
|
||||||
|
let db_skill_groups: Vec<_> = skill_groups
|
||||||
|
.into_iter()
|
||||||
|
.map(|sg| SkillGroup {
|
||||||
|
character_id,
|
||||||
|
skill_group_type: serde_json::to_string(&sg.skill_group_type).unwrap(),
|
||||||
|
exp: sg.exp as i32,
|
||||||
|
available_sp: sg.available_sp as i32,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
db_skill_groups
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_skills_to_database(
|
||||||
|
character_id: CharacterId,
|
||||||
|
skills: HashMap<skills::Skill, skills::Level>,
|
||||||
|
) -> Vec<Skill> {
|
||||||
|
let db_skills: Vec<_> = skills
|
||||||
|
.iter()
|
||||||
|
.map(|(s, l)| Skill {
|
||||||
|
character_id,
|
||||||
|
skill_type: serde_json::to_string(&s).unwrap(),
|
||||||
|
level: l.map(|l| l as i32),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
db_skills
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
use super::schema::{body, character, entity, item, stats};
|
use super::schema::{body, character, entity, item, skill, skill_group, stats};
|
||||||
|
|
||||||
#[derive(Debug, Insertable, PartialEq)]
|
#[derive(Debug, Insertable, PartialEq)]
|
||||||
#[table_name = "entity"]
|
#[table_name = "entity"]
|
||||||
@ -57,3 +57,22 @@ pub struct Body {
|
|||||||
pub variant: String,
|
pub variant: String,
|
||||||
pub body_data: String,
|
pub body_data: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Associations, Identifiable, Insertable, Queryable, Debug)]
|
||||||
|
#[primary_key(character_id, skill_type)]
|
||||||
|
#[table_name = "skill"]
|
||||||
|
pub struct Skill {
|
||||||
|
pub character_id: i64,
|
||||||
|
pub skill_type: String,
|
||||||
|
pub level: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Associations, Identifiable, Insertable, Queryable, Debug)]
|
||||||
|
#[primary_key(character_id, skill_group_type)]
|
||||||
|
#[table_name = "skill_group"]
|
||||||
|
pub struct SkillGroup {
|
||||||
|
pub character_id: i64,
|
||||||
|
pub skill_group_type: String,
|
||||||
|
pub exp: i32,
|
||||||
|
pub available_sp: i32,
|
||||||
|
}
|
||||||
|
@ -42,6 +42,24 @@ table! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
skill (character_id, skill_type) {
|
||||||
|
character_id -> BigInt,
|
||||||
|
#[sql_name = "skill"]
|
||||||
|
skill_type -> Text,
|
||||||
|
level -> Nullable<Integer>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
skill_group (character_id, skill_group_type) {
|
||||||
|
character_id -> BigInt,
|
||||||
|
skill_group_type -> Text,
|
||||||
|
exp -> Integer,
|
||||||
|
available_sp -> Integer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
joinable!(character -> body (character_id));
|
joinable!(character -> body (character_id));
|
||||||
joinable!(character -> stats (character_id));
|
joinable!(character -> stats (character_id));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user