From 66f6b81575dadfff09ea159d454195dcdd32abda Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Thu, 28 Sep 2023 00:26:47 +0200 Subject: [PATCH] singleplayer server initialization status --- assets/voxygen/i18n/en/common.ftl | 2 ++ assets/voxygen/i18n/en/hud/misc.ftl | 18 ++++++++---- server-cli/src/main.rs | 1 + server/src/lib.rs | 26 ++++++++++++++++++ voxygen/benches/meshing_benchmark.rs | 1 + voxygen/src/menu/main/mod.rs | 8 ++++++ voxygen/src/menu/main/ui/connecting.rs | 38 ++++++++++++++++++++++++++ voxygen/src/singleplayer/mod.rs | 7 ++++- world/examples/dungeon_voxel_export.rs | 2 ++ world/examples/pricing_csv.rs | 3 +- world/examples/view.rs | 6 +++- world/examples/water.rs | 3 +- world/examples/world_generate_time.rs | 3 +- world/src/civ/mod.rs | 19 +++++++++++-- world/src/lib.rs | 30 ++++++++++++++++++-- world/src/sim/erosion.rs | 3 ++ world/src/sim/mod.rs | 19 ++++++++++++- world/src/site/economy/context.rs | 17 ++++++++---- 18 files changed, 185 insertions(+), 21 deletions(-) diff --git a/assets/voxygen/i18n/en/common.ftl b/assets/voxygen/i18n/en/common.ftl index 0b69c4d703..6d304bfdbc 100644 --- a/assets/voxygen/i18n/en/common.ftl +++ b/assets/voxygen/i18n/en/common.ftl @@ -2,6 +2,8 @@ common-username = username common-singleplayer = Singleplayer common-multiplayer = Multiplayer common-servers = Servers +common-server = Server +common-client = Client common-quit = Quit common-settings = Settings common-languages = Languages diff --git a/assets/voxygen/i18n/en/hud/misc.ftl b/assets/voxygen/i18n/en/hud/misc.ftl index b4656f251e..9dfc2a1254 100644 --- a/assets/voxygen/i18n/en/hud/misc.ftl +++ b/assets/voxygen/i18n/en/hud/misc.ftl @@ -61,10 +61,18 @@ hud-sit = Sit hud-steer = Steer hud-portal = Portal hud-init-stage-singleplayer = Starting singleplayer server... +hud-init-stage-server-db-migrations = [{ common-server }]: Applying database migrations +hud-init-stage-server-db-vacuum = [{ common-server }]: Cleaning up database +hud-init-stage-server-worldsim-erosion = [{ common-server }]: Erosion { $percentage }% +hud-init-stage-server-worldciv-civcreate = [{ common-server }]: Generated { $generated } out of { $total } civilizations +hud-init-stage-server-worldciv-site = [{ common-server }]: Generating sites +hud-init-stage-server-economysim = [{ common-server }]: Simulating economy +hud-init-stage-server-spotgen = [{ common-server }]: Generating spots +hud-init-stage-server-starting = [{ common-server }]: Starting server... hud-init-stage-multiplayer = Starting multiplayer -hud-init-stage-client-connection-establish = Establishing connection to server -hud-init-stage-client-request-server-version = Wating for server version -hud-init-stage-client-authentication = Authenticating -hud-init-stage-client-load-init-data = Loading initialization data from server -hud-init-stage-client-starting-client = Preparing Client... +hud-init-stage-client-connection-establish = [{ common-client }]: Establishing connection to server +hud-init-stage-client-request-server-version = [{ common-client }]: Wating for server version +hud-init-stage-client-authentication = [{ common-client }]: Authenticating +hud-init-stage-client-load-init-data = [{ common-client }]: Loading initialization data from server +hud-init-stage-client-starting-client = [{ common-client }]: Preparing Client... hud-init-stage-render-pipeline = Creating render pipeline ({ $done }/{ $total }) diff --git a/server-cli/src/main.rs b/server-cli/src/main.rs index c3e6cf2092..1a26846b3e 100644 --- a/server-cli/src/main.rs +++ b/server-cli/src/main.rs @@ -192,6 +192,7 @@ fn main() -> io::Result<()> { editable_settings, database_settings, &server_data_dir, + None, runtime, ) .expect("Failed to create server instance!"); diff --git a/server/src/lib.rs b/server/src/lib.rs index ce54a4e997..a86271834b 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -112,11 +112,13 @@ use test_world::{IndexOwned, World}; use tokio::{runtime::Runtime, sync::Notify}; use tracing::{debug, error, info, trace, warn}; use vek::*; +pub use world::{civ::WorldCivStage, sim::WorldSimStage, WorldGenerateStage}; use crate::{ persistence::{DatabaseSettings, SqlLogMode}, sys::terrain, }; +use crossbeam_channel::Sender; use hashbrown::HashMap; use std::sync::RwLock; @@ -198,6 +200,13 @@ pub struct ChunkRequest { key: Vec2, } +pub enum ServerInitStage { + DbMigrations, + DbVacuum, + WorldGen(WorldGenerateStage), + StartingSystems, +} + pub struct Server { state: State, world: Arc, @@ -221,6 +230,7 @@ impl Server { editable_settings: EditableSettings, database_settings: DatabaseSettings, data_dir: &std::path::Path, + stage_report_tx: Option>, runtime: Arc, ) -> Result { prof_span!("Server::new"); @@ -229,10 +239,18 @@ impl Server { info!("Authentication is disabled"); } + let report_stage = |stage: ServerInitStage| { + if let Some(stage_report_tx) = &stage_report_tx { + let _ = stage_report_tx.send(stage); + } + }; + + report_stage(ServerInitStage::DbMigrations); // Run pending DB migrations (if any) debug!("Running DB migrations..."); persistence::run_migrations(&database_settings); + report_stage(ServerInitStage::DbVacuum); // Vacuum database debug!("Vacuuming database..."); persistence::vacuum_database(&database_settings); @@ -253,6 +271,7 @@ impl Server { let pools = State::pools(GameMode::Server); + let world_generate_status_tx = stage_report_tx.clone(); #[cfg(feature = "worldgen")] let (world, index) = World::generate( settings.world_seed, @@ -267,6 +286,11 @@ impl Server { calendar: Some(settings.calendar_mode.calendar_now()), }, &pools, + Arc::new(move |stage| { + if let Some(stage_report_tx) = &world_generate_status_tx { + let _ = stage_report_tx.send(ServerInitStage::WorldGen(stage)); + } + }), ); #[cfg(not(feature = "worldgen"))] let (world, index) = World::generate(settings.world_seed); @@ -287,6 +311,8 @@ impl Server { let lod = lod::Lod::from_world(&world, index.as_index_ref(), &pools); + report_stage(ServerInitStage::StartingSystems); + let mut state = State::server( pools, world.sim().map_size_lg(), diff --git a/voxygen/benches/meshing_benchmark.rs b/voxygen/benches/meshing_benchmark.rs index 9d6d250def..cdcc8c442e 100644 --- a/voxygen/benches/meshing_benchmark.rs +++ b/voxygen/benches/meshing_benchmark.rs @@ -25,6 +25,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { calendar: None, }, &pool, + Arc::new(|_| {}), ); let mut terrain = TerrainGrid::new( world.sim().map_size_lg(), diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 809ca63e07..be1e9833a1 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -21,6 +21,7 @@ use common::comp; use common_base::span; use i18n::LocalizationHandle; use scene::Scene; +use server::ServerInitStage; use std::sync::Arc; use tokio::runtime; use tracing::error; @@ -29,6 +30,7 @@ use ui::{Event as MainMenuEvent, MainMenuUi}; pub enum DetailedInitializationStage { // TODO: Map generation and server startup progress Singleplayer, + SingleplayerServer(ServerInitStage), StartingMultiplayer, Client(ClientInitStage), CreatingRenderPipeline(usize, usize), @@ -106,6 +108,12 @@ impl PlayState for MainMenuState { #[cfg(feature = "singleplayer")] { if let Some(singleplayer) = global_state.singleplayer.as_running() { + if let Ok(stage_update) = singleplayer.init_stage_receiver.try_recv() { + self.main_menu_ui.update_stage( + DetailedInitializationStage::SingleplayerServer(stage_update), + ); + } + match singleplayer.receiver.try_recv() { Ok(Ok(())) => { // Attempt login after the server is finished initializing diff --git a/voxygen/src/menu/main/ui/connecting.rs b/voxygen/src/menu/main/ui/connecting.rs index 6bae83df3e..8db3fb3efd 100644 --- a/voxygen/src/menu/main/ui/connecting.rs +++ b/voxygen/src/menu/main/ui/connecting.rs @@ -16,6 +16,7 @@ use i18n::Localization; use iced::{button, Align, Column, Container, Length, Row, Space, Text}; use keyboard_keynames::key_layout::KeyLayout; use serde::{Deserialize, Serialize}; +use server::{ServerInitStage, WorldCivStage, WorldGenerateStage, WorldSimStage}; struct LoadingAnimation { speed_factor: f32, @@ -141,6 +142,43 @@ impl Screen { DetailedInitializationStage::Singleplayer => { i18n.get_msg("hud-init-stage-singleplayer") }, + DetailedInitializationStage::SingleplayerServer(server_stage) => { + match server_stage { + ServerInitStage::DbMigrations => { + i18n.get_msg("hud-init-stage-server-db-migrations") + }, + ServerInitStage::DbVacuum => { + i18n.get_msg("hud-init-stage-server-db-vacuum") + }, + ServerInitStage::WorldGen(worldgen_stage) => match worldgen_stage { + WorldGenerateStage::WorldSimGenerate(worldsim_stage) => { + match worldsim_stage { + WorldSimStage::Erosion(done) => i18n + .get_msg_ctx( + "hud-init-stage-server-worldsim-erosion", + &i18n::fluent_args! { "percentage" => format!("{done:.0}") } + ), + } + }, + WorldGenerateStage::WorldCivGenerate(worldciv_stage) => { + match worldciv_stage { + WorldCivStage::CivCreation(generated, total) => i18n + .get_msg_ctx( + "hud-init-stage-server-worldciv-civcreate", + &i18n::fluent_args! { + "generated" => generated.to_string(), + "total" => total.to_string(), + } + ), + WorldCivStage::SiteGeneration => i18n.get_msg("hud-init-stage-server-worldciv-site"), + } + }, + WorldGenerateStage::EconomySimulation => i18n.get_msg("hud-init-stage-server-economysim"), + WorldGenerateStage::SpotGeneration => i18n.get_msg("hud-init-stage-server-spotgen"), + }, + ServerInitStage::StartingSystems => i18n.get_msg("hud-init-stage-server-starting"), + } + }, DetailedInitializationStage::StartingMultiplayer => { i18n.get_msg("hud-init-stage-multiplayer") }, diff --git a/voxygen/src/singleplayer/mod.rs b/voxygen/src/singleplayer/mod.rs index 95f67401b7..7d6fa7f84d 100644 --- a/voxygen/src/singleplayer/mod.rs +++ b/voxygen/src/singleplayer/mod.rs @@ -2,7 +2,7 @@ use common::clock::Clock; use crossbeam_channel::{bounded, unbounded, Receiver, Sender, TryRecvError}; use server::{ persistence::{DatabaseSettings, SqlLogMode}, - Error as ServerError, Event, Input, Server, + Error as ServerError, Event, Input, Server, ServerInitStage, }; use std::{ sync::{ @@ -26,6 +26,7 @@ pub struct Singleplayer { _server_thread: JoinHandle<()>, stop_server_s: Sender<()>, pub receiver: Receiver>, + pub init_stage_receiver: Receiver, // Wether the server is stopped or not paused: Arc, } @@ -89,6 +90,8 @@ impl SingleplayerState { let (stop_server_s, stop_server_r) = unbounded(); + let (server_stage_tx, server_stage_rx) = unbounded(); + // Create server // Relative to data_dir @@ -119,6 +122,7 @@ impl SingleplayerState { editable_settings, database_settings, &server_data_dir, + Some(server_stage_tx), runtime, ) { Ok(server) => (Some(server), Ok(())), @@ -143,6 +147,7 @@ impl SingleplayerState { *self = SingleplayerState::Running(Singleplayer { _server_thread: thread, stop_server_s, + init_stage_receiver: server_stage_rx, receiver: result_receiver, paused, }); diff --git a/world/examples/dungeon_voxel_export.rs b/world/examples/dungeon_voxel_export.rs index 8c6b7841aa..d96570a176 100644 --- a/world/examples/dungeon_voxel_export.rs +++ b/world/examples/dungeon_voxel_export.rs @@ -2,6 +2,7 @@ use std::{ collections::HashMap, fs::File, io::{prelude::*, SeekFrom}, + sync::Arc, }; type Result = std::io::Result<()>; @@ -32,6 +33,7 @@ fn main() -> Result { calendar: None, }, &pool, + Arc::new(|_| {}), ); println!("Loaded world"); let export_path = "dungeon.vox"; diff --git a/world/examples/pricing_csv.rs b/world/examples/pricing_csv.rs index f522ee7da5..54e12cf174 100644 --- a/world/examples/pricing_csv.rs +++ b/world/examples/pricing_csv.rs @@ -4,7 +4,7 @@ use common::{ }; use rayon::ThreadPoolBuilder; use rusqlite::{Connection, ToSql}; -use std::error::Error; +use std::{error::Error, sync::Arc}; use strum::IntoEnumIterator; use vek::Vec2; use veloren_world::{ @@ -169,6 +169,7 @@ fn main() { calendar: None, }, &pool, + Arc::new(|_| {}), ); println!("Loaded world"); diff --git a/world/examples/view.rs b/world/examples/view.rs index 3cf3658697..b4bda62152 100644 --- a/world/examples/view.rs +++ b/world/examples/view.rs @@ -1,4 +1,7 @@ -use std::ops::{Add, Mul, Sub}; +use std::{ + ops::{Add, Mul, Sub}, + sync::Arc, +}; use vek::*; use veloren_world::{sim::WorldOpts, util::Sampler, World}; @@ -14,6 +17,7 @@ fn main() { ..WorldOpts::default() }, &threadpool, + Arc::new(|_| {}), ); let index = index.as_index_ref(); diff --git a/world/examples/water.rs b/world/examples/water.rs index 3a27760688..cf020c07e0 100644 --- a/world/examples/water.rs +++ b/world/examples/water.rs @@ -7,7 +7,7 @@ use common::{ vol::RectVolSize, }; use rayon::prelude::*; -use std::{f64, io::Write, path::PathBuf, time::SystemTime}; +use std::{f64, io::Write, path::PathBuf, sync::Arc, time::SystemTime}; use tracing::{warn, Level}; use tracing_subscriber::{ filter::{EnvFilter, LevelFilter}, @@ -53,6 +53,7 @@ fn main() { calendar: None, }, &threadpool, + Arc::new(|_| {}), ); let index = index.as_index_ref(); tracing::info!("Sampling data..."); diff --git a/world/examples/world_generate_time.rs b/world/examples/world_generate_time.rs index 63593223f8..012e5cbd73 100644 --- a/world/examples/world_generate_time.rs +++ b/world/examples/world_generate_time.rs @@ -1,4 +1,4 @@ -use std::time::Instant; +use std::{sync::Arc, time::Instant}; use veloren_world::{ sim::{FileOpts, WorldOpts, DEFAULT_WORLD_MAP}, World, @@ -17,6 +17,7 @@ fn main() { calendar: None, }, &threadpool, + Arc::new(|_| {}), ); core::hint::black_box((world, index)); println!("{} ms", start.elapsed().as_nanos() / 1_000_000); diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index 27a4bd8f20..c02a04ac76 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -27,6 +27,7 @@ use core::{fmt, hash::BuildHasherDefault, ops::Range}; use fxhash::FxHasher64; use rand::prelude::*; use rand_chacha::ChaChaRng; +use std::sync::Arc; use tracing::{debug, info, warn}; use vek::*; @@ -223,8 +224,20 @@ impl<'a, R: Rng> GenCtx<'a, R> { } } +pub enum WorldCivStage { + /// Civilization creation, how many out of how many civilizations have been + /// generated yet + CivCreation(u32, u32), + SiteGeneration, +} + impl Civs { - pub fn generate(seed: u32, sim: &mut WorldSim, index: &mut Index) -> Self { + pub fn generate( + seed: u32, + sim: &mut WorldSim, + index: &mut Index, + report_stage: Arc, + ) -> Self { prof_span!("Civs::generate"); let mut this = Self::default(); let rng = ChaChaRng::from_seed(seed_expan::rng_state(seed)); @@ -247,16 +260,18 @@ impl Civs { info!("starting civilisation creation"); prof_span!(guard, "create civs"); - for _ in 0..initial_civ_count { + for i in 0..initial_civ_count { prof_span!("create civ"); debug!("Creating civilisation..."); if this.birth_civ(&mut ctx.reseed()).is_none() { warn!("Failed to find starting site for civilisation."); } + report_stage(WorldCivStage::CivCreation(i, initial_civ_count)); } drop(guard); info!(?initial_civ_count, "all civilisations created"); + report_stage(WorldCivStage::SiteGeneration); prof_span!(guard, "find locations and establish sites"); let world_dims = ctx.sim.get_aabr(); for _ in 0..initial_civ_count * 3 { diff --git a/world/src/lib.rs b/world/src/lib.rs index f64898bd18..f0fd5f266d 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -32,9 +32,11 @@ pub use crate::{ layer::PathLocals, }; pub use block::BlockGen; +use civ::WorldCivStage; pub use column::ColumnSample; pub use common::terrain::site::{DungeonKindMeta, SettlementKindMeta}; pub use index::{IndexOwned, IndexRef}; +use sim::WorldSimStage; use crate::{ column::ColumnGen, @@ -62,7 +64,7 @@ use enum_map::EnumMap; use rand::{prelude::*, Rng}; use rand_chacha::ChaCha8Rng; use serde::Deserialize; -use std::time::Duration; +use std::{sync::Arc, time::Duration}; use vek::*; #[cfg(all(feature = "be-dyn-lib", feature = "use-dyn-lib"))] @@ -85,6 +87,13 @@ pub enum Error { Other(String), } +pub enum WorldGenerateStage { + WorldSimGenerate(WorldSimStage), + WorldCivGenerate(WorldCivStage), + EconomySimulation, + SpotGeneration, +} + pub struct World { sim: sim::WorldSim, civs: civ::Civs, @@ -110,6 +119,7 @@ impl World { seed: u32, opts: sim::WorldOpts, threadpool: &rayon::ThreadPool, + report_stage: Arc, ) -> (Self, IndexOwned) { prof_span!("World::generate"); // NOTE: Generating index first in order to quickly fail if the color manifest @@ -117,12 +127,26 @@ impl World { threadpool.install(|| { let mut index = Index::new(seed); - let mut sim = sim::WorldSim::generate(seed, opts, threadpool); + let sim_stage_tx = Arc::clone(&report_stage); + let mut sim = sim::WorldSim::generate( + seed, + opts, + threadpool, + Arc::new(move |stage| sim_stage_tx(WorldGenerateStage::WorldSimGenerate(stage))), + ); - let civs = civ::Civs::generate(seed, &mut sim, &mut index); + let civ_stage_tx = Arc::clone(&report_stage); + let civs = civ::Civs::generate( + seed, + &mut sim, + &mut index, + Arc::new(move |stage| civ_stage_tx(WorldGenerateStage::WorldCivGenerate(stage))), + ); + report_stage(WorldGenerateStage::EconomySimulation); sim2::simulate(&mut index, &mut sim); + report_stage(WorldGenerateStage::SpotGeneration); Spot::generate(&mut sim); (Self { sim, civs }, IndexOwned::new(index)) diff --git a/world/src/sim/erosion.rs b/world/src/sim/erosion.rs index c2ec8fe09b..b6f987f088 100644 --- a/world/src/sim/erosion.rs +++ b/world/src/sim/erosion.rs @@ -19,6 +19,7 @@ use std::{ cmp::{Ordering, Reverse}, collections::BinaryHeap, f32, fmt, mem, + rc::Rc, time::Instant, u32, }; @@ -2540,6 +2541,7 @@ pub fn do_erosion( k_d_scale: f64, k_da_scale: impl Fn(f64) -> f64, threadpool: &rayon::ThreadPool, + report_progress: Rc, ) -> (Box<[Alt]>, Box<[Alt]> /* , Box<[Alt]> */) { debug!("Initializing erosion arrays..."); let oldh_ = (0..map_size_lg.chunks_len()) @@ -2644,6 +2646,7 @@ pub fn do_erosion( // Print out the percentage complete. Do this at most 20 times. if i % std::cmp::max(n_steps / 20, 1) == 0 { let pct = (i as f64 / n_steps as f64) * 100.0; + report_progress(pct); info!("{:.2}% complete", pct); } diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 22d5d6397f..460da29b8b 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -69,6 +69,7 @@ use std::{ io::{BufReader, BufWriter}, ops::{Add, Div, Mul, Neg, Sub}, path::PathBuf, + rc::Rc, sync::Arc, }; use strum::IntoEnumIterator; @@ -645,6 +646,11 @@ impl WorldFile { } } +pub enum WorldSimStage { + // TODO: Add more stages + Erosion(f64), +} + pub struct WorldSim { pub seed: u32, /// Base 2 logarithm of the map size. @@ -663,7 +669,12 @@ pub struct WorldSim { } impl WorldSim { - pub fn generate(seed: u32, opts: WorldOpts, threadpool: &rayon::ThreadPool) -> Self { + pub fn generate( + seed: u32, + opts: WorldOpts, + threadpool: &rayon::ThreadPool, + stage_report: Arc, + ) -> Self { prof_span!("WorldSim::generate"); let calendar = opts.calendar; // separate lifetime of elements let world_file = opts.world_file; @@ -1250,6 +1261,9 @@ impl WorldSim { // Perform some erosion. + let report_erosion: Rc = + Rc::new(move |progress: f64| stage_report(WorldSimStage::Erosion(progress))); + let (alt, basement) = if let Some(map) = parsed_world_file { (map.alt, map.basement) } else { @@ -1278,6 +1292,7 @@ impl WorldSim { k_d_scale(n_approx), k_da_scale, threadpool, + Rc::clone(&report_erosion), ); // Quick "small scale" erosion cycle in order to lower extreme angles. @@ -1302,6 +1317,7 @@ impl WorldSim { k_d_scale(n_approx), k_da_scale, threadpool, + Rc::clone(&report_erosion), ) }; @@ -1351,6 +1367,7 @@ impl WorldSim { k_d_scale(n_approx), k_da_scale, threadpool, + Rc::clone(&report_erosion), ) }; diff --git a/world/src/site/economy/context.rs b/world/src/site/economy/context.rs index df60ad86ce..dfcdd70fff 100644 --- a/world/src/site/economy/context.rs +++ b/world/src/site/economy/context.rs @@ -328,6 +328,8 @@ mod tests { #[test] #[ignore] fn test_economy0() { + use std::sync::Arc; + execute_with_tracing(Level::INFO, || { let threadpool = rayon::ThreadPoolBuilder::new().build().unwrap(); info!("init"); @@ -340,9 +342,9 @@ mod tests { }; let mut index = crate::index::Index::new(seed); info!("Index created"); - let mut sim = sim::WorldSim::generate(seed, opts, &threadpool); + let mut sim = sim::WorldSim::generate(seed, opts, &threadpool, Arc::new(|_| {})); info!("World loaded"); - let _civs = crate::civ::Civs::generate(seed, &mut sim, &mut index); + let _civs = crate::civ::Civs::generate(seed, &mut sim, &mut index, Arc::new(|_| {})); info!("Civs created"); crate::sim2::simulate(&mut index, &mut sim); show_economy(&index.sites, &None); @@ -354,6 +356,8 @@ mod tests { #[test] #[ignore] fn test_economy1() { + use std::sync::Arc; + execute_with_tracing(Level::INFO, || { let threadpool = rayon::ThreadPoolBuilder::new().build().unwrap(); info!("init"); @@ -366,12 +370,13 @@ mod tests { }; let mut index = crate::index::Index::new(seed); info!("Index created"); - let mut sim = sim::WorldSim::generate(seed, opts, &threadpool); + let mut sim = sim::WorldSim::generate(seed, opts, &threadpool, Arc::new(|_| {})); info!("World loaded"); let mut names = None; let regenerate_input = false; if regenerate_input { - let _civs = crate::civ::Civs::generate(seed, &mut sim, &mut index); + let _civs = + crate::civ::Civs::generate(seed, &mut sim, &mut index, Arc::new(|_| {})); info!("Civs created"); let mut outarr: Vec = Vec::new(); for i in index.sites.values() { @@ -470,6 +475,8 @@ mod tests { #[test] /// test whether a site in moderate climate can survive on its own fn test_economy_moderate_standalone() { + use std::sync::Arc; + fn add_settlement( env: &mut Simenv, name: &str, @@ -505,7 +512,7 @@ mod tests { }; let index = crate::index::Index::new(seed); info!("Index created"); - let mut sim = sim::WorldSim::generate(seed, opts, &threadpool); + let mut sim = sim::WorldSim::generate(seed, opts, &threadpool, Arc::new(|_| {})); info!("World loaded"); let rng = ChaChaRng::from_seed(seed_expan::rng_state(seed)); let mut env = Simenv {