mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'juliancoffee/entity_refactor' into 'master'
Improve terms of EntityConfig and LoadoutBuilder See merge request veloren/veloren!2688
This commit is contained in:
commit
680492cea6
@ -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 (
|
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"),
|
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"),
|
body: RandomWith("humanoid"),
|
||||||
|
|
||||||
/// Alignment, can be Uninit
|
|
||||||
alignment: Alignment(Enemy),
|
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"),
|
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")),
|
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: [
|
meta: [
|
||||||
LoadoutAsset("common.loadout.village.merchant"),
|
LoadoutAsset("common.loadout.village.merchant"),
|
||||||
SkillSetAsset("common.skillset.village.merchant"),
|
SkillSetAsset("common.skillset.village.merchant"),
|
||||||
|
@ -24,17 +24,14 @@ use tracing::warn;
|
|||||||
/// `ItemConfig`
|
/// `ItemConfig`
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use veloren_common::{
|
/// use veloren_common::{comp::Item, LoadoutBuilder};
|
||||||
/// assets::AssetExt,
|
|
||||||
/// comp::item::tool::AbilityMap,
|
|
||||||
/// comp::Item,
|
|
||||||
/// LoadoutBuilder,
|
|
||||||
/// };
|
|
||||||
///
|
///
|
||||||
/// // Build a loadout with character starter defaults and a specific sword with default sword abilities
|
/// // Build a loadout with character starter defaults
|
||||||
/// let loadout = LoadoutBuilder::new()
|
/// // 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()
|
/// .defaults()
|
||||||
/// .active_mainhand(Some(Item::new_from_asset_expect("common.items.weapons.sword.steel-8")))
|
/// .active_mainhand(Some(sword))
|
||||||
/// .build();
|
/// .build();
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -362,13 +359,9 @@ fn default_main_tool(body: &Body) -> Item {
|
|||||||
maybe_tool.unwrap_or_else(Item::empty)
|
maybe_tool.unwrap_or_else(Item::empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LoadoutBuilder {
|
|
||||||
fn default() -> Self { Self::new() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LoadoutBuilder {
|
impl LoadoutBuilder {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self { Self(Loadout::new_empty()) }
|
pub fn empty() -> Self { Self(Loadout::new_empty()) }
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
/// Construct new `LoadoutBuilder` from `asset_specifier`
|
/// 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 {
|
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
|
// It's impossible to use lambdas because `loadout` is used by value
|
||||||
#![allow(clippy::option_if_let_else)]
|
#![allow(clippy::option_if_let_else)]
|
||||||
let loadout = Self::new();
|
let loadout = Self::empty();
|
||||||
|
|
||||||
if let Some(rng) = rng {
|
if let Some(rng) = rng {
|
||||||
loadout.with_asset_expect(asset_specifier, 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
|
/// 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
|
/// Use it if you don't care much about it, for example in "/spawn" command
|
||||||
pub fn from_default(body: &Body) -> Self {
|
pub fn from_default(body: &Body) -> Self {
|
||||||
let loadout = Self::new();
|
let loadout = Self::empty();
|
||||||
loadout
|
loadout
|
||||||
.with_default_maintool(body)
|
.with_default_maintool(body)
|
||||||
.with_default_equipment(body)
|
.with_default_equipment(body)
|
||||||
@ -691,7 +684,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_loadout_presets() {
|
fn test_loadout_presets() {
|
||||||
for preset in Preset::iter() {
|
for preset in Preset::iter() {
|
||||||
std::mem::drop(LoadoutBuilder::default().with_preset(preset));
|
std::mem::drop(LoadoutBuilder::empty().with_preset(preset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ impl InventorySortOrder {
|
|||||||
/// that contains items etc) must first ensure items are unloaded from the item.
|
/// that contains items etc) must first ensure items are unloaded from the item.
|
||||||
/// This is handled in `inventory\slot.rs`
|
/// This is handled in `inventory\slot.rs`
|
||||||
impl Inventory {
|
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 {
|
pub fn new_with_loadout(loadout: Loadout) -> Inventory {
|
||||||
Inventory {
|
Inventory {
|
||||||
|
@ -21,7 +21,7 @@ fn push_full() {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|a| Some(a.duplicate(ability_map, msm)))
|
.map(|a| Some(a.duplicate(ability_map, msm)))
|
||||||
.collect(),
|
.collect(),
|
||||||
loadout: LoadoutBuilder::new().build(),
|
loadout: LoadoutBuilder::empty().build(),
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
inv.push(TEST_ITEMS[0].duplicate(ability_map, msm))
|
inv.push(TEST_ITEMS[0].duplicate(ability_map, msm))
|
||||||
@ -41,7 +41,7 @@ fn push_all_full() {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|a| Some(a.duplicate(ability_map, msm)))
|
.map(|a| Some(a.duplicate(ability_map, msm)))
|
||||||
.collect(),
|
.collect(),
|
||||||
loadout: LoadoutBuilder::new().build(),
|
loadout: LoadoutBuilder::empty().build(),
|
||||||
};
|
};
|
||||||
let Error::Full(leftovers) = inv
|
let Error::Full(leftovers) = inv
|
||||||
.push_all(
|
.push_all(
|
||||||
@ -71,7 +71,7 @@ fn push_unique_all_full() {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|a| Some(a.duplicate(ability_map, msm)))
|
.map(|a| Some(a.duplicate(ability_map, msm)))
|
||||||
.collect(),
|
.collect(),
|
||||||
loadout: LoadoutBuilder::new().build(),
|
loadout: LoadoutBuilder::empty().build(),
|
||||||
};
|
};
|
||||||
inv.push_all_unique(
|
inv.push_all_unique(
|
||||||
TEST_ITEMS
|
TEST_ITEMS
|
||||||
@ -90,7 +90,7 @@ fn push_all_empty() {
|
|||||||
let mut inv = Inventory {
|
let mut inv = Inventory {
|
||||||
next_sort_order: InventorySortOrder::Name,
|
next_sort_order: InventorySortOrder::Name,
|
||||||
slots: vec![None, None],
|
slots: vec![None, None],
|
||||||
loadout: LoadoutBuilder::new().build(),
|
loadout: LoadoutBuilder::empty().build(),
|
||||||
};
|
};
|
||||||
inv.push_all(
|
inv.push_all(
|
||||||
TEST_ITEMS
|
TEST_ITEMS
|
||||||
@ -109,7 +109,7 @@ fn push_all_unique_empty() {
|
|||||||
let mut inv = Inventory {
|
let mut inv = Inventory {
|
||||||
next_sort_order: InventorySortOrder::Name,
|
next_sort_order: InventorySortOrder::Name,
|
||||||
slots: vec![None, None],
|
slots: vec![None, None],
|
||||||
loadout: LoadoutBuilder::new().build(),
|
loadout: LoadoutBuilder::empty().build(),
|
||||||
};
|
};
|
||||||
inv.push_all_unique(
|
inv.push_all_unique(
|
||||||
TEST_ITEMS
|
TEST_ITEMS
|
||||||
|
@ -57,14 +57,73 @@ enum Meta {
|
|||||||
SkillSetAsset(String),
|
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)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct EntityConfig {
|
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,
|
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,
|
body: BodyBuilder,
|
||||||
|
|
||||||
|
/// Alignment, can be Uninit
|
||||||
alignment: AlignmentMark,
|
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,
|
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,
|
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<Meta>,
|
meta: Vec<Meta>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,7 +535,7 @@ mod tests {
|
|||||||
match field {
|
match field {
|
||||||
Meta::LoadoutAsset(asset) => {
|
Meta::LoadoutAsset(asset) => {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let builder = LoadoutBuilder::default();
|
let builder = LoadoutBuilder::empty();
|
||||||
// we need to just load it check if it exists,
|
// we need to just load it check if it exists,
|
||||||
// because all loadouts are tested in LoadoutBuilder module
|
// because all loadouts are tested in LoadoutBuilder module
|
||||||
std::mem::drop(builder.with_asset_expect(&asset, rng));
|
std::mem::drop(builder.with_asset_expect(&asset, rng));
|
||||||
|
@ -91,7 +91,7 @@ impl CharacterBehavior for Data {
|
|||||||
|
|
||||||
let loadout = {
|
let loadout = {
|
||||||
let loadout_builder =
|
let loadout_builder =
|
||||||
LoadoutBuilder::new().with_default_maintool(&body);
|
LoadoutBuilder::empty().with_default_maintool(&body);
|
||||||
// If preset is none, use default equipment
|
// If preset is none, use default equipment
|
||||||
if let Some(preset) = loadout_config {
|
if let Some(preset) = loadout_config {
|
||||||
loadout_builder.with_preset(preset).build()
|
loadout_builder.with_preset(preset).build()
|
||||||
|
@ -36,7 +36,7 @@ pub fn create_character(
|
|||||||
let stats = Stats::new(character_alias.to_string());
|
let stats = Stats::new(character_alias.to_string());
|
||||||
let skill_set = SkillSet::default();
|
let skill_set = SkillSet::default();
|
||||||
|
|
||||||
let loadout = LoadoutBuilder::new()
|
let loadout = LoadoutBuilder::empty()
|
||||||
.defaults()
|
.defaults()
|
||||||
.active_mainhand(Some(Item::new_from_asset_expect(&tool_id)))
|
.active_mainhand(Some(Item::new_from_asset_expect(&tool_id)))
|
||||||
.build();
|
.build();
|
||||||
|
@ -361,7 +361,7 @@ pub fn convert_loadout_from_database_items(
|
|||||||
loadout_container_id: i64,
|
loadout_container_id: i64,
|
||||||
database_items: &[Item],
|
database_items: &[Item],
|
||||||
) -> Result<Loadout, PersistenceError> {
|
) -> Result<Loadout, PersistenceError> {
|
||||||
let loadout_builder = LoadoutBuilder::new();
|
let loadout_builder = LoadoutBuilder::empty();
|
||||||
let mut loadout = loadout_builder.build();
|
let mut loadout = loadout_builder.build();
|
||||||
let mut item_indices = HashMap::new();
|
let mut item_indices = HashMap::new();
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
// TODO: this should be a bit more intelligent
|
// TODO: this should be a bit more intelligent
|
||||||
let loadout = match body {
|
let loadout = match body {
|
||||||
comp::Body::Humanoid(_) => entity.get_loadout(),
|
comp::Body::Humanoid(_) => entity.get_loadout(),
|
||||||
_ => LoadoutBuilder::new().with_default_maintool(&body).build(),
|
_ => LoadoutBuilder::empty().with_default_maintool(&body).build(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let event = match body {
|
let event = match body {
|
||||||
|
@ -230,7 +230,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let loadout = {
|
let loadout = {
|
||||||
let mut loadout_builder = LoadoutBuilder::new();
|
let mut loadout_builder = LoadoutBuilder::empty();
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
|
|
||||||
// If main tool is passed, use it. Otherwise fallback to default tool
|
// If main tool is passed, use it. Otherwise fallback to default tool
|
||||||
|
@ -12,7 +12,7 @@ use std::time::{Duration, Instant};
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn maps_wield_while_equipping() {
|
fn maps_wield_while_equipping() {
|
||||||
let loadout = LoadoutBuilder::new()
|
let loadout = LoadoutBuilder::empty()
|
||||||
.active_mainhand(Some(Item::new_from_asset_expect(
|
.active_mainhand(Some(Item::new_from_asset_expect(
|
||||||
"common.items.weapons.axe.starter_axe",
|
"common.items.weapons.axe.starter_axe",
|
||||||
)))
|
)))
|
||||||
@ -39,7 +39,7 @@ fn maps_wield_while_equipping() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn maps_unwield() {
|
fn maps_unwield() {
|
||||||
let loadout = LoadoutBuilder::new()
|
let loadout = LoadoutBuilder::empty()
|
||||||
.active_mainhand(Some(Item::new_from_asset_expect(
|
.active_mainhand(Some(Item::new_from_asset_expect(
|
||||||
"common.items.weapons.bow.starter",
|
"common.items.weapons.bow.starter",
|
||||||
)))
|
)))
|
||||||
@ -61,7 +61,7 @@ fn maps_unwield() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn maps_basic_melee() {
|
fn maps_basic_melee() {
|
||||||
let loadout = LoadoutBuilder::new()
|
let loadout = LoadoutBuilder::empty()
|
||||||
.active_mainhand(Some(Item::new_from_asset_expect(
|
.active_mainhand(Some(Item::new_from_asset_expect(
|
||||||
"common.items.weapons.axe.starter_axe",
|
"common.items.weapons.axe.starter_axe",
|
||||||
)))
|
)))
|
||||||
@ -106,7 +106,7 @@ fn maps_basic_melee() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn matches_ability_stage() {
|
fn matches_ability_stage() {
|
||||||
let loadout = LoadoutBuilder::new()
|
let loadout = LoadoutBuilder::empty()
|
||||||
.active_mainhand(Some(Item::new_from_asset_expect(
|
.active_mainhand(Some(Item::new_from_asset_expect(
|
||||||
"common.items.weapons.sword.starter",
|
"common.items.weapons.sword.starter",
|
||||||
)))
|
)))
|
||||||
@ -168,7 +168,7 @@ fn matches_ability_stage() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ignores_different_ability_stage() {
|
fn ignores_different_ability_stage() {
|
||||||
let loadout = LoadoutBuilder::new()
|
let loadout = LoadoutBuilder::empty()
|
||||||
.active_mainhand(Some(Item::new_from_asset_expect(
|
.active_mainhand(Some(Item::new_from_asset_expect(
|
||||||
"common.items.weapons.axe.starter_axe",
|
"common.items.weapons.axe.starter_axe",
|
||||||
)))
|
)))
|
||||||
|
@ -180,7 +180,7 @@ impl Mode {
|
|||||||
pub fn create(name: String) -> Self {
|
pub fn create(name: String) -> Self {
|
||||||
let tool = STARTER_SWORD;
|
let tool = STARTER_SWORD;
|
||||||
|
|
||||||
let loadout = LoadoutBuilder::new()
|
let loadout = LoadoutBuilder::empty()
|
||||||
.defaults()
|
.defaults()
|
||||||
.active_mainhand(Some(Item::new_from_asset_expect(tool)))
|
.active_mainhand(Some(Item::new_from_asset_expect(tool)))
|
||||||
.build();
|
.build();
|
||||||
|
Loading…
Reference in New Issue
Block a user