Move figure meshing to a background thread.

This commit is contained in:
Joshua Yanovski 2020-08-28 03:02:17 +02:00
parent 1aec2ac6ef
commit 3a96b73b2c
76 changed files with 2589 additions and 2695 deletions

View File

@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Overhauled world colours
- Improved projectile physics
- Improved overhead aiming
- Figure meshing no longer blocks the main thread.
### Removed

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.acacia.1",
center: (17, 18, 4)
@ -20,5 +21,4 @@
specifier: "world.tree.acacia.5",
center: (19, 19, 4)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.birch.1",
center: (12, 9, 10)
@ -48,5 +49,4 @@
specifier: "world.tree.birch.12",
center: (9, 10, 10)
),
]
)
]

View File

@ -1,5 +1,7 @@
(
[ (
#![enable(unwrap_newtypes)]
[
(
specifier: "world.structure.dungeon.jungle_temple.entrance.1",
center: (50, 40, 10)
),
@ -43,6 +45,4 @@
specifier: "world.structure.dungeon.misc_entrance.tower-ruin",
center: (13, 16, 9)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.fruit.1",
center: (6, 6, 7)
@ -24,5 +25,4 @@
specifier: "world.tree.fruit.6",
center: (7, 7, 7)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.mangroves.1",
center: (19, 18, 8)
@ -32,5 +33,4 @@
specifier: "world.tree.mangroves.8",
center: (18, 19, 9)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.oak_stump.1",
center: (15, 18, 10)
@ -36,5 +37,4 @@
specifier: "world.tree.oak_stump.9",
center:(26, 26, 10)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.oak_green.1",
center: (15, 17, 14)
@ -36,5 +37,4 @@
specifier: "world.tree.oak_green.9",
center:(21, 21, 14)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.desert_palm.1",
center: (7, 8, 2)
@ -40,5 +41,4 @@
specifier: "world.tree.desert_palm.10",
center: (6, 7, 2)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.pine_green.1",
center: (15, 15, 14)
@ -32,5 +33,4 @@
specifier: "world.tree.pine_green.8",
center: (12, 10, 12)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.structure.natural.witch-hut",
center: (10, 13, 9)
@ -8,5 +9,4 @@
specifier: "world.structure.natural.tree-house",
center: (20, 15, 10)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.structure.natural.ribcage-small",
center: (7, 13, 4)
@ -12,5 +13,4 @@
specifier: "world.structure.natural.skull-large",
center: (15, 20, 4)
),
]
)
]

View File

@ -1,5 +1,6 @@
(
[
#![enable(unwrap_newtypes)]
[
(
specifier: "world.tree.snow_pine.1",
center: (15, 15, 14)
@ -31,6 +32,5 @@
(
specifier: "world.tree.snow_pine.8",
center: (12, 10, 12)
)
],
)
),
]

View File

@ -1,14 +1,14 @@
//! Load assets (images or voxel data) from files
pub mod watch;
use core::{any::Any, fmt, marker::PhantomData};
use dot_vox::DotVoxData;
use hashbrown::HashMap;
use image::DynamicImage;
use lazy_static::lazy_static;
use serde::Deserialize;
use serde_json::Value;
use std::{
any::Any,
fmt,
fs::{self, File, ReadDir},
io::{BufReader, Read},
path::PathBuf,
@ -61,39 +61,70 @@ lazy_static! {
RwLock::new(HashMap::new());
}
// TODO: Remove this function. It's only used in world/ in a really ugly way.To
// do this properly assets should have all their necessary data in one file. A
// ron file could be used to combine voxel data with positioning data for
// example.
/// Function used to load assets from the filesystem or the cache. Permits
/// manipulating the loaded asset with a mapping function. Example usage:
/// ```no_run
/// use vek::*;
/// use veloren_common::{assets, terrain::Structure};
///
/// let my_tree_structure = assets::load_map("world.tree.oak_green.1", |s: Structure| {
/// s.with_center(Vec3::new(15, 18, 14))
/// })
/// .unwrap();
/// ```
pub fn load_map<A: Asset + 'static, F: FnOnce(A) -> A>(
fn reload<A: Asset>(specifier: &str) -> Result<(), Error>
where
A::Output: Send + Sync + 'static,
{
let asset = Arc::new(A::parse(load_file(specifier, A::ENDINGS)?)?);
let mut assets_write = ASSETS.write().unwrap();
match assets_write.get_mut(specifier) {
Some(a) => *a = asset,
None => {
assets_write.insert(specifier.to_owned(), asset);
},
}
Ok(())
}
/// The Asset trait, which is implemented by all structures that have their data
/// stored in the filesystem.
pub trait Asset: Sized {
type Output = Self;
const ENDINGS: &'static [&'static str];
/// Parse the input file and return the correct Asset.
fn parse(buf_reader: BufReader<File>) -> Result<Self::Output, Error>;
// TODO: Remove this function. It's only used in world/ in a really ugly way.To
// do this properly assets should have all their necessary data in one file. A
// ron file could be used to combine voxel data with positioning data for
// example.
/// Function used to load assets from the filesystem or the cache. Permits
/// manipulating the loaded asset with a mapping function. Example usage:
/// ```no_run
/// use vek::*;
/// use veloren_common::{assets::Asset, terrain::Structure};
///
/// let my_tree_structure = Structure::load_map("world.tree.oak_green.1", |s: Structure| {
/// s.with_center(Vec3::new(15, 18, 14))
/// })
/// .unwrap();
/// ```
fn load_map<F: FnOnce(Self::Output) -> Self::Output>(
specifier: &str,
f: F,
) -> Result<Arc<A>, Error> {
) -> Result<Arc<Self::Output>, Error>
where
Self::Output: Send + Sync + 'static,
{
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 asset = Arc::new(f(Self::parse(load_file(specifier, Self::ENDINGS)?)?));
let clone = Arc::clone(&asset);
ASSETS.write().unwrap().insert(specifier.to_owned(), clone);
Ok(asset)
},
}
}
}
pub fn load_glob<A: Asset + 'static>(specifier: &str) -> Result<Arc<Vec<Arc<A>>>, Error> {
fn load_glob(specifier: &str) -> Result<Arc<Vec<Arc<Self::Output>>>, Error>
where
Self::Output: Send + Sync + 'static,
{
if let Some(assets) = ASSETS.read().unwrap().get(specifier) {
return Ok(Arc::clone(assets).downcast()?);
}
@ -118,11 +149,13 @@ pub fn load_glob<A: Asset + 'static>(specifier: &str) -> Result<Arc<Vec<Arc<A>>>
glob_matches
.into_iter()
.filter_map(|name| {
load(&specifier.replace("*", &name))
Self::load(&specifier.replace("*", &name))
.map_err(|e| {
error!(
?e,
"Failed to load \"{}\" as part of glob \"{}\"", name, specifier
"Failed to load \"{}\" as part of glob \"{}\"",
name,
specifier
)
})
.ok()
@ -137,61 +170,76 @@ pub fn load_glob<A: Asset + 'static>(specifier: &str) -> Result<Arc<Vec<Arc<A>>>
},
Err(error) => Err(error),
}
}
}
/// Function used to load assets from the filesystem or the cache.
/// Example usage:
/// ```no_run
/// use image::DynamicImage;
/// use veloren_common::assets;
///
/// let my_image = assets::load::<DynamicImage>("core.ui.backgrounds.city").unwrap();
/// ```
pub fn load<A: Asset + 'static>(specifier: &str) -> Result<Arc<A>, Error> {
load_map(specifier, |x| x)
}
/// Function used to load assets from the filesystem or the cache.
/// Example usage:
/// ```no_run
/// use image::DynamicImage;
/// use veloren_common::assets::Asset;
///
/// let my_image = DynamicImage::load("core.ui.backgrounds.city").unwrap();
/// ```
fn load(specifier: &str) -> Result<Arc<Self::Output>, Error>
where
Self::Output: Send + Sync + 'static,
{
Self::load_map(specifier, |x| x)
}
/// Function used to load assets from the filesystem or the cache and return a
/// clone.
pub fn load_cloned<A: Asset + Clone + 'static>(specifier: &str) -> Result<A, Error> {
load::<A>(specifier).map(|asset| (*asset).clone())
}
/// Function used to load assets from the filesystem or the cache and return
/// a clone.
fn load_cloned(specifier: &str) -> Result<Self::Output, Error>
where
Self::Output: Clone + Send + Sync + 'static,
{
Self::load(specifier).map(|asset| (*asset).clone())
}
/// Function used to load essential assets from the filesystem or the cache. It
/// will panic if the asset is not found. Example usage:
/// ```no_run
/// use image::DynamicImage;
/// use veloren_common::assets;
///
/// let my_image = assets::load_expect::<DynamicImage>("core.ui.backgrounds.city");
/// ```
pub fn load_expect<A: Asset + 'static>(specifier: &str) -> Arc<A> {
load(specifier).unwrap_or_else(|err| {
/// Function used to load essential assets from the filesystem or the cache.
/// It will panic if the asset is not found. Example usage:
/// ```no_run
/// use image::DynamicImage;
/// use veloren_common::assets::Asset;
///
/// let my_image = DynamicImage::load_expect("core.ui.backgrounds.city");
/// ```
fn load_expect(specifier: &str) -> Arc<Self::Output>
where
Self::Output: Send + Sync + 'static,
{
Self::load(specifier).unwrap_or_else(|err| {
panic!(
"Failed loading essential asset: {} (error={:?})",
specifier, err
)
})
}
}
/// Function used to load essential assets from the filesystem or the cache and
/// return a clone. It will panic if the asset is not found.
pub fn load_expect_cloned<A: Asset + Clone + 'static>(specifier: &str) -> A {
load_expect::<A>(specifier).as_ref().clone()
}
/// Function used to load essential assets from the filesystem or the cache
/// and return a clone. It will panic if the asset is not found.
fn load_expect_cloned(specifier: &str) -> Self::Output
where
Self::Output: Clone + Send + Sync + 'static,
{
Self::load_expect(specifier).as_ref().clone()
}
/// Load an asset while registering it to be watched and reloaded when it
/// changes
pub fn load_watched<A: Asset + 'static>(
/// Load an asset while registering it to be watched and reloaded when it
/// changes
fn load_watched(
specifier: &str,
indicator: &mut watch::ReloadIndicator,
) -> Result<Arc<A>, Error> {
let asset = load(specifier)?;
) -> Result<Arc<Self::Output>, Error>
where
Self::Output: Send + Sync + 'static,
{
let asset = Self::load(specifier)?;
// Determine path to watch
let path = unpack_specifier(specifier);
let mut path_with_extension = None;
for ending in A::ENDINGS {
for ending in Self::ENDINGS {
let mut path = path.clone();
path.set_extension(ending);
@ -203,37 +251,17 @@ pub fn load_watched<A: Asset + 'static>(
let owned_specifier = specifier.to_string();
indicator.add(
path_with_extension.ok_or_else(|| Error::NotFound(path.to_string_lossy().into_owned()))?,
path_with_extension
.ok_or_else(|| Error::NotFound(path.to_string_lossy().into_owned()))?,
move || {
if let Err(e) = reload::<A>(&owned_specifier) {
if let Err(e) = reload::<Self>(&owned_specifier) {
error!(?e, ?owned_specifier, "Error reloading owned_specifier");
}
},
);
Ok(asset)
}
fn reload<A: Asset + 'static>(specifier: &str) -> Result<(), Error> {
let asset = Arc::new(A::parse(load_file(specifier, A::ENDINGS)?)?);
let clone = Arc::clone(&asset);
let mut assets_write = ASSETS.write().unwrap();
match assets_write.get_mut(specifier) {
Some(a) => *a = clone,
None => {
assets_write.insert(specifier.to_owned(), clone);
},
}
Ok(())
}
/// The Asset trait, which is implemented by all structures that have their data
/// stored in the filesystem.
pub trait Asset: Send + Sync + Sized {
const ENDINGS: &'static [&'static str];
/// Parse the input file and return the correct Asset.
fn parse(buf_reader: BufReader<File>) -> Result<Self, Error>;
}
impl Asset for DynamicImage {
@ -265,13 +293,45 @@ impl Asset for Value {
}
}
impl Asset for String {
const ENDINGS: &'static [&'static str] = &["glsl"];
/// Load fron an arbitrary RON file.
pub struct Ron<T>(pub PhantomData<T>);
fn parse(mut buf_reader: BufReader<File>) -> Result<Self, Error> {
let mut string = String::new();
buf_reader.read_to_string(&mut string)?;
Ok(string)
impl<T: Send + Sync + for<'de> Deserialize<'de>> Asset for Ron<T> {
type Output = T;
const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<T, Error> {
ron::de::from_reader(buf_reader).map_err(Error::parse_error)
}
}
/// Load from a specific asset path.
pub struct AssetWith<T: Asset, const ASSET_PATH: &'static str> {
pub asset: Arc<T::Output>,
}
impl<T: Asset, const ASSET_PATH: &'static str> Clone for AssetWith<T, ASSET_PATH> {
fn clone(&self) -> Self {
Self {
asset: Arc::clone(&self.asset),
}
}
}
impl<T: Asset, const ASSET_PATH: &'static str> AssetWith<T, ASSET_PATH>
where
T::Output: Send + Sync + 'static,
{
#[inline]
pub fn load_watched(indicator: &mut watch::ReloadIndicator) -> Result<Self, Error> {
T::load_watched(ASSET_PATH, indicator).map(|asset| Self { asset })
}
#[inline]
pub fn reload(&mut self) -> Result<(), Error> {
self.asset = T::load(ASSET_PATH)?;
Ok(())
}
}

