mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Changed component recipe book to generate some stuff automatically to avoid potential for stuff inside to become unsynced (no assets).
This commit is contained in:
parent
49ff094286
commit
37442b638c
@ -965,11 +965,7 @@ impl Item {
|
|||||||
pub fn ability_spec(&self) -> Option<Cow<AbilitySpec>> {
|
pub fn ability_spec(&self) -> Option<Cow<AbilitySpec>> {
|
||||||
match &self.item_base {
|
match &self.item_base {
|
||||||
ItemBase::Raw(item_def) => {
|
ItemBase::Raw(item_def) => {
|
||||||
item_def
|
item_def.ability_spec.as_ref().map(Cow::Borrowed).or({
|
||||||
.ability_spec
|
|
||||||
.as_ref()
|
|
||||||
.map(Cow::Borrowed)
|
|
||||||
.or_else(|| {
|
|
||||||
// If no custom ability set is specified, fall back to abilityset of tool
|
// If no custom ability set is specified, fall back to abilityset of tool
|
||||||
// kind.
|
// kind.
|
||||||
if let ItemKind::Tool(tool) = &item_def.kind {
|
if let ItemKind::Tool(tool) = &item_def.kind {
|
||||||
|
@ -812,11 +812,12 @@ mod tests {
|
|||||||
assert!((lootsum2 - 1.0).abs() < 1e-4);
|
assert!((lootsum2 - 1.0).abs() < 1e-4);
|
||||||
|
|
||||||
// highly nested
|
// highly nested
|
||||||
// let loot3 = expand_loot_table("common.loot_tables.creature.biped_large.wendigo");
|
|
||||||
// let lootsum3 = loot3.iter().fold(0.0, |s, i| s + i.0);
|
|
||||||
// TODO: Re-enable this. See note at top of test (though this specific
|
// TODO: Re-enable this. See note at top of test (though this specific
|
||||||
// table can also be fixed by properly integrating modular weapons into
|
// table can also be fixed by properly integrating modular weapons into
|
||||||
// probability files)
|
// probability files)
|
||||||
|
// let loot3 =
|
||||||
|
// expand_loot_table("common.loot_tables.creature.biped_large.wendigo");
|
||||||
|
// let lootsum3 = loot3.iter().fold(0.0, |s, i| s + i.0);
|
||||||
// assert!((lootsum3 - 1.0).abs() < 1e-5);
|
// assert!((lootsum3 - 1.0).abs() < 1e-5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,6 +372,25 @@ pub enum RawRecipeInput {
|
|||||||
ListSameItem(String),
|
ListSameItem(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RawRecipeInput {
|
||||||
|
fn load_recipe_input(&self) -> Result<RecipeInput, assets::Error> {
|
||||||
|
let input = match self {
|
||||||
|
RawRecipeInput::Item(name) => RecipeInput::Item(Arc::<ItemDef>::load_cloned(name)?),
|
||||||
|
RawRecipeInput::Tag(tag) => RecipeInput::Tag(*tag),
|
||||||
|
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)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Ok(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
pub(crate) struct RawRecipe {
|
pub(crate) struct RawRecipe {
|
||||||
pub(crate) output: (String, u32),
|
pub(crate) output: (String, u32),
|
||||||
@ -392,7 +411,7 @@ impl assets::Asset for RawRecipeBook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct ItemList(Vec<String>);
|
struct ItemList(Vec<String>);
|
||||||
|
|
||||||
impl assets::Asset for ItemList {
|
impl assets::Asset for ItemList {
|
||||||
type Loader = assets::RonLoader;
|
type Loader = assets::RonLoader;
|
||||||
@ -415,19 +434,7 @@ impl assets::Compound for RecipeBook {
|
|||||||
fn load_recipe_input(
|
fn load_recipe_input(
|
||||||
(input, amount, is_mod_comp): &(RawRecipeInput, u32, bool),
|
(input, amount, is_mod_comp): &(RawRecipeInput, u32, bool),
|
||||||
) -> Result<(RecipeInput, u32, bool), assets::Error> {
|
) -> Result<(RecipeInput, u32, bool), assets::Error> {
|
||||||
let def = match &input {
|
let def = input.load_recipe_input()?;
|
||||||
RawRecipeInput::Item(name) => RecipeInput::Item(Arc::<ItemDef>::load_cloned(name)?),
|
|
||||||
RawRecipeInput::Tag(tag) => RecipeInput::Tag(*tag),
|
|
||||||
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)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Ok((def, *amount, *is_mod_comp))
|
Ok((def, *amount, *is_mod_comp))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +485,7 @@ impl ComponentRecipeBook {
|
|||||||
|
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
struct RawComponentRecipeBook(HashMap<ComponentKey, RawComponentRecipe>);
|
struct RawComponentRecipeBook(Vec<RawComponentRecipe>);
|
||||||
|
|
||||||
impl assets::Asset for RawComponentRecipeBook {
|
impl assets::Asset for RawComponentRecipeBook {
|
||||||
type Loader = assets::RonLoader;
|
type Loader = assets::RonLoader;
|
||||||
@ -494,7 +501,7 @@ pub struct ComponentKey {
|
|||||||
pub toolkind: ToolKind,
|
pub toolkind: ToolKind,
|
||||||
/// Refers to the item definition id of the material
|
/// Refers to the item definition id of the material
|
||||||
pub material: String,
|
pub material: String,
|
||||||
/// Refers to the item definition id of the material
|
/// Refers to the item definition id of the modifier
|
||||||
pub modifier: Option<String>,
|
pub modifier: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,10 +678,6 @@ impl ComponentRecipe {
|
|||||||
|
|
||||||
pub fn inputs(&self) -> impl ExactSizeIterator<Item = (&RecipeInput, u32)> {
|
pub fn inputs(&self) -> impl ExactSizeIterator<Item = (&RecipeInput, u32)> {
|
||||||
pub struct ComponentRecipeInputsIterator<'a> {
|
pub struct ComponentRecipeInputsIterator<'a> {
|
||||||
// material: bool,
|
|
||||||
// modifier: bool,
|
|
||||||
// index: usize,
|
|
||||||
// recipe: &'a ComponentRecipe,
|
|
||||||
material: Option<&'a (RecipeInput, u32)>,
|
material: Option<&'a (RecipeInput, u32)>,
|
||||||
modifier: Option<&'a (RecipeInput, u32)>,
|
modifier: Option<&'a (RecipeInput, u32)>,
|
||||||
additional_inputs: std::slice::Iter<'a, (RecipeInput, u32)>,
|
additional_inputs: std::slice::Iter<'a, (RecipeInput, u32)>,
|
||||||
@ -684,21 +687,6 @@ impl ComponentRecipe {
|
|||||||
type Item = &'a (RecipeInput, u32);
|
type Item = &'a (RecipeInput, u32);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<&'a (RecipeInput, u32)> {
|
fn next(&mut self) -> Option<&'a (RecipeInput, u32)> {
|
||||||
// if !self.material {
|
|
||||||
// self.material = true;
|
|
||||||
// Some(&self.recipe.material)
|
|
||||||
// } else if !self.modifier {
|
|
||||||
// self.modifier = true;
|
|
||||||
// if self.recipe.modifier.is_some() {
|
|
||||||
// self.recipe.modifier.as_ref()
|
|
||||||
// } else {
|
|
||||||
// self.index += 1;
|
|
||||||
// self.recipe.additional_inputs.get(self.index - 1)
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// self.index += 1;
|
|
||||||
// self.recipe.additional_inputs.get(self.index - 1)
|
|
||||||
// }
|
|
||||||
self.material
|
self.material
|
||||||
.take()
|
.take()
|
||||||
.or_else(|| self.modifier.take())
|
.or_else(|| self.modifier.take())
|
||||||
@ -712,10 +700,6 @@ impl ComponentRecipe {
|
|||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
ComponentRecipeInputsIterator {
|
ComponentRecipeInputsIterator {
|
||||||
// material: false,
|
|
||||||
// modifier: false,
|
|
||||||
// index: 0,
|
|
||||||
// recipe: self,
|
|
||||||
material: Some(&self.material),
|
material: Some(&self.material),
|
||||||
modifier: self.modifier.as_ref(),
|
modifier: self.modifier.as_ref(),
|
||||||
additional_inputs: self.additional_inputs.as_slice().iter(),
|
additional_inputs: self.additional_inputs.as_slice().iter(),
|
||||||
@ -725,8 +709,6 @@ impl ComponentRecipe {
|
|||||||
|
|
||||||
impl<'a> ExactSizeIterator for ComponentRecipeInputsIterator<'a> {
|
impl<'a> ExactSizeIterator for ComponentRecipeInputsIterator<'a> {
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
// 1 + self.recipe.modifier.is_some() as usize +
|
|
||||||
// self.recipe.additional_inputs.len()
|
|
||||||
self.material.is_some() as usize
|
self.material.is_some() as usize
|
||||||
+ self.modifier.is_some() as usize
|
+ self.modifier.is_some() as usize
|
||||||
+ self.additional_inputs.len()
|
+ self.additional_inputs.len()
|
||||||
@ -740,8 +722,10 @@ impl ComponentRecipe {
|
|||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
struct RawComponentRecipe {
|
struct RawComponentRecipe {
|
||||||
output: RawComponentOutput,
|
output: RawComponentOutput,
|
||||||
material: (RawRecipeInput, u32),
|
/// String refers to an item definition id
|
||||||
modifier: Option<(RawRecipeInput, u32)>,
|
material: (String, u32),
|
||||||
|
/// String refers to an item definition id
|
||||||
|
modifier: Option<(String, u32)>,
|
||||||
additional_inputs: Vec<(RawRecipeInput, u32)>,
|
additional_inputs: Vec<(RawRecipeInput, u32)>,
|
||||||
craft_sprite: Option<SpriteKind>,
|
craft_sprite: Option<SpriteKind>,
|
||||||
}
|
}
|
||||||
@ -756,10 +740,9 @@ enum ComponentOutput {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
enum RawComponentOutput {
|
enum RawComponentOutput {
|
||||||
ItemComponents {
|
/// Creates the primary component of a modular tool. Assumes that the
|
||||||
item: String,
|
/// material used is the only component in the item.
|
||||||
components: Vec<String>,
|
ToolPrimaryComponent { toolkind: ToolKind, item: String },
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for ComponentRecipeBook {
|
impl assets::Compound for ComponentRecipeBook {
|
||||||
@ -768,42 +751,54 @@ impl assets::Compound for ComponentRecipeBook {
|
|||||||
specifier: &str,
|
specifier: &str,
|
||||||
) -> Result<Self, assets::BoxedError> {
|
) -> Result<Self, assets::BoxedError> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn load_recipe_input(
|
fn load_recipe_key(raw_recipe: &RawComponentRecipe) -> ComponentKey {
|
||||||
(input, amount): &(RawRecipeInput, u32),
|
match &raw_recipe.output {
|
||||||
) -> Result<(RecipeInput, u32), assets::Error> {
|
RawComponentOutput::ToolPrimaryComponent { toolkind, item: _ } => {
|
||||||
let def = match &input {
|
let material = String::from(&raw_recipe.material.0);
|
||||||
RawRecipeInput::Item(name) => RecipeInput::Item(Arc::<ItemDef>::load_cloned(name)?),
|
let modifier = raw_recipe
|
||||||
RawRecipeInput::Tag(tag) => RecipeInput::Tag(*tag),
|
.modifier
|
||||||
RawRecipeInput::TagSameItem(tag) => RecipeInput::TagSameItem(*tag),
|
.as_ref()
|
||||||
RawRecipeInput::ListSameItem(list) => {
|
.map(|(modifier, _amount)| String::from(modifier));
|
||||||
let assets = &ItemList::load_expect(list).read().0;
|
ComponentKey {
|
||||||
let items = assets
|
toolkind: *toolkind,
|
||||||
.iter()
|
material,
|
||||||
.map(|asset| Arc::<ItemDef>::load_expect_cloned(asset))
|
modifier,
|
||||||
.collect();
|
}
|
||||||
RecipeInput::ListSameItem(items)
|
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
Ok((def, *amount))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn load_recipe_output(
|
fn load_recipe(raw_recipe: &RawComponentRecipe) -> Result<ComponentRecipe, assets::Error> {
|
||||||
output: &RawComponentOutput,
|
let output = match &raw_recipe.output {
|
||||||
) -> Result<ComponentOutput, assets::Error> {
|
RawComponentOutput::ToolPrimaryComponent { toolkind: _, item } => {
|
||||||
let def = match &output {
|
let item = Arc::<ItemDef>::load_cloned(item)?;
|
||||||
RawComponentOutput::ItemComponents {
|
let components = vec![Arc::<ItemDef>::load_cloned(&raw_recipe.material.0)?];
|
||||||
item: def,
|
ComponentOutput::ItemComponents { item, components }
|
||||||
components: defs,
|
|
||||||
} => ComponentOutput::ItemComponents {
|
|
||||||
item: Arc::<ItemDef>::load_cloned(def)?,
|
|
||||||
components: defs
|
|
||||||
.iter()
|
|
||||||
.map(|def| Arc::<ItemDef>::load_cloned(def))
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Ok(def)
|
let material = (
|
||||||
|
RecipeInput::Item(Arc::<ItemDef>::load_cloned(&raw_recipe.material.0)?),
|
||||||
|
raw_recipe.material.1,
|
||||||
|
);
|
||||||
|
let modifier = if let Some((modifier, amount)) = &raw_recipe.modifier {
|
||||||
|
let modifier = Arc::<ItemDef>::load_cloned(modifier)?;
|
||||||
|
Some((RecipeInput::Item(modifier), *amount))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let additional_inputs = raw_recipe
|
||||||
|
.additional_inputs
|
||||||
|
.iter()
|
||||||
|
.map(|(input, amount)| input.load_recipe_input().map(|input| (input, *amount)))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
Ok(ComponentRecipe {
|
||||||
|
output,
|
||||||
|
material,
|
||||||
|
modifier,
|
||||||
|
additional_inputs,
|
||||||
|
craft_sprite: raw_recipe.craft_sprite,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let raw = cache.load::<RawComponentRecipeBook>(specifier)?.cloned();
|
let raw = cache.load::<RawComponentRecipeBook>(specifier)?.cloned();
|
||||||
@ -811,33 +806,9 @@ impl assets::Compound for ComponentRecipeBook {
|
|||||||
let recipes = raw
|
let recipes = raw
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.map(
|
.map(|raw_recipe| {
|
||||||
|(
|
load_recipe(raw_recipe).map(|recipe| (load_recipe_key(raw_recipe), recipe))
|
||||||
key,
|
})
|
||||||
RawComponentRecipe {
|
|
||||||
output,
|
|
||||||
material,
|
|
||||||
modifier,
|
|
||||||
additional_inputs,
|
|
||||||
craft_sprite,
|
|
||||||
},
|
|
||||||
)| {
|
|
||||||
let additional_inputs = additional_inputs
|
|
||||||
.iter()
|
|
||||||
.map(load_recipe_input)
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
|
||||||
let material = load_recipe_input(material)?;
|
|
||||||
let modifier = modifier.as_ref().map(load_recipe_input).transpose()?;
|
|
||||||
let output = load_recipe_output(output)?;
|
|
||||||
Ok((key.clone(), ComponentRecipe {
|
|
||||||
output,
|
|
||||||
material,
|
|
||||||
modifier,
|
|
||||||
additional_inputs,
|
|
||||||
craft_sprite: *craft_sprite,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.collect::<Result<_, assets::Error>>()?;
|
.collect::<Result<_, assets::Error>>()?;
|
||||||
|
|
||||||
Ok(ComponentRecipeBook { recipes })
|
Ok(ComponentRecipeBook { recipes })
|
||||||
|
@ -1940,8 +1940,8 @@ where
|
|||||||
if target_inventory.free_slots() < count {
|
if target_inventory.free_slots() < count {
|
||||||
return Err("Inventory doesn't have enough slots".to_owned());
|
return Err("Inventory doesn't have enough slots".to_owned());
|
||||||
}
|
}
|
||||||
for (item_id, quantity) in kit {
|
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
|
for (item_id, quantity) in kit {
|
||||||
let mut item = match &item_id {
|
let mut item = match &item_id {
|
||||||
KitSpec::Item(item_id) => comp::Item::new_from_asset(item_id)
|
KitSpec::Item(item_id) => comp::Item::new_from_asset(item_id)
|
||||||
.map_err(|_| format!("Unknown item: {:#?}", item_id))?,
|
.map_err(|_| format!("Unknown item: {:#?}", item_id))?,
|
||||||
|
@ -882,13 +882,3 @@ FROM item_graph
|
|||||||
WHERE parent_pseudo_id IS NOT NULL;
|
WHERE parent_pseudo_id IS NOT NULL;
|
||||||
|
|
||||||
PRAGMA defer_foreign_keys = false;
|
PRAGMA defer_foreign_keys = false;
|
||||||
|
|
||||||
SELECT i.item_id,
|
|
||||||
i.item_id,
|
|
||||||
i.parent_container_item_id,
|
|
||||||
t.new_item_definition_id,
|
|
||||||
t.pseudo_id,
|
|
||||||
parent_pseudo_id
|
|
||||||
FROM _temp_modular_component_items t
|
|
||||||
JOIN item i ON (i.item_definition_id = t.new_item_definition_id)
|
|
||||||
WHERE t.parent_pseudo_id IS NULL;
|
|
@ -511,6 +511,9 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
let metal_comp_recipe = make_psuedo_recipe(SpriteKind::Anvil);
|
let metal_comp_recipe = make_psuedo_recipe(SpriteKind::Anvil);
|
||||||
let wood_comp_recipe = make_psuedo_recipe(SpriteKind::CraftingBench);
|
let wood_comp_recipe = make_psuedo_recipe(SpriteKind::CraftingBench);
|
||||||
let modular_entries = {
|
let modular_entries = {
|
||||||
|
// A BTreeMap is used over a HashMap as when a HashMap is used, the UI shuffles
|
||||||
|
// the positions of these every tick, so a BTreeMap is necessary to keep it
|
||||||
|
// ordered.
|
||||||
let mut modular_entries = BTreeMap::new();
|
let mut modular_entries = BTreeMap::new();
|
||||||
modular_entries.insert(
|
modular_entries.insert(
|
||||||
String::from("veloren.core.pseudo_recipe.modular_weapon"),
|
String::from("veloren.core.pseudo_recipe.modular_weapon"),
|
||||||
@ -1288,7 +1291,8 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
.mid_bottom_with_margin_on(state.ids.align_ing, -31.0)
|
.mid_bottom_with_margin_on(state.ids.align_ing, -31.0)
|
||||||
.parent(state.ids.window_frame)
|
.parent(state.ids.window_frame)
|
||||||
.set(state.ids.btn_craft, ui)
|
.set(state.ids.btn_craft, ui)
|
||||||
.was_clicked() && can_perform
|
.was_clicked()
|
||||||
|
&& can_perform
|
||||||
{
|
{
|
||||||
match recipe_kind {
|
match recipe_kind {
|
||||||
RecipeKind::ModularWeapon => {
|
RecipeKind::ModularWeapon => {
|
||||||
@ -1501,7 +1505,7 @@ impl<'a> Widget for Crafting<'a> {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.or_else(|| tag.exemplar_identifier())
|
.or_else(|| tag.exemplar_identifier())
|
||||||
.unwrap_or_else(|| "common.items.weapons.empty.empty"),
|
.unwrap_or("common.items.weapons.empty.empty"),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
RecipeInput::ListSameItem(item_defs) => Arc::<ItemDef>::load_expect_cloned(
|
RecipeInput::ListSameItem(item_defs) => Arc::<ItemDef>::load_expect_cloned(
|
||||||
|
Loading…
Reference in New Issue
Block a user