added log! macro
This commit is contained in:
parent
86f9333aec
commit
b45d04b872
5 changed files with 140 additions and 522 deletions
166
src/log.rs
166
src/log.rs
|
|
@ -1,20 +1,18 @@
|
|||
use std::{collections::HashMap, sync::Mutex};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use bevy_ecs::{prelude::*, system::SystemParam};
|
||||
use macros::LogMessage;
|
||||
|
||||
use crate::{
|
||||
entity_registry::EntityRegistry,
|
||||
hierarchy::Children,
|
||||
player::{
|
||||
stats::{
|
||||
AdditiveBonus, BaselineStat, CritRate, DamageBonus, Defence, Dexterity, EffectiveStat,
|
||||
MultiplicativeBonus, SimpleStatBaseline, SimpleStatBonus, SimpleStatEffective,
|
||||
SimpleStatMarker, Speed, StatMarker, StatType, Strength, WeaponAccuracy,
|
||||
},
|
||||
Player,
|
||||
player::stats::{
|
||||
AdditiveBonus, BaselineStat, CritRate, DamageBonus, Defence, Dexterity, EffectiveStat,
|
||||
MultiplicativeBonus, SimpleStatBaseline, SimpleStatBonus, SimpleStatEffective,
|
||||
SimpleStatMarker, Speed, StatMarker, StatType, Strength, WeaponAccuracy,
|
||||
},
|
||||
weapon::{Weapon, WeaponVerb},
|
||||
Name, Stages,
|
||||
weapon::WeaponVerb,
|
||||
Stages,
|
||||
};
|
||||
|
||||
#[derive(Resource)]
|
||||
|
|
@ -49,6 +47,7 @@ pub enum LogValue<'a> {
|
|||
Unsigned(u32),
|
||||
Bool(bool),
|
||||
String(String),
|
||||
Entity(Entity),
|
||||
OptionNone,
|
||||
Display(&'a (dyn std::fmt::Display + Send + Sync)),
|
||||
Debug(&'a (dyn std::fmt::Debug + Send + Sync)),
|
||||
|
|
@ -86,6 +85,12 @@ impl From<bool> for LogValue<'static> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Entity> for LogValue<'static> {
|
||||
fn from(value: Entity) -> Self {
|
||||
Self::Entity(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> From<Option<T>> for LogValue<'a>
|
||||
where
|
||||
T: Into<LogValue<'a>>,
|
||||
|
|
@ -100,11 +105,7 @@ where
|
|||
|
||||
#[cfg(feature = "json")]
|
||||
impl<'a> LogValue<'a> {
|
||||
fn to_value(
|
||||
&self,
|
||||
player_registry: &HashMap<Entity, PlayerInfo>,
|
||||
weapon_registry: &HashMap<Entity, WeaponInfo>,
|
||||
) -> serde_json::Value {
|
||||
fn to_value(&self, entity_registry: &EntityRegistry) -> serde_json::Value {
|
||||
match self {
|
||||
LogValue::OptionNone => serde_json::Value::Null,
|
||||
LogValue::Float(val) => {
|
||||
|
|
@ -115,27 +116,20 @@ impl<'a> LogValue<'a> {
|
|||
LogValue::Unsigned(val) => serde_json::Value::Number(serde_json::Number::from(*val)),
|
||||
LogValue::Debug(boxed) => serde_json::Value::String(format!("{boxed:?}")),
|
||||
LogValue::Display(boxed) => serde_json::Value::String(format!("{boxed}")),
|
||||
LogValue::Player(id) => serde_json::json!({
|
||||
"type": "player",
|
||||
"name": player_registry.get(id).unwrap().name,
|
||||
}),
|
||||
LogValue::Weapon(id) => serde_json::json!({
|
||||
"type": "weapon",
|
||||
"name": weapon_registry.get(id).unwrap().name,
|
||||
}),
|
||||
LogValue::Player(id) => {
|
||||
serde_json::to_value(entity_registry.0.get(id).unwrap()).unwrap()
|
||||
}
|
||||
LogValue::Weapon(id) => {
|
||||
serde_json::to_value(entity_registry.0.get(id).unwrap()).unwrap()
|
||||
}
|
||||
LogValue::Entity(id) => {
|
||||
serde_json::to_value(entity_registry.0.get(id).unwrap()).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LogMessage: Send + Sync + 'static {
|
||||
fn torn_style(
|
||||
&self,
|
||||
_player_registry: HashMap<Entity, PlayerInfo>,
|
||||
_weapon_registry: HashMap<Entity, WeaponInfo>,
|
||||
) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn tag(&self) -> &'static str;
|
||||
|
||||
fn entries(&self) -> Vec<(&'static str, LogValue<'_>)>;
|
||||
|
|
@ -143,9 +137,6 @@ pub trait LogMessage: Send + Sync + 'static {
|
|||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct Log {
|
||||
pub player_registry: HashMap<Entity, PlayerInfo>,
|
||||
pub weapon_registry: HashMap<Entity, WeaponInfo>,
|
||||
|
||||
pub entries: Vec<Box<dyn LogMessage>>,
|
||||
|
||||
pub expanded: bool,
|
||||
|
|
@ -153,7 +144,7 @@ pub struct Log {
|
|||
|
||||
impl Log {
|
||||
#[cfg(feature = "json")]
|
||||
pub fn to_value(&self) -> serde_json::Value {
|
||||
pub fn to_value(&self, entity_registry: &EntityRegistry) -> serde_json::Value {
|
||||
use serde_json::json;
|
||||
|
||||
serde_json::json!({
|
||||
|
|
@ -161,7 +152,7 @@ impl Log {
|
|||
json!({
|
||||
"type": e.tag(),
|
||||
"values": serde_json::Value::Object(
|
||||
e.entries().iter().map(|e| (e.0.to_owned(), e.1.to_value(&self.player_registry, &self.weapon_registry))).collect()
|
||||
e.entries().iter().map(|e| (e.0.to_owned(), e.1.to_value(entity_registry))).collect()
|
||||
)
|
||||
})
|
||||
).collect::<Vec<_>>()
|
||||
|
|
@ -190,11 +181,8 @@ impl std::fmt::Display for Log {
|
|||
LogValue::OptionNone => write!(f, "None")?,
|
||||
LogValue::Display(val) => write!(f, "\"{val}\"")?,
|
||||
LogValue::Debug(val) => write!(f, "\"{val:?}\"")?,
|
||||
LogValue::Player(id) => {
|
||||
write!(f, "\"{}\"", self.player_registry.get(&id).unwrap().name)?
|
||||
}
|
||||
LogValue::Weapon(id) => {
|
||||
write!(f, "\"{}\"", self.weapon_registry.get(&id).unwrap().name)?
|
||||
LogValue::Player(id) | LogValue::Weapon(id) | LogValue::Entity(id) => {
|
||||
write!(f, "{:?}", id)?
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -418,31 +406,6 @@ fn logging_enabled(logging: Res<Logging>) -> bool {
|
|||
logging.0
|
||||
}
|
||||
|
||||
fn register_entities(
|
||||
player_q: Query<(Entity, &Name), With<Player>>,
|
||||
weapon_q: Query<(Entity, &Name, &WeaponVerb), With<Weapon>>,
|
||||
mut log: ResMut<Log>,
|
||||
) {
|
||||
for (player, name) in player_q.iter() {
|
||||
log.player_registry.insert(
|
||||
player,
|
||||
PlayerInfo {
|
||||
name: name.0.clone(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for (weapon, name, verb) in weapon_q.iter() {
|
||||
log.weapon_registry.insert(
|
||||
weapon,
|
||||
WeaponInfo {
|
||||
name: name.0.clone(),
|
||||
verb: *verb,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn append_log_messages(mut events: EventReader<LogEvent>, mut log: ResMut<Log>) {
|
||||
for event in events.read() {
|
||||
log.entries.push(event.0.lock().unwrap().take().unwrap());
|
||||
|
|
@ -541,13 +504,59 @@ fn log_simple_stat_changes<Stat: SimpleStatMarker>(
|
|||
}
|
||||
}
|
||||
|
||||
pub struct DynamicLogMessage {
|
||||
pub label: &'static str,
|
||||
pub entries: Vec<(&'static str, LogValue<'static>)>,
|
||||
}
|
||||
|
||||
impl LogMessage for DynamicLogMessage {
|
||||
fn tag(&self) -> &'static str {
|
||||
self.label
|
||||
}
|
||||
|
||||
fn entries(&self) -> Vec<(&'static str, LogValue<'_>)> {
|
||||
self.entries.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log {
|
||||
($logger:expr, $tag:literal, { $($fields:tt)* }) => {
|
||||
$logger.log(|| $crate::log_message!($tag, { $($fields)* }))
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_message {
|
||||
($tag:literal, { $($fields:tt)* }) => {
|
||||
$crate::log::DynamicLogMessage { label: $tag, entries: $crate::log_values!($($fields)*) }
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_values {
|
||||
(@ { $(,)* $($out:expr),* $(,)* } $(,)*) => {
|
||||
vec![$($out),*]
|
||||
};
|
||||
(@ { $(,)* $($out:expr),* } $label:ident: $val:expr, $($rest:tt)*) => {
|
||||
$crate::log_values!(@ { $($out),*, (stringify!($label),$val.into()) } $($rest)*)
|
||||
};
|
||||
(@ { $(,)* $($out:expr),* } $label:ident: ?$val:expr, $($rest:tt)*) => {
|
||||
$crate::log_values!(@ { $($out),*, (stringify!($label),$crate::log::LogValue::String(format!("{:?}",$val))) } $($rest)*)
|
||||
};
|
||||
(@ { $(,)* $($out:expr),* } $label:ident: %$val:expr, $($rest:tt)*) => {
|
||||
$crate::log_values!(@ { $($out),*, (stringify!($label),$crate::log::LogValue::String(format!("{}",$val))) } $($rest)*)
|
||||
};
|
||||
|
||||
($($args:tt)* ) => {
|
||||
$crate::log_values!(@ { } $($args)*,)
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn configure(stages: &mut Stages) {
|
||||
stages.world.insert_resource(Log::default());
|
||||
stages.world.insert_resource(Logging(false));
|
||||
stages.add_event::<LogEvent>();
|
||||
stages
|
||||
.equip
|
||||
.add_systems(register_entities.run_if(logging_enabled));
|
||||
|
||||
stages.post_turn.add_systems(append_log_messages);
|
||||
stages.turn.add_systems(
|
||||
|
|
@ -563,3 +572,22 @@ pub(crate) fn configure(stages: &mut Stages) {
|
|||
.run_if(logging_enabled),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn log_keys() {
|
||||
let message = log_message!("test", { foo: 12u32, bar: ?17 });
|
||||
|
||||
assert_eq!(message.label, "test");
|
||||
let mut entries = message.entries.into_iter();
|
||||
|
||||
let next = entries.next();
|
||||
assert!(matches!(next, Some(("foo", LogValue::Unsigned(12)))));
|
||||
|
||||
let next = entries.next();
|
||||
assert!(matches!(next, Some(("bar", LogValue::String(val))) if val == "17"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue