diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..ab1f416
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..03d9549
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..ca74eb7
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/prettier.xml b/.idea/prettier.xml
new file mode 100644
index 0000000..b0c1c68
--- /dev/null
+++ b/.idea/prettier.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/quic_ecs_dt.iml b/.idea/quic_ecs_dt.iml
new file mode 100644
index 0000000..0df299e
--- /dev/null
+++ b/.idea/quic_ecs_dt.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index c4fffb5..3a6c616 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,30 @@
[workspace]
resolver = "3"
members = ["simulator", "substrate"]
+
+# Enable a small amount of optimization in the dev profile.
+[profile.dev]
+opt-level = 1
+
+# Enable a large amount of optimization in the dev profile for dependencies.
+[profile.dev.package."*"]
+opt-level = 3
+
+# Enable more optimization in the release profile at the cost of compile time.
+[profile.release]
+# Compile the entire crate as one unit.
+# Slows compile times, marginal improvements.
+codegen-units = 1
+# Do a second optimization pass over the entire program, including dependencies.
+# Slows compile times, marginal improvements.
+lto = "thin"
+
+# Optimize for size in the wasm-release profile to reduce load times and bandwidth usage on web.
+[profile.wasm-release]
+# Default to release profile values.
+inherits = "release"
+# Optimize with size in mind (also try "z", sometimes it is better).
+# Slightly slows compile times, great improvements to file size and runtime performance.
+opt-level = "s"
+# Strip all debugging information from the binary to slightly reduce file size.
+strip = "debuginfo"
diff --git a/simulator/Cargo.toml b/simulator/Cargo.toml
index 85d985e..7b9d63e 100644
--- a/simulator/Cargo.toml
+++ b/simulator/Cargo.toml
@@ -4,3 +4,7 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+thiserror = "2"
+anyhow = "1"
+bevy = "0.18"
+game_sockets = { git = "https://github.com/VALERE91/game_sockets.git"}
\ No newline at end of file
diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml
index 00f83c3..25a5860 100644
--- a/substrate/Cargo.toml
+++ b/substrate/Cargo.toml
@@ -4,3 +4,13 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+bevy = "0.18"
+thiserror = "2"
+anyhow = "1"
+tracing-subscriber = "0.3"
+quinn = { version = "0.11" }
+rustls = { version = "0.23" }
+tokio = { version = "1", features = ["full"] }
+uuid = { version = "1.23", features = ["v4"] }
+figment = { version = "0.10", features = ["toml", "env"] }
+serde = { version = "1", features = ["derive"] }
\ No newline at end of file
diff --git a/substrate/src/config.rs b/substrate/src/config.rs
new file mode 100644
index 0000000..718f5e0
--- /dev/null
+++ b/substrate/src/config.rs
@@ -0,0 +1,49 @@
+use bevy::prelude::Resource;
+use figment::Figment;
+use figment::providers::{Env, Format, Serialized, Toml};
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Resource, Serialize, Deserialize)]
+pub struct AppConfig {
+ pub network: QuicConfig,
+ pub simulation: SimulationConfig,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct SimulationConfig {
+ pub tick_rate_hz: u32,
+ pub max_entities: usize,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct QuicConfig {
+ pub server_port: u16,
+ pub server_interface: String,
+ pub server_cert: String,
+}
+
+impl Default for AppConfig {
+ fn default() -> Self {
+ Self {
+ network : QuicConfig {
+ server_port: 9000,
+ server_interface: "0.0.0.0".to_string(),
+ server_cert: "cert.pem".to_string(),
+ },
+ simulation: SimulationConfig {
+ tick_rate_hz: 60,
+ max_entities: 10000,
+ },
+ }
+ }
+}
+
+impl AppConfig {
+ pub fn load(config_file: &str) -> Result {
+ Figment::new()
+ .merge(Serialized::defaults(Self::default())) // compiled-in defaults
+ .merge(Toml::file(config_file)) // config file
+ .merge(Env::prefixed("APP_")) // env overrides, e.g. APP_NETWORK__PORT=9000
+ .extract()
+ }
+}
\ No newline at end of file
diff --git a/substrate/src/main.rs b/substrate/src/main.rs
index e7a11a9..170faa1 100644
--- a/substrate/src/main.rs
+++ b/substrate/src/main.rs
@@ -1,3 +1,17 @@
+mod transport;
+mod config;
+
+use std::sync::Arc;
+use bevy::prelude::*;
+use crate::config::AppConfig;
+
fn main() {
- println!("Hello, world!");
-}
+ let config = AppConfig::load("config.toml").expect("Failed to load config");
+ println!("{:?}", config);
+
+ App::new()
+ .insert_resource(config)
+ .add_plugins(MinimalPlugins)
+ .add_plugins(transport::ecs::EcsQuicTransportPlugin{})
+ .run();
+}
\ No newline at end of file
diff --git a/substrate/src/transport/ecs.rs b/substrate/src/transport/ecs.rs
new file mode 100644
index 0000000..e3e40ce
--- /dev/null
+++ b/substrate/src/transport/ecs.rs
@@ -0,0 +1,69 @@
+use std::sync::{Arc, Mutex};
+use bevy::prelude::*;
+use tokio::sync::mpsc;
+use crate::config::QuicConfig;
+use crate::transport::QuicMessage;
+use crate::transport::server::run_substrate_server;
+
+const T1_CAPACITY: usize = 1024;
+const T2_CAPACITY: usize = 512;
+const T3_CAPACITY: usize = 256;
+
+pub struct EcsQuicTransportPlugin{}
+
+#[derive(Resource)]
+struct BridgeReceivers {
+ t1: Mutex>,
+ t2: Mutex>,
+ t3: Mutex>,
+}
+
+fn ingest_system(bridge: Res){
+ let mut t1 = bridge.t1.lock().unwrap();
+ // Tier 1: drain up to N messages, drop the rest
+ for _ in 0..T1_CAPACITY {
+ match t1.try_recv() {
+ Ok(msg) => { /* write RawSensorData */ }
+ Err(_) => break,
+ }
+ }
+
+ // T2/T3: drain completely, these are low volume
+ let mut t2 = bridge.t2.lock().unwrap();
+ while let Ok(msg) = t2.try_recv() { /* ... */ }
+
+ let mut t3 = bridge.t3.lock().unwrap();
+ while let Ok(msg) = t3.try_recv() { /* ... */ }
+}
+
+impl Plugin for EcsQuicTransportPlugin{
+ fn build(&self, app: &mut App) {
+ // Create the channels for multi-thread communication
+ let (t1_tx, t1_rx) =
+ mpsc::channel::(T1_CAPACITY);
+ let (t2_tx, t2_rx) =
+ mpsc::channel::(T2_CAPACITY);
+ let (t3_tx, t3_rx) =
+ mpsc::channel::(T3_CAPACITY);
+
+ let quic_handle = std::thread::spawn(move || {
+ let rt = tokio::runtime::Builder::new_multi_thread()
+ .worker_threads(2)
+ .enable_all()
+ .build()
+ .unwrap();
+
+ rt.block_on(async move {
+ run_substrate_server(t1_tx, t2_tx, t3_tx).await;
+ });
+ });
+
+ app.insert_resource(BridgeReceivers {
+ t1: Mutex::new(t1_rx),
+ t2: Mutex::new(t2_rx),
+ t3: Mutex::new(t3_rx),
+ });
+
+ app.add_systems(PreUpdate, ingest_system);
+ }
+}
\ No newline at end of file
diff --git a/substrate/src/transport/mod.rs b/substrate/src/transport/mod.rs
new file mode 100644
index 0000000..090b820
--- /dev/null
+++ b/substrate/src/transport/mod.rs
@@ -0,0 +1,11 @@
+pub mod ecs;
+mod server;
+
+#[derive(Debug, Clone, Default, Copy, PartialEq)]
+pub struct QuicMessage{
+ pub device_id: uuid::Uuid,
+ pub data_stream_id: u16,
+ pub raw_value: f64,
+ pub timestamp_us: u64,
+ pub sequence_number: u32,
+}
\ No newline at end of file
diff --git a/substrate/src/transport/server.rs b/substrate/src/transport/server.rs
new file mode 100644
index 0000000..99d000f
--- /dev/null
+++ b/substrate/src/transport/server.rs
@@ -0,0 +1,8 @@
+use tokio::sync::mpsc::Sender;
+use crate::transport::QuicMessage;
+
+pub async fn run_substrate_server(t1_tx: Sender,
+ t2_tx: Sender,
+ t3_tx: Sender) {
+
+}
\ No newline at end of file