mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
singleplayer server initialization status
This commit is contained in:
@ -2,6 +2,8 @@ common-username = username
|
|||||||
common-singleplayer = Singleplayer
|
common-singleplayer = Singleplayer
|
||||||
common-multiplayer = Multiplayer
|
common-multiplayer = Multiplayer
|
||||||
common-servers = Servers
|
common-servers = Servers
|
||||||
|
common-server = Server
|
||||||
|
common-client = Client
|
||||||
common-quit = Quit
|
common-quit = Quit
|
||||||
common-settings = Settings
|
common-settings = Settings
|
||||||
common-languages = Languages
|
common-languages = Languages
|
||||||
|
@ -61,10 +61,18 @@ hud-sit = Sit
|
|||||||
hud-steer = Steer
|
hud-steer = Steer
|
||||||
hud-portal = Portal
|
hud-portal = Portal
|
||||||
hud-init-stage-singleplayer = Starting singleplayer server...
|
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-multiplayer = Starting multiplayer
|
||||||
hud-init-stage-client-connection-establish = Establishing connection to server
|
hud-init-stage-client-connection-establish = [{ common-client }]: Establishing connection to server
|
||||||
hud-init-stage-client-request-server-version = Wating for server version
|
hud-init-stage-client-request-server-version = [{ common-client }]: Wating for server version
|
||||||
hud-init-stage-client-authentication = Authenticating
|
hud-init-stage-client-authentication = [{ common-client }]: Authenticating
|
||||||
hud-init-stage-client-load-init-data = Loading initialization data from server
|
hud-init-stage-client-load-init-data = [{ common-client }]: Loading initialization data from server
|
||||||
hud-init-stage-client-starting-client = Preparing Client...
|
hud-init-stage-client-starting-client = [{ common-client }]: Preparing Client...
|
||||||
hud-init-stage-render-pipeline = Creating render pipeline ({ $done }/{ $total })
|
hud-init-stage-render-pipeline = Creating render pipeline ({ $done }/{ $total })
|
||||||
|
@ -192,6 +192,7 @@ fn main() -> io::Result<()> {
|
|||||||
editable_settings,
|
editable_settings,
|
||||||
database_settings,
|
database_settings,
|
||||||
&server_data_dir,
|
&server_data_dir,
|
||||||
|
None,
|
||||||
runtime,
|
runtime,
|
||||||
)
|
)
|
||||||
.expect("Failed to create server instance!");
|
.expect("Failed to create server instance!");
|
||||||
|
@ -112,11 +112,13 @@ use test_world::{IndexOwned, World};
|
|||||||
use tokio::{runtime::Runtime, sync::Notify};
|
use tokio::{runtime::Runtime, sync::Notify};
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
pub use world::{civ::WorldCivStage, sim::WorldSimStage, WorldGenerateStage};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
persistence::{DatabaseSettings, SqlLogMode},
|
persistence::{DatabaseSettings, SqlLogMode},
|
||||||
sys::terrain,
|
sys::terrain,
|
||||||
};
|
};
|
||||||
|
use crossbeam_channel::Sender;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
@ -198,6 +200,13 @@ pub struct ChunkRequest {
|
|||||||
key: Vec2<i32>,
|
key: Vec2<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ServerInitStage {
|
||||||
|
DbMigrations,
|
||||||
|
DbVacuum,
|
||||||
|
WorldGen(WorldGenerateStage),
|
||||||
|
StartingSystems,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
state: State,
|
state: State,
|
||||||
world: Arc<World>,
|
world: Arc<World>,
|
||||||
@ -221,6 +230,7 @@ impl Server {
|
|||||||
editable_settings: EditableSettings,
|
editable_settings: EditableSettings,
|
||||||
database_settings: DatabaseSettings,
|
database_settings: DatabaseSettings,
|
||||||
data_dir: &std::path::Path,
|
data_dir: &std::path::Path,
|
||||||
|
stage_report_tx: Option<Sender<ServerInitStage>>,
|
||||||
runtime: Arc<Runtime>,
|
runtime: Arc<Runtime>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
prof_span!("Server::new");
|
prof_span!("Server::new");
|
||||||
@ -229,10 +239,18 @@ impl Server {
|
|||||||
info!("Authentication is disabled");
|
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)
|
// Run pending DB migrations (if any)
|
||||||
debug!("Running DB migrations...");
|
debug!("Running DB migrations...");
|
||||||
persistence::run_migrations(&database_settings);
|
persistence::run_migrations(&database_settings);
|
||||||
|
|
||||||
|
report_stage(ServerInitStage::DbVacuum);
|
||||||
// Vacuum database
|
// Vacuum database
|
||||||
debug!("Vacuuming database...");
|
debug!("Vacuuming database...");
|
||||||
persistence::vacuum_database(&database_settings);
|
persistence::vacuum_database(&database_settings);
|
||||||
@ -253,6 +271,7 @@ impl Server {
|
|||||||
|
|
||||||
let pools = State::pools(GameMode::Server);
|
let pools = State::pools(GameMode::Server);
|
||||||
|
|
||||||
|
let world_generate_status_tx = stage_report_tx.clone();
|
||||||
#[cfg(feature = "worldgen")]
|
#[cfg(feature = "worldgen")]
|
||||||
let (world, index) = World::generate(
|
let (world, index) = World::generate(
|
||||||
settings.world_seed,
|
settings.world_seed,
|
||||||
@ -267,6 +286,11 @@ impl Server {
|
|||||||
calendar: Some(settings.calendar_mode.calendar_now()),
|
calendar: Some(settings.calendar_mode.calendar_now()),
|
||||||
},
|
},
|
||||||
&pools,
|
&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"))]
|
#[cfg(not(feature = "worldgen"))]
|
||||||
let (world, index) = World::generate(settings.world_seed);
|
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);
|
let lod = lod::Lod::from_world(&world, index.as_index_ref(), &pools);
|
||||||
|
|
||||||
|
report_stage(ServerInitStage::StartingSystems);
|
||||||
|
|
||||||
let mut state = State::server(
|
let mut state = State::server(
|
||||||
pools,
|
pools,
|
||||||
world.sim().map_size_lg(),
|
world.sim().map_size_lg(),
|
||||||
|
@ -25,6 +25,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
calendar: None,
|
calendar: None,
|
||||||
},
|
},
|
||||||
&pool,
|
&pool,
|
||||||
|
Arc::new(|_| {}),
|
||||||
);
|
);
|
||||||
let mut terrain = TerrainGrid::new(
|
let mut terrain = TerrainGrid::new(
|
||||||
world.sim().map_size_lg(),
|
world.sim().map_size_lg(),
|
||||||
|
@ -21,6 +21,7 @@ use common::comp;
|
|||||||
use common_base::span;
|
use common_base::span;
|
||||||
use i18n::LocalizationHandle;
|
use i18n::LocalizationHandle;
|
||||||
use scene::Scene;
|
use scene::Scene;
|
||||||
|
use server::ServerInitStage;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::runtime;
|
use tokio::runtime;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
@ -29,6 +30,7 @@ use ui::{Event as MainMenuEvent, MainMenuUi};
|
|||||||
pub enum DetailedInitializationStage {
|
pub enum DetailedInitializationStage {
|
||||||
// TODO: Map generation and server startup progress
|
// TODO: Map generation and server startup progress
|
||||||
Singleplayer,
|
Singleplayer,
|
||||||
|
SingleplayerServer(ServerInitStage),
|
||||||
StartingMultiplayer,
|
StartingMultiplayer,
|
||||||
Client(ClientInitStage),
|
Client(ClientInitStage),
|
||||||
CreatingRenderPipeline(usize, usize),
|
CreatingRenderPipeline(usize, usize),
|
||||||
@ -106,6 +108,12 @@ impl PlayState for MainMenuState {
|
|||||||
#[cfg(feature = "singleplayer")]
|
#[cfg(feature = "singleplayer")]
|
||||||
{
|
{
|
||||||
if let Some(singleplayer) = global_state.singleplayer.as_running() {
|
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() {
|
match singleplayer.receiver.try_recv() {
|
||||||
Ok(Ok(())) => {
|
Ok(Ok(())) => {
|
||||||
// Attempt login after the server is finished initializing
|
// Attempt login after the server is finished initializing
|
||||||
|
@ -16,6 +16,7 @@ use i18n::Localization;
|
|||||||
use iced::{button, Align, Column, Container, Length, Row, Space, Text};
|
use iced::{button, Align, Column, Container, Length, Row, Space, Text};
|
||||||
use keyboard_keynames::key_layout::KeyLayout;
|
use keyboard_keynames::key_layout::KeyLayout;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use server::{ServerInitStage, WorldCivStage, WorldGenerateStage, WorldSimStage};
|
||||||
|
|
||||||
struct LoadingAnimation {
|
struct LoadingAnimation {
|
||||||
speed_factor: f32,
|
speed_factor: f32,
|
||||||
@ -141,6 +142,43 @@ impl Screen {
|
|||||||
DetailedInitializationStage::Singleplayer => {
|
DetailedInitializationStage::Singleplayer => {
|
||||||
i18n.get_msg("hud-init-stage-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 => {
|
DetailedInitializationStage::StartingMultiplayer => {
|
||||||
i18n.get_msg("hud-init-stage-multiplayer")
|
i18n.get_msg("hud-init-stage-multiplayer")
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,7 @@ use common::clock::Clock;
|
|||||||
use crossbeam_channel::{bounded, unbounded, Receiver, Sender, TryRecvError};
|
use crossbeam_channel::{bounded, unbounded, Receiver, Sender, TryRecvError};
|
||||||
use server::{
|
use server::{
|
||||||
persistence::{DatabaseSettings, SqlLogMode},
|
persistence::{DatabaseSettings, SqlLogMode},
|
||||||
Error as ServerError, Event, Input, Server,
|
Error as ServerError, Event, Input, Server, ServerInitStage,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
sync::{
|
sync::{
|
||||||
@ -26,6 +26,7 @@ pub struct Singleplayer {
|
|||||||
_server_thread: JoinHandle<()>,
|
_server_thread: JoinHandle<()>,
|
||||||
stop_server_s: Sender<()>,
|
stop_server_s: Sender<()>,
|
||||||
pub receiver: Receiver<Result<(), ServerError>>,
|
pub receiver: Receiver<Result<(), ServerError>>,
|
||||||
|
pub init_stage_receiver: Receiver<ServerInitStage>,
|
||||||
// Wether the server is stopped or not
|
// Wether the server is stopped or not
|
||||||
paused: Arc<AtomicBool>,
|
paused: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
@ -89,6 +90,8 @@ impl SingleplayerState {
|
|||||||
|
|
||||||
let (stop_server_s, stop_server_r) = unbounded();
|
let (stop_server_s, stop_server_r) = unbounded();
|
||||||
|
|
||||||
|
let (server_stage_tx, server_stage_rx) = unbounded();
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
|
|
||||||
// Relative to data_dir
|
// Relative to data_dir
|
||||||
@ -119,6 +122,7 @@ impl SingleplayerState {
|
|||||||
editable_settings,
|
editable_settings,
|
||||||
database_settings,
|
database_settings,
|
||||||
&server_data_dir,
|
&server_data_dir,
|
||||||
|
Some(server_stage_tx),
|
||||||
runtime,
|
runtime,
|
||||||
) {
|
) {
|
||||||
Ok(server) => (Some(server), Ok(())),
|
Ok(server) => (Some(server), Ok(())),
|
||||||
@ -143,6 +147,7 @@ impl SingleplayerState {
|
|||||||
*self = SingleplayerState::Running(Singleplayer {
|
*self = SingleplayerState::Running(Singleplayer {
|
||||||
_server_thread: thread,
|
_server_thread: thread,
|
||||||
stop_server_s,
|
stop_server_s,
|
||||||
|
init_stage_receiver: server_stage_rx,
|
||||||
receiver: result_receiver,
|
receiver: result_receiver,
|
||||||
paused,
|
paused,
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@ use std::{
|
|||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{prelude::*, SeekFrom},
|
io::{prelude::*, SeekFrom},
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
type Result = std::io::Result<()>;
|
type Result = std::io::Result<()>;
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ fn main() -> Result {
|
|||||||
calendar: None,
|
calendar: None,
|
||||||
},
|
},
|
||||||
&pool,
|
&pool,
|
||||||
|
Arc::new(|_| {}),
|
||||||
);
|
);
|
||||||
println!("Loaded world");
|
println!("Loaded world");
|
||||||
let export_path = "dungeon.vox";
|
let export_path = "dungeon.vox";
|
||||||
|
@ -4,7 +4,7 @@ use common::{
|
|||||||
};
|
};
|
||||||
use rayon::ThreadPoolBuilder;
|
use rayon::ThreadPoolBuilder;
|
||||||
use rusqlite::{Connection, ToSql};
|
use rusqlite::{Connection, ToSql};
|
||||||
use std::error::Error;
|
use std::{error::Error, sync::Arc};
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
use vek::Vec2;
|
use vek::Vec2;
|
||||||
use veloren_world::{
|
use veloren_world::{
|
||||||
@ -169,6 +169,7 @@ fn main() {
|
|||||||
calendar: None,
|
calendar: None,
|
||||||
},
|
},
|
||||||
&pool,
|
&pool,
|
||||||
|
Arc::new(|_| {}),
|
||||||
);
|
);
|
||||||
println!("Loaded world");
|
println!("Loaded world");
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use std::ops::{Add, Mul, Sub};
|
use std::{
|
||||||
|
ops::{Add, Mul, Sub},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use veloren_world::{sim::WorldOpts, util::Sampler, World};
|
use veloren_world::{sim::WorldOpts, util::Sampler, World};
|
||||||
|
|
||||||
@ -14,6 +17,7 @@ fn main() {
|
|||||||
..WorldOpts::default()
|
..WorldOpts::default()
|
||||||
},
|
},
|
||||||
&threadpool,
|
&threadpool,
|
||||||
|
Arc::new(|_| {}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let index = index.as_index_ref();
|
let index = index.as_index_ref();
|
||||||
|
@ -7,7 +7,7 @@ use common::{
|
|||||||
vol::RectVolSize,
|
vol::RectVolSize,
|
||||||
};
|
};
|
||||||
use rayon::prelude::*;
|
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::{warn, Level};
|
||||||
use tracing_subscriber::{
|
use tracing_subscriber::{
|
||||||
filter::{EnvFilter, LevelFilter},
|
filter::{EnvFilter, LevelFilter},
|
||||||
@ -53,6 +53,7 @@ fn main() {
|
|||||||
calendar: None,
|
calendar: None,
|
||||||
},
|
},
|
||||||
&threadpool,
|
&threadpool,
|
||||||
|
Arc::new(|_| {}),
|
||||||
);
|
);
|
||||||
let index = index.as_index_ref();
|
let index = index.as_index_ref();
|
||||||
tracing::info!("Sampling data...");
|
tracing::info!("Sampling data...");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::time::Instant;
|
use std::{sync::Arc, time::Instant};
|
||||||
use veloren_world::{
|
use veloren_world::{
|
||||||
sim::{FileOpts, WorldOpts, DEFAULT_WORLD_MAP},
|
sim::{FileOpts, WorldOpts, DEFAULT_WORLD_MAP},
|
||||||
World,
|
World,
|
||||||
@ -17,6 +17,7 @@ fn main() {
|
|||||||
calendar: None,
|
calendar: None,
|
||||||
},
|
},
|
||||||
&threadpool,
|
&threadpool,
|
||||||
|
Arc::new(|_| {}),
|
||||||
);
|
);
|
||||||
core::hint::black_box((world, index));
|
core::hint::black_box((world, index));
|
||||||
println!("{} ms", start.elapsed().as_nanos() / 1_000_000);
|
println!("{} ms", start.elapsed().as_nanos() / 1_000_000);
|
||||||
|
@ -27,6 +27,7 @@ use core::{fmt, hash::BuildHasherDefault, ops::Range};
|
|||||||
use fxhash::FxHasher64;
|
use fxhash::FxHasher64;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rand_chacha::ChaChaRng;
|
use rand_chacha::ChaChaRng;
|
||||||
|
use std::sync::Arc;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
use vek::*;
|
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 {
|
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<dyn Fn(WorldCivStage)>,
|
||||||
|
) -> Self {
|
||||||
prof_span!("Civs::generate");
|
prof_span!("Civs::generate");
|
||||||
let mut this = Self::default();
|
let mut this = Self::default();
|
||||||
let rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
|
let rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
|
||||||
@ -247,16 +260,18 @@ impl Civs {
|
|||||||
|
|
||||||
info!("starting civilisation creation");
|
info!("starting civilisation creation");
|
||||||
prof_span!(guard, "create civs");
|
prof_span!(guard, "create civs");
|
||||||
for _ in 0..initial_civ_count {
|
for i in 0..initial_civ_count {
|
||||||
prof_span!("create civ");
|
prof_span!("create civ");
|
||||||
debug!("Creating civilisation...");
|
debug!("Creating civilisation...");
|
||||||
if this.birth_civ(&mut ctx.reseed()).is_none() {
|
if this.birth_civ(&mut ctx.reseed()).is_none() {
|
||||||
warn!("Failed to find starting site for civilisation.");
|
warn!("Failed to find starting site for civilisation.");
|
||||||
}
|
}
|
||||||
|
report_stage(WorldCivStage::CivCreation(i, initial_civ_count));
|
||||||
}
|
}
|
||||||
drop(guard);
|
drop(guard);
|
||||||
info!(?initial_civ_count, "all civilisations created");
|
info!(?initial_civ_count, "all civilisations created");
|
||||||
|
|
||||||
|
report_stage(WorldCivStage::SiteGeneration);
|
||||||
prof_span!(guard, "find locations and establish sites");
|
prof_span!(guard, "find locations and establish sites");
|
||||||
let world_dims = ctx.sim.get_aabr();
|
let world_dims = ctx.sim.get_aabr();
|
||||||
for _ in 0..initial_civ_count * 3 {
|
for _ in 0..initial_civ_count * 3 {
|
||||||
|
@ -32,9 +32,11 @@ pub use crate::{
|
|||||||
layer::PathLocals,
|
layer::PathLocals,
|
||||||
};
|
};
|
||||||
pub use block::BlockGen;
|
pub use block::BlockGen;
|
||||||
|
use civ::WorldCivStage;
|
||||||
pub use column::ColumnSample;
|
pub use column::ColumnSample;
|
||||||
pub use common::terrain::site::{DungeonKindMeta, SettlementKindMeta};
|
pub use common::terrain::site::{DungeonKindMeta, SettlementKindMeta};
|
||||||
pub use index::{IndexOwned, IndexRef};
|
pub use index::{IndexOwned, IndexRef};
|
||||||
|
use sim::WorldSimStage;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
column::ColumnGen,
|
column::ColumnGen,
|
||||||
@ -62,7 +64,7 @@ use enum_map::EnumMap;
|
|||||||
use rand::{prelude::*, Rng};
|
use rand::{prelude::*, Rng};
|
||||||
use rand_chacha::ChaCha8Rng;
|
use rand_chacha::ChaCha8Rng;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::time::Duration;
|
use std::{sync::Arc, time::Duration};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[cfg(all(feature = "be-dyn-lib", feature = "use-dyn-lib"))]
|
#[cfg(all(feature = "be-dyn-lib", feature = "use-dyn-lib"))]
|
||||||
@ -85,6 +87,13 @@ pub enum Error {
|
|||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum WorldGenerateStage {
|
||||||
|
WorldSimGenerate(WorldSimStage),
|
||||||
|
WorldCivGenerate(WorldCivStage),
|
||||||
|
EconomySimulation,
|
||||||
|
SpotGeneration,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
sim: sim::WorldSim,
|
sim: sim::WorldSim,
|
||||||
civs: civ::Civs,
|
civs: civ::Civs,
|
||||||
@ -110,6 +119,7 @@ impl World {
|
|||||||
seed: u32,
|
seed: u32,
|
||||||
opts: sim::WorldOpts,
|
opts: sim::WorldOpts,
|
||||||
threadpool: &rayon::ThreadPool,
|
threadpool: &rayon::ThreadPool,
|
||||||
|
report_stage: Arc<dyn Fn(WorldGenerateStage) + Send + Sync>,
|
||||||
) -> (Self, IndexOwned) {
|
) -> (Self, IndexOwned) {
|
||||||
prof_span!("World::generate");
|
prof_span!("World::generate");
|
||||||
// NOTE: Generating index first in order to quickly fail if the color manifest
|
// NOTE: Generating index first in order to quickly fail if the color manifest
|
||||||
@ -117,12 +127,26 @@ impl World {
|
|||||||
threadpool.install(|| {
|
threadpool.install(|| {
|
||||||
let mut index = Index::new(seed);
|
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);
|
sim2::simulate(&mut index, &mut sim);
|
||||||
|
|
||||||
|
report_stage(WorldGenerateStage::SpotGeneration);
|
||||||
Spot::generate(&mut sim);
|
Spot::generate(&mut sim);
|
||||||
|
|
||||||
(Self { sim, civs }, IndexOwned::new(index))
|
(Self { sim, civs }, IndexOwned::new(index))
|
||||||
|
@ -19,6 +19,7 @@ use std::{
|
|||||||
cmp::{Ordering, Reverse},
|
cmp::{Ordering, Reverse},
|
||||||
collections::BinaryHeap,
|
collections::BinaryHeap,
|
||||||
f32, fmt, mem,
|
f32, fmt, mem,
|
||||||
|
rc::Rc,
|
||||||
time::Instant,
|
time::Instant,
|
||||||
u32,
|
u32,
|
||||||
};
|
};
|
||||||
@ -2540,6 +2541,7 @@ pub fn do_erosion(
|
|||||||
k_d_scale: f64,
|
k_d_scale: f64,
|
||||||
k_da_scale: impl Fn(f64) -> f64,
|
k_da_scale: impl Fn(f64) -> f64,
|
||||||
threadpool: &rayon::ThreadPool,
|
threadpool: &rayon::ThreadPool,
|
||||||
|
report_progress: Rc<dyn Fn(f64)>,
|
||||||
) -> (Box<[Alt]>, Box<[Alt]> /* , Box<[Alt]> */) {
|
) -> (Box<[Alt]>, Box<[Alt]> /* , Box<[Alt]> */) {
|
||||||
debug!("Initializing erosion arrays...");
|
debug!("Initializing erosion arrays...");
|
||||||
let oldh_ = (0..map_size_lg.chunks_len())
|
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.
|
// Print out the percentage complete. Do this at most 20 times.
|
||||||
if i % std::cmp::max(n_steps / 20, 1) == 0 {
|
if i % std::cmp::max(n_steps / 20, 1) == 0 {
|
||||||
let pct = (i as f64 / n_steps as f64) * 100.0;
|
let pct = (i as f64 / n_steps as f64) * 100.0;
|
||||||
|
report_progress(pct);
|
||||||
info!("{:.2}% complete", pct);
|
info!("{:.2}% complete", pct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ use std::{
|
|||||||
io::{BufReader, BufWriter},
|
io::{BufReader, BufWriter},
|
||||||
ops::{Add, Div, Mul, Neg, Sub},
|
ops::{Add, Div, Mul, Neg, Sub},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
rc::Rc,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
@ -645,6 +646,11 @@ impl WorldFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum WorldSimStage {
|
||||||
|
// TODO: Add more stages
|
||||||
|
Erosion(f64),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WorldSim {
|
pub struct WorldSim {
|
||||||
pub seed: u32,
|
pub seed: u32,
|
||||||
/// Base 2 logarithm of the map size.
|
/// Base 2 logarithm of the map size.
|
||||||
@ -663,7 +669,12 @@ pub struct WorldSim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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<dyn Fn(WorldSimStage)>,
|
||||||
|
) -> Self {
|
||||||
prof_span!("WorldSim::generate");
|
prof_span!("WorldSim::generate");
|
||||||
let calendar = opts.calendar; // separate lifetime of elements
|
let calendar = opts.calendar; // separate lifetime of elements
|
||||||
let world_file = opts.world_file;
|
let world_file = opts.world_file;
|
||||||
@ -1250,6 +1261,9 @@ impl WorldSim {
|
|||||||
|
|
||||||
// Perform some erosion.
|
// Perform some erosion.
|
||||||
|
|
||||||
|
let report_erosion: Rc<dyn Fn(f64)> =
|
||||||
|
Rc::new(move |progress: f64| stage_report(WorldSimStage::Erosion(progress)));
|
||||||
|
|
||||||
let (alt, basement) = if let Some(map) = parsed_world_file {
|
let (alt, basement) = if let Some(map) = parsed_world_file {
|
||||||
(map.alt, map.basement)
|
(map.alt, map.basement)
|
||||||
} else {
|
} else {
|
||||||
@ -1278,6 +1292,7 @@ impl WorldSim {
|
|||||||
k_d_scale(n_approx),
|
k_d_scale(n_approx),
|
||||||
k_da_scale,
|
k_da_scale,
|
||||||
threadpool,
|
threadpool,
|
||||||
|
Rc::clone(&report_erosion),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Quick "small scale" erosion cycle in order to lower extreme angles.
|
// Quick "small scale" erosion cycle in order to lower extreme angles.
|
||||||
@ -1302,6 +1317,7 @@ impl WorldSim {
|
|||||||
k_d_scale(n_approx),
|
k_d_scale(n_approx),
|
||||||
k_da_scale,
|
k_da_scale,
|
||||||
threadpool,
|
threadpool,
|
||||||
|
Rc::clone(&report_erosion),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1351,6 +1367,7 @@ impl WorldSim {
|
|||||||
k_d_scale(n_approx),
|
k_d_scale(n_approx),
|
||||||
k_da_scale,
|
k_da_scale,
|
||||||
threadpool,
|
threadpool,
|
||||||
|
Rc::clone(&report_erosion),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -328,6 +328,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn test_economy0() {
|
fn test_economy0() {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
execute_with_tracing(Level::INFO, || {
|
execute_with_tracing(Level::INFO, || {
|
||||||
let threadpool = rayon::ThreadPoolBuilder::new().build().unwrap();
|
let threadpool = rayon::ThreadPoolBuilder::new().build().unwrap();
|
||||||
info!("init");
|
info!("init");
|
||||||
@ -340,9 +342,9 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let mut index = crate::index::Index::new(seed);
|
let mut index = crate::index::Index::new(seed);
|
||||||
info!("Index created");
|
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");
|
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");
|
info!("Civs created");
|
||||||
crate::sim2::simulate(&mut index, &mut sim);
|
crate::sim2::simulate(&mut index, &mut sim);
|
||||||
show_economy(&index.sites, &None);
|
show_economy(&index.sites, &None);
|
||||||
@ -354,6 +356,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn test_economy1() {
|
fn test_economy1() {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
execute_with_tracing(Level::INFO, || {
|
execute_with_tracing(Level::INFO, || {
|
||||||
let threadpool = rayon::ThreadPoolBuilder::new().build().unwrap();
|
let threadpool = rayon::ThreadPoolBuilder::new().build().unwrap();
|
||||||
info!("init");
|
info!("init");
|
||||||
@ -366,12 +370,13 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let mut index = crate::index::Index::new(seed);
|
let mut index = crate::index::Index::new(seed);
|
||||||
info!("Index created");
|
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");
|
info!("World loaded");
|
||||||
let mut names = None;
|
let mut names = None;
|
||||||
let regenerate_input = false;
|
let regenerate_input = false;
|
||||||
if regenerate_input {
|
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");
|
info!("Civs created");
|
||||||
let mut outarr: Vec<EconomySetup> = Vec::new();
|
let mut outarr: Vec<EconomySetup> = Vec::new();
|
||||||
for i in index.sites.values() {
|
for i in index.sites.values() {
|
||||||
@ -470,6 +475,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
/// test whether a site in moderate climate can survive on its own
|
/// test whether a site in moderate climate can survive on its own
|
||||||
fn test_economy_moderate_standalone() {
|
fn test_economy_moderate_standalone() {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
fn add_settlement(
|
fn add_settlement(
|
||||||
env: &mut Simenv,
|
env: &mut Simenv,
|
||||||
name: &str,
|
name: &str,
|
||||||
@ -505,7 +512,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let index = crate::index::Index::new(seed);
|
let index = crate::index::Index::new(seed);
|
||||||
info!("Index created");
|
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");
|
info!("World loaded");
|
||||||
let rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
|
let rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
|
||||||
let mut env = Simenv {
|
let mut env = Simenv {
|
||||||
|
Reference in New Issue
Block a user