diff --git a/assets/common/entity/template.ron b/assets/common/entity/template.ron index 5743f305a3..0b9adba264 100644 --- a/assets/common/entity/template.ron +++ b/assets/common/entity/template.ron @@ -1,40 +1,16 @@ +/// Template file for EntityConfig, check documentation in code for more +/// By the time of writing this comment it lives in common/src/generation.rs EntityConfig ( - /// Name of Entity - /// Can be Name(String) with given name - /// or Automatic which will call automatic name depend on Body - /// or Uninit (means it should be specified somewhere in code) name: Name("Paddy"), - /// Body - /// Can be Exact (Body with all fields e.g BodyType, Species, Hair color and such) - /// or RandomWith (will generate random body or species) - /// or Uninit (means it should be specified somewhere in code) body: RandomWith("humanoid"), - /// Alignment, can be Uninit alignment: Alignment(Enemy), - /// Loot - /// Can be Item (with asset_specifier for item) - /// or LootTable (with asset_specifier for loot table) - /// or Uninit (means it should be specified something in the code) loot: LootTable("common.loot_tables.humanoids"), - /// Hands: - /// - TwoHanded(ItemSpec) for one 2h or 1h weapon, - /// - Paired(ItemSpec) for two 1h weapons aka berserker mode, - /// - Mix { - /// mainhand: ItemSpec, - /// offhand: ItemSpec, - /// } for two different 1h weapons, - /// - Uninit which means that tool should be specified somewhere in code, - /// Where ItemSpec is taken from loadout_builder module hands: TwoHanded(Item("common.items.weapons.sword.cultist")), - /// Meta Info - /// Possible fields: - /// LoadoutAsset(String) with asset_specifier for loadout - /// SkillSetAsset(String) with asset_specifier for skillset meta: [ LoadoutAsset("common.loadout.village.merchant"), SkillSetAsset("common.skillset.village.merchant"), diff --git a/common/src/comp/inventory/loadout_builder.rs b/common/src/comp/inventory/loadout_builder.rs index 7051349812..052cbb467a 100644 --- a/common/src/comp/inventory/loadout_builder.rs +++ b/common/src/comp/inventory/loadout_builder.rs @@ -24,17 +24,14 @@ use tracing::warn; /// `ItemConfig` /// /// ``` -/// use veloren_common::{ -/// assets::AssetExt, -/// comp::item::tool::AbilityMap, -/// comp::Item, -/// LoadoutBuilder, -/// }; +/// use veloren_common::{comp::Item, LoadoutBuilder}; /// -/// // Build a loadout with character starter defaults and a specific sword with default sword abilities -/// let loadout = LoadoutBuilder::new() +/// // Build a loadout with character starter defaults +/// // and a specific sword with default sword abilities +/// let sword = Item::new_from_asset_expect("common.items.weapons.sword.steel-8"); +/// let loadout = LoadoutBuilder::empty() /// .defaults() -/// .active_mainhand(Some(Item::new_from_asset_expect("common.items.weapons.sword.steel-8"))) +/// .active_mainhand(Some(sword)) /// .build(); /// ``` #[derive(Clone)] @@ -362,13 +359,9 @@ fn default_main_tool(body: &Body) -> Item { maybe_tool.unwrap_or_else(Item::empty) } -impl Default for LoadoutBuilder { - fn default() -> Self { Self::new() } -} - impl LoadoutBuilder { #[must_use] - pub fn new() -> Self { Self(Loadout::new_empty()) } + pub fn empty() -> Self { Self(Loadout::new_empty()) } #[must_use] /// Construct new `LoadoutBuilder` from `asset_specifier` @@ -376,7 +369,7 @@ impl LoadoutBuilder { pub fn from_asset_expect(asset_specifier: &str, rng: Option<&mut impl Rng>) -> Self { // It's impossible to use lambdas because `loadout` is used by value #![allow(clippy::option_if_let_else)] - let loadout = Self::new(); + let loadout = Self::empty(); if let Some(rng) = rng { loadout.with_asset_expect(asset_specifier, rng) @@ -392,7 +385,7 @@ impl LoadoutBuilder { /// NOTE: make sure that you check what is default for this body /// Use it if you don't care much about it, for example in "/spawn" command pub fn from_default(body: &Body) -> Self { - let loadout = Self::new(); + let loadout = Self::empty(); loadout .with_default_maintool(body) .with_default_equipment(body) @@ -691,7 +684,7 @@ mod tests { #[test] fn test_loadout_presets() { for preset in Preset::iter() { - std::mem::drop(LoadoutBuilder::default().with_preset(preset)); + std::mem::drop(LoadoutBuilder::empty().with_preset(preset)); } } diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index b2ba3696ae..84a5e2b7d7 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -81,7 +81,7 @@ impl InventorySortOrder { /// that contains items etc) must first ensure items are unloaded from the item. /// This is handled in `inventory\slot.rs` impl Inventory { - pub fn new_empty() -> Inventory { Self::new_with_loadout(LoadoutBuilder::new().build()) } + pub fn new_empty() -> Inventory { Self::new_with_loadout(LoadoutBuilder::empty().build()) } pub fn new_with_loadout(loadout: Loadout) -> Inventory { Inventory { diff --git a/common/src/comp/inventory/test.rs b/common/src/comp/inventory/test.rs index e75c923ce7..243e8ae845 100644 --- a/common/src/comp/inventory/test.rs +++ b/common/src/comp/inventory/test.rs @@ -21,7 +21,7 @@ fn push_full() { .iter() .map(|a| Some(a.duplicate(ability_map, msm))) .collect(), - loadout: LoadoutBuilder::new().build(), + loadout: LoadoutBuilder::empty().build(), }; assert_eq!( inv.push(TEST_ITEMS[0].duplicate(ability_map, msm)) @@ -41,7 +41,7 @@ fn push_all_full() { .iter() .map(|a| Some(a.duplicate(ability_map, msm))) .collect(), - loadout: LoadoutBuilder::new().build(), + loadout: LoadoutBuilder::empty().build(), }; let Error::Full(leftovers) = inv .push_all( @@ -71,7 +71,7 @@ fn push_unique_all_full() { .iter() .map(|a| Some(a.duplicate(ability_map, msm))) .collect(), - loadout: LoadoutBuilder::new().build(), + loadout: LoadoutBuilder::empty().build(), }; inv.push_all_unique( TEST_ITEMS @@ -90,7 +90,7 @@ fn push_all_empty() { let mut inv = Inventory { next_sort_order: InventorySortOrder::Name, slots: vec![None, None], - loadout: LoadoutBuilder::new().build(), + loadout: LoadoutBuilder::empty().build(), }; inv.push_all( TEST_ITEMS @@ -109,7 +109,7 @@ fn push_all_unique_empty() { let mut inv = Inventory { next_sort_order: InventorySortOrder::Name, slots: vec![None, None], - loadout: LoadoutBuilder::new().build(), + loadout: LoadoutBuilder::empty().build(), }; inv.push_all_unique( TEST_ITEMS diff --git a/common/src/generation.rs b/common/src/generation.rs index bfc819cc1b..00598e3877 100644 --- a/common/src/generation.rs +++ b/common/src/generation.rs @@ -57,14 +57,73 @@ enum Meta { SkillSetAsset(String), } +// FIXME: currently this is used for both base definition +// and extension manifest. +// This is why all fields have Uninit kind which is means +// that this field should be either Default or Unchanged +// depending on how it is used. +// +// When we will use exension manifests more, it would be nicer to +// split EntityBase and EntityExtension to different structs. +// +// Fields which have Uninit enum kind +// should be optional (or renamed to Unchanged) in EntityExtension +// and required (or renamed to Default) in EntityBase +/// Struct for EntityInfo manifest. +/// +/// Intended to use with .ron files as base definion or +/// in rare cases as extension manifest. +/// Check assets/common/entity/template.ron or other examples. +/// +/// # Example +/// ``` +/// use vek::Vec3; +/// use veloren_common::generation::EntityInfo; +/// +/// // create new EntityInfo at dummy position +/// // and fill it with template config +/// let dummy_position = Vec3::new(0.0, 0.0, 0.0); +/// let entity = EntityInfo::at(dummy_position).with_asset_expect("common.entity.template"); +/// ``` #[derive(Debug, Deserialize, Clone)] pub struct EntityConfig { + /// Name of Entity + /// Can be Name(String) with given name + /// or Automatic which will call automatic name depend on Body + /// or Uninit (means it should be specified somewhere in code) name: NameKind, + + /// Body + /// Can be Exact (Body with all fields e.g BodyType, Species, Hair color and + /// such) or RandomWith (will generate random body or species) + /// or Uninit (means it should be specified somewhere in code) body: BodyBuilder, + + /// Alignment, can be Uninit alignment: AlignmentMark, + + /// Loot + /// Can be Item (with asset_specifier for item) + /// or LootTable (with asset_specifier for loot table) + /// or Uninit (means it should be specified something in the code) loot: LootKind, + + /// Hands: + /// - TwoHanded(ItemSpec) for one 2h or 1h weapon, + /// - Paired(ItemSpec) for two 1h weapons aka berserker mode, + /// - Mix { mainhand: ItemSpec, offhand: ItemSpec, + /// } for two different 1h weapons, + /// - Uninit which means that tool should be specified somewhere in code, + /// Where ItemSpec is taken from loadout_builder module + // TODO: better name for this? + // wielding? equipped? what do you think Tigers are wielding? + // should we use this field for animals without visible weapons at all? hands: Hands, - // Meta fields + + /// Meta Info for optional fields + /// Possible fields: + /// LoadoutAsset(String) with asset_specifier for loadout + /// SkillSetAsset(String) with asset_specifier for skillset meta: Vec, } @@ -476,7 +535,7 @@ mod tests { match field { Meta::LoadoutAsset(asset) => { let rng = &mut rand::thread_rng(); - let builder = LoadoutBuilder::default(); + let builder = LoadoutBuilder::empty(); // we need to just load it check if it exists, // because all loadouts are tested in LoadoutBuilder module std::mem::drop(builder.with_asset_expect(&asset, rng)); diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs index 22487c1026..35f012b5bf 100644 --- a/common/src/states/basic_summon.rs +++ b/common/src/states/basic_summon.rs @@ -91,7 +91,7 @@ impl CharacterBehavior for Data { let loadout = { let loadout_builder = - LoadoutBuilder::new().with_default_maintool(&body); + LoadoutBuilder::empty().with_default_maintool(&body); // If preset is none, use default equipment if let Some(preset) = loadout_config { loadout_builder.with_preset(preset).build() diff --git a/server/src/character_creator.rs b/server/src/character_creator.rs index c7b5b50edc..688b0829fd 100644 --- a/server/src/character_creator.rs +++ b/server/src/character_creator.rs @@ -36,7 +36,7 @@ pub fn create_character( let stats = Stats::new(character_alias.to_string()); let skill_set = SkillSet::default(); - let loadout = LoadoutBuilder::new() + let loadout = LoadoutBuilder::empty() .defaults() .active_mainhand(Some(Item::new_from_asset_expect(&tool_id))) .build(); diff --git a/server/src/persistence/character/conversions.rs b/server/src/persistence/character/conversions.rs index b7618d15ca..6f01da3c2c 100644 --- a/server/src/persistence/character/conversions.rs +++ b/server/src/persistence/character/conversions.rs @@ -361,7 +361,7 @@ pub fn convert_loadout_from_database_items( loadout_container_id: i64, database_items: &[Item], ) -> Result { - let loadout_builder = LoadoutBuilder::new(); + let loadout_builder = LoadoutBuilder::empty(); let mut loadout = loadout_builder.build(); let mut item_indices = HashMap::new(); diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index 19139db36b..5121a7193a 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -119,7 +119,7 @@ impl<'a> System<'a> for Sys { // TODO: this should be a bit more intelligent let loadout = match body { comp::Body::Humanoid(_) => entity.get_loadout(), - _ => LoadoutBuilder::new().with_default_maintool(&body).build(), + _ => LoadoutBuilder::empty().with_default_maintool(&body).build(), }; let event = match body { diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 114a771019..0f3ea5e3a5 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -230,7 +230,7 @@ impl<'a> System<'a> for Sys { }; let loadout = { - let mut loadout_builder = LoadoutBuilder::new(); + let mut loadout_builder = LoadoutBuilder::empty(); let rng = &mut rand::thread_rng(); // If main tool is passed, use it. Otherwise fallback to default tool diff --git a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs index 29f6315894..4532c412dd 100644 --- a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs @@ -12,7 +12,7 @@ use std::time::{Duration, Instant}; #[test] fn maps_wield_while_equipping() { - let loadout = LoadoutBuilder::new() + let loadout = LoadoutBuilder::empty() .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.axe.starter_axe", ))) @@ -39,7 +39,7 @@ fn maps_wield_while_equipping() { #[test] fn maps_unwield() { - let loadout = LoadoutBuilder::new() + let loadout = LoadoutBuilder::empty() .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.bow.starter", ))) @@ -61,7 +61,7 @@ fn maps_unwield() { #[test] fn maps_basic_melee() { - let loadout = LoadoutBuilder::new() + let loadout = LoadoutBuilder::empty() .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.axe.starter_axe", ))) @@ -106,7 +106,7 @@ fn maps_basic_melee() { #[test] fn matches_ability_stage() { - let loadout = LoadoutBuilder::new() + let loadout = LoadoutBuilder::empty() .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.sword.starter", ))) @@ -168,7 +168,7 @@ fn matches_ability_stage() { #[test] fn ignores_different_ability_stage() { - let loadout = LoadoutBuilder::new() + let loadout = LoadoutBuilder::empty() .active_mainhand(Some(Item::new_from_asset_expect( "common.items.weapons.axe.starter_axe", ))) diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index 5aa34f1639..d48bfafe6e 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -180,7 +180,7 @@ impl Mode { pub fn create(name: String) -> Self { let tool = STARTER_SWORD; - let loadout = LoadoutBuilder::new() + let loadout = LoadoutBuilder::empty() .defaults() .active_mainhand(Some(Item::new_from_asset_expect(tool))) .build();