mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Items with components can now have their name modified by the components. Also addressed more review. NO ASSETS
This commit is contained in:
parent
524845b661
commit
81c83c5e83
@ -50,6 +50,7 @@ impl<T: ItemDesc> From<&T> for ItemKey {
|
||||
}
|
||||
},
|
||||
ModularComponent::ToolSecondaryComponent { .. } => {
|
||||
// TODO: Maybe use a different ItemKey?
|
||||
ItemKey::Tool(item_definition_id.to_owned())
|
||||
},
|
||||
}
|
||||
|
@ -219,7 +219,6 @@ impl TagExampleInfo for Material {
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ItemTag {
|
||||
Leather,
|
||||
Material(Material),
|
||||
MaterialKind(MaterialKind),
|
||||
Cultist,
|
||||
@ -237,7 +236,6 @@ impl TagExampleInfo for ItemTag {
|
||||
match self {
|
||||
ItemTag::Material(material) => material.name(),
|
||||
ItemTag::MaterialKind(material_kind) => material_kind.into(),
|
||||
ItemTag::Leather => "leather",
|
||||
ItemTag::Cultist => "cultist",
|
||||
ItemTag::Potion => "potion",
|
||||
ItemTag::Food => "food",
|
||||
@ -254,7 +252,6 @@ impl TagExampleInfo for ItemTag {
|
||||
match self {
|
||||
ItemTag::Material(_) => "common.items.tag_examples.placeholder",
|
||||
ItemTag::MaterialKind(_) => "common.items.tag_examples.placeholder",
|
||||
ItemTag::Leather => "common.items.tag_examples.leather",
|
||||
ItemTag::Cultist => "common.items.tag_examples.cultist",
|
||||
ItemTag::Potion => "common.items.tag_examples.placeholder",
|
||||
ItemTag::Food => "common.items.tag_examples.placeholder",
|
||||
@ -715,8 +712,8 @@ impl Item {
|
||||
ItemBase::Raw(Arc::<ItemDef>::load_cloned(asset)?)
|
||||
};
|
||||
// TODO: Get msm and ability_map less hackily
|
||||
let msm = MaterialStatManifest::default();
|
||||
let ability_map = AbilityMap::default();
|
||||
let msm = MaterialStatManifest::load().read();
|
||||
let ability_map = AbilityMap::load().read();
|
||||
Ok(Item::new_from_item_base(
|
||||
inner_item,
|
||||
Vec::new(),
|
||||
@ -862,15 +859,15 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn matches_recipe_input(&self, recipe_input: &RecipeInput) -> bool {
|
||||
pub fn matches_recipe_input(&self, recipe_input: &RecipeInput, amount: u32) -> bool {
|
||||
match recipe_input {
|
||||
RecipeInput::Item(item_def) => self.is_same_item_def(item_def),
|
||||
RecipeInput::Tag(tag) => self.tags().contains(tag),
|
||||
RecipeInput::TagSameItem(tag, amount) => {
|
||||
self.tags().contains(tag) && u32::from(self.amount) >= *amount
|
||||
RecipeInput::TagSameItem(tag) => {
|
||||
self.tags().contains(tag) && u32::from(self.amount) >= amount
|
||||
},
|
||||
RecipeInput::ListSameItem(item_defs, amount) => item_defs.iter().any(|item_def| {
|
||||
self.is_same_item_def(item_def) && u32::from(self.amount) >= *amount
|
||||
RecipeInput::ListSameItem(item_defs) => item_defs.iter().any(|item_def| {
|
||||
self.is_same_item_def(item_def) && u32::from(self.amount) >= amount
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -893,7 +890,13 @@ impl Item {
|
||||
|
||||
pub fn name(&self) -> Cow<str> {
|
||||
match &self.item_base {
|
||||
ItemBase::Raw(item_def) => Cow::Borrowed(&item_def.name),
|
||||
ItemBase::Raw(item_def) => {
|
||||
if self.components.is_empty() {
|
||||
Cow::Borrowed(&item_def.name)
|
||||
} else {
|
||||
modular::modify_name(&item_def.name, self)
|
||||
}
|
||||
},
|
||||
ItemBase::Modular(mod_base) => mod_base.generate_name(self.components()),
|
||||
}
|
||||
}
|
||||
@ -911,7 +914,7 @@ impl Item {
|
||||
ItemBase::Raw(item_def) => Cow::Borrowed(&item_def.kind),
|
||||
ItemBase::Modular(mod_base) => {
|
||||
// TODO: Try to move further upward
|
||||
let msm = MaterialStatManifest::default();
|
||||
let msm = MaterialStatManifest::load().read();
|
||||
|
||||
mod_base.kind(self.components(), &msm)
|
||||
},
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{
|
||||
tool::{self, AbilitySpec, Hands, MaterialStatManifest},
|
||||
tool::{self, AbilityMap, AbilitySpec, Hands, MaterialStatManifest},
|
||||
Item, ItemBase, ItemDef, ItemDesc, ItemKind, Material, Quality, ToolKind,
|
||||
};
|
||||
use crate::{assets::AssetExt, recipe};
|
||||
@ -287,8 +287,8 @@ pub fn random_weapon(
|
||||
) -> Result<Item, ModularWeaponCreationError> {
|
||||
if let Some(material_id) = material.asset_identifier() {
|
||||
// Loads default ability map and material stat manifest for later use
|
||||
let ability_map = Default::default();
|
||||
let msm = Default::default();
|
||||
let ability_map = AbilityMap::load().read();
|
||||
let msm = MaterialStatManifest::load().read();
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
@ -351,6 +351,25 @@ pub fn random_weapon(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_name<'a>(item_name: &'a str, item: &'a Item) -> Cow<'a, str> {
|
||||
if let ItemKind::ModularComponent(_) = &*item.kind() {
|
||||
if let Some(material_name) = item
|
||||
.components()
|
||||
.iter()
|
||||
.find_map(|comp| match &*comp.kind() {
|
||||
ItemKind::Ingredient { descriptor, .. } => Some(descriptor.to_owned()),
|
||||
_ => None,
|
||||
})
|
||||
{
|
||||
Cow::Owned(format!("{} {}", material_name, item_name))
|
||||
} else {
|
||||
Cow::Borrowed(item_name)
|
||||
}
|
||||
} else {
|
||||
Cow::Borrowed(item_name)
|
||||
}
|
||||
}
|
||||
|
||||
/// This is used as a key to uniquely identify the modular weapon in asset
|
||||
/// manifests in voxygen (Main component, material, hands)
|
||||
pub type ModularWeaponKey = (String, String, Hands);
|
||||
|
@ -2,7 +2,7 @@
|
||||
// version in voxygen\src\meta.rs in order to reset save files to being empty
|
||||
|
||||
use crate::{
|
||||
assets::{self, Asset, AssetExt},
|
||||
assets::{self, Asset, AssetExt, AssetHandle},
|
||||
comp::{skills::Skill, CharacterAbility},
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
@ -217,6 +217,10 @@ impl DivAssign<usize> for Stats {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct MaterialStatManifest(pub HashMap<String, Stats>);
|
||||
|
||||
impl MaterialStatManifest {
|
||||
pub fn load() -> AssetHandle<Self> { Self::load_expect("common.material_stats_manifest") }
|
||||
}
|
||||
|
||||
// This could be a Compound that also loads the keys, but the RecipeBook
|
||||
// Compound impl already does that, so checking for existence here is redundant.
|
||||
impl Asset for MaterialStatManifest {
|
||||
@ -225,13 +229,6 @@ impl Asset for MaterialStatManifest {
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
impl Default for MaterialStatManifest {
|
||||
fn default() -> MaterialStatManifest {
|
||||
// TODO: Don't do this, loading a default should have no ability to panic
|
||||
MaterialStatManifest::load_expect_cloned("common.material_stats_manifest")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Tool {
|
||||
pub kind: ToolKind,
|
||||
@ -348,16 +345,9 @@ pub struct AbilityItem {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AbilityMap<T = AbilityItem>(HashMap<AbilitySpec, AbilitySet<T>>);
|
||||
|
||||
impl Default for AbilityMap {
|
||||
fn default() -> Self {
|
||||
// TODO: Revert to old default
|
||||
if let Ok(map) = Self::load_cloned("common.abilities.ability_set_manifest") {
|
||||
map
|
||||
} else {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(AbilitySpec::Tool(ToolKind::Empty), AbilitySet::default());
|
||||
AbilityMap(map)
|
||||
}
|
||||
impl AbilityMap {
|
||||
pub fn load() -> AssetHandle<Self> {
|
||||
Self::load_expect("common.abilities.ability_set_manifest")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,13 +22,19 @@ pub enum RecipeInput {
|
||||
/// Similar to RecipeInput::Tag(_), but all items must be the same.
|
||||
/// Specifically this means that a mix of different items with the tag
|
||||
/// cannot be used.
|
||||
TagSameItem(ItemTag, u32),
|
||||
/// TODO: Currently requires that all items must be in the same slot.
|
||||
/// Eventually should be reworked so that items can be spread over multiple
|
||||
/// slots.
|
||||
TagSameItem(ItemTag),
|
||||
/// List is similar to tag, but has items defined in centralized file
|
||||
/// Similar to RecipeInput::TagSameItem(_), all items must be the same, they
|
||||
/// cannot be a mix of different items defined in the list.
|
||||
// Intent of using List over Tag is to make it harder for tag to be innocuously added to an
|
||||
// item breaking a recipe
|
||||
ListSameItem(Vec<Arc<ItemDef>>, u32),
|
||||
/// TODO: Currently requires that all items must be in the same slot.
|
||||
/// Eventually should be reworked so that items can be spread over multiple
|
||||
/// slots.
|
||||
ListSameItem(Vec<Arc<ItemDef>>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@ -62,7 +68,8 @@ impl Recipe {
|
||||
self.inputs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(i, (input, mut required, mut is_component))| {
|
||||
.for_each(|(i, (input, amount, mut is_component))| {
|
||||
let mut required = *amount;
|
||||
// Check used for recipes that have an input that is not consumed, e.g.
|
||||
// craftsman hammer
|
||||
let mut contains_any = false;
|
||||
@ -75,7 +82,7 @@ impl Recipe {
|
||||
// Checks that the item in the slot can be used for the input
|
||||
if let Some(item) = inv
|
||||
.get(*slot)
|
||||
.filter(|item| item.matches_recipe_input(input))
|
||||
.filter(|item| item.matches_recipe_input(input, *amount))
|
||||
{
|
||||
// Gets the number of items claimed from the slot, or sets to 0 if slot has
|
||||
// not been claimed by another input yet
|
||||
@ -165,14 +172,15 @@ impl Recipe {
|
||||
// The inputs to a recipe that have missing items, and the amount missing
|
||||
let mut missing = Vec::<(&RecipeInput, u32)>::new();
|
||||
|
||||
for (i, (input, mut needed, _)) in self.inputs().enumerate() {
|
||||
for (i, (input, amount, _)) in self.inputs().enumerate() {
|
||||
let mut needed = amount;
|
||||
let mut contains_any = false;
|
||||
// Checks through every slot, filtering to only those that contain items that
|
||||
// can satisfy the input
|
||||
for (inv_slot_id, slot) in inv.slots_with_id() {
|
||||
if let Some(item) = slot
|
||||
.as_ref()
|
||||
.filter(|item| item.matches_recipe_input(&*input))
|
||||
.filter(|item| item.matches_recipe_input(&*input, amount))
|
||||
{
|
||||
let claim = slot_claims.entry(inv_slot_id).or_insert(0);
|
||||
slots.push((i as u32, inv_slot_id));
|
||||
@ -390,14 +398,14 @@ impl assets::Compound for RecipeBook {
|
||||
let def = match &input {
|
||||
RawRecipeInput::Item(name) => RecipeInput::Item(Arc::<ItemDef>::load_cloned(name)?),
|
||||
RawRecipeInput::Tag(tag) => RecipeInput::Tag(*tag),
|
||||
RawRecipeInput::TagSameItem(tag) => RecipeInput::TagSameItem(*tag, *amount),
|
||||
RawRecipeInput::TagSameItem(tag) => RecipeInput::TagSameItem(*tag),
|
||||
RawRecipeInput::ListSameItem(list) => {
|
||||
let assets = &ItemList::load_expect(list).read().0;
|
||||
let items = assets
|
||||
.iter()
|
||||
.map(|asset| Arc::<ItemDef>::load_expect_cloned(asset))
|
||||
.collect();
|
||||
RecipeInput::ListSameItem(items, *amount)
|
||||
RecipeInput::ListSameItem(items)
|
||||
},
|
||||
};
|
||||
Ok((def, *amount, *is_mod_comp))
|
||||
|
@ -43,7 +43,7 @@ pub struct ReadData<'a> {
|
||||
stats: ReadStorage<'a, Stats>,
|
||||
skill_sets: ReadStorage<'a, SkillSet>,
|
||||
active_abilities: ReadStorage<'a, ActiveAbilities>,
|
||||
msm: Read<'a, MaterialStatManifest>,
|
||||
msm: ReadExpect<'a, MaterialStatManifest>,
|
||||
combos: ReadStorage<'a, Combo>,
|
||||
alignments: ReadStorage<'a, comp::Alignment>,
|
||||
terrain: ReadExpect<'a, TerrainGrid>,
|
||||
|
@ -73,7 +73,7 @@ use common::{
|
||||
calendar::Calendar,
|
||||
character::CharacterId,
|
||||
cmd::ChatCommand,
|
||||
comp::{self, item::MaterialStatManifest},
|
||||
comp,
|
||||
event::{EventBus, ServerEvent},
|
||||
recipe::default_recipe_book,
|
||||
resources::{BattleMode, Time, TimeOfDay},
|
||||
@ -310,7 +310,7 @@ impl Server {
|
||||
);
|
||||
state.ecs_mut().insert(ability_map);
|
||||
|
||||
let msm = comp::inventory::item::MaterialStatManifest::default();
|
||||
let msm = comp::inventory::item::MaterialStatManifest::load().cloned();
|
||||
state.ecs_mut().insert(msm);
|
||||
|
||||
state.ecs_mut().insert(CharacterLoader::new(
|
||||
@ -1087,7 +1087,11 @@ impl Server {
|
||||
client_timeout: self.settings().client_timeout,
|
||||
world_map: self.map.clone(),
|
||||
recipe_book: default_recipe_book().cloned(),
|
||||
material_stats: MaterialStatManifest::default(),
|
||||
material_stats: (&*self
|
||||
.state
|
||||
.ecs()
|
||||
.read_resource::<comp::item::tool::MaterialStatManifest>())
|
||||
.clone(),
|
||||
ability_map: (&*self
|
||||
.state
|
||||
.ecs()
|
||||
|
@ -36,8 +36,9 @@ pub struct ItemModelPair {
|
||||
// shouldn't matter unless someone's hot-reloading material stats on the live
|
||||
// server
|
||||
lazy_static! {
|
||||
pub static ref MATERIAL_STATS_MANIFEST: MaterialStatManifest = MaterialStatManifest::default();
|
||||
pub static ref ABILITY_MAP: AbilityMap = AbilityMap::default();
|
||||
pub static ref MATERIAL_STATS_MANIFEST: MaterialStatManifest =
|
||||
MaterialStatManifest::load().cloned();
|
||||
pub static ref ABILITY_MAP: AbilityMap = AbilityMap::load().cloned();
|
||||
}
|
||||
|
||||
/// Returns a vector that contains all item rows to upsert; parent is
|
||||
|
@ -198,12 +198,10 @@ impl CraftingTab {
|
||||
},
|
||||
CraftingTab::Glider => matches!(&*item.kind(), ItemKind::Glider(_)),
|
||||
CraftingTab::Potion => item.tags().contains(&ItemTag::Potion),
|
||||
CraftingTab::ProcessedMaterial => item.tags().iter().any(|tag| {
|
||||
matches!(
|
||||
tag,
|
||||
&ItemTag::MaterialKind(_) | &ItemTag::Leather | &ItemTag::BaseMaterial
|
||||
)
|
||||
}),
|
||||
CraftingTab::ProcessedMaterial => item
|
||||
.tags()
|
||||
.iter()
|
||||
.any(|tag| matches!(tag, &ItemTag::MaterialKind(_) | &ItemTag::BaseMaterial)),
|
||||
CraftingTab::Bag => item.tags().contains(&ItemTag::Bag),
|
||||
CraftingTab::Tool => item.tags().contains(&ItemTag::CraftingTool),
|
||||
CraftingTab::Utility => item.tags().contains(&ItemTag::Utility),
|
||||
@ -469,10 +467,10 @@ impl<'a> Widget for Crafting<'a> {
|
||||
let input_name = match input {
|
||||
RecipeInput::Item(def) => def.name(),
|
||||
RecipeInput::Tag(tag) => Cow::Borrowed(tag.name()),
|
||||
RecipeInput::TagSameItem(tag, _) => Cow::Borrowed(tag.name()),
|
||||
RecipeInput::TagSameItem(tag) => Cow::Borrowed(tag.name()),
|
||||
// Works, but probably will have some...interesting false positives
|
||||
// Code reviewers probably required to do magic to make not hacky
|
||||
RecipeInput::ListSameItem(defs, _) => {
|
||||
RecipeInput::ListSameItem(defs) => {
|
||||
Cow::Owned(defs.iter().map(|def| def.name()).collect())
|
||||
},
|
||||
}
|
||||
@ -914,13 +912,13 @@ impl<'a> Widget for Crafting<'a> {
|
||||
for (i, (recipe_input, amount, _)) in recipe.inputs.iter().enumerate() {
|
||||
let item_def = match recipe_input {
|
||||
RecipeInput::Item(item_def) => Arc::clone(item_def),
|
||||
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag, _) => {
|
||||
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag) => {
|
||||
Arc::<ItemDef>::load_expect_cloned(
|
||||
self.inventory
|
||||
.slots()
|
||||
.find_map(|slot| {
|
||||
slot.as_ref().and_then(|item| {
|
||||
if item.matches_recipe_input(recipe_input) {
|
||||
if item.matches_recipe_input(recipe_input, *amount) {
|
||||
Some(item.item_definition_id())
|
||||
} else {
|
||||
None
|
||||
@ -930,12 +928,12 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.unwrap_or_else(|| tag.exemplar_identifier()),
|
||||
)
|
||||
},
|
||||
RecipeInput::ListSameItem(item_defs, _) => Arc::<ItemDef>::load_expect_cloned(
|
||||
RecipeInput::ListSameItem(item_defs) => Arc::<ItemDef>::load_expect_cloned(
|
||||
self.inventory
|
||||
.slots()
|
||||
.find_map(|slot| {
|
||||
slot.as_ref().and_then(|item| {
|
||||
if item.matches_recipe_input(recipe_input) {
|
||||
if item.matches_recipe_input(recipe_input, *amount) {
|
||||
Some(item.item_definition_id())
|
||||
} else {
|
||||
None
|
||||
@ -1047,10 +1045,10 @@ impl<'a> Widget for Crafting<'a> {
|
||||
// Ingredients
|
||||
let name = match recipe_input {
|
||||
RecipeInput::Item(_) => item_def.name().to_string(),
|
||||
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag, _) => {
|
||||
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag) => {
|
||||
format!("Any {} item", tag.name())
|
||||
},
|
||||
RecipeInput::ListSameItem(item_defs, _) => {
|
||||
RecipeInput::ListSameItem(item_defs) => {
|
||||
format!(
|
||||
"Any of {}",
|
||||
item_defs.iter().map(|def| def.name()).collect::<String>()
|
||||
|
Loading…
Reference in New Issue
Block a user