mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'songtronix/add-server-config' into 'master'
Add server config Closes #173 See merge request veloren/veloren!277
This commit is contained in:
commit
e912b96332
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,5 +31,6 @@
|
||||
# Veloren
|
||||
*.rar
|
||||
*.log
|
||||
settings.ron
|
||||
run.sh
|
||||
screenshots
|
||||
|
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -2766,7 +2766,10 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scan_fmt 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uvth 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vek 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -6,6 +6,8 @@ pub enum Error {
|
||||
ServerWentMad,
|
||||
ServerTimeout,
|
||||
ServerShutdown,
|
||||
TooManyPlayers,
|
||||
//TODO: InvalidAlias,
|
||||
Other(String),
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ pub use specs::Entity as EcsEntity;
|
||||
|
||||
use common::{
|
||||
comp,
|
||||
msg::{ClientMsg, ClientState, ServerInfo, ServerMsg},
|
||||
msg::{ClientMsg, ClientState, ServerError, ServerInfo, ServerMsg},
|
||||
net::PostBox,
|
||||
state::State,
|
||||
terrain::{block::Block, chonk::ChonkMetrics, TerrainChunk, TerrainChunkSize},
|
||||
@ -73,6 +73,9 @@ impl Client {
|
||||
.ok_or(Error::ServerWentMad)?;
|
||||
(state, entity, server_info)
|
||||
}
|
||||
Some(ServerMsg::Error(ServerError::TooManyPlayers)) => {
|
||||
return Err(Error::TooManyPlayers)
|
||||
}
|
||||
_ => return Err(Error::ServerWentMad),
|
||||
};
|
||||
|
||||
@ -361,8 +364,12 @@ impl Client {
|
||||
if new_msgs.len() > 0 {
|
||||
for msg in new_msgs {
|
||||
match msg {
|
||||
ServerMsg::InitialSync { .. } => return Err(Error::ServerWentMad),
|
||||
ServerMsg::Error(e) => match e {
|
||||
ServerError::TooManyPlayers => return Err(Error::ServerWentMad),
|
||||
//TODO: ServerError::InvalidAlias => return Err(Error::InvalidAlias),
|
||||
},
|
||||
ServerMsg::Shutdown => return Err(Error::ServerShutdown),
|
||||
ServerMsg::InitialSync { .. } => return Err(Error::ServerWentMad),
|
||||
ServerMsg::Ping => self.postbox.send_message(ClientMsg::Pong),
|
||||
ServerMsg::Pong => {
|
||||
self.last_ping_delta = Instant::now()
|
||||
|
@ -19,7 +19,6 @@ impl Player {
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.alias.chars().all(|c| c.is_alphanumeric() || c == '_')
|
||||
&& self.alias.len() <= MAX_ALIAS_LEN
|
||||
// TODO: Check view distance here based on server config too
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ pub mod server;
|
||||
// Reexports
|
||||
pub use self::client::ClientMsg;
|
||||
pub use self::ecs_packet::{EcsCompPacket, EcsResPacket};
|
||||
pub use self::server::{RequestStateError, ServerInfo, ServerMsg};
|
||||
pub use self::server::{RequestStateError, ServerError, ServerInfo, ServerMsg};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ClientState {
|
||||
|
@ -41,6 +41,13 @@ pub enum ServerMsg {
|
||||
key: Vec2<i32>,
|
||||
chunk: Box<TerrainChunk>,
|
||||
},
|
||||
Error(ServerError),
|
||||
Disconnect,
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ServerError {
|
||||
TooManyPlayers,
|
||||
//TODO: InvalidAlias,
|
||||
}
|
||||
|
@ -9,4 +9,4 @@ server = { package = "veloren-server", path = "../server" }
|
||||
common = { package = "veloren-common", path = "../common" }
|
||||
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.3"
|
||||
pretty_env_logger = "0.3"
|
@ -1,6 +1,6 @@
|
||||
use common::clock::Clock;
|
||||
use log::info;
|
||||
use server::{Event, Input, Server};
|
||||
use server::{Event, Input, Server, ServerSettings};
|
||||
use std::time::Duration;
|
||||
|
||||
const TPS: u64 = 30;
|
||||
@ -14,8 +14,11 @@ fn main() {
|
||||
// Set up an fps clock
|
||||
let mut clock = Clock::start();
|
||||
|
||||
// Load settings
|
||||
let settings = ServerSettings::load();
|
||||
|
||||
// Create server
|
||||
let mut server = Server::new().expect("Failed to create server instance!");
|
||||
let mut server = Server::new(settings).expect("Failed to create server instance!");
|
||||
|
||||
loop {
|
||||
let events = server
|
||||
|
@ -14,3 +14,6 @@ vek = "0.9"
|
||||
uvth = "3.1.0"
|
||||
lazy_static = "1.3.0"
|
||||
scan_fmt = "0.1.3"
|
||||
ron = "0.5.1"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
@ -41,6 +41,10 @@ impl Clients {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&mut self) -> usize {
|
||||
self.clients.len()
|
||||
}
|
||||
|
||||
pub fn add(&mut self, entity: EcsEntity, client: Client) {
|
||||
self.clients.insert(entity, client);
|
||||
}
|
||||
|
@ -4,9 +4,10 @@ pub mod client;
|
||||
pub mod cmd;
|
||||
pub mod error;
|
||||
pub mod input;
|
||||
pub mod settings;
|
||||
|
||||
// Reexports
|
||||
pub use crate::{error::Error, input::Input};
|
||||
pub use crate::{error::Error, input::Input, settings::ServerSettings};
|
||||
|
||||
use crate::{
|
||||
client::{Client, Clients},
|
||||
@ -14,9 +15,9 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
comp,
|
||||
msg::{ClientMsg, ClientState, RequestStateError, ServerInfo, ServerMsg},
|
||||
msg::{ClientMsg, ClientState, RequestStateError, ServerError, ServerInfo, ServerMsg},
|
||||
net::PostOffice,
|
||||
state::{State, TerrainChange, Uid},
|
||||
state::{State, TerrainChange, TimeOfDay, Uid},
|
||||
terrain::{block::Block, TerrainChunk, TerrainChunkSize, TerrainMap},
|
||||
vol::VolSize,
|
||||
vol::Vox,
|
||||
@ -36,8 +37,6 @@ use world::World;
|
||||
|
||||
const CLIENT_TIMEOUT: f64 = 20.0; // Seconds
|
||||
|
||||
const DEFAULT_WORLD_SEED: u32 = 1337;
|
||||
|
||||
pub enum Event {
|
||||
ClientConnected {
|
||||
entity: EcsEntity,
|
||||
@ -66,19 +65,20 @@ pub struct Server {
|
||||
chunk_rx: mpsc::Receiver<(Vec2<i32>, TerrainChunk)>,
|
||||
pending_chunks: HashSet<Vec2<i32>>,
|
||||
|
||||
server_settings: ServerSettings,
|
||||
server_info: ServerInfo,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
/// Create a new `Server` bound to the default socket.
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
Self::bind(SocketAddr::from(([0; 4], 59003)))
|
||||
pub fn new(settings: ServerSettings) -> Result<Self, Error> {
|
||||
Self::bind(settings.address, settings)
|
||||
}
|
||||
|
||||
/// Create a new server bound to the given socket.
|
||||
#[allow(dead_code)]
|
||||
pub fn bind<A: Into<SocketAddr>>(addrs: A) -> Result<Self, Error> {
|
||||
pub fn bind<A: Into<SocketAddr>>(addrs: A, settings: ServerSettings) -> Result<Self, Error> {
|
||||
let (chunk_tx, chunk_rx) = mpsc::channel();
|
||||
|
||||
let mut state = State::default();
|
||||
@ -86,9 +86,12 @@ impl Server {
|
||||
.ecs_mut()
|
||||
.add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 380.0)));
|
||||
|
||||
// Set starting time for the server.
|
||||
state.ecs_mut().write_resource::<TimeOfDay>().0 = settings.start_time;
|
||||
|
||||
let this = Self {
|
||||
state,
|
||||
world: Arc::new(World::generate(DEFAULT_WORLD_SEED)),
|
||||
world: Arc::new(World::generate(settings.world_seed)),
|
||||
|
||||
postoffice: PostOffice::bind(addrs.into())?,
|
||||
clients: Clients::empty(),
|
||||
@ -101,9 +104,10 @@ impl Server {
|
||||
pending_chunks: HashSet::new(),
|
||||
|
||||
server_info: ServerInfo {
|
||||
name: "Server name".to_owned(),
|
||||
description: "This is the best Veloren server.".to_owned(),
|
||||
name: settings.server_name.clone(),
|
||||
description: settings.server_description.clone(),
|
||||
},
|
||||
server_settings: settings,
|
||||
};
|
||||
|
||||
Ok(this)
|
||||
@ -356,16 +360,20 @@ impl Server {
|
||||
last_ping: self.state.get_time(),
|
||||
};
|
||||
|
||||
// Return the state of the current world (all of the components that Sphynx tracks).
|
||||
client.notify(ServerMsg::InitialSync {
|
||||
ecs_state: self.state.ecs().gen_state_package(),
|
||||
entity_uid: self.state.ecs().uid_from_entity(entity).unwrap().into(), // Can't fail.
|
||||
server_info: self.server_info.clone(),
|
||||
});
|
||||
if self.server_settings.max_players <= self.clients.len() {
|
||||
client.notify(ServerMsg::Error(ServerError::TooManyPlayers));
|
||||
} else {
|
||||
// Return the state of the current world (all of the components that Sphynx tracks).
|
||||
client.notify(ServerMsg::InitialSync {
|
||||
ecs_state: self.state.ecs().gen_state_package(),
|
||||
entity_uid: self.state.ecs().uid_from_entity(entity).unwrap().into(), // Can't fail.
|
||||
server_info: self.server_info.clone(),
|
||||
});
|
||||
|
||||
frontend_events.push(Event::ClientConnected { entity });
|
||||
}
|
||||
|
||||
self.clients.add(entity, client);
|
||||
|
||||
frontend_events.push(Event::ClientConnected { entity });
|
||||
}
|
||||
|
||||
Ok(frontend_events)
|
||||
|
65
server/src/settings.rs
Normal file
65
server/src/settings.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{fs, io::prelude::*, net::SocketAddr, path::PathBuf};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct ServerSettings {
|
||||
pub address: SocketAddr,
|
||||
pub max_players: usize,
|
||||
pub world_seed: u32,
|
||||
//pub pvp_enabled: bool,
|
||||
pub server_name: String,
|
||||
pub server_description: String,
|
||||
//pub login_server: whatever
|
||||
pub start_time: f64,
|
||||
}
|
||||
|
||||
impl Default for ServerSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
address: SocketAddr::from(([0; 4], 59003)),
|
||||
world_seed: 1337,
|
||||
server_name: "Server name".to_owned(),
|
||||
server_description: "This is the best Veloren server.".to_owned(),
|
||||
max_players: 16,
|
||||
start_time: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ServerSettings {
|
||||
pub fn load() -> Self {
|
||||
let path = ServerSettings::get_settings_path();
|
||||
|
||||
if let Ok(file) = fs::File::open(path) {
|
||||
match ron::de::from_reader(file) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
log::warn!("Failed to parse setting file! Fallback to default. {}", e);
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let default_settings = Self::default();
|
||||
|
||||
match default_settings.save_to_file() {
|
||||
Err(e) => log::error!("Failed to create default setting file! {}", e),
|
||||
_ => {}
|
||||
}
|
||||
default_settings
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_to_file(&self) -> std::io::Result<()> {
|
||||
let path = ServerSettings::get_settings_path();
|
||||
let mut config_file = fs::File::create(path)?;
|
||||
|
||||
let s: &str = &ron::ser::to_string_pretty(self, ron::ser::PrettyConfig::default()).unwrap();
|
||||
config_file.write_all(s.as_bytes()).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_settings_path() -> PathBuf {
|
||||
PathBuf::from(r"settings.ron")
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ pub enum Error {
|
||||
// Parsing/host name resolution successful but could not connect.
|
||||
ConnectionFailed(ClientError),
|
||||
ClientCrashed,
|
||||
ServerIsFull,
|
||||
}
|
||||
|
||||
// Used to asynchronously parse the server address, resolve host names,
|
||||
@ -76,6 +77,10 @@ impl ClientInit {
|
||||
ClientError::Network(_) => {
|
||||
last_err = Some(Error::ConnectionFailed(err))
|
||||
}
|
||||
ClientError::TooManyPlayers => {
|
||||
last_err = Some(Error::ServerIsFull);
|
||||
break;
|
||||
}
|
||||
// TODO: Handle errors?
|
||||
_ => panic!(
|
||||
"Unexpected non-network error when creating client: {:?}",
|
||||
|
@ -64,6 +64,7 @@ impl PlayState for MainMenuState {
|
||||
self.main_menu_ui.login_error(
|
||||
match err {
|
||||
InitError::BadAddress(_) | InitError::NoAddress => "Server not found",
|
||||
InitError::ServerIsFull => "Server is Full!",
|
||||
InitError::ConnectionFailed(_) => "Connection failed",
|
||||
InitError::ClientCrashed => "Client crashed",
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use client::Client;
|
||||
use common::clock::Clock;
|
||||
use log::info;
|
||||
use portpicker::pick_unused_port;
|
||||
use server::{Event, Input, Server};
|
||||
use server::{Event, Input, Server, ServerSettings};
|
||||
use std::{
|
||||
net::SocketAddr,
|
||||
sync::mpsc::{channel, Receiver, Sender, TryRecvError},
|
||||
@ -36,7 +36,8 @@ impl Singleplayer {
|
||||
));
|
||||
|
||||
// Create server
|
||||
let server = Server::bind(sock.clone()).expect("Failed to create server instance!");
|
||||
let server = Server::bind(sock.clone(), ServerSettings::default())
|
||||
.expect("Failed to create server instance!");
|
||||
|
||||
let server = match client {
|
||||
Some(client) => server.with_thread_pool(client.thread_pool().clone()),
|
||||
|
Loading…
Reference in New Issue
Block a user