From a4f882a8d65ddf1a9a67decba61a888f8b61fbe5 Mon Sep 17 00:00:00 2001
From: juliancoffee <lightdarkdaughter@gmail.com>
Date: Mon, 11 Oct 2021 13:40:59 +0300
Subject: [PATCH] Fix Traveller names

- Previously RtSim were created with automatic name for body generated
  from EntityConfig, not from RtSim body. Now RtSim body is set for
  EntityConfig.
---
 common/src/generation.rs | 32 ++++++++++++++++++++------------
 server/src/rtsim/tick.rs | 10 ++++++----
 2 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/common/src/generation.rs b/common/src/generation.rs
index 2b2f2c435d..783b102686 100644
--- a/common/src/generation.rs
+++ b/common/src/generation.rs
@@ -14,21 +14,21 @@ use serde::Deserialize;
 use vek::*;
 
 #[derive(Debug, Deserialize, Clone)]
-enum NameKind {
+pub enum NameKind {
     Name(String),
     Automatic,
     Uninit,
 }
 
 #[derive(Debug, Deserialize, Clone)]
-enum BodyBuilder {
+pub enum BodyBuilder {
     RandomWith(String),
     Exact(Body),
     Uninit,
 }
 
 #[derive(Debug, Deserialize, Clone)]
-enum AlignmentMark {
+pub enum AlignmentMark {
     Alignment(Alignment),
     Uninit,
 }
@@ -38,7 +38,7 @@ impl Default for AlignmentMark {
 }
 
 #[derive(Debug, Deserialize, Clone)]
-enum Hands {
+pub enum Hands {
     TwoHanded(ItemSpec),
     Paired(ItemSpec),
     Mix {
@@ -53,7 +53,7 @@ impl Default for Hands {
 }
 
 #[derive(Debug, Deserialize, Clone)]
-enum Meta {
+pub enum Meta {
     LoadoutAsset(String),
     SkillSetAsset(String),
 }
@@ -92,16 +92,17 @@ pub struct EntityConfig {
     /// 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)
+    // Hidden, because its behaviour depends on `body` field.
     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,
+    pub body: BodyBuilder,
 
     /// Alignment, can be Uninit
-    alignment: AlignmentMark,
+    pub alignment: AlignmentMark,
 
     /// Loot
     /// See LootSpec in lottery
@@ -117,14 +118,14 @@ pub struct EntityConfig {
     // 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,
+    pub hands: Hands,
 
     /// Meta Info for optional fields
     /// Possible fields:
     /// LoadoutAsset(String) with asset_specifier for loadout
     /// SkillSetAsset(String) with asset_specifier for skillset
     #[serde(default)]
-    meta: Vec<Meta>,
+    pub meta: Vec<Meta>,
 }
 
 impl assets::Asset for EntityConfig {
@@ -134,10 +135,16 @@ impl assets::Asset for EntityConfig {
 }
 
 impl EntityConfig {
-    pub fn from_asset_expect(asset_specifier: &str) -> EntityConfig {
+    pub fn from_asset_expect(asset_specifier: &str) -> Self {
         Self::load_owned(asset_specifier)
             .unwrap_or_else(|e| panic!("Failed to load {}. Error: {}", asset_specifier, e))
     }
+
+    pub fn with_body(mut self, body: BodyBuilder) -> Self {
+        self.body = body;
+
+        self
+    }
 }
 
 /// Return all entity config specifiers
@@ -193,14 +200,15 @@ impl EntityInfo {
         }
     }
 
+    /// Helper function for applying config from asset
     pub fn with_asset_expect(self, asset_specifier: &str) -> Self {
         let config = EntityConfig::load_expect(asset_specifier).read().clone();
 
         self.with_entity_config(config, Some(asset_specifier))
     }
 
-    // helper function to apply config
-    fn with_entity_config(mut self, config: EntityConfig, config_asset: Option<&str>) -> Self {
+    /// Evaluate and apply EntityConfig
+    pub fn with_entity_config(mut self, config: EntityConfig, config_asset: Option<&str>) -> Self {
         let EntityConfig {
             name,
             body,
diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs
index c69ec4e5ed..a8238226fa 100644
--- a/server/src/rtsim/tick.rs
+++ b/server/src/rtsim/tick.rs
@@ -5,7 +5,7 @@ use crate::sys::terrain::NpcData;
 use common::{
     comp,
     event::{EventBus, ServerEvent},
-    generation::EntityInfo,
+    generation::{BodyBuilder, EntityConfig, EntityInfo},
     resources::{DeltaTime, Time},
     terrain::TerrainGrid,
 };
@@ -127,15 +127,17 @@ impl<'a> System<'a> for Sys {
                     rtsim_entity,
                 }
             } else {
-                let entity_config = entity.get_entity_config();
+                let entity_config_path = entity.get_entity_config();
                 let mut loadout_rng = entity.loadout_rng();
                 let ad_hoc_loadout = entity.get_adhoc_loadout();
                 // Body is rewritten so that body parameters
                 // are consistent between reifications
+                let entity_config = EntityConfig::from_asset_expect(entity_config_path)
+                    .with_body(BodyBuilder::Exact(body));
+
                 let entity_info = EntityInfo::at(pos.0)
-                    .with_asset_expect(entity_config)
+                    .with_entity_config(entity_config, Some(entity_config_path))
                     .with_lazy_loadout(ad_hoc_loadout)
-                    .with_body(body)
                     .with_health_scaling(10);
                 match NpcData::from_entity_info(entity_info, &mut loadout_rng) {
                     NpcData::Data {