Skip to content

Commit 92be6bc

Browse files
feat: Hyperion is now a module (#736)
- allows for easier testing of ECS
1 parent d2ac22e commit 92be6bc

File tree

6 files changed

+74
-54
lines changed

6 files changed

+74
-54
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hyperion/src/common/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Defined the [`Global`] struct which is used to store global data which defines a [`crate::Hyperion`]
1+
//! Defined the [`Global`] struct which is used to store global data which defines a [`crate::HyperionCore`]
22
use std::{
33
sync::{Arc, atomic::AtomicUsize},
44
time::Duration,

crates/hyperion/src/lib.rs

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ use std::{
3232
cell::RefCell,
3333
fmt::Debug,
3434
io::Write,
35-
net::ToSocketAddrs,
35+
net::{SocketAddr, ToSocketAddrs},
3636
sync::{Arc, atomic::AtomicBool},
3737
};
3838

39-
use anyhow::{Context, bail};
40-
use derive_more::{Deref, DerefMut};
39+
use anyhow::Context;
40+
use derive_more::{Constructor, Deref, DerefMut};
4141
use egress::EgressModule;
4242
use flecs_ecs::prelude::*;
4343
pub use glam;
44-
use glam::IVec2;
44+
use glam::{I16Vec2, IVec2};
4545
use ingress::IngressModule;
4646
#[cfg(unix)]
4747
use libc::{RLIMIT_NOFILE, getrlimit, setrlimit};
@@ -69,7 +69,6 @@ use crate::{
6969
mod common;
7070
pub use common::*;
7171
use hyperion_crafting::CraftingRegistry;
72-
use system_order::SystemOrderModule;
7372
pub use valence_ident;
7473

7574
use crate::{
@@ -142,27 +141,55 @@ pub fn adjust_file_descriptor_limits(recommended_min: u64) -> std::io::Result<()
142141
Ok(())
143142
}
144143

145-
/// The central [`Hyperion`] struct which owns and manages the entire server.
146-
pub struct Hyperion;
144+
#[derive(Component, Debug, Clone, PartialEq, Eq, Hash, Constructor)]
145+
pub struct Address(SocketAddr);
146+
147+
#[derive(Component)]
148+
pub struct AddressModule;
149+
150+
impl Module for AddressModule {
151+
fn module(world: &World) {
152+
world.component::<Address>();
153+
}
154+
}
155+
156+
/// The central [`HyperionCore`] struct which owns and manages the entire server.
157+
#[derive(Component)]
158+
pub struct HyperionCore;
147159

148160
#[derive(Component)]
149161
struct Shutdown {
150162
value: Arc<AtomicBool>,
151163
}
152164

153-
impl Hyperion {
154-
/// Initializes the server.
155-
pub fn init(address: impl ToSocketAddrs + Send + Sync + 'static) -> anyhow::Result<()> {
156-
Self::init_with(address, |_| {})
165+
impl Module for HyperionCore {
166+
fn module(world: &World) {
167+
let address = world.get::<&Address>(|address| address.0);
168+
Self::init_with(world, address).unwrap();
157169
}
170+
}
158171

172+
impl HyperionCore {
159173
/// Initializes the server with a custom handler.
160-
pub fn init_with(
174+
fn init_with(
175+
world: &World,
161176
address: impl ToSocketAddrs + Send + Sync + 'static,
162-
handlers: impl FnOnce(&World) + Send + Sync + 'static,
163177
) -> anyhow::Result<()> {
164178
// Denormals (numbers very close to 0) are flushed to zero because doing computations on them
165179
// is slow.
180+
181+
no_denormals::no_denormals(|| Self::init_with_helper(world, address))
182+
}
183+
184+
/// Initialize the server.
185+
fn init_with_helper(
186+
world: &World,
187+
address: impl ToSocketAddrs + Send + Sync + 'static,
188+
) -> anyhow::Result<()> {
189+
// 10k players * 2 file handles / player = 20,000. We can probably get away with 16,384 file handles
190+
#[cfg(unix)]
191+
adjust_file_descriptor_limits(32_768).context("failed to set file limits")?;
192+
166193
rayon::ThreadPoolBuilder::new()
167194
.num_threads(NUM_THREADS)
168195
.spawn_handler(|thread| {
@@ -179,38 +206,12 @@ impl Hyperion {
179206
.build_global()
180207
.context("failed to build thread pool")?;
181208

182-
no_denormals::no_denormals(|| Self::init_with_helper(address, handlers))
183-
}
184-
185-
/// Initialize the server.
186-
fn init_with_helper(
187-
address: impl ToSocketAddrs + Send + Sync + 'static,
188-
handlers: impl FnOnce(&World) + Send + Sync + 'static,
189-
) -> anyhow::Result<()> {
190-
// 10k players * 2 file handles / player = 20,000. We can probably get away with 16,384 file handles
191-
#[cfg(unix)]
192-
adjust_file_descriptor_limits(32_768).context("failed to set file limits")?;
193-
194209
let shared = Arc::new(Shared {
195210
compression_threshold: CompressionThreshold(256),
196211
compression_level: CompressionLvl::new(2)
197212
.map_err(|_| anyhow::anyhow!("failed to create compression level"))?,
198213
});
199214

200-
let world = World::new();
201-
202-
let world = Box::new(world);
203-
let world: &World = Box::leak(world);
204-
205-
let mut app = world.app();
206-
207-
app.enable_rest(0)
208-
.enable_stats(true)
209-
.set_threads(i32::try_from(rayon::current_num_threads())?)
210-
.set_target_fps(20.0);
211-
212-
world.set_threads(i32::try_from(rayon::current_num_threads())?);
213-
214215
let address = address
215216
.to_socket_addrs()?
216217
.next()
@@ -234,6 +235,8 @@ impl Hyperion {
234235
// .bit("glowing", *EntityFlags::GLOWING)
235236
// .bit("flying_with_elytra", *EntityFlags::FLYING_WITH_ELYTRA);
236237

238+
component!(world, I16Vec2 { x: i16, y: i16 });
239+
237240
component!(world, IVec2 { x: i32, y: i32 });
238241
world.component::<PendingRemove>();
239242

@@ -350,6 +353,15 @@ impl Hyperion {
350353
world.set(runtime);
351354
world.set(StreamLookup::default());
352355

356+
world.set_threads(i32::try_from(rayon::current_num_threads())?);
357+
358+
let mut app = world.app();
359+
360+
app.enable_rest(0)
361+
.enable_stats(true)
362+
.set_threads(i32::try_from(rayon::current_num_threads())?)
363+
.set_target_fps(20.0);
364+
353365
world.import::<SimModule>();
354366
world.import::<EgressModule>();
355367
world.import::<IngressModule>();
@@ -377,14 +389,7 @@ impl Hyperion {
377389

378390
world.set(IgnMap::default());
379391

380-
handlers(world);
381-
382-
// must be init last
383-
world.import::<SystemOrderModule>();
384-
385-
app.run();
386-
387-
bail!("app exited");
392+
Ok(())
388393
}
389394
}
390395

events/tag/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ rayon = { workspace = true }
2222
roaring = { workspace = true }
2323
rustc-hash = { workspace = true }
2424
spatial = { workspace = true }
25+
system-order = { workspace = true }
2526
tracing = { workspace = true }
2627
tracing-subscriber = { workspace = true }
2728
tracing-tracy = { workspace = true }

events/tag/src/lib.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
#![feature(stmt_expr_attributes)]
44
#![feature(exact_size_is_empty)]
55

6-
use std::{collections::HashSet, net::ToSocketAddrs};
6+
use std::{collections::HashSet, net::SocketAddr};
77

88
use flecs_ecs::prelude::*;
99
use hyperion::{
10-
Hyperion,
10+
Address, AddressModule, HyperionCore,
1111
runtime::AsyncRuntime,
1212
simulation::{Player, blocks::Blocks},
1313
};
@@ -24,6 +24,7 @@ use hyperion::{
2424
use hyperion_rank_tree::Team;
2525
use module::{attack::AttackModule, level::LevelModule, regeneration::RegenerationModule};
2626
use spatial::SpatialIndex;
27+
use system_order::SystemOrderModule;
2728
use tracing::debug;
2829

2930
use crate::{
@@ -157,10 +158,19 @@ impl Module for TagModule {
157158
}
158159
}
159160

160-
pub fn init_game(address: impl ToSocketAddrs + Send + Sync + 'static) -> anyhow::Result<()> {
161-
Hyperion::init_with(address, |world| {
162-
world.import::<TagModule>();
163-
})?;
161+
pub fn init_game(address: SocketAddr) -> anyhow::Result<()> {
162+
let world = World::new();
163+
164+
world.import::<AddressModule>();
165+
world.set(Address::new(address));
166+
167+
world.import::<HyperionCore>();
168+
world.import::<TagModule>();
169+
170+
// must be init last
171+
world.import::<SystemOrderModule>();
172+
173+
world.app().run();
164174

165175
Ok(())
166176
}

events/tag/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::net::SocketAddr;
2+
13
use clap::Parser;
24
use tag::init_game;
35
use tracing_subscriber::{EnvFilter, Registry, layer::SubscriberExt};
@@ -42,6 +44,7 @@ fn main() {
4244
let Args { ip, port } = Args::parse();
4345

4446
let address = format!("{ip}:{port}");
47+
let address = address.parse::<SocketAddr>().unwrap();
4548

4649
init_game(address).unwrap();
4750
}

0 commit comments

Comments
 (0)