mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'ProfessionalHobbyist/configurable_day_night_length' into 'master'
Add setting to control length of day/night cycle for servers. ("Fix" for https://gitlab.com/veloren/veloren/-/issues/1798) See merge request veloren/veloren!3836
This commit is contained in:
commit
1298fc792b
@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
with a keybind to enable/disable the setting, and an Auto/Toggle behavior setting. Auto behavior
|
||||
will only lock the camera zoom while movement and combat inputs are also being pressed.
|
||||
- Custom spots can be added without recompilation (only ron and vox files)
|
||||
- Setting in userdata/server/server_config/settings.ron that controls the length of each day/night cycle.
|
||||
|
||||
### Changed
|
||||
- Bats move slower and use a simple proportional controller to maintain altitude
|
||||
|
@ -40,6 +40,7 @@ use common::{
|
||||
outcome::Outcome,
|
||||
recipe::{ComponentRecipeBook, RecipeBook},
|
||||
resources::{GameMode, PlayerEntity, Time, TimeOfDay},
|
||||
shared_server_config::ServerConstants,
|
||||
spiral::Spiral2d,
|
||||
terrain::{
|
||||
block::Block, map::MapConfig, neighbors, site::DungeonKindMeta, BiomeKind,
|
||||
@ -264,6 +265,8 @@ pub struct Client {
|
||||
|
||||
pending_chunks: HashMap<Vec2<i32>, Instant>,
|
||||
target_time_of_day: Option<TimeOfDay>,
|
||||
|
||||
connected_server_constants: ServerConstants,
|
||||
}
|
||||
|
||||
/// Holds data related to the current players characters, as well as some
|
||||
@ -355,6 +358,7 @@ impl Client {
|
||||
component_recipe_book,
|
||||
material_stats,
|
||||
ability_map,
|
||||
server_constants,
|
||||
} = loop {
|
||||
tokio::select! {
|
||||
// Spawn in a blocking thread (leaving the network thread free). This is mostly
|
||||
@ -744,6 +748,8 @@ impl Client {
|
||||
|
||||
pending_chunks: HashMap::new(),
|
||||
target_time_of_day: None,
|
||||
|
||||
connected_server_constants: server_constants,
|
||||
})
|
||||
}
|
||||
|
||||
@ -1802,6 +1808,7 @@ impl Client {
|
||||
},
|
||||
true,
|
||||
None,
|
||||
&self.connected_server_constants,
|
||||
);
|
||||
// TODO: avoid emitting these in the first place
|
||||
let _ = self
|
||||
|
@ -12,6 +12,7 @@ use common::{
|
||||
outcome::Outcome,
|
||||
recipe::{ComponentRecipeBook, RecipeBook},
|
||||
resources::{Time, TimeOfDay},
|
||||
shared_server_config::ServerConstants,
|
||||
terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize},
|
||||
trade::{PendingTrade, SitePrices, TradeId, TradeResult},
|
||||
uid::Uid,
|
||||
@ -66,6 +67,7 @@ pub enum ServerInit {
|
||||
component_recipe_book: ComponentRecipeBook,
|
||||
material_stats: MaterialStatManifest,
|
||||
ability_map: comp::item::tool::AbilityMap,
|
||||
server_constants: ServerConstants,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ pub mod combat;
|
||||
pub mod comp;
|
||||
pub mod consts;
|
||||
pub mod resources;
|
||||
pub mod shared_server_config;
|
||||
pub mod uid;
|
||||
|
||||
// NOTE: Comment out macro to get rustfmt to re-order these as needed.
|
||||
|
16
common/src/shared_server_config.rs
Normal file
16
common/src/shared_server_config.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Per-server constant data (configs) that stays the same for the server's
|
||||
/// life.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ServerConstants {
|
||||
pub day_cycle_coefficient: f64,
|
||||
}
|
||||
impl Default for ServerConstants {
|
||||
fn default() -> Self {
|
||||
ServerConstants {
|
||||
// == 30.0 via server settings (the default)
|
||||
day_cycle_coefficient: 24.0 * 2.0,
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ use common::{
|
||||
DeltaTime, EntitiesDiedLastTick, GameMode, PlayerEntity, PlayerPhysicsSettings, Time,
|
||||
TimeOfDay,
|
||||
},
|
||||
shared_server_config::ServerConstants,
|
||||
slowjob::SlowJobPool,
|
||||
terrain::{Block, MapSizeLg, TerrainChunk, TerrainGrid},
|
||||
time::DayPeriod,
|
||||
@ -39,9 +40,6 @@ use std::{sync::Arc, time::Instant};
|
||||
use timer_queue::TimerQueue;
|
||||
use vek::*;
|
||||
|
||||
/// How much faster should an in-game day be compared to a real day?
|
||||
// TODO: Don't hard-code this.
|
||||
const DAY_CYCLE_FACTOR: f64 = 24.0 * 2.0;
|
||||
/// At what point should we stop speeding up physics to compensate for lag? If
|
||||
/// we speed physics up too fast, we'd skip important physics events like
|
||||
/// collisions. This constant determines the upper limit. If delta time exceeds
|
||||
@ -598,6 +596,7 @@ impl State {
|
||||
add_systems: impl Fn(&mut DispatcherBuilder),
|
||||
update_terrain_and_regions: bool,
|
||||
mut metrics: Option<&mut StateTickMetrics>,
|
||||
server_constants: &ServerConstants,
|
||||
) {
|
||||
span!(_guard, "tick", "State::tick");
|
||||
|
||||
@ -611,7 +610,8 @@ impl State {
|
||||
}
|
||||
|
||||
// Change the time accordingly.
|
||||
self.ecs.write_resource::<TimeOfDay>().0 += dt.as_secs_f64() * DAY_CYCLE_FACTOR;
|
||||
self.ecs.write_resource::<TimeOfDay>().0 +=
|
||||
dt.as_secs_f64() * server_constants.day_cycle_coefficient;
|
||||
self.ecs.write_resource::<Time>().0 += dt.as_secs_f64();
|
||||
|
||||
// Update delta time.
|
||||
|
@ -6,6 +6,7 @@ mod tests {
|
||||
Controller, Energy, Ori, PhysicsState, Poise, Pos, Skill, Stats, Vel,
|
||||
},
|
||||
resources::{DeltaTime, GameMode, Time},
|
||||
shared_server_config::ServerConstants,
|
||||
terrain::{MapSizeLg, TerrainChunk},
|
||||
uid::Uid,
|
||||
util::Dir,
|
||||
@ -81,6 +82,8 @@ mod tests {
|
||||
},
|
||||
false,
|
||||
None,
|
||||
// Dummy ServerConstants
|
||||
&ServerConstants::default(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::utils;
|
||||
use approx::assert_relative_eq;
|
||||
use common::{comp::Controller, resources::Time};
|
||||
use common::{comp::Controller, resources::Time, shared_server_config::ServerConstants};
|
||||
use specs::WorldExt;
|
||||
use std::error::Error;
|
||||
use utils::{DT, DT_F64, EPSILON};
|
||||
@ -18,6 +18,7 @@ fn simple_run() {
|
||||
},
|
||||
false,
|
||||
None,
|
||||
&ServerConstants::default(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ use common::{
|
||||
Vel,
|
||||
},
|
||||
resources::{DeltaTime, GameMode, Time},
|
||||
shared_server_config::ServerConstants,
|
||||
skillset_builder::SkillSetBuilder,
|
||||
terrain::{
|
||||
Block, BlockKind, MapSizeLg, SpriteKind, TerrainChunk, TerrainChunkMeta, TerrainGrid,
|
||||
@ -64,6 +65,7 @@ pub fn tick(state: &mut State, dt: Duration) {
|
||||
},
|
||||
false,
|
||||
None,
|
||||
&ServerConstants::default(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,7 @@ use common::{
|
||||
event::{EventBus, ServerEvent},
|
||||
resources::{BattleMode, GameMode, Time, TimeOfDay},
|
||||
rtsim::RtSimEntity,
|
||||
shared_server_config::ServerConstants,
|
||||
slowjob::SlowJobPool,
|
||||
terrain::{TerrainChunk, TerrainChunkSize},
|
||||
vol::RectRasterableVol,
|
||||
@ -205,6 +206,8 @@ pub struct Server {
|
||||
metrics_shutdown: Arc<Notify>,
|
||||
database_settings: Arc<RwLock<DatabaseSettings>>,
|
||||
disconnect_all_clients_requested: bool,
|
||||
|
||||
server_constants: ServerConstants,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
@ -561,6 +564,10 @@ impl Server {
|
||||
#[cfg(not(feature = "worldgen"))]
|
||||
rtsim::init(&mut state);
|
||||
|
||||
let server_constants = ServerConstants {
|
||||
day_cycle_coefficient: 1440.0 / settings.day_length,
|
||||
};
|
||||
|
||||
let this = Self {
|
||||
state,
|
||||
world,
|
||||
@ -571,6 +578,8 @@ impl Server {
|
||||
metrics_shutdown,
|
||||
database_settings,
|
||||
disconnect_all_clients_requested: false,
|
||||
|
||||
server_constants,
|
||||
};
|
||||
|
||||
debug!(?settings, "created veloren server with");
|
||||
@ -701,6 +710,7 @@ impl Server {
|
||||
},
|
||||
false,
|
||||
Some(&mut state_tick_metrics),
|
||||
&self.server_constants,
|
||||
);
|
||||
|
||||
let before_handle_events = Instant::now();
|
||||
|
@ -22,6 +22,7 @@ use core::time::Duration;
|
||||
use portpicker::pick_unused_port;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
fmt::Display,
|
||||
fs,
|
||||
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
|
||||
path::{Path, PathBuf},
|
||||
@ -166,6 +167,8 @@ pub struct Settings {
|
||||
pub world_seed: u32,
|
||||
pub server_name: String,
|
||||
pub start_time: f64,
|
||||
/// Length of a day in minutes.
|
||||
pub day_length: f64,
|
||||
/// When set to None, loads the default map file (if available); otherwise,
|
||||
/// uses the value of the file options to decide how to proceed.
|
||||
pub map_file: Option<FileOpts>,
|
||||
@ -203,6 +206,7 @@ impl Default for Settings {
|
||||
world_seed: DEFAULT_WORLD_SEED,
|
||||
server_name: "Veloren Server".into(),
|
||||
max_players: 100,
|
||||
day_length: 30.0,
|
||||
start_time: 9.0 * 3600.0,
|
||||
map_file: None,
|
||||
max_view_distance: Some(65),
|
||||
@ -223,7 +227,7 @@ impl Settings {
|
||||
pub fn load(path: &Path) -> Self {
|
||||
let path = Self::get_settings_path(path);
|
||||
|
||||
if let Ok(file) = fs::File::open(&path) {
|
||||
let mut settings = if let Ok(file) = fs::File::open(&path) {
|
||||
match ron::de::from_reader(file) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
@ -249,7 +253,10 @@ impl Settings {
|
||||
error!(?e, "Failed to create default settings file!");
|
||||
}
|
||||
default_settings
|
||||
}
|
||||
};
|
||||
|
||||
settings.validate();
|
||||
settings
|
||||
}
|
||||
|
||||
fn save_to_file(&self, path: &Path) -> std::io::Result<()> {
|
||||
@ -302,6 +309,35 @@ impl Settings {
|
||||
path.push(SETTINGS_FILENAME);
|
||||
path
|
||||
}
|
||||
|
||||
fn validate(&mut self) {
|
||||
const INVALID_SETTING_MSG: &str =
|
||||
"Invalid value for setting in userdata/server/server_config/settings.ron.";
|
||||
|
||||
let default_values = Settings::default();
|
||||
|
||||
if self.day_length <= 0.0 {
|
||||
warn!(
|
||||
"{} Setting: day_length, Value: {}. Set day_length to it's default value of {}. \
|
||||
Help: day_length must be a positive floating point value above 0.",
|
||||
INVALID_SETTING_MSG, self.day_length, default_values.day_length
|
||||
);
|
||||
self.day_length = default_values.day_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum InvalidSettingsError {
|
||||
InvalidDayDuration,
|
||||
}
|
||||
impl Display for InvalidSettingsError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
InvalidSettingsError::InvalidDayDuration => {
|
||||
f.write_str("Invalid settings error: Day length was invalid (zero or negative).")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_config_dir(path: &Path) -> PathBuf {
|
||||
|
@ -10,6 +10,7 @@ use common::{
|
||||
event::{EventBus, ServerEvent},
|
||||
recipe::{default_component_recipe_book, default_recipe_book},
|
||||
resources::TimeOfDay,
|
||||
shared_server_config::ServerConstants,
|
||||
uid::{Uid, UidAllocator},
|
||||
};
|
||||
use common_base::prof_span;
|
||||
@ -349,6 +350,9 @@ impl<'a> System<'a> for Sys {
|
||||
component_recipe_book: default_component_recipe_book().cloned(),
|
||||
material_stats: (*read_data.material_stats).clone(),
|
||||
ability_map: (*read_data.ability_map).clone(),
|
||||
server_constants: ServerConstants {
|
||||
day_cycle_coefficient: 1440.0 / read_data.settings.day_length
|
||||
},
|
||||
})?;
|
||||
debug!("Done initial sync with client.");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user