View File

@ -5,7 +5,7 @@ pub mod tool;
pub use tool::{Hands, Tool, ToolCategory, ToolKind};
use crate::{
assets::{self, Asset},
assets::{self, Asset, Ron},
effect::Effect,
lottery::Lottery,
terrain::{Block, BlockKind},
@ -14,7 +14,6 @@ use rand::prelude::*;
use serde::{Deserialize, Serialize};
use specs::{Component, FlaggedStorage};
use specs_idvs::IdvStorage;
use std::{fs::File, io::BufReader};
use vek::Rgb;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -90,13 +89,7 @@ pub struct Item {
pub kind: ItemKind,
}
impl Asset for Item {
const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
}
}
pub type ItemAsset = Ron<Item>;
impl Item {
// TODO: consider alternatives such as default abilities that can be added to a
@ -109,7 +102,7 @@ impl Item {
}
}
pub fn expect_from_asset(asset: &str) -> Self { (*assets::load_expect::<Self>(asset)).clone() }
pub fn expect_from_asset(asset: &str) -> Self { (*ItemAsset::load_expect(asset)).clone() }
pub fn set_amount(&mut self, give_amount: u32) -> Result<(), assets::Error> {
use ItemKind::*;
@ -145,75 +138,44 @@ impl Item {
}
pub fn try_reclaim_from_block(block: Block) -> Option<Self> {
let chosen;
let mut rng = rand::thread_rng();
match block.kind() {
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.ore.veloritefrag"))
},
BlockKind::BlueFlower => Some(assets::load_expect_cloned("common.items.flowers.blue")),
BlockKind::PinkFlower => Some(assets::load_expect_cloned("common.items.flowers.pink")),
BlockKind::PurpleFlower => {
Some(assets::load_expect_cloned("common.items.flowers.purple"))
},
BlockKind::RedFlower => Some(assets::load_expect_cloned("common.items.flowers.red")),
BlockKind::WhiteFlower => {
Some(assets::load_expect_cloned("common.items.flowers.white"))
},
BlockKind::YellowFlower => {
Some(assets::load_expect_cloned("common.items.flowers.yellow"))
},
BlockKind::Sunflower => Some(assets::load_expect_cloned("common.items.flowers.sun")),
BlockKind::LongGrass => Some(assets::load_expect_cloned("common.items.grasses.long")),
BlockKind::MediumGrass => {
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.food.coconut")),
Some(ItemAsset::load_expect_cloned(match block.kind() {
BlockKind::Apple => "common.items.food.apple",
BlockKind::Mushroom => "common.items.food.mushroom",
BlockKind::Velorite => "common.items.ore.velorite",
BlockKind::VeloriteFrag => "common.items.ore.veloritefrag",
BlockKind::BlueFlower => "common.items.flowers.blue",
BlockKind::PinkFlower => "common.items.flowers.pink",
BlockKind::PurpleFlower => "common.items.flowers.purple",
BlockKind::RedFlower => "common.items.flowers.red",
BlockKind::WhiteFlower => "common.items.flowers.white",
BlockKind::YellowFlower => "common.items.flowers.yellow",
BlockKind::Sunflower => "common.items.flowers.sun",
BlockKind::LongGrass => "common.items.grasses.long",
BlockKind::MediumGrass => "common.items.grasses.medium",
BlockKind::ShortGrass => "common.items.grasses.short",
BlockKind::Coconut => "common.items.food.coconut",
BlockKind::Chest => {
let chosen = match rng.gen_range(0, 7) {
0 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_weapon_uncommon",
),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_weapon_common",
),
2 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_light",
),
3 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_cloth",
),
4 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_heavy",
),
_ => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_misc",
),
};
let chosen = chosen.choose();
Some(assets::load_expect_cloned(chosen))
chosen = Lottery::<String>::load_expect(match rng.gen_range(0, 7) {
0 => "common.loot_tables.loot_table_weapon_uncommon",
1 => "common.loot_tables.loot_table_weapon_common",
2 => "common.loot_tables.loot_table_armor_light",
3 => "common.loot_tables.loot_table_armor_cloth",
4 => "common.loot_tables.loot_table_armor_heavy",
_ => "common.loot_tables.loot_table_armor_misc",
});
chosen.choose()
},
BlockKind::Crate => {
let chosen =
assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table_food");
let chosen = chosen.choose();
Some(assets::load_expect_cloned(chosen))
chosen = Lottery::<String>::load_expect("common.loot_tables.loot_table_food");
chosen.choose()
},
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,
}
BlockKind::Stones => "common.items.crafting_ing.stones",
BlockKind::Twigs => "common.items.crafting_ing.twigs",
BlockKind::ShinyGem => "common.items.crafting_ing.shiny_gem",
_ => return None,
}))
}
/// Determines whether two items are superficially equivalent to one another

View File

@ -1,8 +1,8 @@
pub mod item;
pub mod slot;
use crate::{assets, recipe::Recipe};
use item::{Item, ItemKind};
use crate::{assets::Asset, recipe::Recipe};
use item::{Item, ItemAsset, ItemKind};
use serde::{Deserialize, Serialize};
use specs::{Component, FlaggedStorage, HashMapStorage};
use specs_idvs::IdvStorage;
@ -517,8 +517,8 @@ impl Default for Inventory {
slots: vec![None; 36],
amount: 0,
};
inventory.push(assets::load_expect_cloned("common.items.food.cheese"));
inventory.push(assets::load_expect_cloned("common.items.food.apple"));
inventory.push(ItemAsset::load_expect_cloned("common.items.food.cheese"));
inventory.push(ItemAsset::load_expect_cloned("common.items.food.apple"));
inventory
}
}

View File

