#![doc = include_str!("../README.md")]
#![deny(
rustdoc::broken_intra_doc_links,
rustdoc::private_intra_doc_links,
rustdoc::missing_crate_level_docs,
rustdoc::invalid_codeblock_attributes,
rustdoc::invalid_rust_codeblocks,
rustdoc::bare_urls,
rustdoc::invalid_html_tags
)]
#![warn(
trivial_casts,
trivial_numeric_casts,
unused_lifetimes,
unused_import_braces,
unreachable_pub,
clippy::dbg_macro
)]
#![allow(clippy::unusual_byte_groupings)]
mod despawn;
mod uuid;
use std::num::NonZeroU32;
use std::time::Duration;
use bevy_app::prelude::*;
use bevy_app::ScheduleRunnerPlugin;
use bevy_ecs::prelude::*;
pub use despawn::*;
use valence_protocol::CompressionThreshold;
use crate::despawn::despawn_marked_entities;
pub use crate::uuid::*;
pub const DEFAULT_TPS: NonZeroU32 = match NonZeroU32::new(20) {
Some(n) => n,
None => unreachable!(),
};
#[derive(Clone, Resource)]
pub struct ServerSettings {
pub tick_rate: NonZeroU32,
pub compression_threshold: CompressionThreshold,
}
impl Default for ServerSettings {
fn default() -> Self {
Self {
tick_rate: DEFAULT_TPS,
compression_threshold: Some(256),
}
}
}
pub struct ServerPlugin;
impl Plugin for ServerPlugin {
fn build(&self, app: &mut App) {
let settings = app
.world
.get_resource_or_insert_with(ServerSettings::default)
.clone();
app.insert_resource(Server {
current_tick: 0,
threshold: settings.compression_threshold,
tick_rate: settings.tick_rate,
});
let tick_period = Duration::from_secs_f64((settings.tick_rate.get() as f64).recip());
app.add_plugins(ScheduleRunnerPlugin::run_loop(tick_period));
fn increment_tick_counter(mut server: ResMut<Server>) {
server.current_tick += 1;
}
app.add_systems(Last, (increment_tick_counter, despawn_marked_entities));
}
}
#[derive(Resource)]
pub struct Server {
current_tick: i64,
threshold: CompressionThreshold,
tick_rate: NonZeroU32,
}
impl Server {
pub fn current_tick(&self) -> i64 {
self.current_tick
}
pub fn compression_threshold(&self) -> CompressionThreshold {
self.threshold
}
pub fn tick_rate(&self) -> NonZeroU32 {
self.tick_rate
}
}