Loadout Update: Managed Rng

Rewrite EntityInfo api to take Rng from caller.
This commit is contained in:
juliancoffee 2022-01-23 18:40:58 +02:00
parent d5b927602a
commit 4a4f2f8d8f
4 changed files with 60 additions and 32 deletions

View File

@ -1,7 +1,3 @@
// TODO:
// Reviewers, bonk me if I forgot to remove every thread_rng() here.
// Rng should be passed outside.
use crate::{
assets::{self, AssetExt, Error},
comp::{
@ -223,14 +219,34 @@ impl EntityInfo {
/// Helper function for applying config from asset
#[must_use]
pub fn with_asset_expect(self, asset_specifier: &str) -> Self {
let loadout_rng = rand::thread_rng();
self.with_asset_expect_and_rng(asset_specifier, loadout_rng)
}
/// Helper function for applying config from asset
/// with specified Rng for managing loadout.
#[must_use]
pub fn with_asset_expect_and_rng<R>(self, asset_specifier: &str, loadout_rng: R) -> Self
where
R: rand::Rng,
{
let config = EntityConfig::load_expect_cloned(asset_specifier);
self.with_entity_config(config, Some(asset_specifier))
self.with_entity_config(config, Some(asset_specifier), loadout_rng)
}
/// Evaluate and apply EntityConfig
#[must_use]
pub fn with_entity_config(mut self, config: EntityConfig, config_asset: Option<&str>) -> Self {
pub fn with_entity_config<R>(
mut self,
config: EntityConfig,
config_asset: Option<&str>,
loadout_rng: R,
) -> Self
where
R: rand::Rng,
{
let EntityConfig {
name,
body,
@ -273,7 +289,7 @@ impl EntityInfo {
self = self.with_loot_drop(loot);
// NOTE: set loadout after body, as it's used with default equipement
self = self.with_loadout(loadout, config_asset);
self = self.with_loadout(loadout, config_asset, loadout_rng);
for field in meta {
match field {
@ -289,24 +305,32 @@ impl EntityInfo {
#[must_use]
/// Return EntityInfo with LoadoutBuilder overwritten
// NOTE: helpder function, think twice before exposing it
fn with_loadout(mut self, loadout: LoadoutKind, config_asset: Option<&str>) -> Self {
fn with_loadout<R>(
mut self,
loadout: LoadoutKind,
config_asset: Option<&str>,
mut rng: R,
) -> Self
where
R: rand::Rng,
{
match loadout {
LoadoutKind::FromBody => {
self = self.with_default_equip();
},
LoadoutKind::Asset(loadout) => {
self = self.with_loadout_asset(loadout);
self = self.with_loadout_asset(loadout, &mut rng);
},
LoadoutKind::Hands(hands) => {
self = self.with_hands(hands, config_asset);
self = self.with_hands(hands, config_asset, &mut rng);
},
LoadoutKind::Extended {
hands,
base_asset,
inventory,
} => {
self = self.with_loadout_asset(base_asset);
self = self.with_hands(hands, config_asset);
self = self.with_loadout_asset(base_asset, &mut rng);
self = self.with_hands(hands, config_asset, &mut rng);
self.inventory = inventory
.into_iter()
.map(|(num, i)| (num, Item::new_from_asset_expect(&i)))
@ -330,20 +354,21 @@ impl EntityInfo {
#[must_use]
/// Return EntityInfo with LoadoutBuilder overwritten
// NOTE: helpder function, think twice before exposing it
fn with_loadout_asset(mut self, loadout: LoadoutAsset) -> Self {
fn with_loadout_asset<R>(mut self, loadout: LoadoutAsset, rng: &mut R) -> Self
where
R: rand::Rng,
{
match loadout {
LoadoutAsset::Loadout(asset) => {
let mut rng = rand::thread_rng();
let loadout = LoadoutBuilder::from_asset_expect(&asset, Some(&mut rng));
let loadout = LoadoutBuilder::from_asset_expect(&asset, Some(rng));
self.loadout = loadout;
},
LoadoutAsset::Choice(assets) => {
let mut rng = rand::thread_rng();
let (_p, asset) = assets
.choose_weighted(&mut rng, |(p, _asset)| *p)
.choose_weighted(rng, |(p, _asset)| *p)
.expect("rng error");
let loadout = LoadoutBuilder::from_asset_expect(asset, Some(&mut rng));
let loadout = LoadoutBuilder::from_asset_expect(asset, Some(rng));
self.loadout = loadout;
},
}
@ -354,9 +379,10 @@ impl EntityInfo {
#[must_use]
/// Return EntityInfo with weapons applied to LoadoutBuilder
// NOTE: helpder function, think twice before exposing it
fn with_hands(mut self, hands: Hands, config_asset: Option<&str>) -> Self {
let rng = &mut rand::thread_rng();
fn with_hands<R>(mut self, hands: Hands, config_asset: Option<&str>, rng: &mut R) -> Self
where
R: rand::Rng,
{
match hands {
Hands::TwoHanded(main_tool) => {
let tool = main_tool.try_to_item(config_asset.unwrap_or("??"), rng);

View File

@ -621,12 +621,16 @@ fn handle_make_npc(
Err(_err) => return Err(format!("Failed to load entity config: {}", entity_config)),
};
let rng = &mut rand::thread_rng();
for _ in 0..number {
let comp::Pos(pos) = position(server, target, "target")?;
let entity_info =
EntityInfo::at(pos).with_entity_config(config.clone(), Some(&entity_config));
match NpcData::from_entity_info(entity_info, rng) {
let loadout_rng = rand::thread_rng();
let entity_info = EntityInfo::at(pos).with_entity_config(
config.clone(),
Some(&entity_config),
loadout_rng,
);
match NpcData::from_entity_info(entity_info) {
NpcData::Waypoint(_) => {
return Err("Waypoint spawning is not implemented".to_owned());
},

View File

@ -128,7 +128,7 @@ impl<'a> System<'a> for Sys {
}
} else {
let entity_config_path = entity.get_entity_config();
let mut loadout_rng = entity.loadout_rng();
let loadout_rng = entity.loadout_rng();
let ad_hoc_loadout = entity.get_adhoc_loadout();
// Body is rewritten so that body parameters
// are consistent between reifications
@ -136,7 +136,7 @@ impl<'a> System<'a> for Sys {
.with_body(BodyBuilder::Exact(body));
let mut entity_info = EntityInfo::at(pos.0)
.with_entity_config(entity_config, Some(entity_config_path))
.with_entity_config(entity_config, Some(entity_config_path), loadout_rng)
.with_lazy_loadout(ad_hoc_loadout);
// Merchants can be traded with
if let Some(economy) = entity.get_trade_info(&world, &index) {
@ -144,7 +144,7 @@ impl<'a> System<'a> for Sys {
.with_agent_mark(comp::agent::Mark::Merchant)
.with_economy(&economy);
}
match NpcData::from_entity_info(entity_info, &mut loadout_rng) {
match NpcData::from_entity_info(entity_info) {
NpcData::Data {
pos,
stats,

View File

@ -32,7 +32,6 @@ use common_ecs::{Job, Origin, Phase, System};
use common_net::msg::{SerializedTerrainChunk, ServerGeneral};
use common_state::TerrainChanges;
use comp::Behavior;
use rand::Rng;
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write, WriteExpect, WriteStorage};
use std::sync::Arc;
use vek::*;
@ -239,8 +238,7 @@ impl<'a> System<'a> for Sys {
"Chunk spawned entity that wasn't nearby",
);
let rng = &mut rand::thread_rng();
let data = NpcData::from_entity_info(entity, rng);
let data = NpcData::from_entity_info(entity);
match data {
NpcData::Waypoint(pos) => {
server_emitter.emit(ServerEvent::CreateWaypoint(pos));
@ -403,7 +401,7 @@ pub enum NpcData {
}
impl NpcData {
pub fn from_entity_info(entity: EntityInfo, _loadout_rng: &mut impl Rng) -> Self {
pub fn from_entity_info(entity: EntityInfo) -> Self {
let EntityInfo {
// flags
is_waypoint,