@ -266,15 +266,16 @@ pub fn swap(
///
/// ```
/// use veloren_common::{
/// assets,
/// assets::Asset,
/// comp::{
/// item::ItemAsset,
/// slot::{equip, EquipSlot},
/// Inventory, Item,
/// },
/// LoadoutBuilder,
/// };
///
/// let boots: Option<Item> = Some(assets::load_expect_cloned(
/// let boots: Option<Item> = Some(ItemAsset::load_expect_cloned(
/// "common.items.testing.test_boots",
/// ));
///
@ -361,7 +362,7 @@ pub fn unequip(slot: EquipSlot, inventory: &mut Inventory, loadout: &mut Loadout
#[cfg(test)]
mod tests {
use super::*;
use crate::{assets, LoadoutBuilder};
use crate::{assets::Asset, comp::item::ItemAsset, LoadoutBuilder};
#[test]
fn test_unequip_items_both_hands() {
@ -396,11 +397,11 @@ mod tests {
#[test]
fn test_equip_item() {
let boots: Option<comp::Item> = Some(assets::load_expect_cloned(
let boots: Option<comp::Item> = Some(ItemAsset::load_expect_cloned(
"common.items.testing.test_boots",
));
let starting_sandles: Option<comp::Item> = Some(assets::load_expect_cloned(
let starting_sandles: Option<comp::Item> = Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.sandals_0",
));
@ -425,11 +426,11 @@ mod tests {
#[test]
fn test_loadout_replace() {
let boots: Option<comp::Item> = Some(assets::load_expect_cloned(
let boots: Option<comp::Item> = Some(ItemAsset::load_expect_cloned(
"common.items.testing.test_boots",
));
let starting_sandles: Option<comp::Item> = Some(assets::load_expect_cloned(
let starting_sandles: Option<comp::Item> = Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.sandals_0",
));

View File

@ -1,9 +1,10 @@
use super::*;
use crate::assets::Asset;
use lazy_static::lazy_static;
lazy_static! {
static ref TEST_ITEMS: Vec<Item> = vec![
assets::load_expect_cloned("common.items.debug.boost"),
assets::load_expect_cloned("common.items.debug.possess")
item::ItemAsset::load_expect_cloned("common.items.debug.boost"),
item::ItemAsset::load_expect_cloned("common.items.debug.possess")
];
}

View File

@ -1,9 +1,12 @@
#![deny(unsafe_code)]
#![allow(clippy::option_map_unit_fn)]
#![allow(incomplete_features)]
#![type_length_limit = "1664759"]
#![feature(
arbitrary_enum_discriminant,
associated_type_defaults,
const_checked_int_methods,
const_generics,
fundamental,
option_unwrap_none,
bool_to_option,

View File

@ -1,7 +1,7 @@
use crate::{
assets,
assets::Asset,
comp::{
item::{Item, ItemKind},
item::{Item, ItemAsset, ItemKind},
Body, CharacterAbility, ItemConfig, Loadout,
},
};
@ -48,16 +48,16 @@ impl LoadoutBuilder {
/// Set default armor items for the loadout. This may vary with game
/// updates, but should be safe defaults for a new character.
pub fn defaults(self) -> Self {
self.chest(Some(assets::load_expect_cloned(
self.chest(Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.rugged_chest",
)))
.pants(Some(assets::load_expect_cloned(
.pants(Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.rugged_pants",
)))
.foot(Some(assets::load_expect_cloned(
.foot(Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.sandals_0",
)))
.lantern(Some(assets::load_expect_cloned(
.lantern(Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.lantern",
)))
}
@ -66,7 +66,7 @@ impl LoadoutBuilder {
pub fn animal(body: Body) -> Self {
Self(Loadout {
active_item: Some(ItemConfig {
item: assets::load_expect_cloned("common.items.weapons.empty.empty"),
item: ItemAsset::load_expect_cloned("common.items.weapons.empty.empty"),
ability1: Some(CharacterAbility::BasicMelee {
energy_cost: 10,
buildup_duration: Duration::from_millis(600),
@ -125,7 +125,7 @@ impl LoadoutBuilder {
/// Get an [Item](../comp/struct.Item.html) by its string
/// reference by loading its asset
pub fn item_from_str(item_ref: Option<&str>) -> Option<Item> {
item_ref.and_then(|specifier| assets::load_cloned::<Item>(&specifier).ok())
item_ref.and_then(|specifier| ItemAsset::load_cloned(&specifier).ok())
}
/// Get an item's (weapon's) default

View File

@ -1,9 +1,9 @@
use crate::assets::{self, Asset};
use rand::prelude::*;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde::{de::DeserializeOwned, Deserialize};
use std::{fs::File, io::BufReader};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Deserialize)]
pub struct Lottery<T> {
items: Vec<(f32, T)>,
total: f32,
@ -48,14 +48,14 @@ impl<T> Lottery<T> {
#[cfg(test)]
mod tests {
use super::*;
use crate::{assets, comp::Item};
use crate::comp::item::ItemAsset;
#[test]
fn test_loot_table() {
let test = assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table");
let test = Lottery::<String>::load_expect("common.loot_tables.loot_table");
for (_, item) in test.iter() {
assert!(
assets::load::<Item>(item).is_ok(),
ItemAsset::load(item).is_ok(),
"Invalid loot table item '{}'",
item
);

View File

@ -1,5 +1,5 @@
use crate::{
assets,
assets::Asset,
comp::{self, AllBodies, Body},
};
use lazy_static::lazy_static;
@ -63,7 +63,7 @@ pub struct SpeciesNames {
pub type NpcNames = AllBodies<BodyNames, SpeciesNames>;
lazy_static! {
pub static ref NPC_NAMES: Arc<NpcNames> = assets::load_expect("common.npc_names");
pub static ref NPC_NAMES: Arc<NpcNames> = NpcNames::load_expect("common.npc_names");
}
impl FromStr for NpcKind {

View File

@ -1,6 +1,6 @@
use crate::{
assets::{self, Asset},
comp::{Inventory, Item},
comp::{item::ItemAsset, Inventory, Item},
};
use hashbrown::HashMap;
use serde::{Deserialize, Serialize};
@ -78,12 +78,12 @@ impl Asset for RecipeBook {
.map::<Result<(String, Recipe), assets::Error>, _>(
|(name, ((output, amount), inputs))| {
Ok((name, Recipe {
output: ((&*assets::load::<Item>(&output)?).clone(), amount),
output: ((&*ItemAsset::load(&output)?).clone(), amount),
inputs: inputs
.into_iter()
.map::<Result<(Item, usize), assets::Error>, _>(
|(name, amount)| {
Ok(((&*assets::load::<Item>(&name)?).clone(), amount))
Ok(((&*ItemAsset::load(&name)?).clone(), amount))
},
)
.collect::<Result<_, _>>()?,
@ -96,4 +96,4 @@ impl Asset for RecipeBook {
}
}
pub fn default_recipe_book() -> Arc<RecipeBook> { assets::load_expect("common.recipe_book") }
pub fn default_recipe_book() -> Arc<RecipeBook> { RecipeBook::load_expect("common.recipe_book") }

View File

@ -1,6 +1,6 @@
use super::BlockKind;
use crate::{
assets::{self, Asset},
assets::{self, Asset, Ron},
make_case_elim,
vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol},
volumes::dyna::{Dyna, DynaError},
@ -53,14 +53,10 @@ pub struct Structure {
impl Structure {
pub fn load_group(specifier: &str) -> Vec<Arc<Structure>> {
let spec = assets::load::<StructuresSpec>(&["world.manifests.", specifier].concat());
spec.unwrap()
.0
.iter()
let spec = StructuresSpec::load_expect(&["world.manifests.", specifier].concat());
spec.iter()
.map(|sp| {
assets::load_map(&sp.specifier[..], |s: Structure| {
s.with_center(Vec3::from(sp.center))
})
Structure::load_map(&sp.specifier[..], |s| s.with_center(Vec3::from(sp.center)))
.unwrap()
})
.collect()
@ -170,13 +166,5 @@ struct StructureSpec {
specifier: String,
center: [i32; 3],
}
#[derive(Deserialize)]
struct StructuresSpec(Vec<StructureSpec>);
impl Asset for StructuresSpec {
const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
}
}
type StructuresSpec = Ron<Vec<StructureSpec>>;

View File

@ -5,9 +5,9 @@
use crate::{client::Client, Server, StateExt};
use chrono::{NaiveTime, Timelike};
use common::{
assets,
assets::Asset,
cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS},
comp::{self, ChatType, Item, LightEmitter, WaypointArea},
comp::{self, item::ItemAsset, ChatType, Item, LightEmitter, WaypointArea},
event::{EventBus, ServerEvent},
msg::{Notification, PlayerListUpdate, ServerMsg},
npc::{self, get_npc_name},
@ -117,7 +117,7 @@ fn handle_give_item(
scan_fmt_some!(&args, &action.arg_fmt(), String, u32)
{
let give_amount = give_amount_opt.unwrap_or(1);
if let Ok(item) = assets::load_cloned(&item_name) {
if let Ok(item) = ItemAsset::load_cloned(&item_name) {
let mut item: Item = item;
if let Ok(()) = item.set_amount(give_amount.min(2000)) {
server
@ -1640,7 +1640,7 @@ fn handle_debug(
_args: String,
_action: &ChatCommand,
) {
if let Ok(items) = assets::load_glob::<Item>("common.items.debug.*") {
if let Ok(items) = ItemAsset::load_glob("common.items.debug.*") {
server
.state()
.ecs()

View File

@ -1,9 +1,9 @@
use crate::{client::Client, comp::quadruped_small, Server, SpawnPoint, StateExt};
use common::{
assets,
assets::Asset,
comp::{
self, object, Alignment, Body, Damage, DamageSource, Group, HealthChange, HealthSource,
Player, Pos, Stats,
self, item::ItemAsset, object, Alignment, Body, Damage, DamageSource, Group, HealthChange,
HealthSource, Player, Pos, Stats,
},
lottery::Lottery,
msg::{PlayerListUpdate, ServerMsg},
@ -186,130 +186,68 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
// Decide for a loot drop before turning into a lootbag
let old_body = state.ecs().write_storage::<Body>().remove(entity);
let mut rng = rand::thread_rng();
let drop = match old_body {
let drop = Lottery::<String>::load_expect(match old_body {
Some(common::comp::Body::Humanoid(_)) => match rng.gen_range(0, 4) {
0 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_humanoids",
),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_light",
),
2 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_cloth",
),
3 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_weapon_common",
),
_ => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_humanoids",
),
0 => "common.loot_tables.loot_table_humanoids",
1 => "common.loot_tables.loot_table_armor_light",
2 => "common.loot_tables.loot_table_armor_cloth",
3 => "common.loot_tables.loot_table_weapon_common",
_ => "common.loot_tables.loot_table_humanoids",
},
Some(common::comp::Body::QuadrupedSmall(quadruped_small)) => {
match quadruped_small.species {
quadruped_small::Species::Dodarock => match rng.gen_range(0, 6) {
0 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_misc",
),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_rocks",
),
_ => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_rocks",
),
0 => "common.loot_tables.loot_table_armor_misc",
1 => "common.loot_tables.loot_table_rocks",
_ => "common.loot_tables.loot_table_rocks",
},
_ => match rng.gen_range(0, 4) {
0 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_food",
),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_misc",
),
2 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_animal_parts",
),
_ => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_animal_parts",
),
0 => "common.loot_tables.loot_table_food",
1 => "common.loot_tables.loot_table_armor_misc",
2 => "common.loot_tables.loot_table_animal_parts",
_ => "common.loot_tables.loot_table_animal_parts",
},
}
},
Some(common::comp::Body::QuadrupedMedium(_)) => match rng.gen_range(0, 4) {
0 => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table_food"),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_misc",
),
2 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_animal_parts",
),
_ => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_animal_parts",
),
0 => "common.loot_tables.loot_table_food",
1 => "common.loot_tables.loot_table_armor_misc",
2 => "common.loot_tables.loot_table_animal_parts",
_ => "common.loot_tables.loot_table_animal_parts",
},
Some(common::comp::Body::BirdMedium(_)) => match rng.gen_range(0, 3) {
0 => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table_food"),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_misc",
),
_ => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table"),
0 => "common.loot_tables.loot_table_food",
1 => "common.loot_tables.loot_table_armor_misc",
_ => "common.loot_tables.loot_table",
},
Some(common::comp::Body::BipedLarge(_)) => match rng.gen_range(0, 8) {
0 => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table_food"),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_nature",
),
3 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_heavy",
),
5 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_weapon_uncommon",
),
6 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_weapon_rare",
),
_ => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_cave_large",
),
0 => "common.loot_tables.loot_table_food",
1 => "common.loot_tables.loot_table_armor_nature",
3 => "common.loot_tables.loot_table_armor_heavy",
5 => "common.loot_tables.loot_table_weapon_uncommon",
6 => "common.loot_tables.loot_table_weapon_rare",
_ => "common.loot_tables.loot_table_cave_large",
},
Some(common::comp::Body::Golem(_)) => match rng.gen_range(0, 9) {
0 => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table_food"),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_misc",
),
2 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_light",
),
3 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_heavy",
),
4 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_armor_misc",
),
5 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_weapon_common",
),
6 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_weapon_uncommon",
),
7 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_weapon_rare",
),
_ => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table"),
},
Some(common::comp::Body::Critter(_)) => {
assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table_animal_parts")
},
Some(common::comp::Body::Dragon(_)) => {
assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table_weapon_rare")
0 => "common.loot_tables.loot_table_food",
1 => "common.loot_tables.loot_table_armor_misc",
2 => "common.loot_tables.loot_table_armor_light",
3 => "common.loot_tables.loot_table_armor_heavy",
4 => "common.loot_tables.loot_table_armor_misc",
5 => "common.loot_tables.loot_table_weapon_common",
6 => "common.loot_tables.loot_table_weapon_uncommon",
7 => "common.loot_tables.loot_table_weapon_rare",
_ => "common.loot_tables.loot_table",
},
Some(common::comp::Body::Critter(_)) => "common.loot_tables.loot_table_animal_parts",
Some(common::comp::Body::Dragon(_)) => "common.loot_tables.loot_table_weapon_rare",
Some(common::comp::Body::QuadrupedLow(_)) => match rng.gen_range(0, 3) {
0 => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table_food"),
1 => assets::load_expect::<Lottery<String>>(
"common.loot_tables.loot_table_animal_parts",
),
_ => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table"),
0 => "common.loot_tables.loot_table_food",
1 => "common.loot_tables.loot_table_animal_parts",
_ => "common.loot_tables.loot_table",
},
_ => assets::load_expect::<Lottery<String>>("common.loot_tables.loot_table"),
};
_ => "common.loot_tables.loot_table",
});
let drop = drop.choose();
// Replace npc with lootbag containing drop
let _ = state
@ -321,7 +259,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
item_drops.remove(entity);
item_drop.0
} else {
assets::load_expect_cloned(drop)
ItemAsset::load_expect_cloned(drop)
};
let _ = state.ecs().write_storage().insert(entity, item);

View File

@ -3,7 +3,7 @@ use crate::{
Server,
};
use common::{
assets,
assets::Asset,
comp::{self, item},
msg::ServerMsg,
sync::{Uid, WorldSyncExt},
@ -125,7 +125,7 @@ pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) {
.expect("Could not read loadouts component while possessing")
.or_insert(comp::Loadout::default());
let item = assets::load_expect_cloned::<comp::Item>("common.items.debug.possess");
let item = item::ItemAsset::load_expect_cloned("common.items.debug.possess");
if let item::ItemKind::Tool(tool) = &item.kind {
let mut abilities = tool.get_abilities();
let mut ability_drain = abilities.drain(..);

View File

@ -1,8 +1,12 @@
use super::SysTimer;
use crate::{chunk_generator::ChunkGenerator, client::Client, Tick};
use common::{
assets,
comp::{self, bird_medium, item, Alignment, CharacterAbility, ItemConfig, Player, Pos},
assets::Asset,
comp::{
self, bird_medium,
item::{self, ItemAsset},
Alignment, CharacterAbility, ItemConfig, Player, Pos,
},
event::{EventBus, ServerEvent},
generation::get_npc_name,
msg::ServerMsg,
@ -135,7 +139,7 @@ impl<'a> System<'a> for Sys {
} else {
Some(ItemConfig {
// We need the empty item so npcs can attack
item: assets::load_expect_cloned("common.items.weapons.empty.empty"),
item: ItemAsset::load_expect_cloned("common.items.weapons.empty.empty"),
ability1: Some(CharacterAbility::BasicMelee {
energy_cost: 0,
buildup_duration: Duration::from_millis(0),
@ -156,7 +160,7 @@ impl<'a> System<'a> for Sys {
active_item,
second_item: None,
shoulder: None,
chest: Some(assets::load_expect_cloned(
chest: Some(ItemAsset::load_expect_cloned(
match rand::thread_rng().gen_range(0, 10) {
0 => "common.items.npc_armor.chest.worker_green_0",
1 => "common.items.npc_armor.chest.worker_green_1",
@ -170,14 +174,14 @@ impl<'a> System<'a> for Sys {
_ => "common.items.npc_armor.chest.worker_orange_1",
},
)),
belt: Some(assets::load_expect_cloned(
belt: Some(ItemAsset::load_expect_cloned(
"common.items.armor.belt.leather_0",
)),
hand: None,
pants: Some(assets::load_expect_cloned(
pants: Some(ItemAsset::load_expect_cloned(
"common.items.armor.pants.worker_blue_0",
)),
foot: Some(assets::load_expect_cloned(
foot: Some(ItemAsset::load_expect_cloned(
match rand::thread_rng().gen_range(0, 2) {
0 => "common.items.armor.foot.leather_0",
_ => "common.items.armor.starter.sandals_0",
@ -193,30 +197,32 @@ impl<'a> System<'a> for Sys {
comp::Alignment::Enemy => comp::Loadout {
active_item,
second_item: None,
shoulder: Some(assets::load_expect_cloned(
shoulder: Some(ItemAsset::load_expect_cloned(
"common.items.npc_armor.shoulder.cultist_shoulder_purple",
)),
chest: Some(assets::load_expect_cloned(
chest: Some(ItemAsset::load_expect_cloned(
"common.items.npc_armor.chest.cultist_chest_purple",
)),
belt: Some(assets::load_expect_cloned(
belt: Some(ItemAsset::load_expect_cloned(
"common.items.npc_armor.belt.cultist_belt",
)),
hand: Some(assets::load_expect_cloned(
hand: Some(ItemAsset::load_expect_cloned(
"common.items.npc_armor.hand.cultist_hands_purple",
)),
pants: Some(assets::load_expect_cloned(
pants: Some(ItemAsset::load_expect_cloned(
"common.items.npc_armor.pants.cultist_legs_purple",
)),
foot: Some(assets::load_expect_cloned(
foot: Some(ItemAsset::load_expect_cloned(
"common.items.npc_armor.foot.cultist_boots",
)),
back: Some(assets::load_expect_cloned(
back: Some(ItemAsset::load_expect_cloned(
"common.items.npc_armor.back.dungeon_purple-0",
)),
ring: None,
neck: None,
lantern: Some(assets::load_expect_cloned("common.items.lantern.black_0")),
lantern: Some(ItemAsset::load_expect_cloned(
"common.items.lantern.black_0",
)),
head: None,
tabard: None,
},
@ -259,7 +265,7 @@ impl<'a> System<'a> for Sys {
}
loadout = comp::Loadout {
active_item: Some(comp::ItemConfig {
item: assets::load_expect_cloned(
item: ItemAsset::load_expect_cloned(
"common.items.npc_weapons.sword.zweihander_sword_0",
),
ability1: Some(CharacterAbility::BasicMelee {
@ -276,22 +282,22 @@ impl<'a> System<'a> for Sys {
dodge_ability: None,
}),
second_item: None,
shoulder: Some(assets::load_expect_cloned(
shoulder: Some(ItemAsset::load_expect_cloned(
"common.items.armor.shoulder.plate_0",
)),
chest: Some(assets::load_expect_cloned(
chest: Some(ItemAsset::load_expect_cloned(
"common.items.armor.chest.plate_green_0",
)),
belt: Some(assets::load_expect_cloned(
belt: Some(ItemAsset::load_expect_cloned(
"common.items.armor.belt.plate_0",
)),
hand: Some(assets::load_expect_cloned(
hand: Some(ItemAsset::load_expect_cloned(
"common.items.armor.hand.plate_0",
)),
pants: Some(assets::load_expect_cloned(
pants: Some(ItemAsset::load_expect_cloned(
"common.items.armor.pants.plate_green_0",
)),
foot: Some(assets::load_expect_cloned(
foot: Some(ItemAsset::load_expect_cloned(
"common.items.armor.foot.plate_0",
)),
back: None,

View File

@ -5,10 +5,14 @@ use std::{
};
use structopt::StructOpt;
use common::{assets, comp};
use common::{
assets::{self, Asset},
comp,
};
use comp::item::{
armor::{ArmorKind, Protection},
tool::ToolKind,
ItemAsset,
};
#[derive(StructOpt)]
@ -43,7 +47,7 @@ fn armor_stats() -> Result<(), Box<dyn Error>> {
.to_string()
.replace("/", ".");
let asset = assets::load_expect_cloned::<comp::Item>(asset_identifier);
let asset = ItemAsset::load_expect_cloned(asset_identifier);
match &asset.kind {
comp::item::ItemKind::Armor(armor) => {
@ -109,7 +113,7 @@ fn weapon_stats() -> Result<(), Box<dyn Error>> {
.display()
.to_string()
.replace("/", ".");
let asset = assets::load_expect_cloned::<comp::Item>(asset_identifier);
let asset = ItemAsset::load_expect_cloned(asset_identifier);
match &asset.kind {
comp::item::ItemKind::Tool(tool) => {

View File

@ -10,10 +10,12 @@ pub use self::{
wield::WieldAnimation,
};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::biped_large::Body;
skeleton_impls!(struct BipedLargeSkeleton {
+ head,
+ jaw,
@ -36,6 +38,7 @@ skeleton_impls!(struct BipedLargeSkeleton {
impl Skeleton for BipedLargeSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 15;
#[cfg(feature = "use-dyn-lib")]
@ -115,8 +118,8 @@ impl Default for SkeletonAttr {
}
}
impl<'a> From<&'a comp::biped_large::Body> for SkeletonAttr {
fn from(body: &'a comp::biped_large::Body) -> Self {
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::biped_large::{BodyType::*, Species::*};
Self {
head: match (body.species, body.body_type) {

View File

@ -6,10 +6,12 @@ pub mod run;
// Reexports
pub use self::{feed::FeedAnimation, fly::FlyAnimation, idle::IdleAnimation, run::RunAnimation};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::bird_medium::Body;
skeleton_impls!(struct BirdMediumSkeleton {
+ head,
+ torso,
@ -22,6 +24,7 @@ skeleton_impls!(struct BirdMediumSkeleton {
impl Skeleton for BirdMediumSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 7;
#[cfg(feature = "use-dyn-lib")]
@ -82,8 +85,8 @@ impl Default for SkeletonAttr {
}
}
impl<'a> From<&'a comp::bird_medium::Body> for SkeletonAttr {
fn from(body: &'a comp::bird_medium::Body) -> Self {
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::bird_medium::Species::*;
Self {
head: match (body.species, body.body_type) {

View File

@ -5,10 +5,12 @@ pub mod run;
// Reexports
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::bird_small::Body;
skeleton_impls!(struct BirdSmallSkeleton {
+ head,
+ torso,
@ -18,6 +20,7 @@ skeleton_impls!(struct BirdSmallSkeleton {
impl Skeleton for BirdSmallSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 4;
#[cfg(feature = "use-dyn-lib")]
@ -59,6 +62,6 @@ impl Default for SkeletonAttr {
fn default() -> Self { Self }
}
impl<'a> From<&'a comp::bird_small::Body> for SkeletonAttr {
fn from(_body: &'a comp::bird_small::Body) -> Self { Self }
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(_body: &'a Body) -> Self { Self }
}

View File

@ -36,10 +36,12 @@ pub use self::{
swimwield::SwimWieldAnimation, wield::WieldAnimation,
};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp;
use core::convert::TryFrom;
pub type Body = comp::humanoid::Body;
skeleton_impls!(struct CharacterSkeleton {
+ head,
+ chest,
@ -65,6 +67,7 @@ skeleton_impls!(struct CharacterSkeleton {
impl Skeleton for CharacterSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 16;
#[cfg(feature = "use-dyn-lib")]
@ -156,7 +159,7 @@ impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
}
impl SkeletonAttr {
pub fn calculate_scale(body: &comp::humanoid::Body) -> f32 {
pub fn calculate_scale(body: &Body) -> f32 {
use comp::humanoid::{BodyType::*, Species::*};
match (body.species, body.body_type) {
(Orc, Male) => 1.14,
@ -175,9 +178,9 @@ impl SkeletonAttr {
}
}
impl<'a> From<&'a comp::humanoid::Body> for SkeletonAttr {
impl<'a> From<&'a Body> for SkeletonAttr {
#[allow(clippy::match_single_binding)] // TODO: Pending review in #587
fn from(body: &'a comp::humanoid::Body) -> Self {
fn from(body: &'a Body) -> Self {
use comp::humanoid::{BodyType::*, Species::*};
Self {
scaler: SkeletonAttr::calculate_scale(body),

View File

@ -5,10 +5,12 @@ pub mod run;
// Reexports
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::critter::Body;
skeleton_impls!(struct CritterSkeleton {
+ head,
+ chest,
@ -27,6 +29,7 @@ pub struct CritterAttr {
impl Skeleton for CritterSkeleton {
type Attr = CritterAttr;
type Body = Body;
const BONE_COUNT: usize = 5;
#[cfg(feature = "use-dyn-lib")]
@ -84,8 +87,8 @@ impl Default for CritterAttr {
}
}
impl<'a> From<&'a comp::critter::Body> for CritterAttr {
fn from(body: &'a comp::critter::Body) -> Self {
impl<'a> From<&'a Body> for CritterAttr {
fn from(body: &'a Body) -> Self {
use comp::critter::Species::*;
Self {
head: match (body.species, body.body_type) {

View File

@ -5,10 +5,12 @@ pub mod run;
// Reexports
pub use self::{fly::FlyAnimation, idle::IdleAnimation, run::RunAnimation};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::dragon::Body;
skeleton_impls!(struct DragonSkeleton {
+ head_upper,
+ head_lower,
@ -29,6 +31,7 @@ skeleton_impls!(struct DragonSkeleton {
impl Skeleton for DragonSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 15;
#[cfg(feature = "use-dyn-lib")]
@ -115,8 +118,8 @@ impl Default for SkeletonAttr {
}
}
impl<'a> From<&'a comp::dragon::Body> for SkeletonAttr {
fn from(body: &'a comp::dragon::Body) -> Self {
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::dragon::Species::*;
Self {
head_upper: match (body.species, body.body_type) {

View File

@ -5,10 +5,12 @@ pub mod run;
// Reexports
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::fish_medium::Body;
skeleton_impls!(struct FishMediumSkeleton {
+ head,
+ torso,
@ -20,6 +22,7 @@ skeleton_impls!(struct FishMediumSkeleton {
impl Skeleton for FishMediumSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 6;
#[cfg(feature = "use-dyn-lib")]
@ -63,6 +66,6 @@ impl Default for SkeletonAttr {
fn default() -> Self { Self }
}
impl<'a> From<&'a comp::fish_medium::Body> for SkeletonAttr {
fn from(_body: &'a comp::fish_medium::Body) -> Self { Self }
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(_body: &'a Body) -> Self { Self }
}

View File

@ -5,10 +5,12 @@ pub mod run;
// Reexports
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::fish_small::Body;
skeleton_impls!(struct FishSmallSkeleton {
+ torso,
+ tail,
@ -16,6 +18,7 @@ skeleton_impls!(struct FishSmallSkeleton {
impl Skeleton for FishSmallSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 2;
#[cfg(feature = "use-dyn-lib")]
@ -55,6 +58,6 @@ impl Default for SkeletonAttr {
fn default() -> Self { Self }
}
impl<'a> From<&'a comp::fish_small::Body> for SkeletonAttr {
fn from(_body: &'a comp::fish_small::Body) -> Self { Self }
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(_body: &'a Body) -> Self { Self }
}

View File

@ -1,5 +1,7 @@
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
pub type Body = ();
#[derive(Clone, Default)]
pub struct FixtureSkeleton;
@ -17,6 +19,7 @@ impl<'a, Factor> Lerp<Factor> for &'a FixtureSkeleton {
impl Skeleton for FixtureSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 1;
#[cfg(feature = "use-dyn-lib")]
@ -33,3 +36,11 @@ impl Skeleton for FixtureSkeleton {
Vec3::default()
}
}
impl Default for SkeletonAttr {
fn default() -> Self { Self }
}
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(_body: &'a Body) -> Self { Self }
}

View File

@ -5,10 +5,12 @@ pub mod run;
// Reexports
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::golem::Body;
skeleton_impls!(struct GolemSkeleton {
+ head,
+ upper_torso,
@ -25,6 +27,7 @@ skeleton_impls!(struct GolemSkeleton {
impl Skeleton for GolemSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 10;
#[cfg(feature = "use-dyn-lib")]
@ -90,8 +93,8 @@ impl Default for SkeletonAttr {
}
}
impl<'a> From<&'a comp::golem::Body> for SkeletonAttr {
fn from(body: &'a comp::golem::Body) -> Self {
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::golem::Species::*;
Self {
head: match (body.species, body.body_type) {

View File

@ -9,14 +9,14 @@ macro_rules! skeleton_impls {
#[derive(Clone, Default)]
pub struct $Skeleton {
$(
$bone: Bone,
$bone: $crate::Bone,
)*
}
impl<'a, Factor> Lerp<Factor> for &'a $Skeleton
impl<'a, Factor> $crate::vek::Lerp<Factor> for &'a $Skeleton
where
Factor: Copy,
Bone: Lerp<Factor, Output=Bone>
$crate::Bone: Lerp<Factor, Output=$crate::Bone>
{
type Output = $Skeleton;
@ -79,6 +79,7 @@ pub type Bone = Transform<f32, f32, f32>;
pub trait Skeleton: Send + Sync + 'static {
type Attr;
type Body;
const BONE_COUNT: usize;

View File

@ -1,4 +1,7 @@
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
pub type Body = comp::object::Body;
#[derive(Clone, Default)]
pub struct ObjectSkeleton;
@ -19,6 +22,7 @@ const SCALE: f32 = 1.0 / 11.0;
impl Skeleton for ObjectSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 1;
#[cfg(feature = "use-dyn-lib")]
@ -34,3 +38,11 @@ impl Skeleton for ObjectSkeleton {
Vec3::default()
}
}
impl Default for SkeletonAttr {
fn default() -> Self { Self }
}
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(_body: &'a Body) -> Self { Self }
}

View File

@ -8,10 +8,12 @@ pub use self::{
alpha::AlphaAnimation, idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation,
};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::quadruped_low::Body;
skeleton_impls!(struct QuadrupedLowSkeleton {
+ head_upper,
+ head_lower,
@ -27,6 +29,7 @@ skeleton_impls!(struct QuadrupedLowSkeleton {
impl Skeleton for QuadrupedLowSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 10;
#[cfg(feature = "use-dyn-lib")]
@ -102,8 +105,8 @@ impl Default for SkeletonAttr {
}
}
impl<'a> From<&'a comp::quadruped_low::Body> for SkeletonAttr {
fn from(body: &'a comp::quadruped_low::Body) -> Self {
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::quadruped_low::Species::*;
Self {
head_upper: match (body.species, body.body_type) {

View File

@ -8,10 +8,12 @@ pub use self::{
alpha::AlphaAnimation, idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation,
};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::quadruped_medium::Body;
skeleton_impls!(struct QuadrupedMediumSkeleton {
+ head_upper,
+ head_lower,
@ -32,6 +34,7 @@ skeleton_impls!(struct QuadrupedMediumSkeleton {
impl Skeleton for QuadrupedMediumSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 15;
#[cfg(feature = "use-dyn-lib")]
@ -124,8 +127,8 @@ impl Default for SkeletonAttr {
}
}
impl<'a> From<&'a comp::quadruped_medium::Body> for SkeletonAttr {
fn from(body: &'a comp::quadruped_medium::Body) -> Self {
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::quadruped_medium::Species::*;
Self {
head_upper: match (body.species, body.body_type) {

View File

@ -6,10 +6,12 @@ pub mod run;
// Reexports
pub use self::{feed::FeedAnimation, idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{make_bone, vek::*, Bone, FigureBoneData, Skeleton};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::quadruped_small::Body;
skeleton_impls!(struct QuadrupedSmallSkeleton {
+ head,
+ chest,
@ -22,6 +24,7 @@ skeleton_impls!(struct QuadrupedSmallSkeleton {
impl Skeleton for QuadrupedSmallSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 7;
#[cfg(feature = "use-dyn-lib")]
@ -90,8 +93,8 @@ impl Default for SkeletonAttr {
}
}
impl<'a> From<&'a comp::quadruped_small::Body> for SkeletonAttr {
fn from(body: &'a comp::quadruped_small::Body) -> Self {
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::quadruped_small::Species::*;
Self {
head: match (body.species, body.body_type) {

View File

@ -1,8 +1,11 @@
use super::*;
use crate::audio::sfx::SfxEvent;
use common::{
assets,
comp::{item::tool::ToolCategory, CharacterAbilityType, CharacterState, ItemConfig, Loadout},
assets::Asset,
comp::{
item::{tool::ToolCategory, ItemAsset},
CharacterAbilityType, CharacterState, ItemConfig, Loadout,
},
states,
};
use std::time::{Duration, Instant};
@ -12,7 +15,7 @@ fn maps_wield_while_equipping() {
let mut loadout = Loadout::default();
loadout.active_item = Some(ItemConfig {
item: assets::load_expect_cloned("common.items.weapons.axe.starter_axe"),
item: ItemAsset::load_expect_cloned("common.items.weapons.axe.starter_axe"),
ability1: None,
ability2: None,
ability3: None,
@ -40,7 +43,7 @@ fn maps_unwield() {
let mut loadout = Loadout::default();
loadout.active_item = Some(ItemConfig {
item: assets::load_expect_cloned("common.items.weapons.bow.starter_bow"),
item: ItemAsset::load_expect_cloned("common.items.weapons.bow.starter_bow"),
ability1: None,
ability2: None,
ability3: None,
@ -66,7 +69,7 @@ fn maps_basic_melee() {
let mut loadout = Loadout::default();
loadout.active_item = Some(ItemConfig {
item: assets::load_expect_cloned("common.items.weapons.axe.starter_axe"),
item: ItemAsset::load_expect_cloned("common.items.weapons.axe.starter_axe"),
ability1: None,
ability2: None,
ability3: None,
@ -102,7 +105,7 @@ fn matches_ability_stage() {
let mut loadout = Loadout::default();
loadout.active_item = Some(ItemConfig {
item: assets::load_expect_cloned("common.items.weapons.sword.starter_sword"),
item: ItemAsset::load_expect_cloned("common.items.weapons.sword.starter_sword"),
ability1: None,
ability2: None,
ability3: None,
@ -143,7 +146,7 @@ fn ignores_different_ability_stage() {
let mut loadout = Loadout::default();
loadout.active_item = Some(ItemConfig {
item: assets::load_expect_cloned("common.items.weapons.sword.starter_sword"),
item: ItemAsset::load_expect_cloned("common.items.weapons.sword.starter_sword"),
ability1: None,
ability2: None,
ability3: None,

View File

@ -97,7 +97,7 @@ impl ItemImgs {
pub fn new(ui: &mut Ui, not_found: Id) -> Self {
let mut indicator = ReloadIndicator::new();
Self {
map: assets::load_watched::<ItemImagesSpec>(
map: ItemImagesSpec::load_watched(
"voxygen.item_image_manifest",
&mut indicator,
)
@ -118,7 +118,7 @@ impl ItemImgs {
/// Reuses img ids
pub fn reload_if_changed(&mut self, ui: &mut Ui) {
if self.indicator.reloaded() {
for (kind, spec) in assets::load::<ItemImagesSpec>("voxygen.item_image_manifest")
for (kind, spec) in ItemImagesSpec::load("voxygen.item_image_manifest")
.expect("Unable to load item image manifest")
.0
.iter()
@ -160,21 +160,21 @@ impl ItemImgs {
// TODO: remove code dup?
fn graceful_load_vox(specifier: &str) -> Arc<DotVoxData> {
let full_specifier: String = ["voxygen.", specifier].concat();
match assets::load::<DotVoxData>(full_specifier.as_str()) {
match DotVoxData::load(full_specifier.as_str()) {
Ok(dot_vox) => dot_vox,
Err(_) => {
error!(?full_specifier, "Could not load vox file for item images",);
assets::load_expect::<DotVoxData>("voxygen.voxel.not_found")
DotVoxData::load_expect("voxygen.voxel.not_found")
},
}
}
fn graceful_load_img(specifier: &str) -> Arc<DynamicImage> {
let full_specifier: String = ["voxygen.", specifier].concat();
match assets::load::<DynamicImage>(full_specifier.as_str()) {
match DynamicImage::load(full_specifier.as_str()) {
Ok(img) => img,
Err(_) => {
error!(?full_specifier, "Could not load image file for item images");
assets::load_expect::<DynamicImage>("voxygen.element.not_found")
DynamicImage::load_expect("voxygen.element.not_found")
},
}
}

View File

@ -56,7 +56,7 @@ use crate::{
GlobalState,
};
use client::Client;
use common::{assets::load_expect, comp, sync::Uid, terrain::TerrainChunk, vol::RectRasterableVol};
use common::{assets::Asset, comp, sync::Uid, terrain::TerrainChunk, vol::RectRasterableVol};
use conrod_core::{
text::cursor::Index,
widget::{self, Button, Image, Text},
@ -602,7 +602,7 @@ impl Hud {
// Load item images.
let item_imgs = ItemImgs::new(&mut ui, imgs.not_found);
// Load language.
let voxygen_i18n = load_expect::<VoxygenLocalization>(&i18n_asset_key(
let voxygen_i18n = VoxygenLocalization::load_expect(&i18n_asset_key(
&global_state.settings.language.selected_language,
));
// Load fonts.

View File

@ -1,7 +1,4 @@
use common::{
assets,
assets::{load_expect, load_glob, Asset},
};
use common::assets::{self, Asset};
use deunicode::deunicode;
use ron::de::from_reader;
use serde_derive::*;
@ -100,7 +97,7 @@ impl VoxygenLocalization {
/// Return the missing keys compared to the reference language
pub fn list_missing_entries(&self) -> (HashSet<String>, HashSet<String>) {
let reference_localization =
load_expect::<VoxygenLocalization>(i18n_asset_key(REFERENCE_LANG).as_ref());
VoxygenLocalization::load_expect(i18n_asset_key(REFERENCE_LANG).as_ref());
let reference_string_keys: HashSet<_> =
reference_localization.string_map.keys().cloned().collect();
@ -169,7 +166,7 @@ impl Asset for VoxygenLocalization {
/// Load all the available languages located in the Voxygen asset directory
pub fn list_localizations() -> Vec<LanguageMetadata> {
let voxygen_locales_assets = "voxygen.i18n.*";
let lang_list = load_glob::<VoxygenLocalization>(voxygen_locales_assets).unwrap();
let lang_list = VoxygenLocalization::load_glob(voxygen_locales_assets).unwrap();
lang_list.iter().map(|e| (*e).metadata.clone()).collect()
}

View File

@ -15,7 +15,7 @@ use veloren_voxygen::{
};
use common::{
assets::{load_watched, watch},
assets::{watch, Asset},
clock::Clock,
};
use std::panic;
@ -132,7 +132,7 @@ fn main() {
let profile = Profile::load();
let mut localization_watcher = watch::ReloadIndicator::new();
let localized_strings = load_watched::<VoxygenLocalization>(
let localized_strings = VoxygenLocalization::load_watched(
&i18n_asset_key(&settings.language.selected_language),
&mut localization_watcher,
)
@ -144,7 +144,7 @@ fn main() {
"Impossible to load language: change to the default language (English) instead.",
);
settings.language.selected_language = i18n::REFERENCE_LANG.to_owned();
load_watched::<VoxygenLocalization>(
VoxygenLocalization::load_watched(
&i18n_asset_key(&settings.language.selected_language),
&mut localization_watcher,
)

View File

@ -10,7 +10,7 @@ use crate::{
Direction, GlobalState, PlayState, PlayStateResult,
};
use client::{self, Client};
use common::{assets, comp, msg::ClientState, state::DeltaTime};
use common::{assets::Asset, comp, msg::ClientState, state::DeltaTime};
use specs::WorldExt;
use std::{cell::RefCell, rc::Rc};
use tracing::error;
@ -126,6 +126,7 @@ impl PlayState for CharSelectionState {
time: client.state().get_time(),
delta_time: client.state().ecs().read_resource::<DeltaTime>().0,
tick: client.get_tick(),
thread_pool: client.thread_pool(),
body: humanoid_body,
gamma: global_state.settings.graphics.gamma,
mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable,
@ -143,7 +144,7 @@ impl PlayState for CharSelectionState {
}
// Tick the client (currently only to keep the connection alive).
let localized_strings = assets::load_expect::<VoxygenLocalization>(&i18n_asset_key(
let localized_strings = VoxygenLocalization::load_expect(&i18n_asset_key(
&global_state.settings.language.selected_language,
));

View File

@ -11,10 +11,9 @@ use crate::{
};
use client::Client;
use common::{
assets,
assets::load_expect,
assets::Asset,
character::{Character, CharacterItem, MAX_CHARACTERS_PER_PLAYER},
comp::{self, humanoid},
comp::{self, humanoid, item::ItemAsset},
LoadoutBuilder,
};
use conrod_core::{
@ -321,7 +320,7 @@ impl CharSelectionUi {
let imgs = Imgs::load(&mut ui).expect("Failed to load images!");
let rot_imgs = ImgsRot::load(&mut ui).expect("Failed to load images!");
// Load language
let voxygen_i18n = load_expect::<VoxygenLocalization>(&i18n_asset_key(
let voxygen_i18n = VoxygenLocalization::load_expect(&i18n_asset_key(
&global_state.settings.language.selected_language,
));
// Load fonts.
@ -378,20 +377,24 @@ impl CharSelectionUi {
},
Mode::Create { loadout, tool, .. } => {
loadout.active_item = tool.map(|tool| comp::ItemConfig {
item: (*load_expect::<comp::Item>(tool)).clone(),
// FIXME: Error gracefully.
item: (*ItemAsset::load_expect(tool)).clone(),
ability1: None,
ability2: None,
ability3: None,
block_ability: None,
dodge_ability: None,
});
loadout.chest = Some(assets::load_expect_cloned(
// FIXME: Error gracefully.
loadout.chest = Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.rugged_chest",
));
loadout.pants = Some(assets::load_expect_cloned(
// FIXME: Error gracefully.
loadout.pants = Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.rugged_pants",
));
loadout.foot = Some(assets::load_expect_cloned(
// FIXME: Error gracefully.
loadout.foot = Some(ItemAsset::load_expect_cloned(
"common.items.armor.starter.sandals_0",
));
Some(loadout.clone())

View File

@ -9,7 +9,7 @@ use crate::{
PlayStateResult,
};
use client_init::{ClientInit, Error as InitError, Msg as InitMsg};
use common::{assets::load_expect, comp};
use common::{assets::Asset, comp};
use tracing::{error, warn};
use ui::{Event as MainMenuEvent, MainMenuUi};
@ -46,7 +46,7 @@ impl PlayState for MainMenuState {
}
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>) -> PlayStateResult {
let localized_strings = load_expect::<crate::i18n::VoxygenLocalization>(
let localized_strings = crate::i18n::VoxygenLocalization::load_expect(
&crate::i18n::i18n_asset_key(&global_state.settings.language.selected_language),
);

View File

@ -9,7 +9,7 @@ use crate::{
},
GlobalState,
};
use common::assets::load_expect;
use common::assets::Asset;
use conrod_core::{
color,
color::TRANSPARENT,
@ -17,6 +17,7 @@ use conrod_core::{
widget::{text_box::Event as TextBoxEvent, Button, Image, List, Rectangle, Text, TextBox},
widget_ids, Borderable, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
};
use image::DynamicImage;
use rand::{seq::SliceRandom, thread_rng, Rng};
use std::time::Duration;
@ -205,12 +206,12 @@ impl<'a> MainMenuUi {
let imgs = Imgs::load(&mut ui).expect("Failed to load images");
let rot_imgs = ImgsRot::load(&mut ui).expect("Failed to load images!");
let bg_img_id = ui.add_graphic(Graphic::Image(
load_expect(bg_imgs.choose(&mut rng).unwrap()),
DynamicImage::load_expect(bg_imgs.choose(&mut rng).unwrap()),
None,
));
//let chosen_tip = *tips.choose(&mut rng).unwrap();
// Load language
let voxygen_i18n = load_expect::<VoxygenLocalization>(&i18n_asset_key(
let voxygen_i18n = VoxygenLocalization::load_expect(&i18n_asset_key(
&global_state.settings.language.selected_language,
));
// Load fonts.

View File

@ -12,7 +12,7 @@ use super::{
AaMode, CloudMode, FilterMethod, FluidMode, LightingMode, Pipeline, RenderError, RenderMode,
ShadowMapMode, ShadowMode, WrapMode,
};
use common::assets::{self, watch::ReloadIndicator};
use common::assets::{self, watch::ReloadIndicator, Asset};
use core::convert::TryFrom;
use gfx::{
self,
@ -21,6 +21,11 @@ use gfx::{
traits::{Device, Factory, FactoryExt},
};
use glsl_include::Context as IncludeContext;
use image::DynamicImage;
use std::{
fs::File,
io::{BufReader, Read},
};
use tracing::{error, warn};
use vek::*;
@ -87,6 +92,21 @@ pub type ColLightInfo = (
Vec2<u16>,
);
/// Load from a GLSL file.
pub struct Glsl;
impl Asset for Glsl {
type Output = String;
const ENDINGS: &'static [&'static str] = &["glsl"];
fn parse(mut buf_reader: BufReader<File>) -> Result<String, assets::Error> {
let mut string = String::new();
buf_reader.read_to_string(&mut string)?;
Ok(string)
}
}
/// A type that holds shadow map data. Since shadow mapping may not be
/// supported on all platforms, we try to keep it separate.
pub struct ShadowMapRenderer {
@ -240,7 +260,7 @@ impl Renderer {
let noise_tex = Texture::new(
&mut factory,
&assets::load_expect("voxygen.texture.noise"),
&DynamicImage::load_expect("voxygen.texture.noise"),
Some(gfx::texture::FilterMethod::Bilinear),
Some(gfx::texture::WrapMode::Tile),
None,
@ -1654,32 +1674,19 @@ fn create_pipelines(
),
RenderError,
> {
let constants = assets::load_watched::<String>(
"voxygen.shaders.include.constants",
shader_reload_indicator,
)
.unwrap();
let constants =
Glsl::load_watched("voxygen.shaders.include.constants", shader_reload_indicator).unwrap();
let globals =
assets::load_watched::<String>("voxygen.shaders.include.globals", shader_reload_indicator)
.unwrap();
let sky =
assets::load_watched::<String>("voxygen.shaders.include.sky", shader_reload_indicator)
.unwrap();
Glsl::load_watched("voxygen.shaders.include.globals", shader_reload_indicator).unwrap();
let sky = Glsl::load_watched("voxygen.shaders.include.sky", shader_reload_indicator).unwrap();
let light =
assets::load_watched::<String>("voxygen.shaders.include.light", shader_reload_indicator)
.unwrap();
let srgb =
assets::load_watched::<String>("voxygen.shaders.include.srgb", shader_reload_indicator)
.unwrap();
Glsl::load_watched("voxygen.shaders.include.light", shader_reload_indicator).unwrap();
let srgb = Glsl::load_watched("voxygen.shaders.include.srgb", shader_reload_indicator).unwrap();
let random =
assets::load_watched::<String>("voxygen.shaders.include.random", shader_reload_indicator)
.unwrap();
let lod =
assets::load_watched::<String>("voxygen.shaders.include.lod", shader_reload_indicator)
.unwrap();
Glsl::load_watched("voxygen.shaders.include.random", shader_reload_indicator).unwrap();
let lod = Glsl::load_watched("voxygen.shaders.include.lod", shader_reload_indicator).unwrap();
let shadows =
assets::load_watched::<String>("voxygen.shaders.include.shadows", shader_reload_indicator)
.unwrap();
Glsl::load_watched("voxygen.shaders.include.shadows", shader_reload_indicator).unwrap();
// We dynamically add extra configuration settings to the constants file.
let constants = format!(
@ -1716,7 +1723,7 @@ fn create_pipelines(
},
);
let anti_alias = assets::load_watched::<String>(
let anti_alias = Glsl::load_watched(
&["voxygen.shaders.antialias.", match mode.aa {
AaMode::None | AaMode::SsaaX4 => "none",
AaMode::Fxaa => "fxaa",
@ -1729,7 +1736,7 @@ fn create_pipelines(
)
.unwrap();
let cloud = assets::load_watched::<String>(
let cloud = Glsl::load_watched(
&["voxygen.shaders.include.cloud.", match mode.cloud {
CloudMode::None => "none",
CloudMode::Regular => "regular",
@ -1752,28 +1759,27 @@ fn create_pipelines(
include_ctx.include("cloud.glsl", &cloud);
let figure_vert =
assets::load_watched::<String>("voxygen.shaders.figure-vert", shader_reload_indicator)
.unwrap();
Glsl::load_watched("voxygen.shaders.figure-vert", shader_reload_indicator).unwrap();
let terrain_point_shadow_vert = assets::load_watched::<String>(
let terrain_point_shadow_vert = Glsl::load_watched(
"voxygen.shaders.light-shadows-vert",
shader_reload_indicator,
)
.unwrap();
let terrain_directed_shadow_vert = assets::load_watched::<String>(
let terrain_directed_shadow_vert = Glsl::load_watched(
"voxygen.shaders.light-shadows-directed-vert",
shader_reload_indicator,
)
.unwrap();
let figure_directed_shadow_vert = assets::load_watched::<String>(
let figure_directed_shadow_vert = Glsl::load_watched(
"voxygen.shaders.light-shadows-figure-vert",
shader_reload_indicator,
)
.unwrap();
let directed_shadow_frag = &assets::load_watched::<String>(
let directed_shadow_frag = Glsl::load_watched(
"voxygen.shaders.light-shadows-directed-frag",
shader_reload_indicator,
)
@ -1783,10 +1789,8 @@ fn create_pipelines(
let skybox_pipeline = create_pipeline(
factory,
skybox::pipe::new(),
&assets::load_watched::<String>("voxygen.shaders.skybox-vert", shader_reload_indicator)
.unwrap(),
&assets::load_watched::<String>("voxygen.shaders.skybox-frag", shader_reload_indicator)
.unwrap(),
&Glsl::load_watched("voxygen.shaders.skybox-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched("voxygen.shaders.skybox-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
@ -1796,8 +1800,7 @@ fn create_pipelines(
factory,
figure::pipe::new(),
&figure_vert,
&assets::load_watched::<String>("voxygen.shaders.figure-frag", shader_reload_indicator)
.unwrap(),
&Glsl::load_watched("voxygen.shaders.figure-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
@ -1806,10 +1809,8 @@ fn create_pipelines(
let terrain_pipeline = create_pipeline(
factory,
terrain::pipe::new(),
&assets::load_watched::<String>("voxygen.shaders.terrain-vert", shader_reload_indicator)
.unwrap(),
&assets::load_watched::<String>("voxygen.shaders.terrain-frag", shader_reload_indicator)
.unwrap(),
&Glsl::load_watched("voxygen.shaders.terrain-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched("voxygen.shaders.terrain-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
@ -1818,9 +1819,8 @@ fn create_pipelines(
let fluid_pipeline = create_pipeline(
factory,
fluid::pipe::new(),
&assets::load_watched::<String>("voxygen.shaders.fluid-vert", shader_reload_indicator)
.unwrap(),
&assets::load_watched::<String>(
&Glsl::load_watched("voxygen.shaders.fluid-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched(
&["voxygen.shaders.fluid-frag.", match mode.fluid {
FluidMode::Cheap => "cheap",
FluidMode::Shiny => "shiny",
@ -1837,10 +1837,8 @@ fn create_pipelines(
let sprite_pipeline = create_pipeline(
factory,
sprite::pipe::new(),
&assets::load_watched::<String>("voxygen.shaders.sprite-vert", shader_reload_indicator)
.unwrap(),
&assets::load_watched::<String>("voxygen.shaders.sprite-frag", shader_reload_indicator)
.unwrap(),
&Glsl::load_watched("voxygen.shaders.sprite-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched("voxygen.shaders.sprite-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
@ -1849,10 +1847,8 @@ fn create_pipelines(
let particle_pipeline = create_pipeline(
factory,
particle::pipe::new(),
&assets::load_watched::<String>("voxygen.shaders.particle-vert", shader_reload_indicator)
.unwrap(),
&assets::load_watched::<String>("voxygen.shaders.particle-frag", shader_reload_indicator)
.unwrap(),
&Glsl::load_watched("voxygen.shaders.particle-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched("voxygen.shaders.particle-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
@ -1861,10 +1857,8 @@ fn create_pipelines(
let ui_pipeline = create_pipeline(
factory,
ui::pipe::new(),
&assets::load_watched::<String>("voxygen.shaders.ui-vert", shader_reload_indicator)
.unwrap(),
&assets::load_watched::<String>("voxygen.shaders.ui-frag", shader_reload_indicator)
.unwrap(),
&Glsl::load_watched("voxygen.shaders.ui-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched("voxygen.shaders.ui-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
@ -1873,16 +1867,8 @@ fn create_pipelines(
let lod_terrain_pipeline = create_pipeline(
factory,
lod_terrain::pipe::new(),
&assets::load_watched::<String>(
"voxygen.shaders.lod-terrain-vert",
shader_reload_indicator,
)
.unwrap(),
&assets::load_watched::<String>(
"voxygen.shaders.lod-terrain-frag",
shader_reload_indicator,
)
.unwrap(),
&Glsl::load_watched("voxygen.shaders.lod-terrain-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched("voxygen.shaders.lod-terrain-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
@ -1891,16 +1877,8 @@ fn create_pipelines(
let postprocess_pipeline = create_pipeline(
factory,
postprocess::pipe::new(),
&assets::load_watched::<String>(
"voxygen.shaders.postprocess-vert",
shader_reload_indicator,
)
.unwrap(),
&assets::load_watched::<String>(
"voxygen.shaders.postprocess-frag",
shader_reload_indicator,
)
.unwrap(),
&Glsl::load_watched("voxygen.shaders.postprocess-vert", shader_reload_indicator).unwrap(),
&Glsl::load_watched("voxygen.shaders.postprocess-frag", shader_reload_indicator).unwrap(),
&include_ctx,
gfx::state::CullFace::Back,
)?;
@ -1918,7 +1896,7 @@ fn create_pipelines(
..figure::pipe::new()
},
&figure_vert,
&assets::load_watched::<String>(
&Glsl::load_watched(
"voxygen.shaders.player-shadow-frag",
shader_reload_indicator,
)
@ -1933,13 +1911,13 @@ fn create_pipelines(
shadow::pipe::new(),
&terrain_point_shadow_vert,
Some(
&assets::load_watched::<String>(
&Glsl::load_watched(
"voxygen.shaders.light-shadows-geom",
shader_reload_indicator,
)
.unwrap(),
),
&assets::load_watched::<String>(
&Glsl::load_watched(
"voxygen.shaders.light-shadows-frag",
shader_reload_indicator,
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,10 +6,9 @@ pub use load::load_mesh; // TODO: Don't make this public.
use crate::{
ecs::comp::Interpolated,
mesh::greedy::GreedyMesh,
render::{
ColLightFmt, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel, Mesh,
RenderError, Renderer, ShadowPipeline, TerrainPipeline, Texture,
ColLightFmt, ColLightInfo, Consts, FigureBoneData, FigureLocals, FigureModel, GlobalModel,
Mesh, RenderError, Renderer, ShadowPipeline, TerrainPipeline, Texture,
},
scene::{
camera::{Camera, CameraMode, Dependents},
@ -308,6 +307,7 @@ pub struct FigureMgr {
fish_medium_model_cache: FigureModelCache<FishMediumSkeleton>,
fish_small_model_cache: FigureModelCache<FishSmallSkeleton>,
biped_large_model_cache: FigureModelCache<BipedLargeSkeleton>,
object_model_cache: FigureModelCache<ObjectSkeleton>,
golem_model_cache: FigureModelCache<GolemSkeleton>,
states: FigureMgrStates,
}
@ -327,6 +327,7 @@ impl FigureMgr {
fish_medium_model_cache: FigureModelCache::new(),
fish_small_model_cache: FigureModelCache::new(),
biped_large_model_cache: FigureModelCache::new(),
object_model_cache: FigureModelCache::new(),
golem_model_cache: FigureModelCache::new(),
states: FigureMgrStates::default(),
}
@ -354,6 +355,7 @@ impl FigureMgr {
.clean(&mut self.col_lights, tick);
self.biped_large_model_cache
.clean(&mut self.col_lights, tick);
self.object_model_cache.clean(&mut self.col_lights, tick);
self.golem_model_cache.clean(&mut self.col_lights, tick);
}
@ -685,7 +687,7 @@ impl FigureMgr {
};
match body {
Body::Humanoid(_) => {
Body::Humanoid(body) => {
let (model, skeleton_attr) = self.model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -694,6 +696,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1046,7 +1049,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1054,7 +1057,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::QuadrupedSmall(_) => {
Body::QuadrupedSmall(body) => {
let (model, skeleton_attr) =
self.quadruped_small_model_cache.get_or_create_model(
renderer,
@ -1064,6 +1067,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1147,7 +1151,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1155,7 +1159,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::QuadrupedMedium(_) => {
Body::QuadrupedMedium(body) => {
let (model, skeleton_attr) =
self.quadruped_medium_model_cache.get_or_create_model(
renderer,
@ -1165,6 +1169,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1248,7 +1253,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1256,7 +1261,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::QuadrupedLow(_) => {
Body::QuadrupedLow(body) => {
let (model, skeleton_attr) =
self.quadruped_low_model_cache.get_or_create_model(
renderer,
@ -1266,6 +1271,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1347,7 +1353,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1355,7 +1361,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::BirdMedium(_) => {
Body::BirdMedium(body) => {
let (model, skeleton_attr) = self.bird_medium_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -1364,6 +1370,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1443,7 +1450,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1451,7 +1458,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::FishMedium(_) => {
Body::FishMedium(body) => {
let (model, skeleton_attr) = self.fish_medium_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -1460,6 +1467,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1528,7 +1536,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1536,7 +1544,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::Dragon(_) => {
Body::Dragon(body) => {
let (model, skeleton_attr) = self.dragon_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -1545,6 +1553,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state =
@ -1609,7 +1618,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1617,7 +1626,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::Critter(_) => {
Body::Critter(body) => {
let (model, skeleton_attr) = self.critter_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -1626,6 +1635,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state =
@ -1691,7 +1701,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1699,7 +1709,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::BirdSmall(_) => {
Body::BirdSmall(body) => {
let (model, skeleton_attr) = self.bird_small_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -1708,6 +1718,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1776,7 +1787,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1784,7 +1795,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::FishSmall(_) => {
Body::FishSmall(body) => {
let (model, skeleton_attr) = self.fish_small_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -1793,6 +1804,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1861,7 +1873,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1869,7 +1881,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::BipedLarge(_) => {
Body::BipedLarge(body) => {
let (model, skeleton_attr) = self.biped_large_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -1878,6 +1890,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
@ -1966,7 +1979,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -1974,7 +1987,7 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::Golem(_) => {
Body::Golem(body) => {
let (model, skeleton_attr) = self.golem_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
@ -1983,6 +1996,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state =
@ -2048,7 +2062,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
in_frustum,
is_player,
@ -2056,8 +2070,8 @@ impl FigureMgr {
&mut update_buf,
);
},
Body::Object(_) => {
let (model, _) = &self.model_cache.get_or_create_model(
Body::Object(body) => {
let (model, _) = self.object_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
*body,
@ -2065,6 +2079,7 @@ impl FigureMgr {
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state =
@ -2080,7 +2095,7 @@ impl FigureMgr {
col,
dt,
state_animation_rate,
&model,
model,
lpindex,
true,
is_player,
@ -2102,7 +2117,7 @@ impl FigureMgr {
}
pub fn render_shadows(
&mut self,
&self,
renderer: &mut Renderer,
state: &State,
tick: u64,
@ -2127,7 +2142,6 @@ impl FigureMgr {
.filter(|(_, _, _, _, stats, _, _)| stats.map_or(true, |s| !s.is_dead))
.for_each(|(entity, pos, _, body, _, loadout, _)| {
if let Some((locals, bone_consts, model, _)) = self.get_model_for_render(
renderer,
tick,
camera,
None,
@ -2153,7 +2167,7 @@ impl FigureMgr {
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
pub fn render(
&mut self,
&self,
renderer: &mut Renderer,
state: &State,
player_entity: EcsEntity,
@ -2184,7 +2198,6 @@ impl FigureMgr {
if !is_player {
if let Some((locals, bone_consts, model, col_lights)) = self.get_model_for_render(
renderer,
tick,
camera,
character_state,
@ -2204,7 +2217,7 @@ impl FigureMgr {
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
pub fn render_player(
&mut self,
&self,
renderer: &mut Renderer,
state: &State,
player_entity: EcsEntity,
@ -2233,7 +2246,6 @@ impl FigureMgr {
let loadout = loadout_storage.get(player_entity);
if let Some((locals, bone_consts, model, col_lights)) = self.get_model_for_render(
renderer,
tick,
camera,
character_state,
@ -2260,8 +2272,7 @@ impl FigureMgr {
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
fn get_model_for_render(
&mut self,
renderer: &mut Renderer,
&self,
tick: u64,
camera: &Camera,
character_state: Option<&CharacterState>,
@ -2283,7 +2294,7 @@ impl FigureMgr {
let character_state = if is_player { character_state } else { None };
let FigureMgr {
col_lights: ref mut col_lights_,
col_lights: ref col_lights_,
model_cache,
critter_model_cache,
quadruped_small_model_cache,
@ -2295,6 +2306,7 @@ impl FigureMgr {
fish_medium_model_cache,
fish_small_model_cache,
biped_large_model_cache,
object_model_cache,
golem_model_cache,
states:
FigureMgrStates {
@ -2313,269 +2325,232 @@ impl FigureMgr {
object_states,
},
} = self;
let col_lights = &mut *col_lights_;
let col_lights = &*col_lights_;
if let Some((locals, bone_consts, model_entry)) = match body {
Body::Humanoid(_) => character_states
Body::Humanoid(body) => character_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&model_cache
.get_or_create_model(
renderer,
model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::QuadrupedSmall(_) => quadruped_small_states
Body::QuadrupedSmall(body) => quadruped_small_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&quadruped_small_model_cache
.get_or_create_model(
renderer,
quadruped_small_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::QuadrupedMedium(_) => quadruped_medium_states
Body::QuadrupedMedium(body) => quadruped_medium_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&quadruped_medium_model_cache
.get_or_create_model(
renderer,
quadruped_medium_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::QuadrupedLow(_) => quadruped_low_states
Body::QuadrupedLow(body) => quadruped_low_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&quadruped_low_model_cache
.get_or_create_model(
renderer,
quadruped_low_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::BirdMedium(_) => bird_medium_states
Body::BirdMedium(body) => bird_medium_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&bird_medium_model_cache
.get_or_create_model(
renderer,
bird_medium_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::FishMedium(_) => fish_medium_states
Body::FishMedium(body) => fish_medium_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&fish_medium_model_cache
.get_or_create_model(
renderer,
fish_medium_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::Critter(_) => critter_states
Body::Critter(body) => critter_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&critter_model_cache
.get_or_create_model(
renderer,
critter_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::Dragon(_) => dragon_states
Body::Dragon(body) => dragon_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&dragon_model_cache
.get_or_create_model(
renderer,
dragon_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::BirdSmall(_) => bird_small_states
Body::BirdSmall(body) => bird_small_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&bird_small_model_cache
.get_or_create_model(
renderer,
bird_small_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::FishSmall(_) => fish_small_states
Body::FishSmall(body) => fish_small_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&fish_small_model_cache
.get_or_create_model(
renderer,
fish_small_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::BipedLarge(_) => biped_large_states
Body::BipedLarge(body) => biped_large_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&biped_large_model_cache
.get_or_create_model(
renderer,
biped_large_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::Golem(_) => golem_states
Body::Golem(body) => golem_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&golem_model_cache
.get_or_create_model(
renderer,
golem_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
Body::Object(_) => object_states
Body::Object(body) => object_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
&model_cache
.get_or_create_model(
renderer,
object_model_cache.get_model(
col_lights,
*body,
loadout,
tick,
player_camera_mode,
character_state,
)
.0,
),
)
}),
} {
let model_entry = model_entry?;
let figure_low_detail_distance = figure_lod_render_distance * 0.75;
let figure_mid_detail_distance = figure_lod_render_distance * 0.5;
@ -2627,14 +2602,13 @@ impl FigureColLights {
/// NOTE: Panics if the vertex range bounds are not in range of the opaque
/// model stored in the BoneMeshes parameter. This is part of the
/// function contract.
pub fn create_figure<'a, const N: usize>(
pub fn create_figure<const N: usize>(
&mut self,
renderer: &mut Renderer,
greedy: GreedyMesh<'a>,
(tex, tex_size): ColLightInfo,
(opaque, bounds): (Mesh<TerrainPipeline>, math::Aabb<f32>),
vertex_range: [Range<u32>; N],
) -> Result<FigureModelEntry<N>, RenderError> {
let (tex, tex_size) = greedy.finalize();
let atlas = &mut self.atlas;
let allocation = atlas
.allocate(guillotiere::Size::new(
@ -2771,14 +2745,31 @@ impl<S: Skeleton> FigureState<S> {
col: vek::Rgba<f32>,
dt: f32,
state_animation_rate: f32,
model: &FigureModelEntry<N>,
model: Option<&FigureModelEntry<N>>,
_lpindex: u8,
_visible: bool,
is_player: bool,
camera: &Camera,
_camera: &Camera,
buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT],
) {
let _frustum = camera.frustum();
// NOTE: As long as update() always gets called after get_or_create_model(), and
// visibility is not set again until after the model is rendered, we
// know we don't pair the character model with invalid model state.
//
// Currently, the only exception to this during normal gameplay is in the very
// first tick after a model is created (so there's no `last_character`
// state). So in theory, we could have incorrect model data during this
// tick. It is possible to resolve this in a few ways, but since
// currently we don't actually use the model state for anything, we
// currently ignore this potential issue.
//
// FIXME: Address the above at some point.
let model = if let Some(model) = model {
model
} else {
self.visible = false;
return;
};
// Approximate as a sphere with radius equal to the
// largest dimension (if we were exact, it should just be half the largest

View File

@ -7,7 +7,7 @@ use crate::{
},
};
use common::{
assets,
assets::Asset,
comp::{item::Reagent, object, Body, CharacterState, Pos},
figure::Segment,
outcome::Outcome,
@ -369,7 +369,7 @@ fn default_cache(renderer: &mut Renderer) -> HashMap<&'static str, Model<Particl
let mut model_cache = HashMap::new();
model_cache.entry(DEFAULT_MODEL_KEY).or_insert_with(|| {
let vox = assets::load_expect::<DotVoxData>(DEFAULT_MODEL_KEY);
let vox = DotVoxData::load_expect(DEFAULT_MODEL_KEY);
// NOTE: If we add texturing we may eventually try to share it among all
// particles in a single atlas.

View File

@ -19,7 +19,7 @@ use anim::{
};
use client::Client;
use common::{
comp::{humanoid, item::ItemKind, Body, Loadout},
comp::{humanoid, item::ItemKind, Loadout},
figure::Segment,
terrain::BlockKind,
vol::{BaseVol, ReadVol, Vox},
@ -87,10 +87,11 @@ pub struct Scene {
char_ori: f32,
}
pub struct SceneData {
pub struct SceneData<'a> {
pub time: f64,
pub delta_time: f32,
pub tick: u64,
pub thread_pool: &'a uvth::ThreadPool,
pub body: Option<humanoid::Body>,
pub gamma: f32,
pub figure_lod_render_distance: f32,
@ -164,7 +165,7 @@ impl Scene {
// 2^27, which fits in a u32.
let range = range.start as u32..range.end as u32;
let model = col_lights
.create_figure(renderer, greedy, (opaque_mesh, bounds), [range])
.create_figure(renderer, greedy.finalize(), (opaque_mesh, bounds), [range])
.unwrap();
let mut buf = [Default::default(); anim::MAX_BONE_COUNT];
state.update(
@ -175,7 +176,7 @@ impl Scene {
Rgba::broadcast(1.0),
15.0, // Want to get there immediately.
1.0,
&model,
Some(&model),
0,
true,
false,
@ -304,16 +305,17 @@ impl Scene {
*self.figure_state.skeleton_mut() =
anim::vek::Lerp::lerp(&*self.figure_state.skeleton_mut(), &tgt_skeleton, dt_lerp);
let model = &self
let model = self
.figure_model_cache
.get_or_create_model(
renderer,
&mut self.col_lights,
Body::Humanoid(body),
body,
loadout,
scene_data.tick,
CameraMode::default(),
None,
scene_data.thread_pool,
)
.0;
let mut buf = [Default::default(); anim::MAX_BONE_COUNT];
@ -325,7 +327,7 @@ impl Scene {
Rgba::broadcast(1.0),
scene_data.delta_time,
1.0,
&model,
model,
0,
true,
false,
@ -350,19 +352,16 @@ impl Scene {
);
if let Some(body) = body {
let model = &self
.figure_model_cache
.get_or_create_model(
renderer,
&mut self.col_lights,
Body::Humanoid(body),
let model = &self.figure_model_cache.get_model(
&self.col_lights,
body,
loadout,
tick,
CameraMode::default(),
None,
)
.0;
);
if let Some(model) = model {
renderer.render_figure(
&model.models[0],
&self.col_lights.texture(model),
@ -372,6 +371,7 @@ impl Scene {
&self.lod,
);
}
}
if let Some((model, state)) = &self.backdrop {
renderer.render_figure(

View File

@ -13,7 +13,7 @@ use crate::{
use super::{math, LodData, SceneData};
use common::{
assets,
assets::Asset,
figure::Segment,
spiral::Spiral2d,
terrain::{Block, BlockKind, TerrainChunk},
@ -25,6 +25,7 @@ use crossbeam::channel;
use dot_vox::DotVoxData;
use guillotiere::AtlasAllocator;
use hashbrown::HashMap;
use image::DynamicImage;
use std::sync::Arc;
use tracing::warn;
use treeculler::{BVol, Frustum, AABB};
@ -525,7 +526,7 @@ impl<V: RectRasterableVol> Terrain<V> {
// NOTE: Tracks the start vertex of the next model to be meshed.
let mut make_models = |(kind, variation), s, offset, lod_axes: Vec3<f32>| {
let scaled = [1.0, 0.8, 0.6, 0.4, 0.2];
let model = assets::load_expect::<DotVoxData>(s);
let model = DotVoxData::load_expect(s);
let zero = Vec3::zero();
let model_size = model
.models
@ -2401,7 +2402,7 @@ impl<V: RectRasterableVol> Terrain<V> {
sprite_col_lights,
waves: renderer
.create_texture(
&assets::load_expect("voxygen.texture.waves"),
&DynamicImage::load_expect("voxygen.texture.waves"),
Some(gfx::texture::FilterMethod::Trilinear),
Some(gfx::texture::WrapMode::Tile),
None,

View File

@ -13,7 +13,7 @@ use crate::{
};
use client::{self, Client};
use common::{
assets::{load_expect, load_watched},
assets::Asset,
comp,
comp::{
ChatMsg, ChatType, InventoryUpdateEvent, Pos, Vel, MAX_MOUNT_RANGE_SQR,
@ -72,7 +72,7 @@ impl SessionState {
.camera_mut()
.set_fov_deg(global_state.settings.graphics.fov);
let hud = Hud::new(global_state, &client.borrow());
let voxygen_i18n = load_expect::<VoxygenLocalization>(&i18n_asset_key(
let voxygen_i18n = VoxygenLocalization::load_expect(&i18n_asset_key(
&global_state.settings.language.selected_language,
));
@ -196,7 +196,7 @@ impl PlayState for SessionState {
fn tick(&mut self, global_state: &mut GlobalState, events: Vec<Event>) -> PlayStateResult {
// NOTE: Not strictly necessary, but useful for hotloading translation changes.
self.voxygen_i18n = load_expect::<VoxygenLocalization>(&i18n_asset_key(
self.voxygen_i18n = VoxygenLocalization::load_expect(&i18n_asset_key(
&global_state.settings.language.selected_language,
));
@ -991,7 +991,7 @@ impl PlayState for SessionState {
HudEvent::ChangeLanguage(new_language) => {
global_state.settings.language.selected_language =
new_language.language_identifier;
self.voxygen_i18n = load_watched::<VoxygenLocalization>(
self.voxygen_i18n = VoxygenLocalization::load_watched(
&i18n_asset_key(&global_state.settings.language.selected_language),
&mut global_state.localization_watcher,
)

View File

@ -1,4 +1,5 @@
use crate::i18n::{Font, VoxygenFonts};
use common::assets::Asset;
pub struct ConrodVoxygenFont {
metadata: Font,
@ -10,7 +11,7 @@ impl ConrodVoxygenFont {
pub fn new(font: &Font, ui: &mut crate::ui::Ui) -> ConrodVoxygenFont {
return Self {
metadata: font.clone(),
conrod_id: ui.new_font(common::assets::load_expect(&font.asset_key)),
conrod_id: ui.new_font(crate::ui::Font::load_expect(&font.asset_key)),
};
}

View File

@ -1,6 +1,6 @@
use super::{Graphic, SampleStrat, Transform};
use common::{
assets::{load, Error},
assets::{Asset, Error},
figure::Segment,
};
use dot_vox::DotVoxData;
@ -24,7 +24,7 @@ impl<'a> GraphicCreator<'a> for ImageGraphic {
type Specifier = &'a str;
fn new_graphic(specifier: Self::Specifier) -> Result<Graphic, Error> {
Ok(Graphic::Image(load::<DynamicImage>(specifier)?, None))
Ok(Graphic::Image(DynamicImage::load(specifier)?, None))
}
}
@ -37,7 +37,7 @@ pub enum VoxelSs9Graphic {}
pub enum VoxelPixArtGraphic {}
fn load_segment(specifier: &str) -> Result<Arc<Segment>, Error> {
let dot_vox = load::<DotVoxData>(specifier)?;
let dot_vox = DotVoxData::load(specifier)?;
let seg = dot_vox.as_ref().into();
Ok(Arc::new(seg))
}

View File

@ -13,10 +13,10 @@ use common::{
vol::{ReadVol, Vox},
};
use core::ops::{Div, Mul, Range};
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use vek::*;
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub pyramid: (u8, u8, u8),
// TODO(@Sharp): After the merge, construct enough infrastructure to make it convenient to

View File

@ -13,7 +13,7 @@ use common::{
vol::RectVolSize,
};
use noise::NoiseFn;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use std::{
cmp::Reverse,
f32, f64,
@ -26,7 +26,7 @@ pub struct ColumnGen<'a> {
pub sim: &'a WorldSim,
}
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub cold_grass: (f32, f32, f32),
pub warm_grass: (f32, f32, f32),

View File

@ -1,6 +1,6 @@
use crate::{site::Site, Colors};
use common::{
assets::{self, watch::ReloadIndicator},
assets::{watch::ReloadIndicator, Asset, Ron},
store::Store,
};
use core::ops::Deref;
@ -53,7 +53,7 @@ impl Index {
/// NOTE: Panics if the color manifest cannot be loaded.
pub fn new(seed: u32) -> (Self, Arc<Colors>) {
let mut indicator = ReloadIndicator::new();
let colors = assets::load_watched::<Colors>(WORLD_COLORS_MANIFEST, &mut indicator)
let colors = Ron::<Colors>::load_watched(WORLD_COLORS_MANIFEST, &mut indicator)
.expect("Could not load world colors!");
(
@ -90,7 +90,7 @@ impl IndexOwned {
) -> Option<R> {
self.indicator.reloaded().then(move || {
// We know the asset was loaded before, so load_expect should be fine.
self.colors = assets::load_expect::<Colors>(WORLD_COLORS_MANIFEST);
self.colors = Ron::<Colors>::load_expect(WORLD_COLORS_MANIFEST);
reload(self)
})
}

View File

@ -5,7 +5,8 @@ use crate::{
IndexRef, CONFIG,
};
use common::{
assets, comp,
assets::Asset,
comp,
generation::{ChunkSupplement, EntityInfo},
lottery::Lottery,
terrain::{Block, BlockKind},
@ -13,14 +14,14 @@ use common::{
};
use noise::NoiseFn;
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use std::{
f32,
ops::{Mul, Sub},
};
use vek::*;
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub bridge: (u8, u8, u8),
pub stalagtite: (u8, u8, u8),
@ -505,7 +506,7 @@ pub fn apply_caves_to<'a>(
if RandomField::new(index.seed).chance(wpos2d.into(), 0.001 * difficulty.powf(1.5))
&& cave_base < surface_z as i32 - 25
{
let kind = *assets::load_expect::<Lottery<BlockKind>>("common.cave_scatter")
let kind = *Lottery::<BlockKind>::load_expect("common.cave_scatter")
.choose_seeded(RandomField::new(index.seed + 1).get(wpos2d.into()));
let _ = vol.set(
Vec3::new(offs.x, offs.y, cave_base),

View File

@ -34,7 +34,6 @@ use crate::{
util::{Grid, Sampler},
};
use common::{
assets::{self, Asset},
comp::{self, bird_medium, critter, quadruped_low, quadruped_medium, quadruped_small},
generation::{ChunkSupplement, EntityInfo},
msg::server::WorldMapMsg,
@ -42,8 +41,8 @@ use common::{
vol::{ReadVol, RectVolSize, Vox, WriteVol},
};
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::{fs::File, io::BufReader, time::Duration};
use serde::Deserialize;
use std::time::Duration;
use vek::*;
#[derive(Debug)]
@ -56,7 +55,7 @@ pub struct World {
civs: civ::Civs,
}
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub deep_stone_color: (u8, u8, u8),
pub block: block::Colors,
@ -65,14 +64,6 @@ pub struct Colors {
pub site: site::Colors,
}
impl Asset for Colors {
const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
}
}
impl World {
pub fn generate(seed: u32, opts: sim::WorldOpts) -> (Self, IndexOwned) {
// NOTE: Generating index first in order to quickly fail if the color manifest

View File

@ -15,7 +15,7 @@ use common::{
};
use core::f32;
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use vek::*;
struct Keep {
@ -49,7 +49,7 @@ pub struct GenCtx<'a, R: Rng> {
rng: &'a mut R,
}
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors;
impl Castle {

View File

@ -8,9 +8,9 @@ use crate::{
IndexRef,
};
use common::{
assets,
assets::Asset,
astar::Astar,
comp,
comp::{self, item::ItemAsset},
generation::{ChunkSupplement, EntityInfo},
lottery::Lottery,
npc,
@ -22,7 +22,7 @@ use core::{f32, hash::BuildHasherDefault};
use fxhash::FxHasher64;
use lazy_static::lazy_static;
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use std::sync::Arc;
use vek::*;
@ -40,7 +40,7 @@ pub struct GenCtx<'a, R: Rng> {
rng: &'a mut R,
}
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub stone: (u8, u8, u8),
}
@ -461,8 +461,7 @@ impl Floor {
&& !tile_is_pillar
{
// Bad
let chosen =
assets::load_expect::<Lottery<String>>(match rng.gen_range(0, 5) {
let chosen = Lottery::<String>::load_expect(match rng.gen_range(0, 5) {
0 => "common.loot_tables.loot_table_humanoids",
1 => "common.loot_tables.loot_table_armor_misc",
_ => "common.loot_tables.loot_table_cultists",
@ -479,8 +478,8 @@ impl Floor {
.with_alignment(comp::Alignment::Enemy)
.with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
.with_automatic_name()
.with_loot_drop(assets::load_expect_cloned(chosen))
.with_main_tool(assets::load_expect_cloned(match rng.gen_range(0, 6) {
.with_loot_drop(ItemAsset::load_expect_cloned(chosen))
.with_main_tool(ItemAsset::load_expect_cloned(match rng.gen_range(0, 6) {
0 => "common.items.npc_weapons.axe.malachite_axe-0",
1 => "common.items.npc_weapons.sword.cultist_purp_2h-0",
2 => "common.items.npc_weapons.sword.cultist_purp_2h-0",
@ -507,7 +506,7 @@ impl Floor {
boss_spawn_tile + if boss_tile_is_pillar { 1 } else { 0 };
if tile_pos == boss_spawn_tile && tile_wcenter.xy() == wpos2d {
let chosen = assets::load_expect::<Lottery<String>>(
let chosen = Lottery::<String>::load_expect(
"common.loot_tables.loot_table_boss_cultist-leader",
);
let chosen = chosen.choose();
@ -520,7 +519,7 @@ impl Floor {
"Cult Leader {}",
npc::get_npc_name(npc::NpcKind::Humanoid)
))
.with_main_tool(assets::load_expect_cloned(
.with_main_tool(ItemAsset::load_expect_cloned(
match rng.gen_range(0, 1) {
//Add more possible cult leader npc_weapons here
_ => {
@ -528,7 +527,7 @@ impl Floor {
},
},
))
.with_loot_drop(assets::load_expect_cloned(chosen));
.with_loot_drop(ItemAsset::load_expect_cloned(chosen));
supplement.add_entity(entity);
}

View File

@ -17,10 +17,10 @@ use common::{
vol::{BaseVol, ReadVol, RectSizedVol, WriteVol},
};
use rand::Rng;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use vek::*;
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub castle: castle::Colors,
pub dungeon: dungeon::Colors,

View File

@ -12,10 +12,10 @@ use common::{
vol::Vox,
};
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use vek::*;
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub foundation: (u8, u8, u8),
pub floor: (u8, u8, u8),

View File

@ -10,10 +10,10 @@ use common::{
vol::Vox,
};
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use vek::*;
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub brick_base: (u8, u8, u8),
pub floor_base: (u8, u8, u8),

View File

@ -4,10 +4,10 @@ pub mod keep;
use super::skeleton::*;
use crate::{site::BlockMask, IndexRef};
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use vek::*;
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub house: house::Colors,
pub keep: keep::Colors,

View File

@ -10,10 +10,10 @@ pub use self::{
use crate::IndexRef;
use common::terrain::Block;
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use vek::*;
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub archetype: archetype::Colors,
}

View File

@ -13,9 +13,9 @@ use crate::{
IndexRef,
};
use common::{
assets,
assets::Asset,
astar::Astar,
comp::{self, bird_medium, humanoid, object, quadruped_small},
comp::{self, bird_medium, humanoid, item::ItemAsset, object, quadruped_small},
generation::{ChunkSupplement, EntityInfo},
path::Path,
spiral::Spiral2d,
@ -26,11 +26,11 @@ use common::{
use fxhash::FxHasher64;
use hashbrown::{HashMap, HashSet};
use rand::prelude::*;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use std::{collections::VecDeque, f32, hash::BuildHasherDefault};
use vek::*;
#[derive(Deserialize, Serialize)]
#[derive(Deserialize)]
pub struct Colors {
pub building: building::Colors,
@ -904,7 +904,7 @@ impl Settlement {
comp::Alignment::Tame
})
.do_if(is_human && rng.gen(), |entity| {
entity.with_main_tool(assets::load_expect_cloned(
entity.with_main_tool(ItemAsset::load_expect_cloned(
match rng.gen_range(0, 7) {
0 => "common.items.npc_weapons.tool.broom",
1 => "common.items.npc_weapons.tool.hoe",