This commit is contained in:
Joshua Barretto 2020-07-14 20:11:39 +00:00 committed by Monty Marz
parent 91fbe23fb6
commit 1c1229fff9
122 changed files with 1406 additions and 129 deletions
CHANGELOG.md
assets
client/src
common/src
assets
comp

@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added spin attack for axe
- Creature specific stats
- Minimap compass
- Initial crafting system implementation
### Changed

@ -2,11 +2,10 @@ Item(
name: "Large Potion",
description: "Restores 100 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: PotionMinor,
kind: PotionLarge,
effect: Health((
amount: 100,
cause: Item,
)),
,
),
)

@ -2,7 +2,7 @@ Item(
name: "Medium Potion",
description: "Restores 70 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: PotionMinor,
kind: PotionMed,
effect: Health((
amount: 70,
cause: Item,

@ -0,0 +1,7 @@
Item(
name: "Empty Vial",
description: "Can be filled with fluids.",
kind: Ingredient(
kind: EmptyVial,
)
)

@ -0,0 +1,7 @@
Item(
name: "Leather Scraps",
description: "Used to craft various items.",
kind: Ingredient(
kind: LeatherScraps,
)
)

@ -0,0 +1,7 @@
Item(
name: "Shiny Gem",
description: "It's so shiny!",
kind: Ingredient(
kind: ShinyGem,
)
)

@ -0,0 +1,7 @@
Item(
name: "Stones",
description: "Pebbles from the ground.",
kind: Ingredient(
kind: Stones,
)
)

@ -0,0 +1,7 @@
Item(
name: "Twigs",
description: "Dry.",
kind: Ingredient(
kind: Twigs,
)
)

@ -0,0 +1,7 @@
Item(
name: "Craftsman Hammer",
description: "Used to craft various items.",
kind: Ingredient(
kind: CraftsmanHammer,
)
)

@ -0,0 +1,7 @@
Item(
name: "Mortar and Pestle",
description: "Crushes and grinds things into\na fine powder or paste.\nUsed to craft various items.",
kind: Ingredient(
kind: MortarPestle,
)
)

@ -0,0 +1,7 @@
Item(
name: "Empty Vial",
description: "Can be filled with fluids.",
kind: Ingredient(
kind: EmptyVial,
)
)

@ -0,0 +1,7 @@
Item(
name: "Leather Scraps",
description: "Used to craft various items.",
kind: Ingredient(
kind: LeatherScraps,
)
)

@ -0,0 +1,7 @@
Item(
name: "Shiny Gem",
description: "It's so shiny!",
kind: Ingredient(
kind: ShinyGem,
)
)

@ -0,0 +1,7 @@
Item(
name: "Stones",
description: "Pebbles from the ground.",
kind: Ingredient(
kind: Stones,
)
)

@ -0,0 +1,7 @@
Item(
name: "Twigs",
description: "Dry.",
kind: Ingredient(
kind: Twigs,
)
)

@ -0,0 +1,11 @@
Item(
name: "Mushroom Curry",
description: "Restores 120 Health\n\nWho could say no to that?\n\n<Right-Click to use>",
kind: Consumable(
kind: AppleShroomCurry,
effect: Health((
amount: 120,
cause: Item,
)),
),
)

@ -0,0 +1,11 @@
Item(
name: "Apple Stick",
description: "Restores 60 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: AppleStick,
effect: Health((
amount: 60,
cause: Item,
)),
),
)

@ -0,0 +1,11 @@
Item(
name: "Mushroom Stick",
description: "Restores 50 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: MushroomStick,
effect: Health((
amount: 50,
cause: Item,
)),
),
)

@ -1,18 +1,23 @@
[
// All loot rates go here
// food
(3, "common.items.cheese"),
(3, "common.items.apple"),
(3, "common.items.mushroom"),
(3, "common.items.food.cheese"),
(3, "common.items.food.apple"),
(3, "common.items.food.mushroom"),
(1, "common.items.food.coconut"),
// miscellaneous
(0.4, "common.items.velorite"),
(0.6, "common.items.veloritefrag"),
(0.6, "common.items.cheese"),
(0.6, "common.items.apple"),
(1.5, "common.items.potion_minor"),
(0.5, "common.items.collar"),
(0.5, "common.items.bomb_pile"),
(1, "common.items.bomb"),
(0.4, "common.items.ore.velorite"),
(0.6, "common.items.ore.veloritefrag"),
(0.1, "common.items.consumable.potion_minor"),
(0.01, "common.items.utility.collar"),
(0.01, "common.items.utility.bomb_pile"),
(0.1, "common.items.utility.bomb"),
// crafting ingredients
(0.5, "common.items.crafting_ing.shiny_gem"),
(2, "common.items.crafting_ing.leather_scraps"),
(1, "common.items.crafting_ing.empty_vial"),
(2, "common.items.crafting_ing.stones"),
(3, "common.items.crafting_ing.twigs"),
// swords
(0.1, "common.items.weapons.sword.starter_sword"),
(0.1, "common.items.weapons.sword.wood_sword"),

@ -0,0 +1,12 @@
{
"crafting_hammer": (("common.items.crafting_tools.craftsman_hammer", 1),[("common.items.crafting_ing.twigs", 10), ("common.items.crafting_ing.stones", 10)]),
"mortar_pestle": (("common.items.crafting_tools.mortar_pestle", 1), [("common.items.crafting_ing.stones", 6), ("common.items.food.coconut", 2), ("common.items.crafting_tools.craftsman_hammer", 0)]),
"velorite_frag": (("common.items.ore.veloritefrag", 2), [("common.items.ore.velorite", 1), ("common.items.crafting_tools.craftsman_hammer", 0)]),
"potion_s": (("common.items.consumable.potion_minor", 1), [("common.items.crafting_ing.empty_vial", 1), ("common.items.ore.veloritefrag", 2)]),
"potion_m": (("common.items.consumable.potion_med", 1), [("common.items.consumable.potion_minor", 2), ("common.items.ore.veloritefrag", 4)]),
"collar_basic": (("common.items.utility.collar", 1), [("common.items.crafting_ing.leather_scraps", 5), ("common.items.crafting_ing.shiny_gem", 1)]),
"bomb_coconut": (("common.items.utility.bomb", 1), [("common.items.crafting_ing.stones", 10), ("common.items.food.coconut", 2), ("common.items.ore.veloritefrag", 2), ("common.items.crafting_tools.mortar_pestle", 0)]),
"apple_shroom_curry": (("common.items.food.apple_mushroom_curry", 1), [("common.items.food.mushroom", 10), ("common.items.food.coconut", 1), ("common.items.food.apple", 5), ("common.items.crafting_tools.mortar_pestle", 0)]),
"apples_stick": (("common.items.food.apple_stick", 1),[("common.items.crafting_ing.twigs", 1), ("common.items.food.apple", 3)]),
"mushroom_stick": (("common.items.food.mushroom_stick", 1),[("common.items.crafting_ing.twigs", 1), ("common.items.food.mushroom", 5)]),
}

Binary file not shown.

Binary file not shown.

Before

(image error) Size: 394 KiB

After

(image error) Size: 885 KiB

Binary file not shown.

After

(image error) Size: 843 B

Binary file not shown.

After

(image error) Size: 2.0 KiB

Binary file not shown.

After

(image error) Size: 2.0 KiB

Binary file not shown.

After

(image error) Size: 2.0 KiB

Binary file not shown.

After

(image error) Size: 2.1 KiB

Binary file not shown.

After

(image error) Size: 355 B

Binary file not shown.

After

(image error) Size: 437 B

Binary file not shown.

After

(image error) Size: 412 B

Binary file not shown.

After

(image error) Size: 261 B

Binary file not shown.

Binary file not shown.

After

(image error) Size: 184 B

Binary file not shown.

After

(image error) Size: 259 B

Binary file not shown.

After

(image error) Size: 250 B

Binary file not shown.

After

(image error) Size: 134 B

Binary file not shown.

After

(image error) Size: 117 B

Binary file not shown.

Before

(image error) Size: 784 B

After

(image error) Size: 466 B

Binary file not shown.

Before

(image error) Size: 929 B

After

(image error) Size: 357 B

Binary file not shown.

Before

(image error) Size: 782 B

Binary file not shown.

After

(image error) Size: 355 B

Binary file not shown.

After

(image error) Size: 248 B

Binary file not shown.

Before

(image error) Size: 808 B

After

(image error) Size: 317 B

Binary file not shown.

Before

(image error) Size: 16 KiB

After

(image error) Size: 275 B

Binary file not shown.

After

(image error) Size: 260 B

Binary file not shown.

Before

(image error) Size: 730 B

After

(image error) Size: 700 B

Binary file not shown.

After

(image error) Size: 338 B

Binary file not shown.

Binary file not shown.

After

(image error) Size: 358 B

Binary file not shown.

After

(image error) Size: 366 B

Binary file not shown.

Before

(image error) Size: 245 B

After

(image error) Size: 244 B

Binary file not shown.

After

(image error) Size: 416 B

Binary file not shown.

After

(image error) Size: 304 B

Binary file not shown.

After

(image error) Size: 348 B

Binary file not shown.

Before

(image error) Size: 1.2 KiB

Binary file not shown.

After

(image error) Size: 389 B

Binary file not shown.

Before

(image error) Size: 795 B

After

(image error) Size: 429 B

Binary file not shown.

Before

(image error) Size: 1.1 KiB

After

(image error) Size: 462 B

Binary file not shown.

After

(image error) Size: 7.6 KiB

Binary file not shown.

After

(image error) Size: 15 KiB

Binary file not shown.

Before

(image error) Size: 58 KiB

After

(image error) Size: 52 KiB

Binary file not shown.

Before

(image error) Size: 5.4 KiB

After

(image error) Size: 5.0 KiB

Binary file not shown.

After

(image error) Size: 6.3 KiB

@ -304,6 +304,8 @@ magischen Gegenstände ergattern?"#,
"hud.settings.audio_device": "Ausgabegerät",
"hud.settings.awaitingkey": "Drückt eine Taste...",
"hud.settings.unbound": "-",
"hud.settings.reset_keybinds": "Auf Standard zurücksetzen",
"hud.social": "Sozial",
"hud.social.online": "Online",
@ -314,6 +316,12 @@ magischen Gegenstände ergattern?"#,
"hud.spell": "Zauber",
"hud.crafting": "Herstellen",
"hud.crafting.recipes": "Rezepte",
"hud.crafting.ingredients": "Zutaten:",
"hud.crafting.craft": "Herstellen",
"hud.crafting.tool_cata": "Benötigt:",
"hud.free_look_indicator": "Freie Sicht aktiv",
"hud.auto_walk_indicator": "Automatisches Laufen aktiv",

@ -118,8 +118,6 @@ Thanks for taking the time to read this notice, we hope you enjoy the game!
// Login process description
"main.login_process": r#"Information on the Login Process:
If you are having issues signing in:
Please note that you now need an account
to play on auth-enabled servers.
@ -313,7 +311,13 @@ magically infused items?"#,
"hud.social.faction": "Faction",
"hud.social.play_online_fmt": "{nb_player} player(s) online",
"hud.spell": "Spells",
"hud.crafting": "Crafting",
"hud.crafting.recipes": "Recipes",
"hud.crafting.ingredients": "Ingredients:",
"hud.crafting.craft": "Craft",
"hud.crafting.tool_cata": "Requires:",
"hud.spell": "Spells",
"hud.free_look_indicator": "Free look active",
"hud.auto_walk_indicator": "Auto walk active",

@ -191,7 +191,7 @@
Tool(Hammer(BasicHammer)): VoxTrans(
"voxel.weapon.hammer.rusty_2h",
(2.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
),
),
// Staffs
Tool(Staff(BasicStaff)): VoxTrans(
"voxel.weapon.staff.wood-fire",
@ -743,24 +743,30 @@
),
// Consumables
Consumable(Apple):
VoxTrans(
Png(
"element.icons.item_apple",
(0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 1.0,
),
Consumable(Coconut): Png(
"element.icons.item_coconut",
),
Consumable(PotionMed): VoxTrans(
"voxel.object.potion_red",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.7,
),
Consumable(PotionMinor): VoxTrans(
"voxel.object.potion_red",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.8,
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.5,
),
Consumable(PotionLarge): VoxTrans(
"voxel.object.potion_red",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.9,
),
Consumable(PotionExp): VoxTrans(
"voxel.object.potion_turq",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.8,
),
Consumable(Cheese): VoxTrans(
Consumable(Cheese): Png(
"element.icons.item_cheese",
(0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 0.9,
),
Consumable(Potion): VoxTrans(
"voxel.object.potion_red",
@ -776,18 +782,32 @@
),
Consumable(VeloriteFrag): VoxTrans(
"voxel.sprite.velorite.velorite_1",
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
(0.0, 0.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
Consumable(AppleShroomCurry): Png(
"element.icons.item_apple_curry",
),
Consumable(AppleStick): Png(
"element.icons.item_apple_stick",
),
Consumable(MushroomStick): Png(
"element.icons.item_shroom_stick",
),
// Throwables
Throwable(Bomb): VoxTrans(
"voxel.object.bomb",
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
(0.0, 0.5, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
Throwable(TrainingDummy): VoxTrans(
"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!
"voxel.weapon.hammer.craftsman",
(1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 1.0,
),
Ingredient(Flower): VoxTrans(
"voxel.sprite.flowers.flower_red_2",
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
@ -796,6 +816,27 @@
"voxel.sprite.grass.grass_long_5",
(0.0, 0.0, 0.0), (-90.0, 50.0, 0.0), 1.0,
),
Ingredient(Stones): VoxTrans(
"voxel.sprite.rocks.rock-0",
(0.0, 0.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
Ingredient(Twigs): VoxTrans(
"voxel.sprite.twigs.twigs-0",
(0.0, 0.0, 0.0), (-20.0, 10.0, 20.0), 0.9,
),
Ingredient(LeatherScraps): Png(
"element.icons.item_leather0",
),
Ingredient(ShinyGem): Png(
"element.icons.gem",
),
Ingredient(MortarPestle): Png(
"element.icons.item_mortarpestlecoco",
),
Ingredient(EmptyVial): VoxTrans(
"voxel.object.potion_empty",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.8,
),
// Debug Items
Tool(Debug(Boost)): VoxTrans(
"voxel.weapon.tool.broom_belzeshrub_purple",

@ -176,6 +176,10 @@
vox_spec: ("weapon.hammer.rusty_2h", (-2.5, -5.5, -4.0)),
color: None
),
/*Dagger(Craftsman): ( //TODO This should be a 1h hammer!
vox_spec: ("weapon.hammer.craftsman", (-2.0, -5.0, -5.5)),
color: None
),*/
// Daggers
Dagger(BasicDagger): (
vox_spec: ("weapon.dagger.dagger_rusty", (-1.5, -3.0, -3.0)),

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,5 +1,5 @@
#![deny(unsafe_code)]
#![feature(label_break_value)]
#![feature(label_break_value, option_zip)]
pub mod cmd;
pub mod error;
@ -25,6 +25,7 @@ use common::{
PlayerInfo, PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg,
MAX_BYTES_CHAT_MSG,
},
recipe::RecipeBook,
state::State,
sync::{Uid, UidAllocator, WorldSyncExt},
terrain::{block::Block, TerrainChunk, TerrainChunkSize},
@ -33,7 +34,7 @@ use common::{
use futures_executor::block_on;
use futures_timer::Delay;
use futures_util::{select, FutureExt};
use hashbrown::HashMap;
use hashbrown::{HashMap, HashSet};
use image::DynamicImage;
use network::{
Network, Participant, Pid, ProtocolAddr, Stream, PROMISES_CONSISTENCY, PROMISES_ORDERED,
@ -75,6 +76,8 @@ pub struct Client {
pub player_list: HashMap<Uid, PlayerInfo>,
pub character_list: CharacterList,
pub active_character_id: Option<i32>,
recipe_book: RecipeBook,
available_recipes: HashSet<String>,
_network: Network,
participant: Option<Participant>,
@ -123,7 +126,7 @@ impl Client {
let mut stream = block_on(participant.open(10, PROMISES_ORDERED | PROMISES_CONSISTENCY))?;
// Wait for initial sync
let (state, entity, server_info, world_map) = block_on(async {
let (state, entity, server_info, world_map, recipe_book) = block_on(async {
loop {
match stream.recv().await? {
ServerMsg::InitialSync {
@ -131,6 +134,7 @@ impl Client {
server_info,
time_of_day,
world_map: (map_size, world_map),
recipe_book,
} => {
// TODO: Display that versions don't match in Voxygen
if &server_info.git_hash != *common::util::GIT_HASH {
@ -174,7 +178,13 @@ impl Client {
);
debug!("Done preparing image...");
break Ok((state, entity, server_info, (world_map, map_size)));
break Ok((
state,
entity,
server_info,
(world_map, map_size),
recipe_book,
));
},
ServerMsg::TooManyPlayers => break Err(Error::TooManyPlayers),
err => {
@ -200,6 +210,8 @@ impl Client {
player_list: HashMap::new(),
character_list: CharacterList::default(),
active_character_id: None,
recipe_book,
available_recipes: HashSet::default(),
_network: network,
participant: Some(participant),
@ -372,6 +384,40 @@ impl Client {
}
}
pub fn recipe_book(&self) -> &RecipeBook { &self.recipe_book }
pub fn available_recipes(&self) -> &HashSet<String> { &self.available_recipes }
pub fn can_craft_recipe(&self, recipe: &str) -> bool {
self.recipe_book
.get(recipe)
.zip(self.inventories().get(self.entity))
.map(|(recipe, inv)| inv.contains_ingredients(&*recipe).is_ok())
.unwrap_or(false)
}
pub fn craft_recipe(&mut self, recipe: &str) -> bool {
if self.can_craft_recipe(recipe) {
self.singleton_stream
.send(ClientMsg::ControlEvent(ControlEvent::InventoryManip(
InventoryManip::CraftRecipe(recipe.to_string()),
)))
.unwrap();
true
} else {
false
}
}
fn update_available_recipes(&mut self) {
self.available_recipes = self
.recipe_book
.iter()
.map(|(name, _)| name.clone())
.filter(|name| self.can_craft_recipe(name))
.collect();
}
pub fn toggle_lantern(&mut self) {
self.singleton_stream
.send(ClientMsg::ControlEvent(ControlEvent::ToggleLantern))
@ -949,6 +995,8 @@ impl Client {
},
}
self.update_available_recipes();
frontend_events.push(Event::InventoryUpdated(event));
},
ServerMsg::TerrainChunkUpdate { key, chunk } => {

@ -80,13 +80,14 @@ pub fn load_map<A: Asset + 'static, F: FnOnce(A) -> A>(
specifier: &str,
f: F,
) -> Result<Arc<A>, Error> {
let mut assets_write = ASSETS.write().unwrap();
let assets_write = ASSETS.read().unwrap();
match assets_write.get(specifier) {
Some(asset) => Ok(Arc::clone(asset).downcast()?),
None => {
drop(assets_write); // Drop the asset hashmap to permit recursive loading
let asset = Arc::new(f(A::parse(load_file(specifier, A::ENDINGS)?)?));
let clone = Arc::clone(&asset);
assets_write.insert(specifier.to_owned(), clone);
ASSETS.write().unwrap().insert(specifier.to_owned(), clone);
Ok(asset)
},
}

@ -15,6 +15,7 @@ pub enum InventoryManip {
Use(Slot),
Swap(Slot, Slot),
Drop(Slot),
CraftRecipe(String),
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]

@ -349,5 +349,14 @@ pub enum Armor {
Tabard(Tabard),
}
impl Armor {
/// Determines whether two pieces of armour are superficially equivalent to
/// one another (i.e: one may be substituted for the other in crafting
/// recipes or item possession checks).
pub fn superficially_eq(&self, other: &Self) -> bool {
std::mem::discriminant(self) == std::mem::discriminant(other)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Stats(pub u32);

@ -26,7 +26,12 @@ pub enum Consumable {
Velorite,
VeloriteFrag,
PotionMinor,
PotionMed,
PotionLarge,
PotionExp,
AppleShroomCurry,
AppleStick,
MushroomStick,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -44,6 +49,13 @@ pub enum Utility {
pub enum Ingredient {
Flower,
Grass,
EmptyVial,
LeatherScraps,
ShinyGem,
Stones,
Twigs,
MortarPestle,
CraftsmanHammer,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -159,13 +171,25 @@ impl Item {
pub fn description(&self) -> &str { &self.description }
pub fn amount(&self) -> u32 {
match &self.kind {
ItemKind::Tool(_) => 1,
ItemKind::Lantern(_) => 1,
ItemKind::Armor { .. } => 1,
ItemKind::Consumable { amount, .. } => *amount,
ItemKind::Throwable { amount, .. } => *amount,
ItemKind::Utility { amount, .. } => *amount,
ItemKind::Ingredient { amount, .. } => *amount,
}
}
pub fn try_reclaim_from_block(block: Block) -> Option<Self> {
match block.kind() {
BlockKind::Apple => Some(assets::load_expect_cloned("common.items.apple")),
BlockKind::Mushroom => Some(assets::load_expect_cloned("common.items.mushroom")),
BlockKind::Velorite => Some(assets::load_expect_cloned("common.items.velorite")),
BlockKind::Apple => Some(assets::load_expect_cloned("common.items.food.apple")),
BlockKind::Mushroom => Some(assets::load_expect_cloned("common.items.food.mushroom")),
BlockKind::Velorite => Some(assets::load_expect_cloned("common.items.ore.velorite")),
BlockKind::VeloriteFrag => {
Some(assets::load_expect_cloned("common.items.veloritefrag"))
Some(assets::load_expect_cloned("common.items.ore.veloritefrag"))
},
BlockKind::BlueFlower => Some(assets::load_expect_cloned("common.items.flowers.blue")),
BlockKind::PinkFlower => Some(assets::load_expect_cloned("common.items.flowers.pink")),
@ -185,16 +209,44 @@ impl Item {
Some(assets::load_expect_cloned("common.items.grasses.medium"))
},
BlockKind::ShortGrass => Some(assets::load_expect_cloned("common.items.grasses.short")),
BlockKind::Coconut => Some(assets::load_expect_cloned("common.items.coconut")),
BlockKind::Coconut => Some(assets::load_expect_cloned("common.items.food.coconut")),
BlockKind::Chest => {
let chosen = assets::load_expect::<lottery::Lottery<_>>("common.loot_table");
let chosen = chosen.choose();
Some(assets::load_expect_cloned(chosen))
},
BlockKind::Stones => Some(assets::load_expect_cloned(
"common.items.crafting_ing.stones",
)),
BlockKind::Twigs => Some(assets::load_expect_cloned(
"common.items.crafting_ing.twigs",
)),
BlockKind::ShinyGem => Some(assets::load_expect_cloned(
"common.items.crafting_ing.shiny_gem",
)),
_ => None,
}
}
/// Determines whether two items are superficially equivalent to one another
/// (i.e: one may be substituted for the other in crafting recipes or
/// item possession checks).
pub fn superficially_eq(&self, other: &Self) -> bool {
match (&self.kind, &other.kind) {
(ItemKind::Tool(a), ItemKind::Tool(b)) => a.superficially_eq(b),
// TODO: Differentiate between lantern colors?
(ItemKind::Lantern(_), ItemKind::Lantern(_)) => true,
(ItemKind::Armor { kind: a, .. }, ItemKind::Armor { kind: b, .. }) => {
a.superficially_eq(b)
},
(ItemKind::Consumable { kind: a, .. }, ItemKind::Consumable { kind: b, .. }) => a == b,
(ItemKind::Throwable { kind: a, .. }, ItemKind::Throwable { kind: b, .. }) => a == b,
(ItemKind::Utility { kind: a, .. }, ItemKind::Utility { kind: b, .. }) => a == b,
(ItemKind::Ingredient { kind: a, .. }, ItemKind::Ingredient { kind: b, .. }) => a == b,
_ => false,
}
}
}
impl Component for Item {

Some files were not shown because too many files have changed in this diff Show More