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,
|
||||
span,
|
||||
};
|
||||
use hashbrown::HashSet;
|
||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
|
||||
use std::collections::HashSet;
|
||||
|
||||
const ENERGY_REGEN_ACCEL: f32 = 10.0;
|
||||
|
||||
|
@ -28,9 +28,9 @@ use common_net::{
|
||||
};
|
||||
use common_sys::state::BlockChange;
|
||||
use comp::item::Reagent;
|
||||
use hashbrown::HashSet;
|
||||
use rand::prelude::*;
|
||||
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
|
||||
use std::collections::HashSet;
|
||||
use tracing::error;
|
||||
use vek::Vec3;
|
||||
|
||||
|
@ -15,6 +15,7 @@ use crate::{
|
||||
convert_body_from_database, convert_body_to_database_json,
|
||||
convert_character_from_database, convert_inventory_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_waypoint_from_database_json,
|
||||
},
|
||||
@ -58,7 +59,9 @@ pub fn load_character_data(
|
||||
char_id: CharacterId,
|
||||
connection: VelorenTransaction,
|
||||
) -> 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)?;
|
||||
|
||||
@ -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((
|
||||
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)?,
|
||||
char_waypoint,
|
||||
))
|
||||
@ -172,7 +188,7 @@ pub fn create_character(
|
||||
|
||||
check_character_limit(uuid, connection)?;
|
||||
|
||||
use schema::{body, character};
|
||||
use schema::{body, character, skill_group};
|
||||
|
||||
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
|
||||
let db_stats = convert_stats_to_database(character_id, &stats, &waypoint)?;
|
||||
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
|
||||
let mut inserts = Vec::new();
|
||||
|
||||
@ -305,7 +335,9 @@ pub fn delete_character(
|
||||
char_id: CharacterId,
|
||||
connection: VelorenTransaction,
|
||||
) -> 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
|
||||
// owns the character
|
||||
@ -317,6 +349,13 @@ pub fn delete_character(
|
||||
)
|
||||
.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
|
||||
let character_count = diesel::delete(
|
||||
character
|
||||
@ -529,7 +568,7 @@ pub fn update(
|
||||
char_waypoint: Option<comp::Waypoint>,
|
||||
connection: VelorenTransaction,
|
||||
) -> 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)?;
|
||||
|
||||
@ -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 stats_count =
|
||||
diesel::update(schema::stats::dsl::stats.filter(schema::stats::dsl::stats_id.eq(char_id)))
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::persistence::{
|
||||
character::EntityId,
|
||||
models::{Body, Character, Item, Stats},
|
||||
models::{Body, Character, Item, Skill, SkillGroup, Stats},
|
||||
};
|
||||
|
||||
use crate::persistence::{
|
||||
@ -15,11 +15,13 @@ use common::{
|
||||
loadout_builder::LoadoutBuilder,
|
||||
slot::InvSlotId,
|
||||
},
|
||||
skills,
|
||||
Body as CompBody, Waypoint, *,
|
||||
},
|
||||
resources::Time,
|
||||
};
|
||||
use core::{convert::TryFrom, num::NonZeroU64};
|
||||
use hashbrown::HashMap;
|
||||
use itertools::{Either, Itertools};
|
||||
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();
|
||||
new_stats.name = alias;
|
||||
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.fitness = stats.fitness 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
|
||||
}
|
||||
@ -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;
|
||||
|
||||
use super::schema::{body, character, entity, item, stats};
|
||||
use super::schema::{body, character, entity, item, skill, skill_group, stats};
|
||||
|
||||
#[derive(Debug, Insertable, PartialEq)]
|
||||
#[table_name = "entity"]
|
||||
@ -57,3 +57,22 @@ pub struct Body {
|
||||
pub variant: 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 -> stats (character_id));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user