From b605048ae3f8b3b49e63fb6a9256ecd28b2c108d Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 17 Apr 2021 15:58:43 +0100 Subject: [PATCH 01/12] Added crafting stations --- assets/common/recipe_book.ron | 201 +++++++++--------- client/src/lib.rs | 32 ++- common/src/comp/controller.rs | 18 +- common/src/comp/inventory/item/modular.rs | 12 +- common/src/recipe.rs | 18 +- server/src/events/inventory_manip.rs | 24 ++- voxygen/src/hud/crafting.rs | 10 +- voxygen/src/hud/mod.rs | 38 +++- voxygen/src/scene/terrain.rs | 2 +- voxygen/src/scene/terrain/watcher.rs | 12 +- voxygen/src/session/mod.rs | 47 ++-- .../settlement/building/archetype/house.rs | 44 +++- 12 files changed, 283 insertions(+), 175 deletions(-) diff --git a/assets/common/recipe_book.ron b/assets/common/recipe_book.ron index ef20666454..a193e72204 100644 --- a/assets/common/recipe_book.ron +++ b/assets/common/recipe_book.ron @@ -1,59 +1,59 @@ { "crafting_hammer": ( - ("common.items.crafting_tools.craftsman_hammer", 1), - [ + output: ("common.items.crafting_tools.craftsman_hammer", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 6), (Item("common.items.crafting_ing.stones"), 6), ], ), "mortar_pestle": ( - ("common.items.crafting_tools.mortar_pestle", 1), - [ + output: ("common.items.crafting_tools.mortar_pestle", 1), + inputs: [ (Item("common.items.crafting_ing.stones"), 6), (Item("common.items.food.coconut"), 1), (Item("common.items.crafting_tools.craftsman_hammer"), 0), ], ), "sewing_set": ( - ("common.items.crafting_tools.sewing_set", 1), - [ + output: ("common.items.crafting_tools.sewing_set", 1), + inputs: [ (Item("common.items.crafting_ing.leather_scraps"), 2), (Item("common.items.crafting_ing.twigs"), 4), (Item("common.items.crafting_ing.stones"), 2), ], ), "velorite_frag": ( - ("common.items.ore.veloritefrag", 2), - [ + output: ("common.items.ore.veloritefrag", 2), + inputs: [ (Item("common.items.ore.velorite"), 1), (Item("common.items.crafting_tools.craftsman_hammer"), 0), ], ), "potion_s": ( - ("common.items.consumable.potion_minor", 1), - [ + output: ("common.items.consumable.potion_minor", 1), + inputs: [ (Item("common.items.crafting_ing.empty_vial"), 1), (Item("common.items.food.apple"), 4), (Item("common.items.crafting_ing.honey"), 1), ], ), "potion_m": ( - ("common.items.consumable.potion_med", 1), - [ + output: ("common.items.consumable.potion_med", 1), + inputs: [ (Item("common.items.consumable.potion_minor"), 2), (Item("common.items.ore.veloritefrag"), 4), ], ), "collar_basic": ( - ("common.items.utility.collar", 1), - [ + output: ("common.items.utility.collar", 1), + inputs: [ (Item("common.items.crafting_ing.leather_scraps"), 5), (Item("common.items.crafting_ing.ruby"), 1), ], ), "bomb_coconut": ( - ("common.items.utility.bomb", 1), - [ + output: ("common.items.utility.bomb", 1), + inputs: [ (Item("common.items.crafting_ing.stones"), 10), (Item("common.items.food.coconut"), 2), (Item("common.items.ore.veloritefrag"), 2), @@ -61,8 +61,8 @@ ], ), "firework_blue": ( - ("common.items.utility.firework_blue", 1), - [ + output: ("common.items.utility.firework_blue", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 1), (Item("common.items.crafting_ing.stones"), 1), (Item("common.items.food.coconut"), 1), @@ -71,8 +71,8 @@ ], ), "firework_green": ( - ("common.items.utility.firework_green", 1), - [ + output: ("common.items.utility.firework_green", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 1), (Item("common.items.crafting_ing.stones"), 1), (Item("common.items.food.coconut"), 1), @@ -81,8 +81,8 @@ ], ), "firework_purple": ( - ("common.items.utility.firework_purple", 1), - [ + output: ("common.items.utility.firework_purple", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 1), (Item("common.items.crafting_ing.stones"), 1), (Item("common.items.food.coconut"), 1), @@ -91,8 +91,8 @@ ], ), "firework_red": ( - ("common.items.utility.firework_red", 1), - [ + output: ("common.items.utility.firework_red", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 1), (Item("common.items.crafting_ing.stones"), 1), (Item("common.items.food.coconut"), 1), @@ -101,8 +101,8 @@ ], ), "firework_white": ( - ("common.items.utility.firework_white", 1), - [ + output: ("common.items.utility.firework_white", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 1), (Item("common.items.crafting_ing.stones"), 1), (Item("common.items.food.coconut"), 1), @@ -111,8 +111,8 @@ ], ), "firework_yellow": ( - ("common.items.utility.firework_yellow", 1), - [ + output: ("common.items.utility.firework_yellow", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 1), (Item("common.items.crafting_ing.stones"), 1), (Item("common.items.food.coconut"), 1), @@ -121,8 +121,8 @@ ], ), "apple_shroom_curry": ( - ("common.items.food.apple_mushroom_curry", 1), - [ + output: ("common.items.food.apple_mushroom_curry", 1), + inputs: [ (Item("common.items.food.mushroom"), 8), (Item("common.items.food.coconut"), 1), (Item("common.items.food.apple"), 4), @@ -130,37 +130,38 @@ ], ), "salad_plain": ( - ("common.items.food.plainsalad", 1), - [ + output: ("common.items.food.plainsalad", 1), + inputs: [ (Item("common.items.food.lettuce"), 1), (Item("common.items.crafting_ing.bowl"), 1), ], + craft_sprite: Some(Pot), ), "salad_tomato": ( - ("common.items.food.tomatosalad", 1), - [ + output: ("common.items.food.tomatosalad", 1), + inputs: [ (Item("common.items.food.lettuce"), 1), (Item("common.items.food.tomato"), 2), (Item("common.items.crafting_ing.bowl"), 1), ], ), "apples_stick": ( - ("common.items.food.apple_stick", 1), - [ + output: ("common.items.food.apple_stick", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 2), (Item("common.items.food.apple"), 2) ], ), "mushroom_stick": ( - ("common.items.food.mushroom_stick", 1), - [ + output: ("common.items.food.mushroom_stick", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 2), (Item("common.items.food.mushroom"), 3), ], ), "sunflower_icetea": ( - ("common.items.food.sunflower_icetea", 4), - [ + output: ("common.items.food.sunflower_icetea", 4), + inputs: [ (Item("common.items.crafting_ing.empty_vial"), 1), (Item("common.items.crafting_ing.icy_fang"), 1), (Item("common.items.flowers.sunflower"), 4), @@ -168,8 +169,8 @@ ], ), "Plain Cloth Glider": ( - ("common.items.glider.glider_basic_white", 1), - [ + output: ("common.items.glider.glider_basic_white", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 5), (Item("common.items.crafting_ing.leather_scraps"), 5), (Item("common.items.crafting_ing.cloth_scraps"), 10), @@ -178,8 +179,8 @@ ], ), "Red Cloth Glider": ( - ("common.items.glider.glider_basic_red", 1), - [ + output: ("common.items.glider.glider_basic_red", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 5), (Item("common.items.crafting_ing.cloth_scraps_red"), 10), (Item("common.items.crafting_ing.leather_scraps"), 5), @@ -188,8 +189,8 @@ ], ), "Leaves Glider": ( - ("common.items.glider.glider_leaves", 1), - [ + output: ("common.items.glider.glider_leaves", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 5), (Item("common.items.crafting_ing.leather_scraps"), 5), (Item("common.items.crafting_ing.cloth_scraps"), 5), @@ -199,8 +200,8 @@ ], ), "Sand Raptor Wings": ( - ("common.items.glider.glider_sandraptor", 1), - [ + output: ("common.items.glider.glider_sandraptor", 1), + inputs: [ (Item("common.items.crafting_ing.raptor_feather"), 6), (Item("common.items.crafting_ing.twigs"), 5), (Item("common.items.crafting_ing.leather_scraps"), 5), @@ -211,8 +212,8 @@ ], ), "Snow Raptor Wings": ( - ("common.items.glider.glider_snowraptor", 1), - [ + output: ("common.items.glider.glider_snowraptor", 1), + inputs: [ (Item("common.items.crafting_ing.raptor_feather"), 6), (Item("common.items.crafting_ing.twigs"), 5), (Item("common.items.crafting_ing.leather_scraps"), 5), @@ -224,8 +225,8 @@ ], ), "Wood Raptor Wings": ( - ("common.items.glider.glider_woodraptor", 1), - [ + output: ("common.items.glider.glider_woodraptor", 1), + inputs: [ (Item("common.items.crafting_ing.raptor_feather"), 6), (Item("common.items.crafting_ing.twigs"), 15), (Item("common.items.crafting_ing.leather_scraps"), 5), @@ -236,8 +237,8 @@ ], ), "Soothing Loop": ( - ("common.items.weapons.sceptre.loops0", 1), - [ + output: ("common.items.weapons.sceptre.loops0", 1), + inputs: [ (Item("common.items.crafting_ing.twigs"), 20), (Item("common.items.ore.veloritefrag"), 8), (Item("common.items.crafting_ing.ruby"), 4), @@ -245,16 +246,16 @@ ], ), "Hunting Bow": ( - ("common.items.weapons.bow.wood-2", 1), - [ + output: ("common.items.weapons.bow.wood-2", 1), + inputs: [ (Item("common.items.crafting_ing.leather_scraps"), 8), (Item("common.items.crafting_ing.twigs"), 6), (Item("common.items.crafting_ing.stones"), 0), ], ), "Forest Spirit": ( - ("common.items.weapons.sword.wood-2", 1), - [ + output: ("common.items.weapons.sword.wood-2", 1), + inputs: [ (Item("common.items.crafting_ing.leather_scraps"), 4), (Item("common.items.crafting_ing.twigs"), 10), (Item("common.items.ore.veloritefrag"), 1), @@ -262,36 +263,36 @@ ], ), "adventure back": ( - ("common.items.armor.agile.back", 1), - [(Item("common.items.crafting_ing.leather_scraps"), 4)], + output: ("common.items.armor.agile.back", 1), + inputs: [(Item("common.items.crafting_ing.leather_scraps"), 4)], ), "adventure belt": ( - ("common.items.armor.agile.belt", 1), - [(Item("common.items.crafting_ing.leather_scraps"), 2)], + output: ("common.items.armor.agile.belt", 1), + inputs: [(Item("common.items.crafting_ing.leather_scraps"), 2)], ), "adventure chest": ( - ("common.items.armor.agile.chest", 1), - [(Item("common.items.crafting_ing.leather_scraps"), 12)], + output: ("common.items.armor.agile.chest", 1), + inputs: [(Item("common.items.crafting_ing.leather_scraps"), 12)], ), "adventure feet": ( - ("common.items.armor.agile.foot", 1), - [(Item("common.items.crafting_ing.leather_scraps"), 3)], + output: ("common.items.armor.agile.foot", 1), + inputs: [(Item("common.items.crafting_ing.leather_scraps"), 3)], ), "adventure hands": ( - ("common.items.armor.agile.hand", 1), - [(Item("common.items.crafting_ing.leather_scraps"), 4)], + output: ("common.items.armor.agile.hand", 1), + inputs: [(Item("common.items.crafting_ing.leather_scraps"), 4)], ), "adventure pants": ( - ("common.items.armor.agile.pants", 1), - [(Item("common.items.crafting_ing.leather_scraps"), 8)], + output: ("common.items.armor.agile.pants", 1), + inputs: [(Item("common.items.crafting_ing.leather_scraps"), 8)], ), "adventure shoulder": ( - ("common.items.armor.agile.shoulder", 1), - [(Item("common.items.crafting_ing.leather_scraps"), 12)], + output: ("common.items.armor.agile.shoulder", 1), + inputs: [(Item("common.items.crafting_ing.leather_scraps"), 12)], ), "Seashell Necklace": ( - ("common.items.armor.misc.neck.shell", 1), - [ + output: ("common.items.armor.misc.neck.shell", 1), + inputs: [ (Item("common.items.crafting_ing.cloth_scraps"), 2), (Item("common.items.crafting_ing.sapphire"), 1), (Item("common.items.crafting_ing.seashells"), 3), @@ -299,46 +300,46 @@ ], ), "red cloth": ( - ("common.items.crafting_ing.cloth_scraps_red", 1), - [ + output: ("common.items.crafting_ing.cloth_scraps_red", 1), + inputs: [ (Item("common.items.crafting_ing.cloth_scraps"), 1), (Item("common.items.flowers.red"), 1), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], ), "tiny red pouch": ( - ("common.items.armor.misc.bag.tiny_red_pouch", 1), - [ + output: ("common.items.armor.misc.bag.tiny_red_pouch", 1), + inputs: [ (Item("common.items.crafting_ing.cloth_scraps_red"), 3), (Item("common.items.crafting_tools.sewing_set"), 0), ], ), "tiny leather pouch": ( - ("common.items.armor.misc.bag.tiny_leather_pouch", 1), - [ + output: ("common.items.armor.misc.bag.tiny_leather_pouch", 1), + inputs: [ (Item("common.items.crafting_ing.leather_scraps"), 6), (Item("common.items.crafting_tools.sewing_set"), 0), ], ), "knitted red pouch": ( - ("common.items.armor.misc.bag.knitted_red_pouch", 1), - [ + output: ("common.items.armor.misc.bag.knitted_red_pouch", 1), + inputs: [ (Item("common.items.crafting_ing.cloth_scraps_red"), 3), (Item("common.items.armor.misc.bag.tiny_red_pouch"), 2), (Item("common.items.crafting_tools.sewing_set"), 0), ], ), "woven red bag": ( - ("common.items.armor.misc.bag.woven_red_bag", 1), - [ + output: ("common.items.armor.misc.bag.woven_red_bag", 1), + inputs: [ (Item("common.items.crafting_ing.cloth_scraps_red"), 6), (Item("common.items.armor.misc.bag.knitted_red_pouch"), 1), (Item("common.items.crafting_tools.sewing_set"), 0), ], ), "traveler backpack": ( - ("common.items.armor.misc.back.backpack", 1), - [ + output: ("common.items.armor.misc.back.backpack", 1), + inputs: [ (Item("common.items.crafting_ing.diamond"), 2), (Item("common.items.crafting_ing.twigs"), 2), (Item("common.items.crafting_ing.cloth_scraps"), 3), @@ -348,8 +349,8 @@ ], ), "sturdy red backpack": ( - ("common.items.armor.misc.bag.sturdy_red_backpack", 1), - [ + output: ("common.items.armor.misc.bag.sturdy_red_backpack", 1), + inputs: [ (Item("common.items.crafting_ing.diamond"), 2), (Item("common.items.crafting_ing.cloth_scraps_red"), 3), (Item("common.items.armor.misc.bag.woven_red_bag"), 1), @@ -357,8 +358,8 @@ ], ), "troll hide pack": ( - ("common.items.armor.misc.bag.troll_hide_pack", 1), - [ + output: ("common.items.armor.misc.bag.troll_hide_pack", 1), + inputs: [ (Item("common.items.crafting_ing.leather_troll"), 10), (Item("common.items.crafting_ing.leather_scraps"), 10), (Item("common.items.crafting_ing.diamond"), 1), @@ -366,8 +367,8 @@ ], ), "Mindflayer Spellbag": ( - ("common.items.armor.misc.bag.mindflayer_spellbag", 1), - [ + output: ("common.items.armor.misc.bag.mindflayer_spellbag", 1), + inputs: [ (Item("common.items.crafting_ing.mindflayer_bag_damaged"), 1), (Item("common.items.crafting_ing.leather_scraps"), 10), (Item("common.items.crafting_ing.diamond"), 4), @@ -376,8 +377,8 @@ ], ), "pickaxe": ( - ("common.items.tool.pick", 1), - [ + output: ("common.items.tool.pick", 1), + inputs: [ (Item("common.items.crafting_ing.cloth_scraps"), 1), // TODO: Replace with plant fiber when obtainable (Item("common.items.crafting_ing.stones"), 5), // TODO: Replace with iron ingots when obtainable (Item("common.items.crafting_ing.twigs"), 4), @@ -385,22 +386,22 @@ ], ), "cloth_scraps": ( - ("common.items.crafting_ing.cloth_scraps", 1), - [ + output: ("common.items.crafting_ing.cloth_scraps", 1), + inputs: [ (Tag(ClothItem), 1), (Item("common.items.crafting_tools.sewing_set"), 0), ], ), "leather_scraps": ( - ("common.items.crafting_ing.leather_scraps", 1), - [ + output: ("common.items.crafting_ing.leather_scraps", 1), + inputs: [ (Tag(LeatherItem), 1), (Item("common.items.crafting_tools.sewing_set"), 0), ], ), //"metal_blade": ( - // ("common.items.crafting_ing.modular.damage.sword.metal_blade", 1), - // [ + // output: ("common.items.crafting_ing.modular.damage.sword.metal_blade", 1), + // inputs: [ // (Tag(MetalIngot), 5), // (Item("common.items.crafting_tools.craftsman_hammer"), 0), // ], diff --git a/client/src/lib.rs b/client/src/lib.rs index 777292495d..89a0b26021 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -36,7 +36,7 @@ use common::{ resources::{DeltaTime, PlayerEntity, TimeOfDay}, terrain::{ block::Block, map::MapConfig, neighbors, BiomeKind, SitesKind, TerrainChunk, - TerrainChunkSize, + TerrainChunkSize, SpriteKind, }, trade::{PendingTrade, SitePrices, TradeAction, TradeId, TradeResult}, uid::{Uid, UidAllocator}, @@ -152,7 +152,7 @@ pub struct Client { sites: HashMap, pub chat_mode: ChatMode, recipe_book: RecipeBook, - available_recipes: HashSet, + available_recipes: HashMap>, max_group_size: u32, // Client has received an invite (inviter uid, time out instant) @@ -655,7 +655,7 @@ impl Client { }) .collect(), recipe_book, - available_recipes: HashSet::default(), + available_recipes: HashMap::default(), chat_mode: ChatMode::default(), max_group_size, @@ -970,20 +970,27 @@ impl Client { pub fn recipe_book(&self) -> &RecipeBook { &self.recipe_book } - pub fn available_recipes(&self) -> &HashSet { &self.available_recipes } + pub fn available_recipes(&self) -> &HashMap> { &self.available_recipes } - pub fn can_craft_recipe(&self, recipe: &str) -> bool { + pub fn can_craft_recipe(&self, recipe: &str) -> Option> { self.recipe_book .get(recipe) .zip(self.inventories().get(self.entity())) - .map(|(recipe, inv)| inv.contains_ingredients(&*recipe).is_ok()) - .unwrap_or(false) + .map(|(recipe, inv)| if inv.contains_ingredients(&*recipe).is_ok() { + Some(recipe.craft_sprite) + } else { + None + }) + .unwrap_or(None) } - pub fn craft_recipe(&mut self, recipe: &str) -> bool { - if self.can_craft_recipe(recipe) { + pub fn craft_recipe(&mut self, recipe: &str, craft_sprite: Option<(Vec3, SpriteKind)>) -> bool { + if self.can_craft_recipe(recipe).map_or(false, |cs| cs.map_or(true, |cs| Some(cs) == craft_sprite.map(|(_, s)| s))) { self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryEvent( - InventoryEvent::CraftRecipe(recipe.to_string()), + InventoryEvent::CraftRecipe { + recipe: recipe.to_string(), + craft_sprite: craft_sprite.map(|(pos, _)| pos), + } ))); true } else { @@ -996,7 +1003,10 @@ impl Client { .recipe_book .iter() .map(|(name, _)| name.clone()) - .filter(|name| self.can_craft_recipe(name)) + .filter_map(|name| { + let required_sprite = self.can_craft_recipe(&name)?; + Some((name, required_sprite)) + }) .collect(); } diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index 8437d9a269..19dc1eb138 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -21,9 +21,12 @@ pub enum InventoryEvent { Swap(InvSlotId, InvSlotId), SplitSwap(InvSlotId, InvSlotId), Drop(InvSlotId), - SplitDrop(InvSlotId), - CraftRecipe(String), + SplitDrop(InvSlotId), Sort, + CraftRecipe { + recipe: String, + craft_sprite: Option>, + }, } #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] @@ -42,9 +45,12 @@ pub enum InventoryManip { Swap(Slot, Slot), SplitSwap(Slot, Slot), Drop(Slot), - SplitDrop(Slot), - CraftRecipe(String), + SplitDrop(Slot), Sort, + CraftRecipe { + recipe: String, + craft_sprite: Option>, + }, } impl From for InventoryManip { @@ -70,9 +76,9 @@ impl From for InventoryManip { Self::SplitSwap(Slot::Inventory(inv1), Slot::Inventory(inv2)) }, InventoryEvent::Drop(inv) => Self::Drop(Slot::Inventory(inv)), - InventoryEvent::SplitDrop(inv) => Self::SplitDrop(Slot::Inventory(inv)), - InventoryEvent::CraftRecipe(recipe) => Self::CraftRecipe(recipe), + InventoryEvent::SplitDrop(inv) => Self::SplitDrop(Slot::Inventory(inv)), InventoryEvent::Sort => Self::Sort, + InventoryEvent::CraftRecipe { recipe, craft_sprite } => Self::CraftRecipe { recipe, craft_sprite }, } } } diff --git a/common/src/comp/inventory/item/modular.rs b/common/src/comp/inventory/item/modular.rs index c30a8ca24c..416ff688dd 100644 --- a/common/src/comp/inventory/item/modular.rs +++ b/common/src/comp/inventory/item/modular.rs @@ -1,5 +1,5 @@ use super::{tool, ItemKind, ItemTag, Quality, RawItemDef, TagExampleInfo, ToolKind}; -use crate::recipe::{RawRecipeBook, RawRecipeInput}; +use crate::recipe::{RawRecipeBook, RawRecipeInput, RawRecipe}; use hashbrown::HashMap; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; @@ -237,8 +237,8 @@ fn make_weapon_def(toolkind: ToolKind) -> (String, RawItemDef) { fn make_recipe_def( identifier: String, toolkind: ToolKind, -) -> ((String, u32), Vec<(RawRecipeInput, u32)>) { - let outputs = (identifier, 1); +) -> RawRecipe { + let output = (identifier, 1); let mut inputs = Vec::new(); for &modkind in &MODKINDS { let input = RawRecipeInput::Tag(ItemTag::ModularComponent(ModularComponentTag { @@ -247,7 +247,11 @@ fn make_recipe_def( })); inputs.push((input, 1)); } - (outputs, inputs) + RawRecipe { + output, + inputs, + craft_sprite: None, + } } fn make_tagexample_def( diff --git a/common/src/recipe.rs b/common/src/recipe.rs index 0e67509059..86be1a3637 100644 --- a/common/src/recipe.rs +++ b/common/src/recipe.rs @@ -4,6 +4,7 @@ use crate::{ item::{modular, ItemDef, ItemTag, MaterialStatManifest}, Inventory, Item, }, + terrain::SpriteKind, }; use hashbrown::HashMap; use serde::{Deserialize, Serialize}; @@ -19,6 +20,7 @@ pub enum RecipeInput { pub struct Recipe { pub output: (Arc, u32), pub inputs: Vec<(RecipeInput, u32)>, + pub craft_sprite: Option, } #[allow(clippy::type_complexity)] @@ -86,11 +88,19 @@ pub enum RawRecipeInput { Tag(ItemTag), } +#[derive(Clone, Deserialize)] +pub(crate) struct RawRecipe { + pub(crate) output: (String, u32), + pub(crate) inputs: Vec<(RawRecipeInput, u32)>, + #[serde(default)] + pub(crate) craft_sprite: Option, +} + #[derive(Clone, Deserialize)] #[serde(transparent)] #[allow(clippy::type_complexity)] pub(crate) struct RawRecipeBook( - pub(crate) HashMap)>, + pub(crate) HashMap, ); impl assets::Asset for RawRecipeBook { @@ -134,13 +144,13 @@ impl assets::Compound for RecipeBook { let recipes = raw .0 .iter() - .map(|(name, (output, inputs))| { + .map(|(name, RawRecipe { output, inputs, craft_sprite })| { let inputs = inputs .iter() .map(load_recipe_input) - .collect::>()?; + .collect::, _>>()?; let output = load_item_def(output)?; - Ok((name.clone(), Recipe { output, inputs })) + Ok((name.clone(), Recipe { output, inputs, craft_sprite: *craft_sprite })) }) .collect::>()?; diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 6e687077b6..dfdae58433 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -576,15 +576,23 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .expect("We know entity exists since we got its inventory."); drop(inventories); }, - comp::InventoryManip::CraftRecipe(recipe) => { + comp::InventoryManip::CraftRecipe { recipe, craft_sprite } => { let recipe_book = default_recipe_book().read(); - let craft_result = recipe_book.get(&recipe).and_then(|r| { - r.perform( - &mut inventory, - &state.ecs().read_resource::(), - ) - .ok() - }); + let craft_result = recipe_book + .get(&recipe) + .filter(|r| { + let sprite = craft_sprite + .and_then(|pos| state.terrain().get(pos).ok().copied()) + .and_then(|block| block.get_sprite()); + r.craft_sprite.map_or(true, |cs| Some(cs) == sprite) + }) + .and_then(|r| { + r.perform( + &mut inventory, + &state.ecs().read_resource::(), + ) + .ok() + }); drop(inventories); // FIXME: We should really require the drop and write to be atomic! diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index 2867bb36dd..630bc3441c 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -127,7 +127,7 @@ impl<'a> Crafting<'a> { } } -#[derive(Debug, EnumIter, PartialEq)] +#[derive(Copy, Clone, Debug, EnumIter, PartialEq)] pub enum CraftingTab { All, Armor, @@ -434,7 +434,10 @@ impl<'a> Widget for Crafting<'a> { .unwrap_or(false) }) }); - let state = if self.client.available_recipes().contains(name.as_str()) { + let state = if self.client.available_recipes() + .get(name.as_str()) + .map_or(false, |cs| cs.map_or(true, |cs| Some(cs) == self.show.craft_sprite.map(|(_, s)| s))) + { RecipeIngredientQuantity::All } else if at_least_some_ingredients { RecipeIngredientQuantity::Some @@ -528,7 +531,8 @@ impl<'a> Widget for Crafting<'a> { let can_perform = self .client .available_recipes() - .contains(recipe_name.as_str()); + .get(recipe_name.as_str()) + .map_or(false, |cs| cs.map_or(true, |cs| Some(cs) == self.show.craft_sprite.map(|(_, s)| s))); // Craft button if Button::image(self.imgs.button) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 4f2524cf74..238474b5e3 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -25,13 +25,14 @@ pub mod util; pub use hotbar::{SlotContents as HotbarSlotContents, State as HotbarState}; pub use item_imgs::animate_by_pulse; pub use settings_window::ScaleChange; +pub use crafting::CraftingTab; use bag::Bag; use buffs::BuffsBar; use buttons::Buttons; use chat::Chat; use chrono::NaiveTime; -use crafting::{Crafting, CraftingTab}; +use crafting::Crafting; use diary::{Diary, SelectedSkillTree}; use esc_menu::EscMenu; use group::Group; @@ -74,7 +75,7 @@ use common::{ BuffKind, Item, }, outcome::Outcome, - terrain::TerrainChunk, + terrain::{TerrainChunk, SpriteKind}, trade::{ReducedInventory, TradeAction}, uid::Uid, util::srgba_to_linear, @@ -380,7 +381,7 @@ pub enum Event { Logout, Quit, - CraftRecipe(String), + CraftRecipe { recipe: String, craft_sprite: Option<(Vec3, SpriteKind)> }, InviteMember(Uid), AcceptInvite, DeclineInvite, @@ -492,6 +493,7 @@ pub struct Show { skilltreetab: SelectedSkillTree, crafting_tab: CraftingTab, crafting_search_key: Option, + craft_sprite: Option<(Vec3, SpriteKind)>, social_search_key: Option, want_grab: bool, stats: bool, @@ -558,6 +560,12 @@ impl Show { } } + pub fn open_crafting_tab(&mut self, tab: CraftingTab, craft_sprite: Option<(Vec3, SpriteKind)>) { + self.selected_crafting_tab(tab); + self.crafting(true); + self.craft_sprite = craft_sprite; + } + fn diary(&mut self, open: bool) { if !self.esc_menu { self.social = false; @@ -734,7 +742,7 @@ pub struct Hud { new_messages: VecDeque, new_notifications: VecDeque, speech_bubbles: HashMap, - show: Show, + pub show: Show, //never_show: bool, //intro: bool, //intro_2: bool, @@ -840,6 +848,7 @@ impl Hud { skilltreetab: SelectedSkillTree::General, crafting_tab: CraftingTab::All, crafting_search_key: None, + craft_sprite: None, social_search_key: None, want_grab: true, ingame: true, @@ -1363,7 +1372,7 @@ impl Hud { } // Render overtime for an interactable block - if let Some(Interactable::Block(block, pos)) = interactable { + if let Some(Interactable::Block(block, pos, _)) = interactable { let overitem_id = overitem_walker.next( &mut self.ids.overitems, &mut ui_widgets.widget_id_generator(), @@ -1395,6 +1404,19 @@ impl Hud { &self.fonts, ) .set(overitem_id, ui_widgets); + } else if let Some(sprite) = block.get_sprite() { + overitem::Overitem::new( + format!("{:?}", sprite).into(), // TODO: A better way to generate text for this + overitem::TEXT_COLOR, + pos.distance_squared(player_pos), + &self.fonts, + &global_state.settings.controls, + true, + &global_state.window.key_layout, + ) + .x_y(0.0, 100.0) + .position_ingame(over_pos) + .set(overitem_id, ui_widgets); } } @@ -2420,8 +2442,8 @@ impl Hud { .set(self.ids.crafting_window, ui_widgets) { match event { - crafting::Event::CraftRecipe(r) => { - events.push(Event::CraftRecipe(r)); + crafting::Event::CraftRecipe(recipe) => { + events.push(Event::CraftRecipe { recipe, craft_sprite: self.show.craft_sprite }); }, crafting::Event::Close => { self.show.stats = false; @@ -2434,7 +2456,7 @@ impl Hud { }; }, crafting::Event::ChangeCraftingTab(sel_cat) => { - self.show.selected_crafting_tab(sel_cat); + self.show.open_crafting_tab(sel_cat, None); }, crafting::Event::Focus(widget_id) => { self.to_focus = Some(Some(widget_id)); diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 3d67e4c060..13121fe75f 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1,5 +1,5 @@ mod watcher; -pub use self::watcher::BlocksOfInterest; +pub use self::watcher::{BlocksOfInterest, Interaction}; use crate::{ mesh::{greedy::GreedyMesh, terrain::SUNLIGHT, Meshable}, diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 74d2fda778..6b5a6eb14f 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -5,6 +5,13 @@ use common::{ use common_base::span; use rand::prelude::*; use vek::*; +use crate::hud::CraftingTab; + +#[derive(Copy, Clone)] +pub enum Interaction { + Collect, + Craft(CraftingTab), +} #[derive(Default)] pub struct BlocksOfInterest { @@ -26,7 +33,7 @@ pub struct BlocksOfInterest { pub frogs: Vec>, // Note: these are only needed for chunks within the iteraction range so this is a potential // area for optimization - pub interactables: Vec>, + pub interactables: Vec<(Vec3, Interaction)>, pub lights: Vec<(Vec3, u8)>, } @@ -108,11 +115,12 @@ impl BlocksOfInterest { Some(SpriteKind::WhiteFlower) => flowers.push(pos), Some(SpriteKind::YellowFlower) => flowers.push(pos), Some(SpriteKind::Sunflower) => flowers.push(pos), + Some(SpriteKind::Pot) => interactables.push((pos, Interaction::Craft(CraftingTab::Food))), _ => {}, }, } if block.is_collectible() { - interactables.push(pos); + interactables.push((pos, Interaction::Collect)); } if let Some(glow) = block.get_glow() { lights.push((pos, glow)); diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 4fd1dbe383..976347af71 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -38,7 +38,7 @@ use crate::{ key_state::KeyState, menu::char_selection::CharSelectionState, render::Renderer, - scene::{camera, CameraMode, Scene, SceneData}, + scene::{camera, CameraMode, Scene, SceneData, terrain::Interaction}, settings::Settings, window::{AnalogGameInput, Event, GameInput}, Direction, Error, GlobalState, PlayState, PlayStateResult, @@ -359,7 +359,7 @@ impl PlayState for SessionState { .map(|sp| sp.map(|e| e.floor() as i32)) .filter(|_| can_build || is_mining) .or_else(|| match self.interactable { - Some(Interactable::Block(_, block_pos)) => Some(block_pos), + Some(Interactable::Block(_, block_pos, _)) => Some(block_pos), _ => None, }), ); @@ -591,10 +591,16 @@ impl PlayState for SessionState { if let Some(interactable) = self.interactable { let mut client = self.client.borrow_mut(); match interactable { - Interactable::Block(block, pos) => { - if block.is_collectible() { - client.collect_block(pos); - } + Interactable::Block(block, pos, interaction) => match interaction { + Interaction::Collect => { + if block.is_collectible() { + client.collect_block(pos); + } + }, + Interaction::Craft(tab) => self.hud.show.open_crafting_tab( + tab, + block.get_sprite().map(|s| (pos, s)), + ), }, Interactable::Entity(entity) => { if client @@ -618,7 +624,7 @@ impl PlayState for SessionState { if let Some(interactable) = self.interactable { let mut client = self.client.borrow_mut(); match interactable { - Interactable::Block(_, _) => {}, + Interactable::Block(_, _, _) => {}, Interactable::Entity(entity) => { if let Some(uid) = client.state().ecs().uid_from_entity(entity) @@ -1181,8 +1187,8 @@ impl PlayState for SessionState { client.request_site_economy(id); }, - HudEvent::CraftRecipe(r) => { - self.client.borrow_mut().craft_recipe(&r); + HudEvent::CraftRecipe { recipe, craft_sprite } => { + self.client.borrow_mut().craft_recipe(&recipe, craft_sprite); }, HudEvent::InviteMember(uid) => { self.client.borrow_mut().send_invite(uid, InviteKind::Group); @@ -1440,7 +1446,7 @@ fn under_cursor( #[derive(Clone, Copy)] pub enum Interactable { - Block(Block, Vec3), + Block(Block, Vec3, Interaction), Entity(specs::Entity), } @@ -1448,7 +1454,7 @@ impl Interactable { pub fn entity(self) -> Option { match self { Self::Entity(e) => Some(e), - Self::Block(_, _) => None, + Self::Block(_, _, _) => None, } } } @@ -1476,7 +1482,7 @@ fn select_interactable( .or_else(|| selected_pos.and_then(|sp| client.state().terrain().get(sp).ok().copied() .filter(|b| hit(*b)) - .map(|b| Interactable::Block(b, sp)) + .map(|b| Interactable::Block(b, sp, Interaction::Collect)) )) .or_else(|| { let ecs = client.state().ecs(); @@ -1540,22 +1546,23 @@ fn select_interactable( .blocks_of_interest .interactables .iter() - .map(move |block_offset| chunk_pos + block_offset) + .map(move |(block_offset, interaction)| (chunk_pos + block_offset, interaction)) }) - .map(|block_pos| ( + .map(|(block_pos, interaction)| ( block_pos, block_pos.map(|e| e as f32 + 0.5) - .distance_squared(player_pos) + .distance_squared(player_pos), + interaction, )) - .min_by_key(|(_, dist_sqr)| OrderedFloat(*dist_sqr)) - .map(|(block_pos, _)| block_pos); + .min_by_key(|(_, dist_sqr, _)| OrderedFloat(*dist_sqr)) + .map(|(block_pos, _, interaction)| (block_pos, interaction)); // Pick closer one if they exist closest_interactable_block_pos - .filter(|block_pos| player_cylinder.min_distance(Cube { min: block_pos.as_(), side_length: 1.0}) < search_dist) - .and_then(|block_pos| + .filter(|(block_pos, _)| player_cylinder.min_distance(Cube { min: block_pos.as_(), side_length: 1.0}) < search_dist) + .and_then(|(block_pos, interaction)| client.state().terrain().get(block_pos).ok().copied() - .map(|b| Interactable::Block(b, block_pos)) + .map(|b| Interactable::Block(b, block_pos, *interaction)) ) .or_else(|| closest_interactable_entity.map(|(e, _)| Interactable::Entity(e))) }) diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index efb0157d11..5a124bfb5f 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -151,9 +151,9 @@ impl Attr { pub fn generate(rng: &mut R, _locus: i32) -> Self { Self { central_supports: rng.gen(), - storey_fill: match rng.gen_range(0..2) { - //0 => StoreyFill::None, - 0 => StoreyFill::Upper, + storey_fill: match rng.gen_range(0..3) { + 0 => StoreyFill::None, + 1 => StoreyFill::Upper, _ => StoreyFill::All, }, roof_style: match rng.gen_range(0..3) { @@ -295,12 +295,13 @@ impl Archetype for House { const EMPTY: BlockMask = BlockMask::nothing(); // TODO: Take environment into account. let internal = BlockMask::new(Block::air(SpriteKind::Empty), internal_layer); + let end_ori = match ori { + Ori::East => 2, + Ori::North => 4, + }; let end_window = BlockMask::new( Block::air(attr.window) - .with_ori(match ori { - Ori::East => 2, - Ori::North => 0, - }) + .with_ori(end_ori) .unwrap(), structural_layer, ); @@ -519,6 +520,31 @@ impl Archetype for House { // Ceiling return floor; } + } else if !attr.storey_fill.has_lower() + && center_offset.sum() % 2 == 0 + && profile.y == 1 + && center_offset.map(|e| e % 3 == 0).reduce_and() + && self + .noise + .chance(Vec3::new(center_offset.x, center_offset.y, z), 0.2) + { + let furniture = match self.noise.get(Vec3::new( + center_offset.x, + center_offset.y, + z + 100, + )) % 5 + { + 0..=1 => SpriteKind::Crate, + 2 => SpriteKind::Bench, + 3 => SpriteKind::ChairSingle, + 4 => SpriteKind::FireBowlGround, + _ => unreachable!(), + }; + + return BlockMask::new( + Block::air(furniture).with_ori(end_ori).unwrap(), + 1, + ); } else if (!attr.storey_fill.has_lower() && profile.y < ceil_height) || (!attr.storey_fill.has_upper() && profile.y >= ceil_height) { @@ -592,10 +618,12 @@ impl Archetype for House { match self .noise .get(Vec3::new(center_offset.x, center_offset.y, z + 100)) - % 4 + % 6 { 0 => SpriteKind::HangingSign, 1 | 2 | 3 => SpriteKind::HangingBasket, + 4 => SpriteKind::WallSconce, + 5 => SpriteKind::WallLampSmall, _ => SpriteKind::DungeonWallDecor, }; From afea896b5b0958ed6a6b0b86545e41dbf8614c8f Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 17 Apr 2021 20:35:48 +0200 Subject: [PATCH 02/12] fmt, add sprites --- assets/common/recipe_book.ron | 18 ++++++- .../voxygen/voxel/armor/bonerattler/chest.vox | Bin 2624 -> 2624 bytes assets/voxygen/voxel/sprite/anvil/anvil-0.vox | Bin 0 -> 4432 bytes .../voxel/sprite/cauldron/cauldron-0.vox | Bin 0 -> 10696 bytes .../crafting_bench/crafting_bench-0.vox | Bin 0 -> 3456 bytes assets/voxygen/voxel/sprite/forge/forge-0.vox | Bin 0 -> 44800 bytes assets/voxygen/voxel/sprite_manifest.ron | 44 ++++++++++++++++++ client/src/lib.rs | 30 ++++++++---- common/src/comp/controller.rs | 10 +++- common/src/comp/inventory/item/modular.rs | 7 +-- common/src/recipe.rs | 33 ++++++++----- common/src/terrain/sprite.rs | 12 +++++ server/src/events/inventory_manip.rs | 5 +- voxygen/src/hud/crafting.rs | 33 ++++++++----- voxygen/src/hud/mod.rs | 23 ++++++--- voxygen/src/scene/terrain/watcher.rs | 15 +++++- voxygen/src/session/mod.rs | 31 +++++++----- .../settlement/building/archetype/house.rs | 20 ++++---- 18 files changed, 208 insertions(+), 73 deletions(-) create mode 100644 assets/voxygen/voxel/sprite/anvil/anvil-0.vox create mode 100644 assets/voxygen/voxel/sprite/cauldron/cauldron-0.vox create mode 100644 assets/voxygen/voxel/sprite/crafting_bench/crafting_bench-0.vox create mode 100644 assets/voxygen/voxel/sprite/forge/forge-0.vox diff --git a/assets/common/recipe_book.ron b/assets/common/recipe_book.ron index a193e72204..6b584e76b1 100644 --- a/assets/common/recipe_book.ron +++ b/assets/common/recipe_book.ron @@ -5,6 +5,7 @@ (Item("common.items.crafting_ing.twigs"), 6), (Item("common.items.crafting_ing.stones"), 6), ], + craft_sprite: Some(CraftingBench), ), "mortar_pestle": ( output: ("common.items.crafting_tools.mortar_pestle", 1), @@ -28,6 +29,7 @@ (Item("common.items.ore.velorite"), 1), (Item("common.items.crafting_tools.craftsman_hammer"), 0), ], + craft_sprite: Some(Anvil), ), "potion_s": ( output: ("common.items.consumable.potion_minor", 1), @@ -36,6 +38,7 @@ (Item("common.items.food.apple"), 4), (Item("common.items.crafting_ing.honey"), 1), ], + craft_sprite: Some(Cauldron), ), "potion_m": ( output: ("common.items.consumable.potion_med", 1), @@ -43,6 +46,7 @@ (Item("common.items.consumable.potion_minor"), 2), (Item("common.items.ore.veloritefrag"), 4), ], + craft_sprite: Some(Cauldron), ), "collar_basic": ( output: ("common.items.utility.collar", 1), @@ -128,14 +132,14 @@ (Item("common.items.food.apple"), 4), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], + craft_sprite: Some(Cauldron), ), "salad_plain": ( output: ("common.items.food.plainsalad", 1), inputs: [ (Item("common.items.food.lettuce"), 1), (Item("common.items.crafting_ing.bowl"), 1), - ], - craft_sprite: Some(Pot), + ], ), "salad_tomato": ( output: ("common.items.food.tomatosalad", 1), @@ -167,6 +171,7 @@ (Item("common.items.flowers.sunflower"), 4), (Item("common.items.crafting_ing.honey"), 1), ], + craft_sprite: Some(Cauldron), ), "Plain Cloth Glider": ( output: ("common.items.glider.glider_basic_white", 1), @@ -177,6 +182,7 @@ (Item("common.items.crafting_tools.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], + craft_sprite: Some(CraftingBench), ), "Red Cloth Glider": ( output: ("common.items.glider.glider_basic_red", 1), @@ -187,6 +193,7 @@ (Item("common.items.crafting_tools.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], + craft_sprite: Some(CraftingBench), ), "Leaves Glider": ( output: ("common.items.glider.glider_leaves", 1), @@ -198,6 +205,7 @@ (Item("common.items.crafting_tools.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], + craft_sprite: Some(CraftingBench), ), "Sand Raptor Wings": ( output: ("common.items.glider.glider_sandraptor", 1), @@ -210,6 +218,7 @@ (Item("common.items.crafting_tools.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], + craft_sprite: Some(CraftingBench), ), "Snow Raptor Wings": ( output: ("common.items.glider.glider_snowraptor", 1), @@ -223,6 +232,7 @@ (Item("common.items.crafting_tools.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], + craft_sprite: Some(CraftingBench), ), "Wood Raptor Wings": ( output: ("common.items.glider.glider_woodraptor", 1), @@ -235,6 +245,7 @@ (Item("common.items.crafting_tools.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], + craft_sprite: Some(CraftingBench), ), "Soothing Loop": ( output: ("common.items.weapons.sceptre.loops0", 1), @@ -252,6 +263,7 @@ (Item("common.items.crafting_ing.twigs"), 6), (Item("common.items.crafting_ing.stones"), 0), ], + craft_sprite: Some(CraftingBench), ), "Forest Spirit": ( output: ("common.items.weapons.sword.wood-2", 1), @@ -261,6 +273,7 @@ (Item("common.items.ore.veloritefrag"), 1), (Item("common.items.crafting_ing.stones"), 0), ], + craft_sprite: Some(Anvil), ), "adventure back": ( output: ("common.items.armor.agile.back", 1), @@ -384,6 +397,7 @@ (Item("common.items.crafting_ing.twigs"), 4), (Item("common.items.crafting_tools.craftsman_hammer"), 0), ], + craft_sprite: Some(Anvil), ), "cloth_scraps": ( output: ("common.items.crafting_ing.cloth_scraps", 1), diff --git a/assets/voxygen/voxel/armor/bonerattler/chest.vox b/assets/voxygen/voxel/armor/bonerattler/chest.vox index bc6a0b10c6e4d1e2d901fc003b80c093ee8fb25c..5415f9a95782bdbd09aa01b613737210bfee4d0e 100644 GIT binary patch literal 2624 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 W&#qQS&8ziB>(}bNf8uNZ`SefI6ZozG literal 0 HcmV?d00001 diff --git a/assets/voxygen/voxel/sprite/cauldron/cauldron-0.vox b/assets/voxygen/voxel/sprite/cauldron/cauldron-0.vox new file mode 100644 index 0000000000000000000000000000000000000000..84279548c00488c6dd9129ce7abca2b87ac60265 GIT binary patch literal 10696 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 literal 0 HcmV?d00001 diff --git a/assets/voxygen/voxel/sprite/crafting_bench/crafting_bench-0.vox b/assets/voxygen/voxel/sprite/crafting_bench/crafting_bench-0.vox new file mode 100644 index 0000000000000000000000000000000000000000..35e1bf978858376ac7a825c483eca9981e658a3c GIT binary patch literal 3456 zcmc)MUyN179l-Iq=giERnKS2{ITr*03tQ02LZbqfKZV-0xK*HFk(TOKtr~5i3)PT@ zDA{NfYl;S;lz>gOls0DD7^#wlwCRH-#uyW03^h%Y#u(EyeKP4o_ul*V>v!d)HEH_T zn|$*7GiQEx&e?MbJ8!*x=!8;g>y4YX5!9YasU4ffM&nGuXBKMER=3|VwrPVW;j=AM zD$mupMna2BtMMEf1`QHgbded>p<&P`)}dk0 zAfZJUdBqwMTI9OZ*Sa&Eh%GTUMAMnpB|YSk_1Nj9*cr6MTxVRLO&eI9^$ML09MMw; z@{;vPUXj;mSWEO;%5=P>U@wFd9N+DC+ea80BiO}{1P+VX7dAZg1Ua%+1D9cPc^!4BGB zIhSRR?I*Ozb-}p`zNg?mik>#)rWkZwaU?H`URxG}JaSDe_@07$q0Ze$8U_{x96SO_ zL{zBJAfZL3-AB20+?(qeqSbCs0SB*LKhP_+8$@EoH8mRg2`#-Y`!mA~!weYX2G%eG z4xV11S0a*E#`SB%4C+K|sk`jYEHkX*8M(f(u4gSX;Na;6%Q-AFP@zVHM873=*`F26 zC^!d9;rf|TfmpH@ zi4|%z^b=b8UG`_58J_#`oW=7@yz3Qk^gMMSmedgyc};AH2`#$p&jK@oPcz(k&FWCpn-dW6XHKxD0=u89p2*R<%)?5}u7VPH|f!6TqVM1>j+5?Wa0_Y`n5 zvE#>!%#Y`}=biVw^PYE}J{&xCK#7P7H5w$e$h7C3_xv_J@4O#a&3-s|dVyX^jHtM- zrf$d+vDKb;o*9N2#`Dhmfq^y5fP<$Ftd)qy_bb%ojbR2_blIO-W>`Pa)=wMj_gG>9 zXMNvO2i8hN>WWyi)*z9$=(1lG{-+&e1+xmyQ*ciO=RpBiFpFLwFA-63T}{6sPpq}n zUG{gJ=iO(HV~*p#obOxbdj+|Jrw%B|Be5dZ#D@Ebn`kyzsv7 zs6BNcmWcE!)@t$w2`%eg_Gf_^foBwa-w-VdxZtNf0{s#Z6?M&8gA}+gVwe3{$&AwX zbjforxhE8G)Ea9rM6+RMuUV-L9YnktI;5#O^Ny%-+#b~I$n!9J6jH2-OA*3m&toySRk_b({fxXIgdZ#Z#e$2k~2S6a$!=* zTdz`&C^-IIQIEwMzEiq~tmJ+pnK5yGIwxf$dA> z!~-j3;_GYV#IB8U;fLRlzrVO!mM@tj8&)ooEni$J5A0kct&^S0=E&~r7s%n8uac>|ua(gaE9BNMuamK_-YDbuY?A{Ij>*v< zjLX#IQ*!b37i8-BJLST!zAI%}%H^|K85$ar6~l{V^);W7&#xSoqfcHTXMVm|{`}T5 zdHzwD5G&m=kg>)G<^yYu9IS@eIu z|5dA2$&c2Yl51C-mi338ka-8^$(z4W^4>R>t|j~BE4Q2#b?|^(w(l}I zfAZ4b@X`6aI|~=eV^dAC88XpC;3GsAN=mp z`99$N`d{n(3P1jx{kJ%?`0s0Xj4qemx2=*#zO`PS-n;QX)@H7q=|6Vg4f5o-M?PNv JR+rkKz9HD literal 0 HcmV?d00001 diff --git a/assets/voxygen/voxel/sprite/forge/forge-0.vox b/assets/voxygen/voxel/sprite/forge/forge-0.vox new file mode 100644 index 0000000000000000000000000000000000000000..8db89f6da9a62a44149519ab25b211e8878098bb GIT binary patch literal 44800 zcmXWj$*t_#x+Yexs2D*qSl3n5q#!F&4K=bMsUbi}r3beyBydc47RU%S(gJnmK-wWA zG#;P}49tr2|Nfu<lai5}D=4XqYZ_WQdIm-&W}?5~ zpZG8MSHhi?jGTg!ikgO&j-G*$iJ67yAnzcLJ1H4C1tk?V4J{o#10xeN3(+z7S4_g4 zl#HB$l8Ty!mX4l*k%^gw=p>JXJ1H4C1tk?V4J{o#10xeN3(;8~33pO5atcZ+Y8qNP zdIm-&W)`B0JQD7tWaJc-RMa%Ibo302Ow24qp*#}qq-5k2lvLC-v~=_gj7-cdL|1tv z+)2sEDJZF^X=v%_85o(ES%_}(NVt=dkyB7oQPa@U(K9eIF|+U&1^*m4M!~;MoVgHk zF604nV4B*t=b1qUcCA6_)9 zh?s;sDH%BhB^5OdEgd}rBNHx2fg>l*TnM>xBO)eAf`9I$ zWaJc-RMa%Ibo302Ow2MCRvtWg@#e#q9~(QtU40xla^lQ|kSjMLVv@W1NXf`4D5eDRICA35g^(*ZB4UzMeWYaM6qHodG_-W|42(?7 zG8R@IJbCfv!{Mgt%AC&4V)yI(&XD)YdGMqa84L`>4CkCcqOQJ=P?qNbsxv({?|MkZz%3o8$vym<5B%a4tnpj96S zj+{7iA>_)9h?t~RA1N7mt3GW>MNLCXXRX%`j7-cj7FHfSdGY4MmmeEDL8m?r96533 zLdcaH5iv=pzApH0sWv00proRvp{1i|V6yPYE`(gU5fPJ2>LVp1r=X;wrlF;y zXJBMvma(w%;K_?OAHMw9*a>F!ap1^_GZ#Xx+=z%txRa8RQ&3V-)6mkF604nV4CA!9UR^kAyoZ894#4KYWI>{qB$s;8rr=X;w zrlF;yXJBMvma!0><&m7_k&=;9P*PFT(9+Q}FfuXAScoq2NG|e7$;c@vsiF604 znV4lPM4|6TC@+*pN=8mWNkvUVOGnSZ$iysTkriF#UFBWnk&=;9P*PFT(9+Q}FfuXA zSY$;vc{h37Ny*45D5`(lappqEm7Dd5m?Zgg zNA>59>dzh3pF1jl_E1t$)6mk$bRzT&4({PHtRdVU40zx>f^+j3n5o- z)+1t)yZT7U$SEkPsA*{F=ouK9m}M-iJY+w4@#e#qADi`^AXOiSRDGN{b0Or)&3Z&k zlB$oCjGTg!ikgO&j-G*$iCM(7jHg%`LS8w2{QF@$kfM)GZ#Xx+^k2$B$@h1 z$;c@vsiF604nV4lPtUP2tdGY4Mmmiz;ognx7BUfLpK2Dsu5OU>aJt8LY{GF7H zoPv^ynueB+o`I2xS;oT3L-vywZ$5nav02|e9~9~<)K{pF6K5`jT)A0~h)FzuCnY1N zproRvp{1i|U}R#Jv9R)x{p7`)4_|(4)_2bbrTR+smFnZfnF}FTZq_4W63^dB$;c@v zsiF604nV4lPtUP2tdGY4Mmmiz;-Sa`^^T(l5A1BUS2)S~z9ubpN>LVp1r=X;w zrlF;yXJBMvma(w%kp1Mvn-5=pY}R*zT74X9^>O0Ng^(*Z>k%xvmOzXH0mQIBd4IGqNbsxqi0}b zVwSP6@{s-H#hVXber(ovf>wPTTJ>?_%!QCEH|r5GNvl3mGI9z^Dry>9I(i01CT1B6 zD-YREUcCA6<;P}yC+O72p;I3x&Rht&a?ARD>v&AF-fmJQZjN1N-Am^S~_|LMkZz%3o8%VPhPzF z@a4y5eJ2?F`7)?)P#-7GTnM>xvmOzXc>YdmJ|m}~q@t#wrK4wHv}aF604nV4lPtUP2tdGY4M zmmiz;-SfeuzDa$P`Z#gsLdcby^@y0n^LJ7*atcZ+Y8qNPdIm-&W*G}B57|#%y!r6u z$7X%^d@%d`ap1^_GZ#Xx+=z%txRa8RQ&3V-)6mk-ioH%nKj1KOo4(_PD zlh|Csos^86f|81whL(<=fsu)sMb^rLCogkvK79GH5yXdo{c+&Pi8B{MuH1--Nw|}e zkyB7oQPa@U(K9eIF|)Ap;K_?OAHMw9*a;H#aYzpCs1EL^4(_N9?x+s#s1EL^4(_Pb zM@*6&+)*9eQ61b-9o$hJ+)*9eQ61b-9o$hJ+)*9eQ61b-9o$hJ+)??nhlyFn!pcMT zlNWD3eEG3i-wE#O<8W6WC(c|5xpK1}5tH22M@mLcK}khTLrX``z{tcbV`1eX`^k$p zAHMw9tnUP=`Z%QOn z&H7G|sgFaZK2Dsu5OU>aJt8K_)JIB2PC-dUO+!mZ&%nsUEMsBiA^XXTHy^(I*sSja zx%xQd>f^+j3n5o-)+1t)Tz#Zu#4KZB{MfAT1f}{oln&H7HzsgFaaK2Dsu5OU>aJt8LQ)JIB2PC-dU zO+!mZ&%nsUEMsBiA^XXTHy^(I*sSjaz4|!x>f^+j3n5o-)+1t)UVWrwKoL@i8B{MuH39g#3Y`-lbX-SDJZF^X=v%_ z85r%Em}M-iJj_3N@#e#qADi{v^TDXTQGKKOIC17e$d#M*h?vClcTzHP3Q8(!8d^Gf z21X`k84D{9*-u`)`S9h(W_|a3FsW}+-=scHoVgHkF604nV4lP zvZANFr@W^;QZjN1N-Am^S~_|LMkZz%i>&D7`%m(cM@mLcK}khTLrX``z{tcbW8v^V zxTBIu@|H#4KYW`p6^s$Ri~qr=X;wrlF;yXJBMvma!0h<&k{l zk&=;9P*PFT(9+Q}FfuXAScrb|NPhB2$;c@vsiF604nV4lPM4LPk?xbYo6qHod zG_-W|42(?7EX2F4-Jd_CWX3rKB^5OdEgd}rBNH=maP;3%9sjupM|V_5cT`7rR7ZDI zM|V_5cT`7rR7ZDIM|V_5cT`7rR7ZDIM?dR#^s|1)f6YXHM|V_5cT`7rRI9I(i01CT1B6(M2A~MII>`IRzyZH4QBtJp&^Xvy6o( zlt&WEBPAoJproRvp{1i|U}R#Ju@GJ5kzD1Gl95wTQc=^;($O<8GBL|oh;H&oxRa8R zQ&3V-)6mkPys@9NkeJ-BBIgQ61e;9o2Y zBd4IGqNbsxqi0}bVwSP6@{s-H#hVXber(ovf>eDRQuT4-%!QCEH|r5GNvb|lGI9z^ zDry>9I(i01CT1B6D-YREUcCA6<;P}yC&<*tAyXeG&Rht&a;>?ARD>v&AF-fjIQZjN1N-Am^S~_|L zMkZz%3o8%VPhPzF@a4y5eJ3c?$DvRkC(c|5xpK1}5t9_^BPAoJproRvp{1i|U}R#J zv9R)x{p7`)4_|(4)^~zZeH=>lapKH{kSjOq5iv=rK2kDr3Q8(!8d^Gf21X`k84D{9 z*-u`)`S9h(W_>59)W@MxA1BUS2)S~z9ubpN>LVp1r=X;wrlF;yXJBMvma(w%kp1Mv zn-5=pY}R*zT74X9^>O0Ng^(*Z>k%xvmOzXH0mQIBd4IGqNbsxqi0}bVwSP6@{s-H#hVXber(ov zf>wPTTJ>?_%!QCEH|r5GNvl3mGI9z^Dry>9I(i01CT1B6D-YREUcCA6<;P}yC+O72 zp;I3x&Rht&a?ARD>v&AF-fmJQZjN1N-Am^S~_|LMkZz%3o8%VPhPzF@a4y5eJ2>y$6-((C(c|5 zxpK1}5t9t+BQ>9qQ&3V-)6mk`rr=X;wrlF;y zXJBMvW|6gOA3S;S=EIjC8`0|PLBgGsjGTg!ikgO&j-G*$iJ67yA&=zY?^mQ` z#zOR!NAi_NN=8mWNkvUVOGnSZ$iysTA^OQ9`N<lb?x;@gs7~&vPVT5q z?x;@gs7`*?@8oCwPXE-#4J{o#10xeN(cj4()yW;z$sLs}GI9z^Dry>9I(i01CT5nu z(?8Kc9?9Y4j_Tx&>g0~<g0~<+Llhg*A9$K z#G8Uq%Jd&$C(yRKkIfZ^n zMQz;B($O<8GBL|oh;H&oxRa8RQ&3V-)6mkF604nV4B*t=b1qUcCA6<;O-4pWIQYjUy+{ zTnM>xBO)f@PD(~jK}khTLrX``z{teR!peguFW!9k@?&FHTac(PQD1U$M|E;Xb^5n6 z7yXbcH|r5GiRbU6WaJc-RMa%Ibo302Ow2MCRvxmSym))(hp+yR&HC>7;O=|N;jX^> z>EBMA^)K3xtNzV;L`-s5A1N6*1tk?V4J{o#10xf&jD?kl?5B6UcF604?U|TmEUY}tKfU9n zeQQ73ulA?itnUQ5`Z(n3%hjhnYcJZ6D>v&AF-fjIQu7%(1tk?V4J{o#1EW0?vy6q6 zhxsQj-ro7qeziaCW_>3p{QfA^SE!Fu;rq*lkSjOq5iyD9@1&m1$SEkPsA*{F=ouL8 znV4lPtUP2tdGY4M*Rwx1>$~TJQhlZRO7(Fn)u+8^L$2JcN5mwazms|9I(i01dnRTX3o8%vPw#kX-`bD%tNm#=>pMZCJ`T<4-;Ry%ulCGE zKh$2eH|r5GNuxee^BFk>B^5OdEgd}rqdgO|jD?kl`KNchv~TT)ul`TFS>Fj-^>Ju@ z{W!Ji(_XY8SN)syh?t~RAF26_oPv^ynueB+o`KPxiCM9I(i01dnRTX3o8%vPhQ^j)_(Zv z|FoO+ouF4AhhBZX`Z#kTmNhgZelO>KoL@nF}FT^Ec}eG0C7lQu7%(1tk?V4J{o#1EW0?vy6q6hxw;> zym<5B%g_8~eJ2>z$6-|8s6Nj67j4K@|7JZRCK=U7N=8mWN#)s^M!%(_XJBMvma(w% z@a)q&UcB``+Alx-&H7F-sgJ{?K2Dsu5OU>aJt8KV)JIB2PC-fK*_uYbrK4wHWMY=F zu=4QilNWD3eEG3i-w9^*ap1^_GZ#Xx+=z%txRa8RQ&3XP>Z8$b>F604nV4BvdGO@L zn-5=pZ0!6kr+*F{IW21ALdcaHk+oQxa3>`rr=X--)JCJ<($O<8GBLBrTD1?Jym<5B zYwgEIxSsyYm1y;KA>mF+MovLVwR$&=eoIHsz{teR!b9eh@FAZY(Zf4P9{%n{N=8mW zNk#qecR5-*Ub?VugC zlXjM|u*!V!{P*maY?7Dkmuxa}3QF@8HH~pgr{6Q^k4*ZrjD^Gd=w$y+ArTPC@F zL8)I+(-^nfj-J7IWYV8yEJPo9Bp-PnHIk7V7uu3azt%RibjCe{{>a2EVeJRVv~=_gj7-cj7NSkw zCXYKQ894FUb7NXFY znT6zWeIEdB8fg>l*TnM>xBO)f@PD(~jK}khT zLrX``z{teR!peguFW!9k@?&EsNYuxTh?pcfy9YVD2RXY3IlBiry9e?4q@t#wrK4wH zWMY=Fu(Gie+`Wez5i!Z#dr0r+|05%(proRvp{1i|V6OE~xCQ>?0y3F?X-*W740^ zEv#(p=7QRBMnp`~*w@&{q(7TmSlQSKTKl*W5tFp` zwe~UT&*m0ZHgQCloYYQtIJHco_HzHz^(SFj=?+0=UN^=dZen-#1Xl`P*cVT5? zCz#}OBO)f5^}qXM?Y==hv7; zKl&N}j9K)f&3N-`=T1sSPC-dUO+!mZ&%nsU%tE}&;!a9NPC-dUz59C7(i!&*j7-eL z!NpnZ;w*M?7Q6hDky99#RMa%IboAB-MkeE#=Z2%tCZDJ{q$Sos3V$EJSDTXJ#R~7&EgFg~rS*L|6N-#w9I(i01CT12^ z9z1#R=EIjC8#_UwK5j(BB+12D?BXou^GQxYNkvUVOGnSZ$iysTVP#_{xO)#bB4U!e z_mJK%&SDp5v5T|V#aZm)EOv1gyEuzooW(BAVi#wzi?i6pS;&oMpTE?5 zh=@td-BbIR^k;JmD;vAHAhR#CkBFGW+Nq;uCu(Gk63v&B%`-q51%-wVQnDl3J z3o9GDxuEd%;6_ADQrK76$D}`-TUgoH2}=985fPJ=_LcTA>CfgCRyKBm%06yH#3Yq{ zm3>V5v$=(pjh&#jj~fv&No`+kACvxUZee9(Cur>BMnp`~*w@&{q(7TmSlQSKTKl*W z5tFp`we~UT&*m0ZHg+K^VCNX#K?PJoP%`L2K z?B;^OzQH~sViI%r!RL3lIE!7J#q2jXTU%J!*v$o_{iFRv#3bhKq@&*tF604nV9WeSlQSKX89aAa^lQ|kSjML zViNA8WaJc-vvZgBBd4IG zqNbsxqi0}bVrJnl3Z11w|Lsrczx@gQw?Cn?ROl=fI!lGlQfeYLPPmhjkyB7oQPa@U z(K9eIF|){8dGIuT@#e#q9~(ieHVzy)appqEl^YQ;33pO5atcZ+Y8qNPdIm-&W)@Z+ zJbCfv!CfgCRyKBXL1tfO9}zK$xqD_Glm2XOVP#`C7v%Qk_7M@2n7ilpG3n3d7FITP zb3x(j!HtNRq_D5Bk4b+vx3IFY6O{IGBO)d#?JMnL(x1&OtZeKAm3`cZh)F8@D*Kr9 zXLAcH8#_U5A2%XmlG?u7J|_Ly+``JnPSDuLjfj|}v9Ga@Nq;uCu(GiewDxf$A|`3= zYwcswpUo|-Z0rP`ecXtMNjm#F`{O#3bhKgU{{|{+F6je=;{)TUgoH%>|?Vqy0q0BMovLVMNLCXN6)~>#LU9VgC{TEeE9NXW9M&C8%It{_|KUOq4AX)k#Vd|xRa8R zQ&3V-)6mk*~yP_3sj| z{$1kLze~J2b6uUeuFhOnXRhl%Egik_z{tc*^mldUlEs~rjGTg!ikgO&j-G*$iJ67y zAdi`a=xEH$LUb}_W;tD*xr~`v&c+vGW|oU_Xw1w)bTwvXA-Wlpa3>`rr=X;wrlF;y zXJBMvX5lZoI&)o}xvtJ!S7)xPGuPFb>*~yP_3skBGrBr+c_(*LGI9z^Dry>9I(i01 zCT12{tM6K5`jT)7bulW->`Bd4IGqNbsxqi0}bVrF6G!IKwn zK79GHu@fZf<3>bGl3bm+uFhOnXRfO=*VUQp>dbX@=DIp_U7fjnKI!Ng7@3%5EUawo z1b6S@Mnp_<_a0I*atcZ+Y8qNPdIm-&W*G}B8#_VjJ=}WMVeAu(GieRQ7QrA||QqV`O4Bx3IFY6V&!`BO)fL?PFwOHn*^{u@f}cfBqW# zh=@td-5Hsf%`L2K?B;^jzSce>ViI$A#{aKa`wi7CyYB-26|=9GOMZg3y>^IBfV>$%C9ia#H$7|J^sHrVoT(fKV@*TLg^r$qk%^gwm5rT9B6FDQ zmhk~@^PuA^?(mS~yWFF?<$h4p&~l-pXJBMvW?^MxCz8kTKjS z)!DPj*|W*nv&q@B$=S2X*|W*nv&q@BiF2#7XA|o-Hnd#m=ouK9m|0la*oh>vIS%73 z;{)90L9V#NL)_&ar{L=nsA*_}uS-YIz{teR!pg=@bWI|2aLuVUZ|(gUYhy#pg^r$q zk%^gwm5rT9BAeqdUK>x1c^mUmlgJ!gtDRc)R-Kwe=HOcGbWy*kQeM7M2iIz+L48oCCXqR~Ry&RAqdGN-%)zzVX;PomsYzrGuGLQS`Pqs< zO(Jt}&1q35P?N|UTyt903DhJq2iKf7Uw>1lCXqR~Ry*zLyE-+A%)zzVDXK?xY7&`) zYqe8SPwK|n*wAvJqi0}bVrF4wV<(cx<~WSk##1&gftrRko0pEBfsu)sg_Vt+=$b_4 z;F{MQ_AU2uKduc_`BsU9*?-8E9(GZLm zb&ZVdb%>6mW3ty(at<{OkwoSoWarZmNo1~)o#Lrp^@kvRz2 z`7}flnd)#2iGv$gjWxH{+*)&M&8;=J*4$ciYt5}Sx7OTRvl=xGkwoSoG_Gr8WUoVX z937Lru99=8X^12;2O&G3hDah)9j+m9aO0}A=8H97todTi7i+#)^TnDk)_k$%i#1=Y zS&f>8NFs9(8rL;4vezLxj*iJ*SIIflG(-}agOHt1LnM)@4%d)4xN&u{=Fam@=lP|x z=FXZsYwoPMv*ym4J8SOzyM(-UE|El*RgG(?X^12;2US$3rXiBZ9E4=vq(&r>Wg*LH zh$J%A;anmIH?BJGq4yqo@1ge|dhen49(wPg_a1uhq4yqo??GNWmq;SZs>U_cG(-}a zgDR?1(-28y4ni_-QX`VcvXJF8L=u_ma4wO98&|#eFnH!1JWCGV!{9v(-oxNM44w() zM6VN>P^;I2_u@KsB8jXP8udnkvXV#b!r+SiOfNW=8tN$>_ie- zEhP1%PRmXtk<~(0r=iX2M6VN>>Tn%92RE(;_h@vFM)zoRk4E=sbdN^&XmpR{M6VN> zP^;IYd*nKHB8jXP8udnkvXV#b!r+SiOfNW=8tN$>_ie-EhP1% zPRmXtk<~(0r=iX2M6VN>>Tn%92RE)p_h|CDW%9XXa*rnWXmXDx_h@pDCjX|X#_n|_ zkqNc)>dC#D+$(diu@gyT=Y+<2jq_-^u(1nqvgWJP9%|?6SDJYXt`wPv3ng!WU9j) zY#iLUntTstpBrbN8)u&zXP+BqpBrbN8)u&zXP+Bq-<#R@X7;_AeQ##po7wkf_V3NE zV_;-rW?^M>&Q2te3AK6Z+4pYty_X^12;2UV|5O+zG+Ij9D8Y8oPm%t1A( zQ_~PhWDcrHotlP7B6Cp9>eMtu5}AW)QKzOMlE@rXt2#9ekwoSoZ0^gZMkJACVVCc6 zB8e;uQ6A;ATuUb ztbV7gey6N{r>uUbtbV7gey6N{=dYfPR?oq!&mgORi(H?r!fKDK_Q-0FtoF!ikF55{ zYLBe;$ZC(Q_Q-0FtoF!ikF55{YLBe;$ZC(Q_Q>kr7tL3juQs2tq2)qH&%nsU%)-jX zP9%}daTu${e2w{x4J{WsdIm-&W)@a9b|Q&vj>A~B=4;JoY=|VX>@Zdr^^3Z(A(F_l z!&r6dow~6hlE|{dSoP|?y0IaW$g;y&4eEosu_2Pkvcp)7>Z7``A(F_l!&pt~le)1X zlE|{dSk3CQy0IaW$g;y&E$WN9u_2Pkvcp)d>Z`i3A(F_l!&q(Vo4Tig^r$qk%^gwm5rT9B2$OW{@m=( z&Hmi%&&~ea?9a{q-0aWI{@m=(&Hmi%&&~ea?9a{q-2DF9>`8Ob)|)-K*^`?+x!IGO zJ-OMFn?1SNlbb!c*^`?+x!IHEAQKw%G@HG+*^B0(qi0}bVrF4wV<(cx<_N8MTJsP| zWLdb#FLEM@EDN2ylM_i~S?J}xoJb!Q*yX#NNFvKZlt(!&7dm)&1f?)rDv zzq|h3^{+X|gvLD0u77v^YaTj!21X`k7FITPB8hB{(3+<;50ONcg^T*}aqqkfJ0HR{)>U!#7F`Zem;s9&Rgjruj}*QigUK6O29<9a%J21X`k7FITP zqH7YF(3+=>`czIL%fdx|krPQ|S?J`QoJb!Q*yNj>NFvL^F5l%u5?L0aoQ5{K&vf(* zj7-cdtZeK=*Cg_**C*E}*VEB6FfuW-u(GieUDIUOaiODUU}R!uVP#_{(uAZRlYUJ4 zG3m#oACrDe`Z4Lpq#u)hO!_hD$D|*Veso=(^kdSGNk1n2nDk@Pk4Zl!{h0J)(vL|$ zCjFT7W73bVr)^wMN6)~>#LU9V#!hriA`@Ekv`Ih8Nn}~L$S-mti7X49ypt12WLfCt zy_`rQ%fcWZiGe)am~`s8{#dIm-&W)@a9cA{&V z>^d%V^bCwl%q*;I>_pm-^!Q*yNj>NFvL^E~g=q$h6V@jP55r10xeN3o9GDbKB(ngPlx4itBA1g0^?x)LJ zU;e4mJ+YMiM{k$gKl_IA$micyPVaebIXzvK(-($v`ubA351h*Slc$nDeJX$EH&5l} z)2GtBa4MtY<=0N-%^wKmeLvZiCx31%|KO`fdH3_D^1&BR<*$ADRDR|UT>HUTZasBX z9(w-K@|KsLDCwE0Tzx8*N5A+$dF*$t%lgq%dFbcN{n=A_$Jb8f^p|}7=WdqMi)}f5 zWh$S%?#q|HYc7BI=Tj-~d$7ECI+d^TANa4l`0S~C`5&LkD_=U5-~BDePn^mZ-g7Gd z`iD>Dn}6d}o^<@|hfn3xKQ8~osl4lvQ~B8Ar}Bw+pUN-GKltWYo_fz!dG3P`m(Tvh z8_V;5`K{%%AAeVQKK$15^!rZbg&#SU&;RXH z`Px4`mABlA<-LzSR6hEa?dKc@4Z`I`q+1t_q^k=@`HczZRN=y zdS`k1M}MF^_ft=nPyfBA%S&JSh4PKx{?+o*uY9z;@-P2p@&C(|ZS2eK+qcVOk6e|v ze8;`==ic~8`Sjn-<;(xLB?|Mpb=%fCOB=bn1F{PGKL zDqsKgca{JCpFdQd`Ngh$>R(OexBg%+-z*ROe}DgPdefWAKYHuu%XdEZh4S`K{(RYA z*vs$y^Hcf5zj`Xa_VB~ykw+dWAHVa7^8MfUm2!IFxiUX9m#=>APripg8}-huTjlTE zeX)G^+dor&{1<<(ZF{@-v_NQhDKD zyi|VaE5BX-$-nzX`LjR$$@1Ml|M~L%fBLoZq2K&QdE$vD${(LfIo+iE&vM^4PUVmO z&7Z9AkM!67t8Np1YoGn!##f7fy7rOB-%vjC_W$Eg*IqsMZ@ufy<*9eRvHbP#dF)%S Lzy11eJ3jqy(ep8C literal 0 HcmV?d00001 diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index 1afc97ac66..b4a5c38c4b 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -2852,4 +2852,48 @@ Lantern: Some(( ], wind_sway: 0.0, )), +// Anvil +Anvil: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.anvil.anvil-0", + offset: (-5.5, -7.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Cauldron +Cauldron: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cauldron.cauldron-0", + offset: (-10.0, -10.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Forge +Forge: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.forge.forge-0", + offset: (-20.0, -20.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), +// Crafting Bench +CraftingBench: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.crafting_bench.crafting_bench-0", + offset: (-9.5, -7.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), ) diff --git a/client/src/lib.rs b/client/src/lib.rs index 89a0b26021..805b5b1bda 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -35,8 +35,8 @@ use common::{ recipe::RecipeBook, resources::{DeltaTime, PlayerEntity, TimeOfDay}, terrain::{ - block::Block, map::MapConfig, neighbors, BiomeKind, SitesKind, TerrainChunk, - TerrainChunkSize, SpriteKind, + block::Block, map::MapConfig, neighbors, BiomeKind, SitesKind, SpriteKind, TerrainChunk, + TerrainChunkSize, }, trade::{PendingTrade, SitePrices, TradeAction, TradeId, TradeResult}, uid::{Uid, UidAllocator}, @@ -970,27 +970,37 @@ impl Client { pub fn recipe_book(&self) -> &RecipeBook { &self.recipe_book } - pub fn available_recipes(&self) -> &HashMap> { &self.available_recipes } + pub fn available_recipes(&self) -> &HashMap> { + &self.available_recipes + } pub fn can_craft_recipe(&self, recipe: &str) -> Option> { self.recipe_book .get(recipe) .zip(self.inventories().get(self.entity())) - .map(|(recipe, inv)| if inv.contains_ingredients(&*recipe).is_ok() { - Some(recipe.craft_sprite) - } else { - None + .map(|(recipe, inv)| { + if inv.contains_ingredients(&*recipe).is_ok() { + Some(recipe.craft_sprite) + } else { + None + } }) .unwrap_or(None) } - pub fn craft_recipe(&mut self, recipe: &str, craft_sprite: Option<(Vec3, SpriteKind)>) -> bool { - if self.can_craft_recipe(recipe).map_or(false, |cs| cs.map_or(true, |cs| Some(cs) == craft_sprite.map(|(_, s)| s))) { + pub fn craft_recipe( + &mut self, + recipe: &str, + craft_sprite: Option<(Vec3, SpriteKind)>, + ) -> bool { + if self.can_craft_recipe(recipe).map_or(false, |cs| { + cs.map_or(true, |cs| Some(cs) == craft_sprite.map(|(_, s)| s)) + }) { self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryEvent( InventoryEvent::CraftRecipe { recipe: recipe.to_string(), craft_sprite: craft_sprite.map(|(pos, _)| pos), - } + }, ))); true } else { diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index 19dc1eb138..282438ea75 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -76,9 +76,15 @@ impl From for InventoryManip { Self::SplitSwap(Slot::Inventory(inv1), Slot::Inventory(inv2)) }, InventoryEvent::Drop(inv) => Self::Drop(Slot::Inventory(inv)), - InventoryEvent::SplitDrop(inv) => Self::SplitDrop(Slot::Inventory(inv)), + InventoryEvent::SplitDrop(inv) => Self::SplitDrop(Slot::Inventory(inv)), InventoryEvent::Sort => Self::Sort, - InventoryEvent::CraftRecipe { recipe, craft_sprite } => Self::CraftRecipe { recipe, craft_sprite }, + InventoryEvent::CraftRecipe { + recipe, + craft_sprite, + } => Self::CraftRecipe { + recipe, + craft_sprite, + }, } } } diff --git a/common/src/comp/inventory/item/modular.rs b/common/src/comp/inventory/item/modular.rs index 416ff688dd..d1f604c8f1 100644 --- a/common/src/comp/inventory/item/modular.rs +++ b/common/src/comp/inventory/item/modular.rs @@ -1,5 +1,5 @@ use super::{tool, ItemKind, ItemTag, Quality, RawItemDef, TagExampleInfo, ToolKind}; -use crate::recipe::{RawRecipeBook, RawRecipeInput, RawRecipe}; +use crate::recipe::{RawRecipe, RawRecipeBook, RawRecipeInput}; use hashbrown::HashMap; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; @@ -234,10 +234,7 @@ fn make_weapon_def(toolkind: ToolKind) -> (String, RawItemDef) { (identifier, item) } -fn make_recipe_def( - identifier: String, - toolkind: ToolKind, -) -> RawRecipe { +fn make_recipe_def(identifier: String, toolkind: ToolKind) -> RawRecipe { let output = (identifier, 1); let mut inputs = Vec::new(); for &modkind in &MODKINDS { diff --git a/common/src/recipe.rs b/common/src/recipe.rs index 86be1a3637..2a1110948d 100644 --- a/common/src/recipe.rs +++ b/common/src/recipe.rs @@ -99,9 +99,7 @@ pub(crate) struct RawRecipe { #[derive(Clone, Deserialize)] #[serde(transparent)] #[allow(clippy::type_complexity)] -pub(crate) struct RawRecipeBook( - pub(crate) HashMap, -); +pub(crate) struct RawRecipeBook(pub(crate) HashMap); impl assets::Asset for RawRecipeBook { type Loader = assets::RonLoader; @@ -144,14 +142,27 @@ impl assets::Compound for RecipeBook { let recipes = raw .0 .iter() - .map(|(name, RawRecipe { output, inputs, craft_sprite })| { - let inputs = inputs - .iter() - .map(load_recipe_input) - .collect::, _>>()?; - let output = load_item_def(output)?; - Ok((name.clone(), Recipe { output, inputs, craft_sprite: *craft_sprite })) - }) + .map( + |( + name, + RawRecipe { + output, + inputs, + craft_sprite, + }, + )| { + let inputs = inputs + .iter() + .map(load_recipe_input) + .collect::, _>>()?; + let output = load_item_def(output)?; + Ok((name.clone(), Recipe { + output, + inputs, + craft_sprite: *craft_sprite, + })) + }, + ) .collect::>()?; Ok(RecipeBook { recipes }) diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index 4d3fdd77f7..6aa1cb841d 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -143,6 +143,10 @@ make_case_elim!( RedAlgae = 0x74, UnderwaterVent = 0x75, Lantern = 0x76, + CraftingBench = 0x77, + Forge = 0x78, + Cauldron = 0x79, + Anvil = 0x7A, } ); @@ -184,6 +188,10 @@ impl SpriteKind { SpriteKind::Mud => 0.36, SpriteKind::ChestBuried => 0.91, SpriteKind::StonyCoral => 1.4, + SpriteKind::CraftingBench => 1.18, + SpriteKind::Forge => 2.7, + SpriteKind::Cauldron => 1.27, + SpriteKind::Anvil => 1.1, // TODO: Find suitable heights. SpriteKind::BarrelCactus | SpriteKind::RoundCactus @@ -309,6 +317,10 @@ impl SpriteKind { | SpriteKind::VialEmpty | SpriteKind::FireBowlGround | SpriteKind::Lantern + | SpriteKind::CraftingBench + | SpriteKind::Forge + | SpriteKind::Cauldron + | SpriteKind::Anvil ) } } diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index dfdae58433..50ea7b07e6 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -576,7 +576,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .expect("We know entity exists since we got its inventory."); drop(inventories); }, - comp::InventoryManip::CraftRecipe { recipe, craft_sprite } => { + comp::InventoryManip::CraftRecipe { + recipe, + craft_sprite, + } => { let recipe_book = default_recipe_book().read(); let craft_result = recipe_book .get(&recipe) diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index 630bc3441c..048386c532 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -434,16 +434,23 @@ impl<'a> Widget for Crafting<'a> { .unwrap_or(false) }) }); - let state = if self.client.available_recipes() - .get(name.as_str()) - .map_or(false, |cs| cs.map_or(true, |cs| Some(cs) == self.show.craft_sprite.map(|(_, s)| s))) - { - RecipeIngredientQuantity::All - } else if at_least_some_ingredients { - RecipeIngredientQuantity::Some - } else { - RecipeIngredientQuantity::None - }; + let state = + if self + .client + .available_recipes() + .get(name.as_str()) + .map_or(false, |cs| { + cs.map_or(true, |cs| { + Some(cs) == self.show.craft_sprite.map(|(_, s)| s) + }) + }) + { + RecipeIngredientQuantity::All + } else if at_least_some_ingredients { + RecipeIngredientQuantity::Some + } else { + RecipeIngredientQuantity::None + }; (name, recipe, state) }) .collect(); @@ -532,7 +539,11 @@ impl<'a> Widget for Crafting<'a> { .client .available_recipes() .get(recipe_name.as_str()) - .map_or(false, |cs| cs.map_or(true, |cs| Some(cs) == self.show.craft_sprite.map(|(_, s)| s))); + .map_or(false, |cs| { + cs.map_or(true, |cs| { + Some(cs) == self.show.craft_sprite.map(|(_, s)| s) + }) + }); // Craft button if Button::image(self.imgs.button) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 238474b5e3..fd82fd1e9d 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -22,10 +22,10 @@ mod social; mod trade; pub mod util; +pub use crafting::CraftingTab; pub use hotbar::{SlotContents as HotbarSlotContents, State as HotbarState}; pub use item_imgs::animate_by_pulse; pub use settings_window::ScaleChange; -pub use crafting::CraftingTab; use bag::Bag; use buffs::BuffsBar; @@ -75,7 +75,7 @@ use common::{ BuffKind, Item, }, outcome::Outcome, - terrain::{TerrainChunk, SpriteKind}, + terrain::{SpriteKind, TerrainChunk}, trade::{ReducedInventory, TradeAction}, uid::Uid, util::srgba_to_linear, @@ -381,7 +381,10 @@ pub enum Event { Logout, Quit, - CraftRecipe { recipe: String, craft_sprite: Option<(Vec3, SpriteKind)> }, + CraftRecipe { + recipe: String, + craft_sprite: Option<(Vec3, SpriteKind)>, + }, InviteMember(Uid), AcceptInvite, DeclineInvite, @@ -560,7 +563,11 @@ impl Show { } } - pub fn open_crafting_tab(&mut self, tab: CraftingTab, craft_sprite: Option<(Vec3, SpriteKind)>) { + pub fn open_crafting_tab( + &mut self, + tab: CraftingTab, + craft_sprite: Option<(Vec3, SpriteKind)>, + ) { self.selected_crafting_tab(tab); self.crafting(true); self.craft_sprite = craft_sprite; @@ -1406,7 +1413,8 @@ impl Hud { .set(overitem_id, ui_widgets); } else if let Some(sprite) = block.get_sprite() { overitem::Overitem::new( - format!("{:?}", sprite).into(), // TODO: A better way to generate text for this + format!("{:?}", sprite).into(), /* TODO: A better way to generate text + * for this */ overitem::TEXT_COLOR, pos.distance_squared(player_pos), &self.fonts, @@ -2443,7 +2451,10 @@ impl Hud { { match event { crafting::Event::CraftRecipe(recipe) => { - events.push(Event::CraftRecipe { recipe, craft_sprite: self.show.craft_sprite }); + events.push(Event::CraftRecipe { + recipe, + craft_sprite: self.show.craft_sprite, + }); }, crafting::Event::Close => { self.show.stats = false; diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index 6b5a6eb14f..baf8fff933 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -1,3 +1,4 @@ +use crate::hud::CraftingTab; use common::{ terrain::{BlockKind, SpriteKind, TerrainChunk}, vol::{IntoVolIterator, RectRasterableVol}, @@ -5,7 +6,6 @@ use common::{ use common_base::span; use rand::prelude::*; use vek::*; -use crate::hud::CraftingTab; #[derive(Copy, Clone)] pub enum Interaction { @@ -115,7 +115,18 @@ impl BlocksOfInterest { Some(SpriteKind::WhiteFlower) => flowers.push(pos), Some(SpriteKind::YellowFlower) => flowers.push(pos), Some(SpriteKind::Sunflower) => flowers.push(pos), - Some(SpriteKind::Pot) => interactables.push((pos, Interaction::Craft(CraftingTab::Food))), + Some(SpriteKind::CraftingBench) => { + interactables.push((pos, Interaction::Craft(CraftingTab::All))) + }, + Some(SpriteKind::Forge) => { + interactables.push((pos, Interaction::Craft(CraftingTab::Dismantle))) + }, + Some(SpriteKind::Cauldron) => { + interactables.push((pos, Interaction::Craft(CraftingTab::Potion))) + }, + Some(SpriteKind::Anvil) => { + interactables.push((pos, Interaction::Craft(CraftingTab::Weapon))) + }, _ => {}, }, } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 976347af71..102cfd3201 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -38,7 +38,7 @@ use crate::{ key_state::KeyState, menu::char_selection::CharSelectionState, render::Renderer, - scene::{camera, CameraMode, Scene, SceneData, terrain::Interaction}, + scene::{camera, terrain::Interaction, CameraMode, Scene, SceneData}, settings::Settings, window::{AnalogGameInput, Event, GameInput}, Direction, Error, GlobalState, PlayState, PlayStateResult, @@ -591,16 +591,20 @@ impl PlayState for SessionState { if let Some(interactable) = self.interactable { let mut client = self.client.borrow_mut(); match interactable { - Interactable::Block(block, pos, interaction) => match interaction { - Interaction::Collect => { - if block.is_collectible() { - client.collect_block(pos); - } - }, - Interaction::Craft(tab) => self.hud.show.open_crafting_tab( - tab, - block.get_sprite().map(|s| (pos, s)), - ), + Interactable::Block(block, pos, interaction) => { + match interaction { + Interaction::Collect => { + if block.is_collectible() { + client.collect_block(pos); + } + }, + Interaction::Craft(tab) => { + self.hud.show.open_crafting_tab( + tab, + block.get_sprite().map(|s| (pos, s)), + ) + }, + } }, Interactable::Entity(entity) => { if client @@ -1187,7 +1191,10 @@ impl PlayState for SessionState { client.request_site_economy(id); }, - HudEvent::CraftRecipe { recipe, craft_sprite } => { + HudEvent::CraftRecipe { + recipe, + craft_sprite, + } => { self.client.borrow_mut().craft_recipe(&recipe, craft_sprite); }, HudEvent::InviteMember(uid) => { diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index 5a124bfb5f..7058736b25 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -300,9 +300,7 @@ impl Archetype for House { Ori::North => 4, }; let end_window = BlockMask::new( - Block::air(attr.window) - .with_ori(end_ori) - .unwrap(), + Block::air(attr.window).with_ori(end_ori).unwrap(), structural_layer, ); let fire = BlockMask::new(Block::air(SpriteKind::Ember), foundation_layer); @@ -532,19 +530,19 @@ impl Archetype for House { center_offset.x, center_offset.y, z + 100, - )) % 5 + )) % 8 { 0..=1 => SpriteKind::Crate, 2 => SpriteKind::Bench, - 3 => SpriteKind::ChairSingle, - 4 => SpriteKind::FireBowlGround, + 3 => SpriteKind::Anvil, + 4 => SpriteKind::Cauldron, + 5 => SpriteKind::CraftingBench, + 6 => SpriteKind::FireBowlGround, + //8 => SpriteKind::Forge, _ => unreachable!(), }; - return BlockMask::new( - Block::air(furniture).with_ori(end_ori).unwrap(), - 1, - ); + return BlockMask::new(Block::air(furniture).with_ori(end_ori).unwrap(), 1); } else if (!attr.storey_fill.has_lower() && profile.y < ceil_height) || (!attr.storey_fill.has_upper() && profile.y >= ceil_height) { @@ -623,7 +621,7 @@ impl Archetype for House { 0 => SpriteKind::HangingSign, 1 | 2 | 3 => SpriteKind::HangingBasket, 4 => SpriteKind::WallSconce, - 5 => SpriteKind::WallLampSmall, + 5 => SpriteKind::WallLampSmall, _ => SpriteKind::DungeonWallDecor, }; From cf33cc870433c8f0f853625c1cdf3fe05e7529c0 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 17 Apr 2021 23:27:42 +0100 Subject: [PATCH 03/12] Prevent crafting without station --- server/src/events/inventory_manip.rs | 31 ++++++++++++++++--- voxygen/src/hud/crafting.rs | 1 + voxygen/src/hud/mod.rs | 11 +++++++ .../settlement/building/archetype/house.rs | 8 ++--- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 50ea7b07e6..f921f584ca 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -584,10 +584,33 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv let craft_result = recipe_book .get(&recipe) .filter(|r| { - let sprite = craft_sprite - .and_then(|pos| state.terrain().get(pos).ok().copied()) - .and_then(|block| block.get_sprite()); - r.craft_sprite.map_or(true, |cs| Some(cs) == sprite) + if let Some(needed_sprite) = r.craft_sprite { + let sprite = craft_sprite + .filter(|pos| { + let entity_cylinder = get_cylinder(state, entity); + if !within_pickup_range(entity_cylinder, || { + Some(find_dist::Cube { + min: pos.as_(), + side_length: 1.0, + }) + }) { + debug!( + ?entity_cylinder, + "Failed to pick up block as not within range, block pos: \ + {}", + pos + ); + false + } else { + true + } + }) + .and_then(|pos| state.terrain().get(pos).ok().copied()) + .and_then(|block| block.get_sprite()); + Some(needed_sprite) == sprite + } else { + false + } }) .and_then(|r| { r.perform( diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index 048386c532..9b59b8398d 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -699,6 +699,7 @@ impl<'a> Widget for Crafting<'a> { .resize(recipe.inputs().len(), &mut ui.widget_id_generator()) }); }; + // Widget generation for every ingredient for (i, (recipe_input, amount)) in recipe.inputs.iter().enumerate() { let item_def = match recipe_input { diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index fd82fd1e9d..5e3cea6c4c 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -74,6 +74,7 @@ use common::{ skills::{Skill, SkillGroupKind}, BuffKind, Item, }, + consts::MAX_PICKUP_RANGE, outcome::Outcome, terrain::{SpriteKind, TerrainChunk}, trade::{ReducedInventory, TradeAction}, @@ -3361,6 +3362,16 @@ impl Hud { .handle_event(conrod_core::event::Input::Text("\t".to_string())); } + // Stop selecting a sprite to perform crafting with when out of range + self.show.craft_sprite = self.show.craft_sprite.filter(|(pos, _)| { + self.show.crafting + && if let Some(player_pos) = client.position() { + pos.map(|e| e as f32 + 0.5).distance(player_pos) < MAX_PICKUP_RANGE + } else { + false + } + }); + // Optimization: skip maintaining UI when it's off. if !self.show.ui { return std::mem::take(&mut self.events); diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index 7058736b25..398789a40c 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -530,13 +530,13 @@ impl Archetype for House { center_offset.x, center_offset.y, z + 100, - )) % 8 + )) % 7 { 0..=1 => SpriteKind::Crate, 2 => SpriteKind::Bench, 3 => SpriteKind::Anvil, - 4 => SpriteKind::Cauldron, - 5 => SpriteKind::CraftingBench, + 4 => SpriteKind::Cauldron, + 5 => SpriteKind::CraftingBench, 6 => SpriteKind::FireBowlGround, //8 => SpriteKind::Forge, _ => unreachable!(), @@ -621,7 +621,7 @@ impl Archetype for House { 0 => SpriteKind::HangingSign, 1 | 2 | 3 => SpriteKind::HangingBasket, 4 => SpriteKind::WallSconce, - 5 => SpriteKind::WallLampSmall, + 5 => SpriteKind::WallLampSmall, _ => SpriteKind::DungeonWallDecor, }; From c40bd37452dc191cab87707aecba3f3b6ffe9016 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 18 Apr 2021 02:25:19 +0200 Subject: [PATCH 04/12] more sprite stuff and crafting UI update fix item images fix CR display --- .../items/crafting_tools/craftsman_hammer.ron | 6 +- assets/common/items/tool/craftsman_hammer.ron | 18 +++++ assets/common/recipe_book.ron | 46 ++++++++---- assets/voxygen/i18n/en/hud/crafting.ron | 7 +- assets/voxygen/item_image_manifest.ron | 27 ++++++- .../voxygen/voxel/biped_weapon_manifest.ron | 6 +- .../voxygen/voxel/glider/glider_cultists.vox | Bin 14960 -> 14960 bytes assets/voxygen/voxel/sprite/anvil/anvil-0.vox | Bin 4432 -> 4432 bytes .../voxel/sprite/cauldron/cauldron-0.vox | Bin 10696 -> 10696 bytes .../voxel/sprite/cooking_pot/pot-0.vox | Bin 0 -> 8340 bytes assets/voxygen/voxel/sprite_manifest.ron | 11 +++ .../voxygen/voxel/weapon/hammer/craftsman.vox | Bin 2240 -> 2240 bytes common/src/terrain/sprite.rs | 3 + voxygen/src/hud/crafting.rs | 66 ++++++++++++++++-- voxygen/src/hud/mod.rs | 10 +-- voxygen/src/scene/terrain/watcher.rs | 3 + .../settlement/building/archetype/house.rs | 6 +- 17 files changed, 175 insertions(+), 34 deletions(-) create mode 100644 assets/common/items/tool/craftsman_hammer.ron create mode 100644 assets/voxygen/voxel/sprite/cooking_pot/pot-0.vox diff --git a/assets/common/items/crafting_tools/craftsman_hammer.ron b/assets/common/items/crafting_tools/craftsman_hammer.ron index f8d7f84ae3..24b5822c37 100644 --- a/assets/common/items/crafting_tools/craftsman_hammer.ron +++ b/assets/common/items/crafting_tools/craftsman_hammer.ron @@ -1,9 +1,9 @@ ItemDef( - name: "Craftsman Hammer", - description: "Used to craft various items.", + name: "Old Hammer", + description: "You don't quite remember where you got this from...", kind: Ingredient( kind: "CraftsmanHammer", ), - quality: Moderate, + quality: Low, tags: [CraftingTool], ) diff --git a/assets/common/items/tool/craftsman_hammer.ron b/assets/common/items/tool/craftsman_hammer.ron new file mode 100644 index 0000000000..599a308d0d --- /dev/null +++ b/assets/common/items/tool/craftsman_hammer.ron @@ -0,0 +1,18 @@ +ItemDef( + name: "Craftsman Hammer", + description: "Used to craft various items.", + kind: Tool(( + kind: Hammer, + hands: One, + stats: Direct(( + equip_time_secs: 0.25, + power: 0.2, + poise_strength: 0.25, + speed: 1.5, + crit_chance: 0.0, + crit_mult: 0.0, + )), + )), + quality: Common, + tags: [CraftingTool], +) \ No newline at end of file diff --git a/assets/common/recipe_book.ron b/assets/common/recipe_book.ron index 6b584e76b1..5b1b11f81b 100644 --- a/assets/common/recipe_book.ron +++ b/assets/common/recipe_book.ron @@ -1,19 +1,20 @@ { "crafting_hammer": ( - output: ("common.items.crafting_tools.craftsman_hammer", 1), + output: ("common.items.tool.craftsman_hammer", 1), inputs: [ (Item("common.items.crafting_ing.twigs"), 6), (Item("common.items.crafting_ing.stones"), 6), ], - craft_sprite: Some(CraftingBench), + craft_sprite: Some(Anvil), ), "mortar_pestle": ( output: ("common.items.crafting_tools.mortar_pestle", 1), inputs: [ (Item("common.items.crafting_ing.stones"), 6), (Item("common.items.food.coconut"), 1), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), ], + craft_sprite: Some(CraftingBench), ), "sewing_set": ( output: ("common.items.crafting_tools.sewing_set", 1), @@ -22,12 +23,13 @@ (Item("common.items.crafting_ing.twigs"), 4), (Item("common.items.crafting_ing.stones"), 2), ], + craft_sprite: Some(CraftingBench), ), "velorite_frag": ( output: ("common.items.ore.veloritefrag", 2), inputs: [ (Item("common.items.ore.velorite"), 1), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), @@ -63,6 +65,7 @@ (Item("common.items.ore.veloritefrag"), 2), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], + craft_sprite: Some(CraftingBench), ), "firework_blue": ( output: ("common.items.utility.firework_blue", 1), @@ -73,6 +76,7 @@ (Item("common.items.ore.veloritefrag"), 1), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], + craft_sprite: Some(CraftingBench), ), "firework_green": ( output: ("common.items.utility.firework_green", 1), @@ -83,6 +87,7 @@ (Item("common.items.ore.veloritefrag"), 1), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], + craft_sprite: Some(CraftingBench), ), "firework_purple": ( output: ("common.items.utility.firework_purple", 1), @@ -93,6 +98,7 @@ (Item("common.items.ore.veloritefrag"), 1), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], + craft_sprite: Some(CraftingBench), ), "firework_red": ( output: ("common.items.utility.firework_red", 1), @@ -103,6 +109,7 @@ (Item("common.items.ore.veloritefrag"), 1), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], + craft_sprite: Some(CraftingBench), ), "firework_white": ( output: ("common.items.utility.firework_white", 1), @@ -113,6 +120,7 @@ (Item("common.items.ore.veloritefrag"), 1), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], + craft_sprite: Some(CraftingBench), ), "firework_yellow": ( output: ("common.items.utility.firework_yellow", 1), @@ -123,6 +131,7 @@ (Item("common.items.ore.veloritefrag"), 1), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], + craft_sprite: Some(CraftingBench), ), "apple_shroom_curry": ( output: ("common.items.food.apple_mushroom_curry", 1), @@ -132,7 +141,7 @@ (Item("common.items.food.apple"), 4), (Item("common.items.crafting_tools.mortar_pestle"), 0), ], - craft_sprite: Some(Cauldron), + craft_sprite: Some(CookingPot), ), "salad_plain": ( output: ("common.items.food.plainsalad", 1), @@ -179,7 +188,7 @@ (Item("common.items.crafting_ing.twigs"), 5), (Item("common.items.crafting_ing.leather_scraps"), 5), (Item("common.items.crafting_ing.cloth_scraps"), 10), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], craft_sprite: Some(CraftingBench), @@ -190,7 +199,7 @@ (Item("common.items.crafting_ing.twigs"), 5), (Item("common.items.crafting_ing.cloth_scraps_red"), 10), (Item("common.items.crafting_ing.leather_scraps"), 5), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], craft_sprite: Some(CraftingBench), @@ -202,7 +211,7 @@ (Item("common.items.crafting_ing.leather_scraps"), 5), (Item("common.items.crafting_ing.cloth_scraps"), 5), (Item("common.items.crafting_ing.emerald"), 1), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], craft_sprite: Some(CraftingBench), @@ -215,7 +224,7 @@ (Item("common.items.crafting_ing.leather_scraps"), 5), (Item("common.items.crafting_ing.cloth_scraps"), 5), (Item("common.items.crafting_ing.ruby"), 1), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], craft_sprite: Some(CraftingBench), @@ -229,7 +238,7 @@ (Item("common.items.crafting_ing.cloth_scraps"), 5), (Item("common.items.crafting_ing.icy_fang"), 1), (Item("common.items.crafting_ing.ruby"), 1), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], craft_sprite: Some(CraftingBench), @@ -242,7 +251,7 @@ (Item("common.items.crafting_ing.leather_scraps"), 5), (Item("common.items.crafting_ing.cloth_scraps"), 5), (Item("common.items.crafting_ing.ruby"), 1), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), (Item("common.items.crafting_tools.sewing_set"), 0), ], craft_sprite: Some(CraftingBench), @@ -253,7 +262,7 @@ (Item("common.items.crafting_ing.twigs"), 20), (Item("common.items.ore.veloritefrag"), 8), (Item("common.items.crafting_ing.ruby"), 4), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), ], ), "Hunting Bow": ( @@ -278,30 +287,37 @@ "adventure back": ( output: ("common.items.armor.agile.back", 1), inputs: [(Item("common.items.crafting_ing.leather_scraps"), 4)], + craft_sprite: Some(CraftingBench), ), "adventure belt": ( output: ("common.items.armor.agile.belt", 1), inputs: [(Item("common.items.crafting_ing.leather_scraps"), 2)], + craft_sprite: Some(CraftingBench), ), "adventure chest": ( output: ("common.items.armor.agile.chest", 1), inputs: [(Item("common.items.crafting_ing.leather_scraps"), 12)], + craft_sprite: Some(CraftingBench), ), "adventure feet": ( output: ("common.items.armor.agile.foot", 1), inputs: [(Item("common.items.crafting_ing.leather_scraps"), 3)], + craft_sprite: Some(CraftingBench), ), "adventure hands": ( output: ("common.items.armor.agile.hand", 1), inputs: [(Item("common.items.crafting_ing.leather_scraps"), 4)], + craft_sprite: Some(CraftingBench), ), "adventure pants": ( output: ("common.items.armor.agile.pants", 1), inputs: [(Item("common.items.crafting_ing.leather_scraps"), 8)], + craft_sprite: Some(CraftingBench), ), "adventure shoulder": ( output: ("common.items.armor.agile.shoulder", 1), inputs: [(Item("common.items.crafting_ing.leather_scraps"), 12)], + craft_sprite: Some(CraftingBench), ), "Seashell Necklace": ( output: ("common.items.armor.misc.neck.shell", 1), @@ -311,6 +327,7 @@ (Item("common.items.crafting_ing.seashells"), 3), (Item("common.items.crafting_tools.sewing_set"), 0), ], + craft_sprite: Some(CraftingBench), ), "red cloth": ( output: ("common.items.crafting_ing.cloth_scraps_red", 1), @@ -360,6 +377,7 @@ (Item("common.items.armor.misc.bag.tiny_leather_pouch"), 2), (Item("common.items.crafting_tools.sewing_set"), 0), ], + craft_sprite: Some(CraftingBench), ), "sturdy red backpack": ( output: ("common.items.armor.misc.bag.sturdy_red_backpack", 1), @@ -395,7 +413,7 @@ (Item("common.items.crafting_ing.cloth_scraps"), 1), // TODO: Replace with plant fiber when obtainable (Item("common.items.crafting_ing.stones"), 5), // TODO: Replace with iron ingots when obtainable (Item("common.items.crafting_ing.twigs"), 4), - (Item("common.items.crafting_tools.craftsman_hammer"), 0), + (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), @@ -417,7 +435,7 @@ // output: ("common.items.crafting_ing.modular.damage.sword.metal_blade", 1), // inputs: [ // (Tag(MetalIngot), 5), - // (Item("common.items.crafting_tools.craftsman_hammer"), 0), + // (Item("common.items.tool.craftsman_hammer"), 0), // ], //), } diff --git a/assets/voxygen/i18n/en/hud/crafting.ron b/assets/voxygen/i18n/en/hud/crafting.ron index 41d5cf4a49..985f4c3bd4 100644 --- a/assets/voxygen/i18n/en/hud/crafting.ron +++ b/assets/voxygen/i18n/en/hud/crafting.ron @@ -8,7 +8,12 @@ "hud.crafting.ingredients": "Ingredients:", "hud.crafting.craft": "Craft", "hud.crafting.tool_cata": "Requires:", - + // Crafting Stations + "hud.crafting.req_crafting_station": "Requires:", + "hud.crafting.anvil": "Anvil", + "hud.crafting.cauldron": "Cauldron", + "hud.crafting.cooking_pot": "Cooking Pot", + "hud.crafting.crafting_bench": "Crafting Bench", // Tabs "hud.crafting.tabs.all": "All", "hud.crafting.tabs.armor": "Armor", diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index c863e6abbc..1a90921bbb 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -2,6 +2,23 @@ // Vox(specier), // VoxTrans(specifier, offset, (x_rot, y_rot, z_rot), zoom) ({ + // Crafting Stations + Tool("Anvil"): VoxTrans( + "voxel.sprite.anvil.anvil-0", + (0.5, 0.5, 0.0), (0.0, 60.0, 90.0), 1.0, + ), + Tool("Cauldron"): VoxTrans( + "voxel.sprite.cauldron.cauldron-0", + (0.0, 0.0, 0.0), (-50.0, 40.0, 30.0), 1.0, + ), + Tool("CookingPot"): VoxTrans( + "voxel.sprite.cooking_pot.pot-0", + (0.0, 0.0, 0.0), (0.0, 90.0, 90.0), 1.2, + ), + Tool("CraftingBench"): VoxTrans( + "voxel.sprite.crafting_bench.crafting_bench-0", + (0.0, 0.0, 0.0), (-50.0, 40.0, 20.0), 1.0, + ), // Weapons // Diary Example Images Tool("example_utility"): VoxTrans( @@ -1920,10 +1937,14 @@ "voxel.object.training_dummy", (0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8, ), - // Ingredients - Ingredient("CraftsmanHammer"): VoxTrans( //TODO This should be a 1h hammer! + // Ingredients + Tool("common.items.tool.craftsman_hammer"): VoxTrans( "voxel.weapon.hammer.craftsman", - (1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 1.0, + (1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 0.9, + ), + Ingredient("CraftsmanHammer"): VoxTrans( + "voxel.weapon.hammer.craftsman", + (1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 0.8, ), Ingredient("SewingSet"): Png( "element.items.sewing_set", diff --git a/assets/voxygen/voxel/biped_weapon_manifest.ron b/assets/voxygen/voxel/biped_weapon_manifest.ron index 1a69cb2f35..27f5b7c0ca 100644 --- a/assets/voxygen/voxel/biped_weapon_manifest.ron +++ b/assets/voxygen/voxel/biped_weapon_manifest.ron @@ -462,7 +462,11 @@ vox_spec: ("weapon.axe_1h.wood-1", (-1.5, -5.0, -3.0)), color: None ), - // Hammers + // Hammers + "common.items.tool.craftsman_hammer": ( + vox_spec: ("weapon.hammer.craftsman", (-2.5, -5.5, -4.5)), + color: None + ), "common.items.weapons.hammer.hammer_1": ( vox_spec: ("weapon.hammer.2hhammer_rusty", (-2.5, -5.5, -4.5)), color: None diff --git a/assets/voxygen/voxel/glider/glider_cultists.vox b/assets/voxygen/voxel/glider/glider_cultists.vox index 9f04aa8d038c276302fcdd76982cbdc8d00cb9fb..997223e789e488c24d4878c4cf7465704173f0ef 100644 GIT binary patch delta 253 zcmWN|I|{-;6h>hpOd$~+(3scE6cI%*pd?WXTRZJsfCNiR?JTsguoU7VEQM^vT3kXF zVBsmg1NVnp9joJOYoDc~gzUmqBKP1UK**+`VYnmo5JPB@x6npM3+bQ>m)nDn03n-# zhT)D7Ll}`aAx-hI>wW1M{^7ED@DU(nQ_v_Ijo!eL#U$C$N3x>dWKY-Wg5J^t{iS0X aXD9m1M)aL+ELjexSF60wmR4EKFSS3W*)SRa delta 253 zcmWN|I|{-;6h>hpOfe`bXv}M7iUdV4pd=9mTRZJsfCNiR(^+U?VXq6Yv=p)xYjFu# zfQ6^{4%{DZRaC`mTR%x#3E6|AMDD_akAO`Rv1B=%UaaylUs`1~JJVw=5I|9OtE+0d$0jF2a!iW6bGMcD5FCP(kuTzq+rZo4xvM_oR$Jop?ep!= z@A)`7>WERtAV;0$?B||#icxiDnVqA}ZFY{$Hxw~_M^1M*n^;aV+WqbRcE35zR6Z=# zF1I*Go7?Ohn~x~QG*7?$Jg?g^Vsq(s6fx{1MH8u!6it*yQZ(^sk)&v1(@2UYrbbdU zu{4sRpZjGVNinWwiU>PN(Zra?WB8F2O{5P=iY7`UDVk`Fq-bK(NQx$=Mp87fG;+>5NK*83{<6+-S!Z6BzsP(wU)S;L@BaPa*(yEO8R=hhdA3H|qqNc}+8(_;Tcc=V z(@2UYrbbdUu{4re577|2NK!QMqLCC$ylNyx6TSN%w|mU)F}ug?XKdQ0QM5g#HZ_X2 n$NLhONYVD#wOylVd%S2b8pX$t*Kz6F?e_0}zkj@c{TBZLT})p6 delta 907 zcmWmCF>Vw=5I|98tE+0dXN^QaK!oIkgn$J3coP$I2&asE5r^Cc-UiQI^%=L?67SFN z&wpO$xpmYQqqaegy2{y)J?#{u>dG=ZN1NO19J_BQV)~Ap?r=7-oMg27+x_i+bDF6< zE!8f!I7ge?>>Rs~D8@8Tzx+6F`!-^C>An>)>?B1KsgV>-ltxlCakfZOG_h+WMH5pa zDVkUsNzspen_E(ho0%fQPEs^6=5`K0lA?+9AxY6hX(UAxt&tQ>>>5eY#MDTNCYDC7 z`P0iq;t)xSe#{@%HMVu-w){oroB6i3-+zy)WS)uRlJ&y?p!<{{hQXHKqUn diff --git a/assets/voxygen/voxel/sprite/cauldron/cauldron-0.vox b/assets/voxygen/voxel/sprite/cauldron/cauldron-0.vox index 84279548c00488c6dd9129ce7abca2b87ac60265..b808556f42c0c1f5b6f51dbcaba7f58c530f8a9b 100644 GIT binary patch delta 851 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 X{kXcj_~X`gkN>2#w_f-s=goful}=et literal 0 HcmV?d00001 diff --git a/assets/voxygen/voxel/sprite_manifest.ron b/assets/voxygen/voxel/sprite_manifest.ron index b4a5c38c4b..4e2b11a7cd 100644 --- a/assets/voxygen/voxel/sprite_manifest.ron +++ b/assets/voxygen/voxel/sprite_manifest.ron @@ -2896,4 +2896,15 @@ CraftingBench: Some(( ], wind_sway: 0.0, )), +// Cooking Pot +CookingPot: Some(( + variations: [ + ( + model: "voxygen.voxel.sprite.cooking_pot.pot-0", + offset: (-9.0, -10.0, 0.0), + lod_axes: (0.0, 0.0, 0.0), + ), + ], + wind_sway: 0.0, +)), ) diff --git a/assets/voxygen/voxel/weapon/hammer/craftsman.vox b/assets/voxygen/voxel/weapon/hammer/craftsman.vox index 283d73539e539fc9ca4f81c4db7c138e19f95eea..0ed2c9b98f680d57a97eb944e81ad8b832674683 100644 GIT binary patch delta 1188 zcmWmD&2iOG3ovzW=>>%k#nu_ z`1j-Q$6p`McMl=@jP`rXUF$ar{Q|I{$J<+`J|tovQwq&DMzWT zr^lZh^!zsmz3A!H-|0==&Zn$*8U{1@@SOGFAFG4e_44o>vHzIJ*zct_G0DhDrZ$oL z%ar?T=KiD9)<>DE{Uy~>TaDiDQ=j`id;eCNCWeq42Gu5JH_vWXOKmk4hb#_RWNPbU zHAk)<)}YC%jwlA?*c*hEIr`Y3ZGMH79oiHxH4F=RtV(fXL( zOHwpvEDl+O6s?cdAW6~0CfhtUMe8H3_lcxvVvS|4SuuBT0e zv>;m81}Rz}LpEd-t&dqY%P3kOi$fL}MeAcVx5_A5ADfJ%w$oF)h`4ztH=EpSati)XQZ%v2HV;kF z`iR3Khp*(Y$l)tFEFvQ(nc74i7CBzd%;U9OG*Jf0GN?AuhfNM&iHs(OjHGB{b}u>0 i)Fu{(kc%_aCRTIgYHmH=+r;1|BsZbj+wu0+m;MLR=CQ*7 delta 1188 zcmWmE&2i&K5C+gjcLN|q{ETis`Q&7rf$gJjjzBuNiYYh-sk8}f0(-IJ@}sIA8~t&L zJrIWc@%rQSpI;uY5%I!rzyI;;-|fQR&y$xu-Y0U8w^ExpWJkOuMeE~?w~3@^;P^3S|3$sG z|3<$}it$&pu|Gn{7^=NNWDbR_EE~ zW}BNIb|=_);Xd2lY77 z^(!8S@K_BJ()u`8hfqe*`nasSWE8EBAtT4?5UviPY`?jgn{U+3H|pjab#pT^lA?+8 z=4Nj1kMvTsATA3@iYA7P96nHOV&4qe4A~6X4A~5k9h=_<8Lf|VGekzw#AV$jqps~I SKMocSAvuI 2.7, SpriteKind::Cauldron => 1.27, SpriteKind::Anvil => 1.1, + SpriteKind::CookingPot => 1.82, // TODO: Find suitable heights. SpriteKind::BarrelCactus | SpriteKind::RoundCactus @@ -321,6 +323,7 @@ impl SpriteKind { | SpriteKind::Forge | SpriteKind::Cauldron | SpriteKind::Anvil + | SpriteKind::CookingPot ) } } diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index 9b59b8398d..dac34d463c 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -1,6 +1,6 @@ use super::{ img_ids::{Imgs, ImgsRot}, - item_imgs::{animate_by_pulse, ItemImgs}, + item_imgs::{animate_by_pulse, ItemImgs, ItemKey::Tool}, Show, TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN, }; use crate::{ @@ -20,6 +20,7 @@ use common::{ Inventory, }, recipe::RecipeInput, + terrain::SpriteKind, }; use conrod_core::{ color, image, @@ -59,6 +60,9 @@ widget_ids! { ingredient_img[], req_text[], ingredients_txt, + req_station_title, + req_station_img, + req_station_txt, output_img_frame, output_img, output_amount, @@ -657,14 +661,66 @@ impl<'a> Widget for Crafting<'a> { .set(state.ids.tags_ing[i], ui); } } - - // Ingredients Text - Text::new(&self.localized_strings.get("hud.crafting.ingredients")) + // Crafting Station Info + if recipe.craft_sprite.is_some() { + Text::new( + &self + .localized_strings + .get("hud.crafting.req_crafting_station"), + ) .top_left_with_margins_on(state.ids.align_ing, 10.0, 5.0) .font_id(self.fonts.cyri.conrod_id) .font_size(self.fonts.cyri.scale(18)) .color(TEXT_COLOR) - .set(state.ids.ingredients_txt, ui); + .set(state.ids.req_station_title, ui); + let station_img = match recipe.craft_sprite { + Some(SpriteKind::Anvil) => "Anvil", + Some(SpriteKind::Cauldron) => "Cauldron", + Some(SpriteKind::CookingPot) => "CookingPot", + Some(SpriteKind::CraftingBench) => "CraftingBench", + None => "CraftsmanHammer", + _ => "CraftsmanHammer", + }; + Image::new(animate_by_pulse( + &self + .item_imgs + .img_ids_or_not_found_img(Tool(station_img.to_string())), + self.pulse, + )) + .w_h(25.0, 25.0) + .down_from(state.ids.req_station_title, 10.0) + .parent(state.ids.align_ing) + .set(state.ids.req_station_img, ui); + + let station_name = match recipe.craft_sprite { + Some(SpriteKind::Anvil) => "hud.crafting.anvil", + Some(SpriteKind::Cauldron) => "hud.crafting.cauldron", + Some(SpriteKind::CookingPot) => "hud.crafting.cooking_pot", + Some(SpriteKind::CraftingBench) => "hud.crafting.crafting_bench", + _ => "", + }; + Text::new(&self.localized_strings.get(station_name)) + .right_from(state.ids.req_station_img, 10.0) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(14)) + .color(if self.show.craft_sprite.is_some() { + TEXT_COLOR + } else { + TEXT_DULL_RED_COLOR + }) + .set(state.ids.req_station_txt, ui); + } + // Ingredients Text + let mut ing_txt = Text::new(&self.localized_strings.get("hud.crafting.ingredients")) + .font_id(self.fonts.cyri.conrod_id) + .font_size(self.fonts.cyri.scale(18)) + .color(TEXT_COLOR); + if recipe.craft_sprite.is_some() { + ing_txt = ing_txt.down_from(state.ids.req_station_img, 10.0); + } else { + ing_txt = ing_txt.top_left_with_margins_on(state.ids.align_ing, 10.0, 5.0); + }; + ing_txt.set(state.ids.ingredients_txt, ui); // Ingredient images with tooltip if state.ids.ingredient_frame.len() < recipe.inputs().len() { diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 5e3cea6c4c..293f2208c2 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -3487,11 +3487,11 @@ fn try_hotbar_slot_from_input(input: GameInput) -> Option { } pub fn cr_color(combat_rating: f32) -> Color { - let common = 4.3; - let moderate = 6.0; - let high = 8.0; - let epic = 10.0; - let legendary = 79.0; + let common = 2.0; + let moderate = 3.5; + let high = 6.5; + let epic = 8.5; + let legendary = 10.4; let artifact = 122.0; let debug = 200.0; diff --git a/voxygen/src/scene/terrain/watcher.rs b/voxygen/src/scene/terrain/watcher.rs index baf8fff933..3b32b2f6a3 100644 --- a/voxygen/src/scene/terrain/watcher.rs +++ b/voxygen/src/scene/terrain/watcher.rs @@ -127,6 +127,9 @@ impl BlocksOfInterest { Some(SpriteKind::Anvil) => { interactables.push((pos, Interaction::Craft(CraftingTab::Weapon))) }, + Some(SpriteKind::CookingPot) => { + interactables.push((pos, Interaction::Craft(CraftingTab::Food))) + }, _ => {}, }, } diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index 398789a40c..9154d4d136 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -535,9 +535,10 @@ impl Archetype for House { 0..=1 => SpriteKind::Crate, 2 => SpriteKind::Bench, 3 => SpriteKind::Anvil, - 4 => SpriteKind::Cauldron, + 4 => SpriteKind::CookingPot, 5 => SpriteKind::CraftingBench, 6 => SpriteKind::FireBowlGround, + //7 => SpriteKind::Cauldron, //8 => SpriteKind::Forge, _ => unreachable!(), }; @@ -561,7 +562,7 @@ impl Archetype for House { center_offset.x, center_offset.y, z + 100, - )) % 12 + )) % 13 { 0 => SpriteKind::Planter, 1 => SpriteKind::ChairSingle, @@ -585,6 +586,7 @@ impl Archetype for House { SpriteKind::VialEmpty } }, + 11 => SpriteKind::Cauldron, _ => { if dynamic_rng.gen_range(0..2) == 0 { SpriteKind::Bowl From 4710a35c29a40c9b36824b9e4bed816dd1575fc3 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 18 Apr 2021 12:11:38 +0100 Subject: [PATCH 05/12] Made sprite/block selection effect more subtle --- assets/voxygen/shaders/sprite-frag.glsl | 7 +++++-- assets/voxygen/shaders/sprite-vert.glsl | 4 ++-- assets/voxygen/shaders/terrain-frag.glsl | 5 +++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 317f385417..c4b094605a 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -18,7 +18,7 @@ in vec3 f_pos; flat in vec3 f_norm; -flat in float f_light; +flat in float f_select; // flat in vec3 f_pos_norm; in vec2 f_uv_pos; in vec2 f_inst_light; @@ -181,7 +181,10 @@ void main() { emitted_light *= ao; reflected_light *= ao; - surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light) * f_light; + f_col += f_select * 0.05; + reflected_light += f_select * 0.03 * max_light / PERSISTENT_AMBIANCE; + + surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light); // vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light); // tgt_color = vec4(color, 1.0); diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index d0118972f7..e22235a1d8 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -72,7 +72,7 @@ uniform u_terrain_locals { out vec3 f_pos; flat out vec3 f_norm; -flat out float f_light; +flat out float f_select; // flat out vec3 f_pos_norm; // out vec3 f_col; // out float f_ao; @@ -228,7 +228,7 @@ void main() { // f_light = 1.0; // if (select_pos.w > 0) */{ vec3 sprite_pos = /*round*/floor(((inst_mat * vec4(-offs.xyz, 1)).xyz) * SCALE/* - vec3(0.5, 0.5, 0.0)*/) + inst_offs; - f_light = (select_pos.w > 0 && select_pos.xyz == sprite_pos/* - vec3(0.5, 0.5, 0.0) * SCALE*/) ? 10.0 : 1.0; + f_select = (select_pos.w > 0 && select_pos.xyz == sprite_pos/* - vec3(0.5, 0.5, 0.0) * SCALE*/) ? 1.0 : 0.0; // } gl_Position = diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 63b668d592..d592b6b18b 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -268,8 +268,9 @@ void main() { vec3 glow = glow_light(f_pos) * (pow(f_glow, 6) * 5 + pow(f_glow, 1.5) * 2); reflected_light += glow; - float f_select = (select_pos.w > 0 && select_pos.xyz == floor(f_pos - f_norm * 0.5)) ? 0.2 / PERSISTENT_AMBIANCE : 0.0; - reflected_light += f_select; + float f_select = (select_pos.w > 0 && select_pos.xyz == floor(f_pos - f_norm * 0.5)) ? 1.0 : 0.0; + f_col += f_select * 0.05; + reflected_light += f_select * 0.03 * max_light / PERSISTENT_AMBIANCE; max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); From b5111131458779bc3eaca37e9cfe5ba06be4bba9 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 18 Apr 2021 12:25:41 +0100 Subject: [PATCH 06/12] Made sprite/block selection effect more subtle --- assets/voxygen/shaders/sprite-frag.glsl | 5 ++--- assets/voxygen/shaders/terrain-frag.glsl | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index c4b094605a..3d6ff65d74 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -181,12 +181,11 @@ void main() { emitted_light *= ao; reflected_light *= ao; - f_col += f_select * 0.05; - reflected_light += f_select * 0.03 * max_light / PERSISTENT_AMBIANCE; - surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light); // vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light); + surf_color += f_select * (surf_color + 0.1) * vec3(0.15, 0.15, 0.15); + // tgt_color = vec4(color, 1.0); tgt_color = vec4(surf_color, 1.0 - clamp((distance(focus_pos.xy, f_pos.xy) - (sprite_render_distance - FADE_DIST)) / FADE_DIST, 0, 1)); } diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index d592b6b18b..12b4fb15af 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -268,10 +268,6 @@ void main() { vec3 glow = glow_light(f_pos) * (pow(f_glow, 6) * 5 + pow(f_glow, 1.5) * 2); reflected_light += glow; - float f_select = (select_pos.w > 0 && select_pos.xyz == floor(f_pos - f_norm * 0.5)) ? 1.0 : 0.0; - f_col += f_select * 0.05; - reflected_light += f_select * 0.03 * max_light / PERSISTENT_AMBIANCE; - max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); // float f_ao = 1.0; @@ -372,5 +368,8 @@ void main() { // vec3 col = /*srgb_to_linear*/(f_col + hash(vec4(floor(f_pos * 3.0 - f_norm * 0.5), 0)) * 0.01); // Small-scale noise vec3 surf_color = illuminate(max_light, view_dir, col * emitted_light, col * reflected_light); + float f_select = (select_pos.w > 0 && select_pos.xyz == floor(f_pos - f_norm * 0.5)) ? 1.0 : 0.0; + surf_color += f_select * (surf_color + 0.1) * vec3(0.5, 0.5, 0.5); + tgt_color = vec4(surf_color, 1.0); } From a0357fdd5873746fddebafdec5c078ef94305b8b Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 19 Apr 2021 17:56:16 +0200 Subject: [PATCH 07/12] change cauldron spawning cooking pot height fmt fmt, changelog --- CHANGELOG.md | 3 ++- common/src/comp/controller.rs | 4 ++-- common/src/terrain/sprite.rs | 2 +- world/src/site/settlement/building/archetype/house.rs | 7 +++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da070ed06..5f7336fbb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Players can now opt-in to server-authoritiative physics in gameplay settings. - Added `/server_physics` admin command. - Sort inventory button -- Option to change the master volume when window is unfocused +- Option to change the master volume when window is unfocused +- Crafting stations in towns ### Changed diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index 282438ea75..62d7f0befd 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -21,7 +21,7 @@ pub enum InventoryEvent { Swap(InvSlotId, InvSlotId), SplitSwap(InvSlotId, InvSlotId), Drop(InvSlotId), - SplitDrop(InvSlotId), + SplitDrop(InvSlotId), Sort, CraftRecipe { recipe: String, @@ -45,7 +45,7 @@ pub enum InventoryManip { Swap(Slot, Slot), SplitSwap(Slot, Slot), Drop(Slot), - SplitDrop(Slot), + SplitDrop(Slot), Sort, CraftRecipe { recipe: String, diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index 2e1deb52b5..e967185ba6 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -193,7 +193,7 @@ impl SpriteKind { SpriteKind::Forge => 2.7, SpriteKind::Cauldron => 1.27, SpriteKind::Anvil => 1.1, - SpriteKind::CookingPot => 1.82, + SpriteKind::CookingPot => 1.36, // TODO: Find suitable heights. SpriteKind::BarrelCactus | SpriteKind::RoundCactus diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index 9154d4d136..7aecd69def 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -530,7 +530,7 @@ impl Archetype for House { center_offset.x, center_offset.y, z + 100, - )) % 7 + )) % 8 { 0..=1 => SpriteKind::Crate, 2 => SpriteKind::Bench, @@ -538,7 +538,7 @@ impl Archetype for House { 4 => SpriteKind::CookingPot, 5 => SpriteKind::CraftingBench, 6 => SpriteKind::FireBowlGround, - //7 => SpriteKind::Cauldron, + 7 => SpriteKind::Cauldron, //8 => SpriteKind::Forge, _ => unreachable!(), }; @@ -562,7 +562,7 @@ impl Archetype for House { center_offset.x, center_offset.y, z + 100, - )) % 13 + )) % 12 { 0 => SpriteKind::Planter, 1 => SpriteKind::ChairSingle, @@ -586,7 +586,6 @@ impl Archetype for House { SpriteKind::VialEmpty } }, - 11 => SpriteKind::Cauldron, _ => { if dynamic_rng.gen_range(0..2) == 0 { SpriteKind::Bowl From 7de0becc0d03a407f22f06074652d7e1a329d087 Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Tue, 20 Apr 2021 02:45:33 +0200 Subject: [PATCH 08/12] clippy --- client/src/lib.rs | 5 +++-- voxygen/src/hud/crafting.rs | 21 ++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 805b5b1bda..afb0cd5a9e 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -993,9 +993,10 @@ impl Client { recipe: &str, craft_sprite: Option<(Vec3, SpriteKind)>, ) -> bool { - if self.can_craft_recipe(recipe).map_or(false, |cs| { + let can_craft = self.can_craft_recipe(recipe).map_or(false, |cs| { cs.map_or(true, |cs| Some(cs) == craft_sprite.map(|(_, s)| s)) - }) { + }); + if can_craft { self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryEvent( InventoryEvent::CraftRecipe { recipe: recipe.to_string(), diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index dac34d463c..057e5141d0 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -438,23 +438,22 @@ impl<'a> Widget for Crafting<'a> { .unwrap_or(false) }) }); - let state = - if self - .client + let show_craft_sprite = + self.client .available_recipes() .get(name.as_str()) .map_or(false, |cs| { cs.map_or(true, |cs| { Some(cs) == self.show.craft_sprite.map(|(_, s)| s) }) - }) - { - RecipeIngredientQuantity::All - } else if at_least_some_ingredients { - RecipeIngredientQuantity::Some - } else { - RecipeIngredientQuantity::None - }; + }); + let state = if show_craft_sprite { + RecipeIngredientQuantity::All + } else if at_least_some_ingredients { + RecipeIngredientQuantity::Some + } else { + RecipeIngredientQuantity::None + }; (name, recipe, state) }) .collect(); From 9cf21aada55326826aaf285f685c60f48f457ab7 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 20 Apr 2021 03:34:11 +0200 Subject: [PATCH 09/12] remove old craftsman hammer, add migration --- assets/common/items/crafting_tools/craftsman_hammer.ron | 9 --------- assets/voxygen/item_image_manifest.ron | 6 +----- server/src/migrations/V35__rename_craftsman_hammer.sql | 3 +++ 3 files changed, 4 insertions(+), 14 deletions(-) delete mode 100644 assets/common/items/crafting_tools/craftsman_hammer.ron create mode 100644 server/src/migrations/V35__rename_craftsman_hammer.sql diff --git a/assets/common/items/crafting_tools/craftsman_hammer.ron b/assets/common/items/crafting_tools/craftsman_hammer.ron deleted file mode 100644 index 24b5822c37..0000000000 --- a/assets/common/items/crafting_tools/craftsman_hammer.ron +++ /dev/null @@ -1,9 +0,0 @@ -ItemDef( - name: "Old Hammer", - description: "You don't quite remember where you got this from...", - kind: Ingredient( - kind: "CraftsmanHammer", - ), - quality: Low, - tags: [CraftingTool], -) diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 1a90921bbb..94c348a731 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -1941,11 +1941,7 @@ Tool("common.items.tool.craftsman_hammer"): VoxTrans( "voxel.weapon.hammer.craftsman", (1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 0.9, - ), - Ingredient("CraftsmanHammer"): VoxTrans( - "voxel.weapon.hammer.craftsman", - (1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 0.8, - ), + ), Ingredient("SewingSet"): Png( "element.items.sewing_set", ), diff --git a/server/src/migrations/V35__rename_craftsman_hammer.sql b/server/src/migrations/V35__rename_craftsman_hammer.sql new file mode 100644 index 0000000000..773436b601 --- /dev/null +++ b/server/src/migrations/V35__rename_craftsman_hammer.sql @@ -0,0 +1,3 @@ +-- Replace old crafting hammer ingredient with functional 1h-hammer variant + +UPDATE item SET item_definition_id = 'common.items.tool.craftsman_hammer' WHERE item_definition_id = 'common.items.crafting_tools.craftsman_hammer'; \ No newline at end of file From e87ee6d8c72a17f15504decf18ecd4a45b77f9d8 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 20 Apr 2021 12:33:22 +0100 Subject: [PATCH 10/12] Cleaned up client-side recipe handling --- client/src/lib.rs | 30 ++++++++++++++++------------ common/src/recipe.rs | 1 - server/src/events/inventory_manip.rs | 6 +++--- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index afb0cd5a9e..5f225758bc 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -974,18 +974,19 @@ impl Client { &self.available_recipes } - pub fn can_craft_recipe(&self, recipe: &str) -> Option> { + /// Returns whether the specified recipe can be crafted and the sprite, if + /// any, that is required to do so. + pub fn can_craft_recipe(&self, recipe: &str) -> (bool, Option) { self.recipe_book .get(recipe) .zip(self.inventories().get(self.entity())) .map(|(recipe, inv)| { - if inv.contains_ingredients(&*recipe).is_ok() { - Some(recipe.craft_sprite) - } else { - None - } + ( + inv.contains_ingredients(&*recipe).is_ok(), + recipe.craft_sprite, + ) }) - .unwrap_or(None) + .unwrap_or((false, None)) } pub fn craft_recipe( @@ -993,10 +994,9 @@ impl Client { recipe: &str, craft_sprite: Option<(Vec3, SpriteKind)>, ) -> bool { - let can_craft = self.can_craft_recipe(recipe).map_or(false, |cs| { - cs.map_or(true, |cs| Some(cs) == craft_sprite.map(|(_, s)| s)) - }); - if can_craft { + let (can_craft, required_sprite) = self.can_craft_recipe(recipe); + let has_sprite = required_sprite.map_or(true, |s| Some(s) == craft_sprite.map(|(_, s)| s)); + if can_craft && has_sprite { self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryEvent( InventoryEvent::CraftRecipe { recipe: recipe.to_string(), @@ -1015,8 +1015,12 @@ impl Client { .iter() .map(|(name, _)| name.clone()) .filter_map(|name| { - let required_sprite = self.can_craft_recipe(&name)?; - Some((name, required_sprite)) + let (can_craft, required_sprite) = self.can_craft_recipe(&name); + if can_craft { + Some((name, required_sprite)) + } else { + None + } }) .collect(); } diff --git a/common/src/recipe.rs b/common/src/recipe.rs index 2a1110948d..1e0a3f3987 100644 --- a/common/src/recipe.rs +++ b/common/src/recipe.rs @@ -98,7 +98,6 @@ pub(crate) struct RawRecipe { #[derive(Clone, Deserialize)] #[serde(transparent)] -#[allow(clippy::type_complexity)] pub(crate) struct RawRecipeBook(pub(crate) HashMap); impl assets::Asset for RawRecipeBook { diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index f921f584ca..fa9e41b01d 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -596,8 +596,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv }) { debug!( ?entity_cylinder, - "Failed to pick up block as not within range, block pos: \ - {}", + "Failed to craft recipe as not within range of required \ + sprite, sprite pos: {}", pos ); false @@ -609,7 +609,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .and_then(|block| block.get_sprite()); Some(needed_sprite) == sprite } else { - false + true } }) .and_then(|r| { From 66460584e71dd5f2d5d29561ca494f65f191a064 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 20 Apr 2021 15:23:52 +0100 Subject: [PATCH 11/12] Made crafting UI check exact crafting sprite --- voxygen/src/hud/crafting.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index 057e5141d0..ee616e822d 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -702,11 +702,13 @@ impl<'a> Widget for Crafting<'a> { .right_from(state.ids.req_station_img, 10.0) .font_id(self.fonts.cyri.conrod_id) .font_size(self.fonts.cyri.scale(14)) - .color(if self.show.craft_sprite.is_some() { - TEXT_COLOR - } else { - TEXT_DULL_RED_COLOR - }) + .color( + if self.show.craft_sprite.map(|(_, s)| s) == recipe.craft_sprite { + TEXT_COLOR + } else { + TEXT_DULL_RED_COLOR + }, + ) .set(state.ids.req_station_txt, ui); } // Ingredients Text From bacabacaaa3276f7f96bc117b8acad20e189f93b Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 20 Apr 2021 15:39:46 +0100 Subject: [PATCH 12/12] Made cooking pots glow --- common/src/terrain/block.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 8068a3a7de..6c6d370c3f 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -171,12 +171,12 @@ impl Block { match self.get_sprite()? { SpriteKind::StreetLamp | SpriteKind::StreetLampTall => Some(24), SpriteKind::Ember => Some(20), - SpriteKind::WallLamp => Some(16), - SpriteKind::WallLampSmall => Some(16), - SpriteKind::WallSconce => Some(16), - SpriteKind::FireBowlGround => Some(16), + SpriteKind::WallLamp + | SpriteKind::WallLampSmall + | SpriteKind::WallSconce + | SpriteKind::FireBowlGround => Some(16), SpriteKind::Velorite | SpriteKind::VeloriteFrag => Some(6), - SpriteKind::CaveMushroom => Some(12), + SpriteKind::CaveMushroom | SpriteKind::CookingPot => Some(12), SpriteKind::Amethyst | SpriteKind::Ruby | SpriteKind::Sapphire