Added hash value to decide if we should invalidate persited skills and allow a respec.

This commit is contained in:
Sam 2021-11-14 13:32:37 -05:00
parent 6ab2839eaa
commit c8675eaf45
6 changed files with 100 additions and 22 deletions

48
Cargo.lock generated
View File

@ -428,6 +428,15 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array 0.14.4",
]
[[package]] [[package]]
name = "bstr" name = "bstr"
version = "0.2.17" version = "0.2.17"
@ -962,6 +971,15 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "cpufeatures"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "cranelift-bforest" name = "cranelift-bforest"
version = "0.74.0" version = "0.74.0"
@ -1381,6 +1399,15 @@ version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2c9736e15e7df1638a7f6eee92a6511615c738246a052af5ba86f039b65aede" checksum = "f2c9736e15e7df1638a7f6eee92a6511615c738246a052af5ba86f039b65aede"
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array 0.14.4",
]
[[package]] [[package]]
name = "directories-next" name = "directories-next"
version = "2.0.0" version = "2.0.0"
@ -3804,6 +3831,12 @@ version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
version = "0.1.4" version = "0.1.4"
@ -5122,6 +5155,19 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
[[package]]
name = "sha2"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa"
dependencies = [
"block-buffer",
"cfg-if 1.0.0",
"cpufeatures",
"digest",
"opaque-debug",
]
[[package]] [[package]]
name = "shaderc" name = "shaderc"
version = "0.6.3" version = "0.6.3"
@ -6145,6 +6191,7 @@ name = "veloren-common"
version = "0.10.0" version = "0.10.0"
dependencies = [ dependencies = [
"approx 0.4.0", "approx 0.4.0",
"bincode",
"bitflags", "bitflags",
"chrono", "chrono",
"chrono-tz", "chrono-tz",
@ -6170,6 +6217,7 @@ dependencies = [
"roots", "roots",
"serde", "serde",
"serde_repr", "serde_repr",
"sha2",
"slab", "slab",
"slotmap 1.0.6", "slotmap 1.0.6",
"specs", "specs",

View File

@ -29,6 +29,8 @@ enum-iterator = "0.7"
vek = { version = "=0.14.1", features = ["serde"] } vek = { version = "=0.14.1", features = ["serde"] }
chrono = "0.4" chrono = "0.4"
chrono-tz = "0.6" chrono-tz = "0.6"
sha2 = "0.9.8"
bincode = "1.3.1"
# Strum # Strum
strum = { version = "0.23", features = ["derive"] } strum = { version = "0.23", features = ["derive"] }

View File

@ -12,7 +12,7 @@ use std::{
time::Duration, time::Duration,
}; };
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
pub enum ToolKind { pub enum ToolKind {
// weapons // weapons
Sword, Sword,

View File

@ -5,18 +5,20 @@ use crate::{
skills::{GeneralSkill, Skill}, skills::{GeneralSkill, Skill},
}, },
}; };
use hashbrown::{HashMap, HashSet}; use bincode;
use hashbrown::HashMap;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use specs::{Component, DerefFlaggedStorage}; use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage; use specs_idvs::IdvStorage;
use std::hash::Hash; use std::{collections::BTreeSet, hash::Hash};
use tracing::{trace, warn}; use tracing::{trace, warn};
pub mod skills; pub mod skills;
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SkillTreeMap(HashMap<SkillGroupKind, HashSet<Skill>>); pub struct SkillTreeMap(HashMap<SkillGroupKind, BTreeSet<Skill>>);
impl Asset for SkillTreeMap { impl Asset for SkillTreeMap {
type Loader = assets::RonLoader; type Loader = assets::RonLoader;
@ -25,7 +27,7 @@ impl Asset for SkillTreeMap {
} }
pub struct SkillGroupDef { pub struct SkillGroupDef {
pub skills: HashSet<Skill>, pub skills: BTreeSet<Skill>,
pub total_skill_point_cost: u16, pub total_skill_point_cost: u16,
} }
@ -94,9 +96,24 @@ lazy_static! {
"common.skill_trees.skill_prerequisites", "common.skill_trees.skill_prerequisites",
).0 ).0
}; };
pub static ref SKILL_GROUP_HASHES: HashMap<SkillGroupKind, Vec<u8>> = {
let map = SkillTreeMap::load_expect_cloned(
"common.skill_trees.skills_skill-groups_manifest",
).0;
let mut hashes = HashMap::new();
for (skill_group_kind, skills) in map.iter() {
let mut hasher = Sha256::new();
let bincode_input: Vec<_> = skills.iter().map(|skill| (*skill, skill.max_level())).collect();
let hash_input = bincode::serialize(&bincode_input).unwrap_or_default();
hasher.update(hash_input);
let hash_result = hasher.finalize();
hashes.insert(*skill_group_kind, hash_result.iter().copied().collect());
}
hashes
};
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum SkillGroupKind { pub enum SkillGroupKind {
General, General,
Weapon(ToolKind), Weapon(ToolKind),

View File

@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
/// handled by dedicated ECS systems. /// handled by dedicated ECS systems.
// NOTE: if skill does use some constant, add it to corresponding // NOTE: if skill does use some constant, add it to corresponding
// SkillTree Modifiers below. // SkillTree Modifiers below.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum Skill { pub enum Skill {
General(GeneralSkill), General(GeneralSkill),
Sword(SwordSkill), Sword(SwordSkill),
@ -26,7 +26,7 @@ pub enum Skill {
UnlockGroup(SkillGroupKind), UnlockGroup(SkillGroupKind),
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum SwordSkill { pub enum SwordSkill {
// Sword passives // Sword passives
InterruptingAttacks, InterruptingAttacks,
@ -50,7 +50,7 @@ pub enum SwordSkill {
SSpins, SSpins,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum AxeSkill { pub enum AxeSkill {
// Double strike upgrades // Double strike upgrades
DsCombo, DsCombo,
@ -71,7 +71,7 @@ pub enum AxeSkill {
LDistance, LDistance,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum HammerSkill { pub enum HammerSkill {
// Single strike upgrades // Single strike upgrades
SsKnockback, SsKnockback,
@ -92,7 +92,7 @@ pub enum HammerSkill {
LRange, LRange,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum BowSkill { pub enum BowSkill {
// Passives // Passives
ProjSpeed, ProjSpeed,
@ -114,7 +114,7 @@ pub enum BowSkill {
SSpread, SSpread,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum StaffSkill { pub enum StaffSkill {
// Basic ranged upgrades // Basic ranged upgrades
BDamage, BDamage,
@ -133,7 +133,7 @@ pub enum StaffSkill {
SCost, SCost,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum SceptreSkill { pub enum SceptreSkill {
// Lifesteal beam upgrades // Lifesteal beam upgrades
LDamage, LDamage,
@ -153,31 +153,31 @@ pub enum SceptreSkill {
ACost, ACost,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum GeneralSkill { pub enum GeneralSkill {
HealthIncrease, HealthIncrease,
EnergyIncrease, EnergyIncrease,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum RollSkill { pub enum RollSkill {
Cost, Cost,
Strength, Strength,
Duration, Duration,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum ClimbSkill { pub enum ClimbSkill {
Cost, Cost,
Speed, Speed,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum SwimSkill { pub enum SwimSkill {
Speed, Speed,
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum MiningSkill { pub enum MiningSkill {
Speed, Speed,
OreGain, OreGain,

View File

@ -547,9 +547,17 @@ fn convert_skill_groups_from_database(
while new_skill_group.earn_skill_point().is_ok() {} while new_skill_group.earn_skill_point().is_ok() {}
new_skill_groups.push(new_skill_group); new_skill_groups.push(new_skill_group);
let mut new_skills = // If the hash stored of the skill group is the same as the current hash of the
serde_json::from_str::<Vec<skills::Skill>>(&skill_group.skills).unwrap_or_default(); // skill group, don't invalidate skills
skills.append(&mut new_skills); if serde_json::from_str::<Vec<u8>>(&skill_group.hash_val)
.ok()
.as_ref()
== skillset::SKILL_GROUP_HASHES.get(&skill_group_kind)
{
let mut new_skills =
serde_json::from_str::<Vec<skills::Skill>>(&skill_group.skills).unwrap_or_default();
skills.append(&mut new_skills);
}
} }
(new_skill_groups, skills) (new_skill_groups, skills)
} }
@ -566,7 +574,10 @@ pub fn convert_skill_groups_to_database(
earned_exp: sg.earned_exp as i32, earned_exp: sg.earned_exp as i32,
// If fails to convert, just forces a respec on next login // If fails to convert, just forces a respec on next login
skills: serde_json::to_string(&sg.ordered_skills).unwrap_or_else(|_| "".to_string()), skills: serde_json::to_string(&sg.ordered_skills).unwrap_or_else(|_| "".to_string()),
hash_val: "".to_string(), hash_val: serde_json::to_string(
&skillset::SKILL_GROUP_HASHES.get(&sg.skill_group_kind),
)
.unwrap_or_else(|_| "".to_string()),
}) })
.collect() .collect()
} }