Only construct specs::Dispatcher once

* use version of shred that has an added SendDispatcher so we can
  construct the dispatcher and send it between threads (only State to
  remain sendable)
* move closure for adding systems from State::tick to the creation
  functions
* this does mean some voxygen systems always run instead of just in the
  session state, but that should not cause issues and we can always
  configure them to do nothing if needed
This commit is contained in:
Imbris 2024-01-02 23:38:31 -05:00
parent 35fc92f872
commit 6c6b9181a5
30 changed files with 177 additions and 125 deletions

93
Cargo.lock generated
View File

@ -58,14 +58,15 @@ dependencies = [
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.8.3" version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"getrandom 0.2.10", "getrandom 0.2.10",
"once_cell", "once_cell",
"version_check", "version_check",
"zerocopy",
] ]
[[package]] [[package]]
@ -320,7 +321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f00425f4c1f3349b35daf0a73477249f6574fe89f4b9d76aca0b2a1356886b3b" checksum = "f00425f4c1f3349b35daf0a73477249f6574fe89f4b9d76aca0b2a1356886b3b"
dependencies = [ dependencies = [
"ab_glyph", "ab_glyph",
"ahash 0.8.3", "ahash 0.8.7",
"bincode", "bincode",
"crossbeam-channel", "crossbeam-channel",
"log", "log",
@ -350,7 +351,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -655,7 +656,7 @@ checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -872,7 +873,7 @@ dependencies = [
"heck 0.4.1", "heck 0.4.1",
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -1572,7 +1573,7 @@ dependencies = [
"ident_case", "ident_case",
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -1594,7 +1595,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [ dependencies = [
"darling_core 0.20.3", "darling_core 0.20.3",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -1755,7 +1756,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -1773,7 +1774,7 @@ version = "5.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd05cab02d6074145c6f92ddf1b57357e4bc1424f87c790c044de62bdc94c13a" checksum = "dd05cab02d6074145c6f92ddf1b57357e4bc1424f87c790c044de62bdc94c13a"
dependencies = [ dependencies = [
"ahash 0.8.3", "ahash 0.8.7",
"lazy_static", "lazy_static",
"log", "log",
"nom", "nom",
@ -1875,7 +1876,7 @@ checksum = "ccb14d927583dd5c2eac0f2cf264fc4762aefe1ae14c47a8a20fc1939d3a5fc0"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -1896,7 +1897,7 @@ dependencies = [
"darling 0.20.3", "darling 0.20.3",
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -2238,7 +2239,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -2703,7 +2704,7 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [ dependencies = [
"ahash 0.8.3", "ahash 0.8.7",
"rayon", "rayon",
"serde", "serde",
] ]
@ -2714,7 +2715,7 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
dependencies = [ dependencies = [
"ahash 0.8.3", "ahash 0.8.7",
"allocator-api2", "allocator-api2",
] ]
@ -4005,7 +4006,7 @@ checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -4112,7 +4113,7 @@ dependencies = [
"proc-macro-crate", "proc-macro-crate",
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -4511,7 +4512,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -4667,7 +4668,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "097bf8b99121dfb8c75eed54dfbdbdb1d53e372c53d2353e8a15aad2a479249d" checksum = "097bf8b99121dfb8c75eed54dfbdbdb1d53e372c53d2353e8a15aad2a479249d"
dependencies = [ dependencies = [
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -5047,7 +5048,7 @@ dependencies = [
"quote 1.0.33", "quote 1.0.33",
"refinery-core", "refinery-core",
"regex", "regex",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -5486,7 +5487,7 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d"
dependencies = [ dependencies = [
"ahash 0.8.3", "ahash 0.8.7",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"hashbrown 0.13.2", "hashbrown 0.13.2",
] ]
@ -5633,7 +5634,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -5665,7 +5666,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -5767,10 +5768,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]] [[package]]
name = "shred" name = "shred"
version = "0.15.0" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/Imberflur/shred.git?rev=5d52c6fc390dd04c12158633e77591f6523d1f85#5d52c6fc390dd04c12158633e77591f6523d1f85"
checksum = "dc6b2cd1ccb08cf2b25d75c936e0cc9c8cb93c39a83814956da32653236338c0"
dependencies = [ dependencies = [
"ahash 0.7.6", "ahash 0.8.7",
"arrayvec 0.7.4", "arrayvec 0.7.4",
"atomic_refcell", "atomic_refcell",
"rayon", "rayon",
@ -5782,8 +5782,7 @@ dependencies = [
[[package]] [[package]]
name = "shred-derive" name = "shred-derive"
version = "0.6.3" version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/Imberflur/shred.git?rev=5d52c6fc390dd04c12158633e77591f6523d1f85#5d52c6fc390dd04c12158633e77591f6523d1f85"
checksum = "d5404c36bd155e41a54276ab6aafedad2fb627e5e5849d36ec439c9ddc044a2f"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
@ -6200,9 +6199,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.29" version = "2.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
@ -6277,7 +6276,7 @@ checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -6456,7 +6455,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -6597,7 +6596,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -6723,7 +6722,7 @@ version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 0.1.10",
"rand 0.8.5", "rand 0.8.5",
"static_assertions", "static_assertions",
] ]
@ -7176,7 +7175,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
] ]
[[package]] [[package]]
@ -7596,7 +7595,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -7653,7 +7652,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [ dependencies = [
"proc-macro2 1.0.66", "proc-macro2 1.0.66",
"quote 1.0.33", "quote 1.0.33",
"syn 2.0.29", "syn 2.0.32",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -8499,3 +8498,23 @@ checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
dependencies = [ dependencies = [
"time 0.3.28", "time 0.3.28",
] ]
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2 1.0.66",
"quote 1.0.33",
"syn 2.0.32",
]

View File

@ -165,6 +165,7 @@ winit = { git = "https://github.com/Imberflur/winit.git", tag = "raw-window-hand
wgpu = { git = "https://github.com/pythonesque/wgpu.git", rev = "179ea209374a92837cde252f1d9ee01f628cae08" } wgpu = { git = "https://github.com/pythonesque/wgpu.git", rev = "179ea209374a92837cde252f1d9ee01f628cae08" }
# ntapi 3.7 fails to compile under windows due to the bug https://github.com/MSxDOS/ntapi/pull/12 # ntapi 3.7 fails to compile under windows due to the bug https://github.com/MSxDOS/ntapi/pull/12
ntapi = { git = "https://github.com/MSxDOS/ntapi.git", rev = "9f56b149c9e25796739157c0fce3e0007a7de6eb" } ntapi = { git = "https://github.com/MSxDOS/ntapi.git", rev = "9f56b149c9e25796739157c0fce3e0007a7de6eb" }
shred = { git = "https://github.com/Imberflur/shred.git", rev = "5d52c6fc390dd04c12158633e77591f6523d1f85" }
[patch."https://github.com/gfx-rs/gfx"] [patch."https://github.com/gfx-rs/gfx"]
gfx-hal = { git = "https://github.com/Imberflur/gfx.git", tag = "veloren-fixes-v1" } gfx-hal = { git = "https://github.com/Imberflur/gfx.git", tag = "veloren-fixes-v1" }

View File

@ -65,6 +65,7 @@ fn main() {
&password, &password,
|provider| provider == "https://auth.veloren.net", |provider| provider == "https://auth.veloren.net",
&|_| {}, &|_| {},
|_| {},
)) ))
.expect("Failed to create client instance"); .expect("Failed to create client instance");
@ -85,7 +86,7 @@ fn main() {
client.send_chat(msg) client.send_chat(msg)
} }
let events = match client.tick(comp::ControllerInputs::default(), clock.dt(), |_| {}) { let events = match client.tick(comp::ControllerInputs::default(), clock.dt()) {
Ok(events) => events, Ok(events) => events,
Err(err) => { Err(err) => {
error!("Error: {:?}", err); error!("Error: {:?}", err);

View File

@ -73,6 +73,7 @@ pub fn make_client(
password, password,
|_| true, |_| true,
&|_| {}, &|_| {},
|_| {},
)) ))
.ok() .ok()
} }
@ -99,7 +100,7 @@ impl BotClient {
for (username, client) in self.bot_clients.iter_mut() { for (username, client) in self.bot_clients.iter_mut() {
trace!(?username, "tick"); trace!(?username, "tick");
let _msgs: Result<Vec<veloren_client::Event>, veloren_client::Error> = let _msgs: Result<Vec<veloren_client::Event>, veloren_client::Error> =
client.tick(comp::ControllerInputs::default(), self.clock.dt(), |_| {}); client.tick(comp::ControllerInputs::default(), self.clock.dt());
} }
} }

View File

@ -123,6 +123,7 @@ fn run_client(
&username, &username,
"", "",
|_| false, |_| false,
|_| {},
)) { )) {
Err(e) => tracing::warn!(?e, "Client {} disconnected", index), Err(e) => tracing::warn!(?e, "Client {} disconnected", index),
Ok(client) => break client, Ok(client) => break client,

View File

@ -307,6 +307,7 @@ impl Client {
password: &str, password: &str,
auth_trusted: impl FnMut(&str) -> bool, auth_trusted: impl FnMut(&str) -> bool,
init_stage_update: &(dyn Fn(ClientInitStage) + Send + Sync), init_stage_update: &(dyn Fn(ClientInitStage) + Send + Sync),
add_foreign_systems: impl Fn(&mut DispatcherBuilder) + Send + 'static,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let network = Network::new(Pid::new(), &runtime); let network = Network::new(Pid::new(), &runtime);
@ -409,7 +410,13 @@ impl Client {
// Initialize `State` // Initialize `State`
let pools = State::pools(GameMode::Client); let pools = State::pools(GameMode::Client);
let mut state = State::client(pools, map_size_lg, world_map.default_chunk); let mut state = State::client(pools, map_size_lg, world_map.default_chunk,
// TODO: Add frontend systems
|dispatch_builder| {
add_local_systems(dispatch_builder);
add_foreign_systems(dispatch_builder);
},
);
// Client-only components // Client-only components
state.ecs_mut().register::<comp::Last<CharacterState>>(); state.ecs_mut().register::<comp::Last<CharacterState>>();
let entity = state.ecs_mut().apply_entity_package(entity_package); let entity = state.ecs_mut().apply_entity_package(entity_package);
@ -1800,7 +1807,6 @@ impl Client {
&mut self, &mut self,
inputs: ControllerInputs, inputs: ControllerInputs,
dt: Duration, dt: Duration,
add_foreign_systems: impl Fn(&mut DispatcherBuilder),
) -> Result<Vec<Event>, Error> { ) -> Result<Vec<Event>, Error> {
span!(_guard, "tick", "Client::tick"); span!(_guard, "tick", "Client::tick");
// This tick function is the centre of the Veloren universe. Most client-side // This tick function is the centre of the Veloren universe. Most client-side
@ -1902,10 +1908,6 @@ impl Client {
// 4) Tick the client's LocalState // 4) Tick the client's LocalState
self.state.tick( self.state.tick(
Duration::from_secs_f64(dt.as_secs_f64() * self.dt_adjustment), Duration::from_secs_f64(dt.as_secs_f64() * self.dt_adjustment),
|dispatch_builder| {
add_local_systems(dispatch_builder);
add_foreign_systems(dispatch_builder);
},
true, true,
None, None,
&self.connected_server_constants, &self.connected_server_constants,
@ -3011,6 +3013,7 @@ mod tests {
password, password,
|suggestion: &str| suggestion == auth_server, |suggestion: &str| suggestion == auth_server,
&|_| {}, &|_| {},
|_| {},
)); ));
let localisation = LocalizationHandle::load_expect("en"); let localisation = LocalizationHandle::load_expect("en");
@ -3020,7 +3023,7 @@ mod tests {
//tick //tick
let events_result: Result<Vec<Event>, Error> = let events_result: Result<Vec<Event>, Error> =
client.tick(ControllerInputs::default(), clock.dt(), |_| {}); client.tick(ControllerInputs::default(), clock.dt());
//chat functionality //chat functionality
client.send_chat("foobar".to_string()); client.send_chat("foobar".to_string());

View File

@ -33,7 +33,7 @@ use hashbrown::{HashMap, HashSet};
use rayon::{ThreadPool, ThreadPoolBuilder}; use rayon::{ThreadPool, ThreadPoolBuilder};
use specs::{ use specs::{
prelude::Resource, prelude::Resource,
shred::{Fetch, FetchMut}, shred::{Fetch, FetchMut, SendDispatcher},
storage::{MaskedStorage as EcsMaskedStorage, Storage as EcsStorage}, storage::{MaskedStorage as EcsMaskedStorage, Storage as EcsStorage},
Component, DispatcherBuilder, Entity as EcsEntity, WorldExt, Component, DispatcherBuilder, Entity as EcsEntity, WorldExt,
}; };
@ -128,6 +128,7 @@ pub struct State {
ecs: specs::World, ecs: specs::World,
// Avoid lifetime annotation by storing a thread pool instead of the whole dispatcher // Avoid lifetime annotation by storing a thread pool instead of the whole dispatcher
thread_pool: Arc<ThreadPool>, thread_pool: Arc<ThreadPool>,
dispatcher: SendDispatcher<'static>,
} }
pub type Pools = Arc<ThreadPool>; pub type Pools = Arc<ThreadPool>;
@ -150,13 +151,35 @@ impl State {
} }
/// Create a new `State` in client mode. /// Create a new `State` in client mode.
pub fn client(pools: Pools, map_size_lg: MapSizeLg, default_chunk: Arc<TerrainChunk>) -> Self { pub fn client(
Self::new(GameMode::Client, pools, map_size_lg, default_chunk) pools: Pools,
map_size_lg: MapSizeLg,
default_chunk: Arc<TerrainChunk>,
add_systems: impl Fn(&mut DispatcherBuilder),
) -> Self {
Self::new(
GameMode::Client,
pools,
map_size_lg,
default_chunk,
add_systems,
)
} }
/// Create a new `State` in server mode. /// Create a new `State` in server mode.
pub fn server(pools: Pools, map_size_lg: MapSizeLg, default_chunk: Arc<TerrainChunk>) -> Self { pub fn server(
Self::new(GameMode::Server, pools, map_size_lg, default_chunk) pools: Pools,
map_size_lg: MapSizeLg,
default_chunk: Arc<TerrainChunk>,
add_systems: impl Fn(&mut DispatcherBuilder),
) -> Self {
Self::new(
GameMode::Server,
pools,
map_size_lg,
default_chunk,
add_systems,
)
} }
pub fn new( pub fn new(
@ -164,10 +187,24 @@ impl State {
pools: Pools, pools: Pools,
map_size_lg: MapSizeLg, map_size_lg: MapSizeLg,
default_chunk: Arc<TerrainChunk>, default_chunk: Arc<TerrainChunk>,
add_systems: impl Fn(&mut DispatcherBuilder),
) -> Self { ) -> Self {
prof_span!(guard, "create dispatcher");
let mut dispatch_builder =
DispatcherBuilder::<'static, 'static>::new().with_pool(Arc::clone(&pools));
// TODO: Consider alternative ways to do this
add_systems(&mut dispatch_builder);
// This dispatches all the systems in parallel.
let dispatcher = dispatch_builder
.build()
.try_into_sendable()
.unwrap_or_else(|_| panic!("Thread local systems not allowed"));
drop(guard);
Self { Self {
ecs: Self::setup_ecs_world(game_mode, Arc::clone(&pools), map_size_lg, default_chunk), ecs: Self::setup_ecs_world(game_mode, Arc::clone(&pools), map_size_lg, default_chunk),
thread_pool: pools, thread_pool: pools,
dispatcher,
} }
} }
@ -615,7 +652,6 @@ impl State {
pub fn tick( pub fn tick(
&mut self, &mut self,
dt: Duration, dt: Duration,
add_systems: impl Fn(&mut DispatcherBuilder),
update_terrain: bool, update_terrain: bool,
mut metrics: Option<&mut StateTickMetrics>, mut metrics: Option<&mut StateTickMetrics>,
server_constants: &ServerConstants, server_constants: &ServerConstants,
@ -645,19 +681,8 @@ impl State {
self.ecs.write_resource::<DeltaTime>().0 = self.ecs.write_resource::<DeltaTime>().0 =
(dt.as_secs_f32() * time_scale as f32).min(MAX_DELTA_TIME); (dt.as_secs_f32() * time_scale as f32).min(MAX_DELTA_TIME);
section_span!(guard, "create dispatcher");
// Run systems to update the world.
// Create and run a dispatcher for ecs systems.
let mut dispatch_builder =
DispatcherBuilder::new().with_pool(Arc::clone(&self.thread_pool));
// TODO: Consider alternative ways to do this
add_systems(&mut dispatch_builder);
// This dispatches all the systems in parallel.
let mut dispatcher = dispatch_builder.build();
drop(guard);
section_span!(guard, "run systems"); section_span!(guard, "run systems");
dispatcher.dispatch(&self.ecs); self.dispatcher.dispatch(&self.ecs);
drop(guard); drop(guard);
section_span!(guard, "maintain ecs"); section_span!(guard, "maintain ecs");

View File

@ -12,7 +12,7 @@ use common::{
}; };
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
use specs::{ use specs::{
shred::ResourceId, Entities, Entity as EcsEntity, Join, Read, ReadStorage, SystemData, World, shred, Entities, Entity as EcsEntity, Join, Read, ReadStorage, SystemData,
}; };
#[derive(SystemData)] #[derive(SystemData)]

View File

@ -17,8 +17,8 @@ use common_ecs::{Job, Origin, ParMode, Phase, System};
use rand::Rng; use rand::Rng;
use rayon::iter::ParallelIterator; use rayon::iter::ParallelIterator;
use specs::{ use specs::{
shred::ResourceId, Entities, LendJoin, ParJoin, Read, ReadExpect, ReadStorage, SystemData, shred, Entities, LendJoin, ParJoin, Read, ReadExpect, ReadStorage,
World, WriteStorage, SystemData, WriteStorage,
}; };
use vek::*; use vek::*;

View File

@ -22,8 +22,8 @@ use common_base::prof_span;
use common_ecs::{Job, Origin, ParMode, Phase, System}; use common_ecs::{Job, Origin, ParMode, Phase, System};
use rayon::iter::ParallelIterator; use rayon::iter::ParallelIterator;
use specs::{ use specs::{
shred::ResourceId, Entities, Entity, LendJoin, ParJoin, Read, ReadExpect, ReadStorage, shred, Entities, Entity, LendJoin, ParJoin, Read, ReadExpect, ReadStorage,
SystemData, World, WriteStorage, SystemData, WriteStorage,
}; };
#[derive(SystemData)] #[derive(SystemData)]

View File

@ -1,6 +1,6 @@
use specs::{ use specs::{
shred::ResourceId, Entities, LazyUpdate, LendJoin, Read, ReadExpect, ReadStorage, SystemData, shred, Entities, LazyUpdate, LendJoin, Read, ReadExpect, ReadStorage,
World, WriteStorage, SystemData, WriteStorage,
}; };
use common::{ use common::{

View File

@ -10,7 +10,7 @@ use common::{
}; };
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
use specs::{ use specs::{
shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, SystemData, World, shred, Entities, Join, Read, ReadExpect, ReadStorage, SystemData,
WriteStorage, WriteStorage,
}; };
use vek::*; use vek::*;

View File

@ -6,8 +6,8 @@ use common_base::prof_span;
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
use common_net::sync::InterpolatableComponent; use common_net::sync::InterpolatableComponent;
use specs::{ use specs::{
prelude::ParallelIterator, shred::ResourceId, Entities, ParJoin, Read, ReadStorage, SystemData, prelude::ParallelIterator, shred, Entities, ParJoin, Read, ReadStorage,
World, WriteStorage, SystemData, WriteStorage,
}; };
#[derive(SystemData)] #[derive(SystemData)]

View File

@ -18,8 +18,7 @@ use common::{
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
use itertools::Itertools; use itertools::Itertools;
use specs::{ use specs::{
shred::ResourceId, Entities, Join, LendJoin, Read, ReadExpect, ReadStorage, SystemData, World, shred, Entities, Join, LendJoin, Read, ReadExpect, ReadStorage, SystemData, WriteStorage,
WriteStorage,
}; };
use vek::*; use vek::*;

View File

@ -22,7 +22,7 @@ use common_base::{prof_span, span};
use common_ecs::{Job, Origin, ParMode, Phase, PhysicsMetrics, System}; use common_ecs::{Job, Origin, ParMode, Phase, PhysicsMetrics, System};
use rayon::iter::ParallelIterator; use rayon::iter::ParallelIterator;
use specs::{ use specs::{
shred::{ResourceId, World}, shred,
Entities, Entity, Join, LendJoin, ParJoin, Read, ReadExpect, ReadStorage, SystemData, Write, Entities, Entity, Join, LendJoin, ParJoin, Read, ReadExpect, ReadStorage, SystemData, Write,
WriteExpect, WriteStorage, WriteExpect, WriteStorage,
}; };

View File

@ -17,8 +17,8 @@ use common::vol::ReadVol;
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
use rand::Rng; use rand::Rng;
use specs::{ use specs::{
shred::ResourceId, Entities, Entity as EcsEntity, Join, Read, ReadExpect, ReadStorage, shred, Entities, Entity as EcsEntity, Join, Read, ReadExpect, ReadStorage,
SystemData, World, WriteStorage, SystemData, WriteStorage,
}; };
use std::time::Duration; use std::time::Duration;
use vek::*; use vek::*;

View File

@ -16,7 +16,8 @@ use common::{
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
use rand::Rng; use rand::Rng;
use specs::{ use specs::{
shred::ResourceId, Entities, Join, LendJoin, Read, ReadStorage, SystemData, World, WriteStorage, shred, Entities, Join, LendJoin, Read, ReadStorage, SystemData,
WriteStorage,
}; };
use vek::*; use vek::*;

View File

@ -12,8 +12,8 @@ use common::{
}; };
use common_ecs::{Job, Origin, Phase, System}; use common_ecs::{Job, Origin, Phase, System};
use specs::{ use specs::{
shred::ResourceId, Entities, LendJoin, Read, ReadExpect, ReadStorage, SystemData, World, Write, shred, Entities, LendJoin, Read, ReadExpect, ReadStorage, SystemData,
WriteStorage, Write, WriteStorage,
}; };
const ENERGY_REGEN_ACCEL: f32 = 1.0; const ENERGY_REGEN_ACCEL: f32 = 1.0;

View File

@ -34,6 +34,9 @@ mod tests {
pools, pools,
DEFAULT_WORLD_CHUNKS_LG, DEFAULT_WORLD_CHUNKS_LG,
Arc::new(TerrainChunk::water(0)), Arc::new(TerrainChunk::water(0)),
|dispatch_builder| {
dispatch::<character_behavior::Sys>(dispatch_builder, &[]);
},
); );
let msm = MaterialStatManifest::load().cloned(); let msm = MaterialStatManifest::load().cloned();
state.ecs_mut().insert(msm); state.ecs_mut().insert(msm);
@ -78,9 +81,6 @@ mod tests {
fn tick(state: &mut State, dt: Duration) { fn tick(state: &mut State, dt: Duration) {
state.tick( state.tick(
dt, dt,
|dispatch_builder| {
dispatch::<character_behavior::Sys>(dispatch_builder, &[]);
},
false, false,
None, None,
&ServerConstants { &ServerConstants {

View File

@ -5,17 +5,13 @@ use specs::WorldExt;
use std::error::Error; use std::error::Error;
use utils::{DT, DT_F64, EPSILON}; use utils::{DT, DT_F64, EPSILON};
use vek::{approx, Vec2, Vec3}; use vek::{approx, Vec2, Vec3};
use veloren_common_systems::add_local_systems;
#[test] #[test]
fn simple_run() { fn simple_run() {
let mut state = utils::setup(); let mut state = utils::setup(veloren_common_systems::add_local_systems);
utils::create_player(&mut state); utils::create_player(&mut state);
state.tick( state.tick(
DT, DT,
|dispatcher_builder| {
add_local_systems(dispatcher_builder);
},
false, false,
None, None,
&ServerConstants { &ServerConstants {
@ -27,7 +23,7 @@ fn simple_run() {
#[test] #[test]
fn dont_fall_outside_world() -> Result<(), Box<dyn Error>> { fn dont_fall_outside_world() -> Result<(), Box<dyn Error>> {
let mut state = utils::setup(); let mut state = utils::setup(utils::add_char_and_phys_systems);
let p1 = utils::create_player(&mut state); let p1 = utils::create_player(&mut state);
{ {
@ -54,7 +50,7 @@ fn dont_fall_outside_world() -> Result<(), Box<dyn Error>> {
#[test] #[test]
fn fall_simple() -> Result<(), Box<dyn Error>> { fn fall_simple() -> Result<(), Box<dyn Error>> {
let mut state = utils::setup(); let mut state = utils::setup(utils::add_char_and_phys_systems);
let p1 = utils::create_player(&mut state); let p1 = utils::create_player(&mut state);
let (pos, vel, _) = utils::get_transform(&state, p1)?; let (pos, vel, _) = utils::get_transform(&state, p1)?;
@ -93,8 +89,8 @@ fn fall_simple() -> Result<(), Box<dyn Error>> {
/// will fall in 20 x DT and 2 x 10*DT steps. compare the end result and make /// will fall in 20 x DT and 2 x 10*DT steps. compare the end result and make
/// log the "error" between both calculations /// log the "error" between both calculations
fn fall_dt_speed_diff() -> Result<(), Box<dyn Error>> { fn fall_dt_speed_diff() -> Result<(), Box<dyn Error>> {
let mut sstate = utils::setup(); let mut sstate = utils::setup(utils::add_char_and_phys_systems);
let mut fstate = utils::setup(); let mut fstate = utils::setup(utils::add_char_and_phys_systems);
let sp1 = utils::create_player(&mut sstate); let sp1 = utils::create_player(&mut sstate);
let fp1 = utils::create_player(&mut fstate); let fp1 = utils::create_player(&mut fstate);
@ -142,7 +138,7 @@ fn fall_dt_speed_diff() -> Result<(), Box<dyn Error>> {
#[test] #[test]
fn walk_simple() -> Result<(), Box<dyn Error>> { fn walk_simple() -> Result<(), Box<dyn Error>> {
let mut state = utils::setup(); let mut state = utils::setup(utils::add_char_and_phys_systems);
let p1 = utils::create_player(&mut state); let p1 = utils::create_player(&mut state);
for _ in 0..100 { for _ in 0..100 {
@ -187,7 +183,7 @@ fn walk_simple() -> Result<(), Box<dyn Error>> {
#[test] #[test]
fn walk_max() -> Result<(), Box<dyn Error>> { fn walk_max() -> Result<(), Box<dyn Error>> {
let mut state = utils::setup(); let mut state = utils::setup(utils::add_char_and_phys_systems);
for x in 2..30 { for x in 2..30 {
utils::generate_chunk(&mut state, Vec2::new(x, 0)); utils::generate_chunk(&mut state, Vec2::new(x, 0));
} }
@ -220,8 +216,8 @@ fn walk_max() -> Result<(), Box<dyn Error>> {
/// will run in 20 x DT and 2 x 10*DT steps. compare the end result and make /// will run in 20 x DT and 2 x 10*DT steps. compare the end result and make
/// log the "error" between both calculations /// log the "error" between both calculations
fn walk_dt_speed_diff() -> Result<(), Box<dyn Error>> { fn walk_dt_speed_diff() -> Result<(), Box<dyn Error>> {
let mut sstate = utils::setup(); let mut sstate = utils::setup(utils::add_char_and_phys_systems);
let mut fstate = utils::setup(); let mut fstate = utils::setup(utils::add_char_and_phys_systems);
let sp1 = utils::create_player(&mut sstate); let sp1 = utils::create_player(&mut sstate);
let fp1 = utils::create_player(&mut fstate); let fp1 = utils::create_player(&mut fstate);
@ -275,7 +271,7 @@ fn walk_dt_speed_diff() -> Result<(), Box<dyn Error>> {
#[test] #[test]
fn cant_run_during_fall() -> Result<(), Box<dyn Error>> { fn cant_run_during_fall() -> Result<(), Box<dyn Error>> {
let mut state = utils::setup(); let mut state = utils::setup(utils::add_char_and_phys_systems);
let p1 = utils::create_player(&mut state); let p1 = utils::create_player(&mut state);
let mut actions = Controller::default(); let mut actions = Controller::default();

View File

@ -35,13 +35,14 @@ const DEFAULT_WORLD_CHUNKS_LG: MapSizeLg =
panic!("Default world chunk size does not satisfy required invariants."); panic!("Default world chunk size does not satisfy required invariants.");
}; };
pub fn setup() -> State { pub fn setup(add_systems: impl Fn(&mut specs::DispatcherBuilder)) -> State {
let pools = State::pools(GameMode::Server); let pools = State::pools(GameMode::Server);
let mut state = State::new( let mut state = State::new(
GameMode::Server, GameMode::Server,
pools, pools,
DEFAULT_WORLD_CHUNKS_LG, DEFAULT_WORLD_CHUNKS_LG,
Arc::new(TerrainChunk::water(0)), Arc::new(TerrainChunk::water(0)),
add_systems,
); );
state.ecs_mut().insert(MaterialStatManifest::with_empty()); state.ecs_mut().insert(MaterialStatManifest::with_empty());
state.ecs_mut().insert(AbilityMap::load().cloned()); state.ecs_mut().insert(AbilityMap::load().cloned());
@ -55,14 +56,14 @@ pub fn setup() -> State {
state state
} }
pub fn add_char_and_phys_systems(dispatch_builder: &mut specs::DispatcherBuilder) {
dispatch::<character_behavior::Sys>(dispatch_builder, &[]);
dispatch::<phys::Sys>(dispatch_builder, &[&character_behavior::Sys::sys_name()]);
}
pub fn tick(state: &mut State, dt: Duration) { pub fn tick(state: &mut State, dt: Duration) {
state.tick( state.tick(
dt, dt,
|dispatch_builder| {
dispatch::<character_behavior::Sys>(dispatch_builder, &[]);
dispatch::<phys::Sys>(dispatch_builder, &[&character_behavior::Sys::sys_name()]);
},
false, false,
None, None,
&ServerConstants { &ServerConstants {

View File

@ -27,8 +27,8 @@ use common::{
uid::{IdMaps, Uid}, uid::{IdMaps, Uid},
}; };
use specs::{ use specs::{
shred::ResourceId, Entities, Entity as EcsEntity, Read, ReadExpect, ReadStorage, SystemData, shred, Entities, Entity as EcsEntity, Read, ReadExpect, ReadStorage,
World, SystemData,
}; };
// TODO: Move rtsim back into AgentData after rtsim2 when it has a separate // TODO: Move rtsim back into AgentData after rtsim2 when it has a separate

View File

@ -306,6 +306,16 @@ impl Server {
pools, pools,
world.sim().map_size_lg(), world.sim().map_size_lg(),
Arc::clone(&map.default_chunk), Arc::clone(&map.default_chunk),
|dispatcher_builder| {
add_local_systems(dispatcher_builder);
sys::msg::add_server_systems(dispatcher_builder);
sys::add_server_systems(dispatcher_builder);
#[cfg(feature = "worldgen")]
{
rtsim::add_server_systems(dispatcher_builder);
weather::add_server_systems(dispatcher_builder);
}
},
); );
state.ecs_mut().insert(battlemode_buffer); state.ecs_mut().insert(battlemode_buffer);
state.ecs_mut().insert(settings.clone()); state.ecs_mut().insert(settings.clone());
@ -752,6 +762,7 @@ impl Server {
let mut state_tick_metrics = Default::default(); let mut state_tick_metrics = Default::default();
self.state.tick( self.state.tick(
dt, dt,
/*
|dispatcher_builder| { |dispatcher_builder| {
add_local_systems(dispatcher_builder); add_local_systems(dispatcher_builder);
sys::msg::add_server_systems(dispatcher_builder); sys::msg::add_server_systems(dispatcher_builder);
@ -762,6 +773,7 @@ impl Server {
weather::add_server_systems(dispatcher_builder); weather::add_server_systems(dispatcher_builder);
} }
}, },
*/
false, false,
Some(&mut state_tick_metrics), Some(&mut state_tick_metrics),
&self.server_constants, &self.server_constants,

View File

@ -24,8 +24,8 @@ use itertools::Either;
use plugin_api::Health; use plugin_api::Health;
use rayon::prelude::*; use rayon::prelude::*;
use specs::{ use specs::{
shred::ResourceId, Entities, Join, LendJoin, ParJoin, Read, ReadExpect, ReadStorage, shred, Entities, Join, LendJoin, ParJoin, Read, ReadExpect, ReadStorage, SystemData,
SystemData, World, WriteStorage, WriteStorage,
}; };
use tracing::{debug, info, trace, warn}; use tracing::{debug, info, trace, warn};

View File

@ -11,10 +11,7 @@ use common_net::{
sync::{CompSyncPackage, EntityPackage, EntitySyncPackage, NetSync, SyncFrom, UpdateTracker}, sync::{CompSyncPackage, EntityPackage, EntitySyncPackage, NetSync, SyncFrom, UpdateTracker},
}; };
use hashbrown::HashMap; use hashbrown::HashMap;
use specs::{ use specs::{shred, Entity as EcsEntity, Join, ReadExpect, ReadStorage, SystemData, WriteExpect};
shred::ResourceId, Entity as EcsEntity, Join, ReadExpect, ReadStorage, SystemData, World,
WriteExpect,
};
use vek::*; use vek::*;
/// Always watching /// Always watching

View File

@ -8,8 +8,7 @@ use common_ecs::{Job, Origin, Phase, System};
use common_state::BlockChange; use common_state::BlockChange;
use hashbrown::HashMap; use hashbrown::HashMap;
use specs::{ use specs::{
shred::ResourceId, Entities, Entity, Join, LendJoin, Read, ReadStorage, SystemData, World, shred, Entities, Entity, Join, LendJoin, Read, ReadStorage, SystemData, Write, WriteStorage,
Write, WriteStorage,
}; };
#[derive(SystemData)] #[derive(SystemData)]

View File

@ -206,11 +206,10 @@ impl PlayState for CharSelectionState {
// Tick the client (currently only to keep the connection alive). // Tick the client (currently only to keep the connection alive).
let localized_strings = &global_state.i18n.read(); let localized_strings = &global_state.i18n.read();
let res = self.client.borrow_mut().tick( let res = self
comp::ControllerInputs::default(), .client
global_state.clock.dt(), .borrow_mut()
|_| {}, .tick(comp::ControllerInputs::default(), global_state.clock.dt());
);
match res { match res {
Ok(events) => { Ok(events) => {
for event in events { for event in events {

View File

@ -85,6 +85,7 @@ impl ClientInit {
&|stage| { &|stage| {
let _ = init_stage_tx.send(stage); let _ = init_stage_tx.send(stage);
}, },
crate::ecs::sys::add_local_systems,
) )
.await .await
{ {

View File

@ -251,11 +251,7 @@ impl PlayState for MainMenuState {
// Tick the client to keep the connection alive if we are waiting on pipelines // Tick the client to keep the connection alive if we are waiting on pipelines
if let InitState::Pipeline(client) = &mut self.init { if let InitState::Pipeline(client) = &mut self.init {
match client.tick( match client.tick(comp::ControllerInputs::default(), global_state.clock.dt()) {
comp::ControllerInputs::default(),
global_state.clock.dt(),
|_| {},
) {
Ok(events) => { Ok(events) => {
for event in events { for event in events {
match event { match event {

View File

@ -272,7 +272,7 @@ impl SessionState {
self.mumble_link.update(player_pos, player_pos); self.mumble_link.update(player_pos, player_pos);
} }
for event in client.tick(self.inputs.clone(), dt, crate::ecs::sys::add_local_systems)? { for event in client.tick(self.inputs.clone(), dt)? {
match event { match event {
client::Event::Chat(m) => { client::Event::Chat(m) => {
self.hud.new_message(m); self.hud.new_message(m);