86 lines
2.8 KiB
Rust
86 lines
2.8 KiB
Rust
|
|
//! Authoritative game simulation.
|
||
|
|
//!
|
||
|
|
//! Used by the dedicated server binary and embedded in the client for
|
||
|
|
//! singleplayer and hosting. Clients only send intents (see
|
||
|
|
//! [`game_core::protocol`]); all game rules run here.
|
||
|
|
|
||
|
|
pub mod actions;
|
||
|
|
pub mod crafting;
|
||
|
|
pub mod movement;
|
||
|
|
pub mod network;
|
||
|
|
pub mod persistence;
|
||
|
|
pub mod players;
|
||
|
|
pub mod scripting;
|
||
|
|
pub mod survival;
|
||
|
|
pub mod world;
|
||
|
|
|
||
|
|
use std::{path::PathBuf, sync::Arc, time::Duration};
|
||
|
|
|
||
|
|
use bevy::prelude::*;
|
||
|
|
use game_core::GameData;
|
||
|
|
|
||
|
|
pub use network::NetworkServerPlugin;
|
||
|
|
|
||
|
|
/// Configuration of the simulation.
|
||
|
|
#[derive(Resource, Clone, Debug)]
|
||
|
|
pub struct ServerSettings {
|
||
|
|
/// Tiled map, relative to the assets directory.
|
||
|
|
pub map: String,
|
||
|
|
/// Where the persistent world is stored. `None` disables saving.
|
||
|
|
pub save_path: Option<PathBuf>,
|
||
|
|
pub autosave_interval: Duration,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Default for ServerSettings {
|
||
|
|
fn default() -> Self {
|
||
|
|
Self {
|
||
|
|
map: game_core::DEFAULT_MAP.to_owned(),
|
||
|
|
save_path: None,
|
||
|
|
autosave_interval: Duration::from_secs(60),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Runs the game world. Requires [`game_core::CorePlugin`] and the replicon plugins.
|
||
|
|
pub struct GameServerPlugin {
|
||
|
|
pub settings: ServerSettings,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Plugin for GameServerPlugin {
|
||
|
|
fn build(&self, app: &mut App) {
|
||
|
|
app.insert_resource(self.settings.clone())
|
||
|
|
.insert_resource(persistence::AutosaveTimer(Timer::new(
|
||
|
|
self.settings.autosave_interval,
|
||
|
|
TimerMode::Repeating,
|
||
|
|
)))
|
||
|
|
.init_resource::<players::Players>()
|
||
|
|
.init_resource::<players::CharacterStore>()
|
||
|
|
.init_resource::<survival::SurvivalTimer>()
|
||
|
|
.add_systems(Startup, (load_scripts, world::setup_world).chain())
|
||
|
|
.add_systems(
|
||
|
|
FixedUpdate,
|
||
|
|
(movement::move_characters, survival::tick_survival),
|
||
|
|
)
|
||
|
|
.add_systems(Update, persistence::autosave)
|
||
|
|
.add_systems(Last, persistence::save_on_exit)
|
||
|
|
.add_observer(players::on_login)
|
||
|
|
.add_observer(players::on_disconnect)
|
||
|
|
.add_observer(movement::on_set_move_dir)
|
||
|
|
.add_observer(actions::on_pick_up)
|
||
|
|
.add_observer(actions::on_drop_item)
|
||
|
|
.add_observer(actions::on_use_item)
|
||
|
|
.add_observer(actions::on_interact)
|
||
|
|
.add_observer(actions::on_craft)
|
||
|
|
.add_observer(actions::on_construct)
|
||
|
|
.add_observer(actions::on_deconstruct);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fn load_scripts(mut commands: Commands, data: Res<GameData>) {
|
||
|
|
let dir = game_core::asset_path("scripts");
|
||
|
|
let engine = scripting::ScriptEngine::load(&dir, &data).unwrap_or_else(|e| panic!("{e}"));
|
||
|
|
info!("compiled scripts from `{}`", dir.display());
|
||
|
|
commands.insert_resource(engine);
|
||
|
|
commands.insert_resource(actions::SharedData(Arc::new(data.clone())));
|
||
|
|
}
|