This commit is contained in:
TotallyNot 2025-11-03 16:36:45 +01:00
parent e7d6b74aab
commit 35413b563c
Signed by: pyrite
GPG key ID: 7F1BA9170CD35D15
33 changed files with 10238 additions and 1891 deletions

View file

@ -1,32 +1,29 @@
#![warn(clippy::perf, clippy::style, clippy::all)]
#![allow(clippy::type_complexity)]
use bevy_ecs::{prelude::*, schedule::ScheduleLabel};
use bevy_ecs::{message::MessageRegistry, prelude::*, schedule::ScheduleLabel};
use effect::{register_effect, EffectBuilder};
use metrics::Metrics;
use proxisim_models::{
bundle::player::{Attacker, Current, Defender},
dto::{
metrics::{Counter, Histogram},
player::PlayerDto,
},
};
use rand::SeedableRng;
use crate::{
log::{Log, Logging},
player::{Attacker, Current, Defender},
};
use crate::log::{Log, Logging};
mod armour;
pub mod dto;
mod effect;
mod entity_registry;
mod hierarchy;
// mod hierarchy;
pub mod log;
mod metrics;
mod passives;
mod player;
mod weapon;
#[derive(Component, Debug, Default)]
struct Name(String);
#[derive(Component, Debug, Default)]
struct Id(usize);
// TODO: This is a bottleneck, so probably better to change this to a `Local` or use `thread_rng`
// instead. Then again, the whole simulator isn't very parallelisable, so it may be a moot point
#[derive(Resource)]
@ -79,19 +76,20 @@ struct Stages {
impl Stages {
fn add_event<T>(&mut self) -> &mut Self
where
T: Event,
T: Message,
{
if !self.world.contains_resource::<Events<T>>() {
self.world.init_resource::<Events<T>>();
if !self.world.contains_resource::<Messages<T>>() {
/* self.world.init_resource::<Messages<T>>();
self.pre_turn.add_systems(
bevy_ecs::event::event_update_system::<T>
.run_if(bevy_ecs::event::event_update_condition::<T>),
);
); */
MessageRegistry::register_message::<T>(&mut self.world);
}
self
}
fn register_effect<Effect: 'static>(&mut self) -> EffectBuilder {
fn register_effect<Effect: 'static>(&mut self) -> EffectBuilder<'_> {
register_effect::<Effect>(self)
}
}
@ -99,7 +97,7 @@ impl Stages {
pub struct Simulation(Stages);
impl Simulation {
pub fn new(attacker: dto::Player, defender: dto::Player) -> Self {
pub fn new(attacker: PlayerDto, defender: PlayerDto) -> Self {
let world = World::new();
let mut stages = Stages {
equip: Schedule::new(Stage::Equip),
@ -125,7 +123,7 @@ impl Simulation {
stages.world.insert_resource(FightStatus::Ongoing);
stages
.world
.insert_resource(Rng(rand::rngs::SmallRng::from_entropy()));
.insert_resource(Rng(rand::rngs::SmallRng::from_os_rng()));
stages.world.insert_resource(Logging(true));
@ -157,17 +155,17 @@ impl Simulation {
metrics.active = recording;
}
pub fn consume_metrics(&mut self) -> (Vec<dto::Counter>, Vec<dto::Histogram>) {
pub fn consume_metrics(&mut self) -> (Vec<Counter>, Vec<Histogram>) {
let entities = self.0.world.entities().len();
let components = self.0.world.components().len();
self.0
.world
.resource::<metrics::Metrics>()
.increment_counter(Entity::from_raw(0), "entities", entities.into());
.increment_counter(None, "entities", entities.into());
self.0
.world
.resource::<metrics::Metrics>()
.increment_counter(Entity::from_raw(0), "components", components as u64);
.increment_counter(None, "components", components as u64);
metrics::consume_metrics(&self.0.world)
}
@ -333,110 +331,12 @@ impl Simulation {
mod tests {
use super::*;
fn attacker() -> dto::Player {
use dto::*;
Player {
name: "Test".to_owned(),
id: 0,
level: 10,
stats: Stats {
str: 10_000.0,
def: 10.0,
spd: 10.0,
dex: 10.0,
},
merits: Default::default(),
education: Default::default(),
faction: Default::default(),
drug: None,
strategy: PlayerStrategy::AlwaysFists,
weapons: Weapons {
primary: Some(Weapon {
name: "Test".to_owned(),
cat: WeaponCategory::Rifle,
dmg: 50.0,
acc: 50.0,
ammo: WeaponAmmo {
clips: 3,
clip_size: 25,
rate_of_fire: [3, 5],
},
mods: vec![WeaponMod::HairTrigger],
bonuses: vec![WeaponBonusInfo {
bonus: WeaponBonus::Expose,
value: 9.0,
}],
experience: 100.0,
}),
..Default::default()
},
armour: ArmourPieces {
helmet: Some(Armour {
name: "Test".to_owned(),
armour_value: 50.0,
coverage: [
100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0,
],
immunities: Vec::default(),
set: None,
}),
..Default::default()
},
}
fn attacker() -> PlayerDto {
serde_json::from_str(include_str!("./attacker.json")).unwrap()
}
fn defender() -> dto::Player {
use dto::*;
Player {
name: "Test".to_owned(),
id: 1,
level: 10,
stats: Stats {
str: 10_000.0,
def: 10.0,
spd: 10.0,
dex: 10.0,
},
merits: Default::default(),
education: Default::default(),
faction: Default::default(),
drug: None,
strategy: PlayerStrategy::AlwaysFists,
weapons: Weapons {
primary: Some(Weapon {
name: "Test".to_owned(),
cat: WeaponCategory::Rifle,
dmg: 50.0,
acc: 50.0,
ammo: WeaponAmmo {
clips: 3,
clip_size: 25,
rate_of_fire: [3, 5],
},
mods: Vec::default(),
bonuses: vec![WeaponBonusInfo {
bonus: WeaponBonus::Powerful,
value: 35.0,
}],
experience: 100.0,
}),
..Default::default()
},
armour: ArmourPieces {
helmet: Some(Armour {
name: "Test".to_owned(),
armour_value: 50.0,
coverage: [
100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0,
],
immunities: Vec::default(),
set: None,
}),
..Default::default()
},
}
fn defender() -> PlayerDto {
serde_json::from_str(include_str!("./defender.json")).unwrap()
}
#[test]
@ -450,6 +350,5 @@ mod tests {
sim.set_metrics(true);
sim.run_once();
sim.consume_metrics();
panic!();
}
}