From b34704ea3fb810f795d2adcdbfde36ae2ffe5477 Mon Sep 17 00:00:00 2001 From: Daniel Mizerski Date: Wed, 5 May 2021 15:54:24 +0200 Subject: [PATCH] (Wiring) OnDeath --- common/src/resources.rs | 4 ++ common/state/src/state.rs | 6 ++- common/systems/src/stats.rs | 7 ++- server/src/cmd.rs | 3 +- server/src/sys/wiring.rs | 5 +- server/src/sys/wiring/compute_outputs.rs | 57 +++++++++++++++++++++-- server/src/sys/wiring/dispatch_actions.rs | 28 ++++++++--- server/src/wiring.rs | 2 + 8 files changed, 97 insertions(+), 15 deletions(-) diff --git a/common/src/resources.rs b/common/src/resources.rs index 2ee998370c..13966a633c 100644 --- a/common/src/resources.rs +++ b/common/src/resources.rs @@ -1,3 +1,4 @@ +use crate::comp::Pos; use serde::{Deserialize, Serialize}; use specs::Entity; @@ -13,6 +14,9 @@ pub struct Time(pub f64); #[derive(Default)] pub struct DeltaTime(pub f32); +#[derive(Default)] +pub struct EntitiesDiedLastTick(pub Vec<(Entity, Pos)>); + /// A resource that indicates what mode the local game is being played in. #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub enum GameMode { diff --git a/common/state/src/state.rs b/common/state/src/state.rs index 236e5996cb..1e2c8af59e 100644 --- a/common/state/src/state.rs +++ b/common/state/src/state.rs @@ -9,7 +9,10 @@ use common::{ event::{EventBus, LocalEvent, ServerEvent}, outcome::Outcome, region::RegionMap, - resources::{DeltaTime, GameMode, PlayerEntity, PlayerPhysicsSettings, Time, TimeOfDay}, + resources::{ + DeltaTime, EntitiesDiedLastTick, GameMode, PlayerEntity, PlayerPhysicsSettings, Time, + TimeOfDay, + }, slowjob::SlowJobPool, terrain::{Block, TerrainChunk, TerrainGrid}, time::DayPeriod, @@ -208,6 +211,7 @@ impl State { ecs.insert(game_mode); ecs.insert(Vec::::new()); ecs.insert(common::CachedSpatialGrid::default()); + ecs.insert(EntitiesDiedLastTick::default()); let num_cpu = num_cpus::get() as u64; let slow_limit = (num_cpu / 2 + num_cpu / 4).max(1); diff --git a/common/systems/src/stats.rs b/common/systems/src/stats.rs index 18ef179826..4539978d62 100644 --- a/common/systems/src/stats.rs +++ b/common/systems/src/stats.rs @@ -7,7 +7,7 @@ use common::{ }, event::{EventBus, ServerEvent}, outcome::Outcome, - resources::{DeltaTime, Time}, + resources::{DeltaTime, EntitiesDiedLastTick, Time}, uid::Uid, }; use common_ecs::{Job, Origin, Phase, System}; @@ -45,6 +45,7 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Poise>, WriteStorage<'a, Energy>, WriteStorage<'a, Combo>, + Write<'a, EntitiesDiedLastTick>, Write<'a, Vec>, ); @@ -62,9 +63,11 @@ impl<'a> System<'a> for Sys { mut poises, mut energies, mut combos, + mut entities_died_last_tick, mut outcomes, ): Self::SystemData, ) { + entities_died_last_tick.0.clear(); let mut server_event_emitter = read_data.server_bus.emitter(); let dt = read_data.dt.0; @@ -98,6 +101,8 @@ impl<'a> System<'a> for Sys { if set_dead { let mut health = health.get_mut_unchecked(); + let cloned_entity = (entity, *pos); + entities_died_last_tick.0.push(cloned_entity); server_event_emitter.emit(ServerEvent::Destroy { entity, cause: health.last_change.1.cause, diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 20b5d05b6d..4213414b51 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1718,8 +1718,9 @@ fn handle_spawn_wiring( pos.0.x += 3.0; let mut outputs1 = HashMap::new(); - outputs1.insert(String::from("color"), wiring::OutputFormula::OnCollide { + outputs1.insert(String::from("color"), wiring::OutputFormula::OnDeath { value: 1.0, + radius: 30.0, }); let builder1 = server diff --git a/server/src/sys/wiring.rs b/server/src/sys/wiring.rs index 9049755000..0f0407e7e0 100644 --- a/server/src/sys/wiring.rs +++ b/server/src/sys/wiring.rs @@ -1,7 +1,8 @@ use crate::wiring::{Circuit, WiringElement}; use common::{ - comp::{LightEmitter, PhysicsState}, + comp::{LightEmitter, PhysicsState, Pos}, event::{EventBus, ServerEvent}, + resources::EntitiesDiedLastTick, }; use common_ecs::{Job, Origin, Phase, System}; use hashbrown::HashMap; @@ -23,8 +24,10 @@ pub struct WiringData<'a> { pub light_emitters: WriteStorage<'a, LightEmitter>, // maybe pub physics_states: ReadStorage<'a, PhysicsState>, // maybe + pub pos: ReadStorage<'a, Pos>, pub event_bus: Read<'a, EventBus>, + pub entities_died_last_tick: Read<'a, EntitiesDiedLastTick>, } /// This system is responsible for handling wiring (signals and wiring systems) diff --git a/server/src/sys/wiring/compute_outputs.rs b/server/src/sys/wiring/compute_outputs.rs index d4d8e44f01..3877776a03 100644 --- a/server/src/sys/wiring/compute_outputs.rs +++ b/server/src/sys/wiring/compute_outputs.rs @@ -1,8 +1,12 @@ use super::WiringData; use crate::wiring::OutputFormula; -use common::comp::PhysicsState; +use common::{ + comp::{PhysicsState, Pos}, + resources::EntitiesDiedLastTick, +}; use hashbrown::HashMap; -use specs::{join::Join, Entity}; +use rand_distr::num_traits::ToPrimitive; +use specs::{join::Join, Entity, Read}; use tracing::warn; pub fn compute_outputs(system_data: &WiringData) -> HashMap> { @@ -10,11 +14,18 @@ pub fn compute_outputs(system_data: &WiringData) -> HashMap HashMap HashMap, physics_state: Option<&PhysicsState>, + entities_died_last_tick: &Read, + pos: Option<&Pos>, ) -> (String, f32) { ( key.to_string(), - compute_output(output_formula, inputs, physics_state), + compute_output( + output_formula, + inputs, + physics_state, + entities_died_last_tick, + pos, + ), ) } +#[allow(clippy::too_many_arguments)] pub fn compute_output( output_formula: &OutputFormula, inputs: &HashMap, physics_state: Option<&PhysicsState>, + entities_died_last_tick: &Read, + pos: Option<&Pos>, ) -> f32 { match output_formula { OutputFormula::Constant { value } => *value, @@ -72,6 +97,9 @@ pub fn compute_output( warn!("Not implemented OutputFormula::OnInteract"); 0.0 }, + OutputFormula::OnDeath { value, radius } => { + output_formula_on_death(value, radius, entities_died_last_tick, pos) + }, } } @@ -83,3 +111,22 @@ fn output_formula_on_collide(value: &f32, physics_state: Option<&PhysicsState>) } 0.0 } + +fn output_formula_on_death( + value: &f32, + radius: &f32, + entities_died_last_tick: &Read, + pos: Option<&Pos>, +) -> f32 { + if let Some(pos_of_entity) = pos { + return *value + * entities_died_last_tick + .0 + .iter() + .filter(|(_, dead_pos)| pos_of_entity.0.distance(dead_pos.0) <= *radius) + .count() + .to_f32() + .unwrap_or(0.0); + } + 0.0 +} diff --git a/server/src/sys/wiring/dispatch_actions.rs b/server/src/sys/wiring/dispatch_actions.rs index 0518c83660..641275a006 100644 --- a/server/src/sys/wiring/dispatch_actions.rs +++ b/server/src/sys/wiring/dispatch_actions.rs @@ -3,12 +3,13 @@ use std::ops::DerefMut; use super::{compute_outputs::compute_output, WiringData}; use crate::wiring::{OutputFormula, WiringActionEffect}; use common::{ - comp::{object, Body, LightEmitter, PhysicsState, ProjectileConstructor}, + comp::{object, Body, LightEmitter, PhysicsState, Pos, ProjectileConstructor}, event::{Emitter, ServerEvent}, + resources::EntitiesDiedLastTick, util::Dir, }; use hashbrown::HashMap; -use specs::{join::Join, Entity}; +use specs::{join::Join, Entity, Read}; use tracing::warn; use vek::Rgb; @@ -19,6 +20,8 @@ pub fn dispatch_actions(system_data: &mut WiringData) { wiring_elements, physics_states, light_emitters, + entities_died_last_tick, + pos, .. } = system_data; let mut server_emitter = event_bus.emitter(); @@ -28,10 +31,11 @@ pub fn dispatch_actions(system_data: &mut WiringData) { wiring_elements, physics_states.maybe(), light_emitters.maybe(), + pos.maybe(), ) .join() .for_each( - |(entity, wiring_element, physics_state, mut light_emitter)| { + |(entity, wiring_element, physics_state, mut light_emitter, pos)| { wiring_element .actions .iter() @@ -40,6 +44,8 @@ pub fn dispatch_actions(system_data: &mut WiringData) { &wiring_action.formula, &wiring_element.inputs, physics_state, + entities_died_last_tick, + pos, ) >= wiring_action.threshold }) .for_each(|wiring_action| { @@ -50,12 +56,15 @@ pub fn dispatch_actions(system_data: &mut WiringData) { &mut server_emitter, &mut light_emitter, physics_state, + entities_died_last_tick, + pos, ); }) }, ) } +#[allow(clippy::too_many_arguments)] fn dispatch_action( entity: Entity, inputs: &HashMap, @@ -65,6 +74,8 @@ fn dispatch_action( light_emitter: &mut Option>, physics_state: Option<&PhysicsState>, + entities_died_last_tick: &Read, + pos: Option<&Pos>, ) { action_effects .iter() @@ -82,6 +93,8 @@ fn dispatch_action( b, &mut light_emitter.as_deref_mut(), physics_state, + entities_died_last_tick, + pos, ), }); } @@ -104,6 +117,7 @@ fn dispatch_action_spawn_projectile( }); } +#[allow(clippy::too_many_arguments)] fn dispatch_action_set_light( inputs: &HashMap, r: &OutputFormula, @@ -113,13 +127,15 @@ fn dispatch_action_set_light( light_emitter: &mut Option<&mut LightEmitter>, physics_state: Option<&PhysicsState>, + entities_died_last_tick: &Read, + pos: Option<&Pos>, ) { if let Some(light_emitter) = light_emitter { // TODO: make compute_output accept multiple formulas - let computed_r = compute_output(r, inputs, physics_state); - let computed_g = compute_output(g, inputs, physics_state); - let computed_b = compute_output(b, inputs, physics_state); + let computed_r = compute_output(r, inputs, physics_state, entities_died_last_tick, pos); + let computed_g = compute_output(g, inputs, physics_state, entities_died_last_tick, pos); + let computed_b = compute_output(b, inputs, physics_state, entities_died_last_tick, pos); light_emitter.col = Rgb::new(computed_r, computed_g, computed_b); } diff --git a/server/src/wiring.rs b/server/src/wiring.rs index 8b9cb38e10..755d9848ea 100644 --- a/server/src/wiring.rs +++ b/server/src/wiring.rs @@ -29,12 +29,14 @@ pub enum OutputFormula { SineWave { amplitude: f32, frequency: f32 }, OnCollide { value: f32 }, OnInteract { value: f32 }, + OnDeath { value: f32, radius: f32 }, } pub enum LogicKind { Min, // acts like And Max, // acts like Or Sub, // `|x| { 5.0 - x }` acts like Not, depending on reference voltages + Sum, } pub struct WiringAction {