1use bevy::prelude::*;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use std::collections::HashMap;
5
6#[derive(Clone, Debug, Serialize, Deserialize, Event, Message)]
8pub struct FleetEvent {
9 pub event_type: String,
10 pub data: HashMap<String, String>,
11 pub timestamp: u64,
12}
13
14impl FleetEvent {
15 pub fn new(event_type: impl Into<String>) -> Self {
16 Self {
17 event_type: event_type.into(),
18 data: HashMap::new(),
19 timestamp: current_unix_time_secs(),
20 }
21 }
22
23 pub fn with_data(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
24 self.data.insert(key.into(), value.into());
25 self
26 }
27}
28
29#[derive(Default, Resource)]
31pub struct FleetEventBuffer {
32 events: Vec<FleetEvent>,
33}
34
35impl FleetEventBuffer {
36 pub fn extend<I>(&mut self, iter: I)
37 where
38 I: IntoIterator<Item = FleetEvent>,
39 {
40 self.events.extend(iter);
41 }
42
43 pub fn take(&mut self) -> Vec<FleetEvent> {
44 std::mem::take(&mut self.events)
45 }
46}
47
48pub fn forward_serialized_events<T>(
50 mut reader: MessageReader<T>,
51 mut fleet_writer: MessageWriter<FleetEvent>,
52) where
53 T: Message + Serialize + Clone + Send + Sync + 'static,
54{
55 for event in reader.read() {
56 let event_type = std::any::type_name::<T>().to_string();
57
58 let (serialized_value, serialization_error) = match serde_json::to_value(event) {
59 Ok(value) => (value, None),
60 Err(err) => (Value::Null, Some(err.to_string())),
61 };
62
63 let mut fleet_event = FleetEvent::new(event_type.clone());
64
65 match &serialized_value {
66 Value::Object(map) => {
67 for (key, value) in map {
68 fleet_event.data.insert(key.clone(), value_to_string(value));
69 }
70 }
71 Value::Null => {}
72 other => {
73 fleet_event
74 .data
75 .insert("value".to_string(), value_to_string(other));
76 }
77 }
78
79 if let Some(err) = &serialization_error {
80 fleet_event
81 .data
82 .insert("serialization_error".to_string(), err.clone());
83 }
84
85 fleet_writer.write(fleet_event);
86 }
87}
88
89pub fn collect_fleet_events(
91 mut reader: MessageReader<FleetEvent>,
92 mut buffer: ResMut<FleetEventBuffer>,
93) {
94 let new_events: Vec<FleetEvent> = reader.read().cloned().collect();
95 if !new_events.is_empty() {
96 buffer.extend(new_events);
97 }
98}
99
100fn current_unix_time_secs() -> u64 {
101 std::time::SystemTime::now()
102 .duration_since(std::time::UNIX_EPOCH)
103 .unwrap_or_default()
104 .as_secs()
105}
106
107fn value_to_string(value: &Value) -> String {
108 match value {
109 Value::String(s) => s.clone(),
110 Value::Null => "null".to_string(),
111 other => other.to_string(),
112 }
113}