Server configuration rework
This commit is contained in:
parent
934ad89fdf
commit
eb641d67fb
17 changed files with 75 additions and 81 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -1,18 +1,9 @@
|
|||
# ---> Rust
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
debug/
|
||||
target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
/*.json
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
|
||||
# Visual Studio crap
|
||||
.vs/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
members = ["gameserver", "protocol", "qwer", "qwer/qwer-derive", "sdkserver"]
|
||||
members = [ "common","gameserver", "protocol", "qwer", "qwer/qwer-derive", "sdkserver"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
|
@ -41,6 +41,7 @@ tracing-subscriber = { version = "0.3.18", features = [
|
|||
] }
|
||||
tracing-bunyan-formatter = "0.3.9"
|
||||
|
||||
common = { version = "0.1.0", path = "common" }
|
||||
protocol = { version = "0.1.0", path = "protocol" }
|
||||
qwer = { version = "0.1.0", path = "qwer", features = ["full"] }
|
||||
qwer-derive = { version = "0.1.0", path = "qwer/qwer-derive" }
|
||||
|
|
11
README.md
11
README.md
|
@ -55,14 +55,9 @@ run the following in a terminal:
|
|||
|
||||
## Configuration
|
||||
|
||||
The game server can be configured using a `.env` file. The file contains one configurable
|
||||
option, `SKIP_TUTORIAL`, which is set to 0 by default.
|
||||
|
||||
If you have a `.env` file in the **same** directory as your executable, then this
|
||||
is the file that will be loaded. Otherwise, upon _first_ running the `gameserver`
|
||||
executable, it will create `{FOLDERID_RoamingAppData}\nap-gameserver\.env`
|
||||
(`C:\Users\{user}\AppData\Roaming\nap-gameserver\.env`) for you, and will source
|
||||
from this config instead.
|
||||
The game server can be configured using a `gameserver.json` file.
|
||||
Configuration file with default settings will be created in
|
||||
the working directory upon first startup.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
6
common/Cargo.toml
Normal file
6
common/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "common"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
1
common/src/lib.rs
Normal file
1
common/src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod util;
|
9
common/src/util.rs
Normal file
9
common/src/util.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
pub fn load_or_create_config(path: &str, defaults: &str) -> String {
|
||||
std::fs::read_to_string(path).map_or_else(
|
||||
|_| {
|
||||
std::fs::write(path, defaults).unwrap();
|
||||
defaults.to_string()
|
||||
},
|
||||
|data| data,
|
||||
)
|
||||
}
|
|
@ -8,7 +8,6 @@ ansi_term.workspace = true
|
|||
anyhow.workspace = true
|
||||
atomic_refcell.workspace = true
|
||||
dirs.workspace = true
|
||||
dotenv.workspace = true
|
||||
env_logger.workspace = true
|
||||
hex.workspace = true
|
||||
lazy_static.workspace = true
|
||||
|
@ -27,6 +26,7 @@ tracing-log.workspace = true
|
|||
tracing-subscriber.workspace = true
|
||||
tracing-bunyan-formatter.workspace = true
|
||||
|
||||
common.workspace = true
|
||||
protocol.workspace = true
|
||||
qwer.workspace = true
|
||||
|
||||
|
|
5
gameserver/gameserver.default.json
Normal file
5
gameserver/gameserver.default.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"gateway_endpoint": "0.0.0.0:10301",
|
||||
"skip_tutorial": false,
|
||||
"system_resources_logging": false
|
||||
}
|
22
gameserver/src/config.rs
Normal file
22
gameserver/src/config.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use common::util::load_or_create_config;
|
||||
use lazy_static::lazy_static;
|
||||
use serde::Deserialize;
|
||||
|
||||
const DEFAULT_CONFIG: &str = include_str!("../gameserver.default.json");
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct GameServerConfig {
|
||||
pub gateway_endpoint: String,
|
||||
pub skip_tutorial: bool,
|
||||
pub system_resources_logging: bool,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref CONFIGURATION: GameServerConfig =
|
||||
serde_json::from_str(&load_or_create_config("gameserver.json", DEFAULT_CONFIG))
|
||||
.expect("Failed to parse server configuration file");
|
||||
}
|
||||
|
||||
pub fn init_config() {
|
||||
let _configuration = &*CONFIGURATION; // init static
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
use std::env;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
static ref SKIP_TUTORIAL: i32 = env::var("SKIP_TUTORIAL").map_or(0, |v| v.parse().unwrap());
|
||||
}
|
||||
|
||||
pub fn should_skip_tutorial() -> bool {
|
||||
*SKIP_TUTORIAL != 0
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
mod context;
|
||||
pub mod data;
|
||||
pub mod globals;
|
||||
pub mod manager;
|
||||
pub mod util;
|
||||
|
||||
|
|
|
@ -23,7 +23,10 @@ macro_rules! log_error {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn init_tracing() {
|
||||
pub fn init_logging() {
|
||||
#[cfg(target_os = "windows")]
|
||||
ansi_term::enable_ansi_support().unwrap();
|
||||
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,56 +1,28 @@
|
|||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use config::init_assets;
|
||||
use tracing::Level;
|
||||
|
||||
mod config;
|
||||
mod data;
|
||||
mod game;
|
||||
mod logging;
|
||||
mod net;
|
||||
|
||||
use logging::{init_system_logging, init_tracing};
|
||||
|
||||
const GATE_HOST: &str = "0.0.0.0";
|
||||
const GATE_PORT: u16 = 10301;
|
||||
use config::{init_config, CONFIGURATION};
|
||||
use data::init_assets;
|
||||
use logging::{init_logging, init_system_logging};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
#[cfg(target_os = "windows")]
|
||||
ansi_term::enable_ansi_support().unwrap();
|
||||
|
||||
init_config()?;
|
||||
init_logging();
|
||||
init_config();
|
||||
init_assets()?;
|
||||
init_tracing();
|
||||
|
||||
let span = tracing::span!(Level::DEBUG, "main");
|
||||
let _enter = span.enter();
|
||||
|
||||
if CONFIGURATION.system_resources_logging {
|
||||
init_system_logging().await;
|
||||
|
||||
net::gateway::listen(GATE_HOST, GATE_PORT).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init_config() -> Result<()> {
|
||||
let local_dotenv = Path::new(".env");
|
||||
if local_dotenv.exists() {
|
||||
dotenv::dotenv()?;
|
||||
} else {
|
||||
let config = dirs::config_dir()
|
||||
.ok_or_else(|| anyhow::anyhow!("No config directory found"))?
|
||||
.join("nap-gameserver");
|
||||
|
||||
std::fs::create_dir_all(&config)?;
|
||||
|
||||
let env = config.join(".env");
|
||||
|
||||
if !env.exists() {
|
||||
std::fs::write(&env, "SKIP_TUTORIAL=0")?;
|
||||
}
|
||||
|
||||
dotenv::from_path(&env)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
net::gateway::listen(&CONFIGURATION.gateway_endpoint).await
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ use crate::log_error;
|
|||
|
||||
use super::NetworkSession;
|
||||
|
||||
pub async fn listen(host: &str, port: u16) -> Result<()> {
|
||||
let listener = TcpListener::bind(format!("{host}:{port}")).await?;
|
||||
tracing::info!("Listening at {host}:{port}");
|
||||
pub async fn listen(bind_addr: &str) -> Result<()> {
|
||||
let listener = TcpListener::bind(bind_addr).await?;
|
||||
tracing::info!("Listening at {bind_addr}");
|
||||
|
||||
loop {
|
||||
let Ok((client_socket, client_addr)) = listener.accept().await else {
|
||||
|
|
|
@ -2,8 +2,9 @@ use qwer::{
|
|||
pdkhashmap, phashmap, phashset, PropertyDoubleKeyHashMap, PropertyHashMap, PropertyHashSet,
|
||||
};
|
||||
|
||||
use crate::config;
|
||||
use crate::game::{globals, util};
|
||||
use crate::config::CONFIGURATION;
|
||||
use crate::data;
|
||||
use crate::game::util;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -17,7 +18,7 @@ pub async fn on_rpc_run_event_graph_arg(
|
|||
let unit = scene_unit_mgr.get(arg.owner_uid);
|
||||
|
||||
let SceneUnitProtocolInfo::NpcProtocolInfo { tag, id, .. } = unit;
|
||||
let main_city_object = config::get_main_city_object(tag, id).unwrap();
|
||||
let main_city_object = data::get_main_city_object(tag, id).unwrap();
|
||||
|
||||
let mut ptc_sync_event_info = PtcSyncEventInfoArg {
|
||||
owner_type: EventGraphOwnerType::SceneUnit,
|
||||
|
@ -89,7 +90,7 @@ pub async fn on_rpc_interact_with_unit_arg(
|
|||
let unit = scene_unit_mgr.get(arg.unit_uid);
|
||||
|
||||
let SceneUnitProtocolInfo::NpcProtocolInfo { tag, id, .. } = unit;
|
||||
let main_city_object = config::get_main_city_object(tag, id).unwrap();
|
||||
let main_city_object = data::get_main_city_object(tag, id).unwrap();
|
||||
|
||||
let mut ptc_sync_event_info = PtcSyncEventInfoArg {
|
||||
owner_type: EventGraphOwnerType::SceneUnit,
|
||||
|
@ -152,7 +153,7 @@ fn create_player(id: u64) -> PlayerInfo {
|
|||
z: 11.18,
|
||||
});
|
||||
|
||||
if globals::should_skip_tutorial() {
|
||||
if CONFIGURATION.skip_tutorial {
|
||||
let beginner_procedure = player.beginner_procedure_info.as_mut().unwrap();
|
||||
beginner_procedure.procedure_info.replace(6);
|
||||
player.nick_name.replace(String::from("xeondev"));
|
||||
|
@ -207,7 +208,7 @@ pub async fn on_rpc_enter_world_arg(
|
|||
item_manager.add_resource(10, 228);
|
||||
item_manager.add_resource(100, 1337);
|
||||
|
||||
for avatar_id in config::iter_avatar_config_collection()
|
||||
for avatar_id in data::iter_avatar_config_collection()
|
||||
.map(|c| c.id)
|
||||
.filter(|id| *id < 2000)
|
||||
{
|
||||
|
@ -215,7 +216,7 @@ pub async fn on_rpc_enter_world_arg(
|
|||
}
|
||||
|
||||
let unlock_manager = session.context.unlock_manager.borrow();
|
||||
for unlock_id in config::iter_unlock_config_collection().map(|c| c.id) {
|
||||
for unlock_id in data::iter_unlock_config_collection().map(|c| c.id) {
|
||||
unlock_manager.unlock(unlock_id);
|
||||
}
|
||||
|
||||
|
@ -257,7 +258,7 @@ pub async fn on_rpc_enter_world_arg(
|
|||
let yorozuya_quest_manager = session.context.yorozuya_quest_manager.borrow();
|
||||
yorozuya_quest_manager.add_hollow_quest(102, HollowQuestType::SideQuest, 10010002);
|
||||
|
||||
if globals::should_skip_tutorial() {
|
||||
if CONFIGURATION.skip_tutorial {
|
||||
Box::pin(enter_main_city(session)).await?;
|
||||
} else {
|
||||
let fresh_scene_uid = *dungeon_manager.create_fresh().unwrap();
|
||||
|
|
Loading…
Reference in a new issue