Change update_duration to tick_rate and tweak favicon_png.

This commit is contained in:
Ryan 2022-04-30 18:01:41 -07:00
parent a0892faa72
commit 27e818d6cd
5 changed files with 34 additions and 58 deletions

View file

@ -1,6 +1,5 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use log::LevelFilter; use log::LevelFilter;
use valence::client::GameMode; use valence::client::GameMode;
@ -17,13 +16,11 @@ pub fn main() -> ShutdownResult {
.init(); .init();
valence::start_server(Game { valence::start_server(Game {
favicon: Arc::from(include_bytes!("favicon.png").as_slice()),
player_count: AtomicUsize::new(0), player_count: AtomicUsize::new(0),
}) })
} }
struct Game { struct Game {
favicon: Arc<[u8]>,
player_count: AtomicUsize, player_count: AtomicUsize,
} }
@ -102,7 +99,7 @@ impl Config for Game {
online_players: self.player_count.load(Ordering::SeqCst) as i32, online_players: self.player_count.load(Ordering::SeqCst) as i32,
max_players: MAX_PLAYERS as i32, max_players: MAX_PLAYERS as i32,
description: "Hello Valence!".color(Color::AQUA), description: "Hello Valence!".color(Color::AQUA),
favicon_png: Some(self.favicon.clone()), favicon_png: Some(include_bytes!("favicon.png")),
} }
} }

View file

@ -27,8 +27,8 @@ use crate::util::{chunks_in_view_distance, is_chunk_in_view_distance};
use crate::var_int::VarInt; use crate::var_int::VarInt;
use crate::world::WorldId; use crate::world::WorldId;
use crate::{ use crate::{
glm, ident, ChunkPos, ChunkStore, EntityId, EntityStore, Server, SharedServer, Text, Ticks, glm, ident, ChunkPos, ChunkStore, EntityId, EntityStore, Server, Text, Ticks, WorldStore,
WorldStore, LIBRARY_NAMESPACE, LIBRARY_NAMESPACE,
}; };
pub struct ClientStore { pub struct ClientStore {
@ -386,7 +386,7 @@ impl Client {
} }
// Check if it's time to send another keepalive. // Check if it's time to send another keepalive.
if other.last_keepalive == other.tick_start() { if other.current_tick() % (other.tick_rate() * 8) == 0 {
if self.got_keepalive { if self.got_keepalive {
let id = rand::random(); let id = rand::random();
self.send_packet(KeepAliveClientbound { id }); self.send_packet(KeepAliveClientbound { id });

View file

@ -1,13 +1,11 @@
use std::any::Any; use std::any::Any;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::panic::{RefUnwindSafe, UnwindSafe}; use std::panic::{RefUnwindSafe, UnwindSafe};
use std::sync::Arc;
use std::time::Duration;
use async_trait::async_trait; use async_trait::async_trait;
use tokio::runtime::Handle as TokioHandle; use tokio::runtime::Handle as TokioHandle;
use crate::{ident, Id, Identifier, NewClientData, Server, SharedServer, Text}; use crate::{ident, Id, Identifier, NewClientData, Server, SharedServer, Text, Ticks};
/// A trait containing callbacks which are invoked by the running Minecraft /// A trait containing callbacks which are invoked by the running Minecraft
/// server. /// server.
@ -41,20 +39,19 @@ pub trait Config: Any + Send + Sync + UnwindSafe + RefUnwindSafe {
SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 25565).into() SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 25565).into()
} }
/// Called once at startup to get the duration of each game update. /// Called once at startup to get the tick rate, which is the number of game
/// updates that should occur in one second.
/// ///
/// On each game update (a.k.a. tick), the server is expected to update game /// On each game update (tick), the server is expected to update game logic
/// logic and respond to packets from clients. Once this is complete, /// and respond to packets from clients. Once this is complete, the server
/// the server will sleep for any remaining time until the full update /// will sleep for any remaining time until a full tick has passed.
/// duration has passed.
/// ///
/// The duration must be nonzero. /// The tick rate must be greater than zero.
/// ///
/// # Default Implementation /// # Default Implementation
/// Returns 1/20th of a second, which is the same as Minecraft's official /// Returns `20`, which is the same as Minecraft's official server.
/// server. fn tick_rate(&self) -> Ticks {
fn update_duration(&self) -> Duration { 20
Duration::from_secs_f64(1.0 / 20.0)
} }
/// Called once at startup to get the "online mode" option, which determines /// Called once at startup to get the "online mode" option, which determines
@ -200,7 +197,7 @@ pub trait Config: Any + Send + Sync + UnwindSafe + RefUnwindSafe {
/// The result of the [`server_list_ping`](Handler::server_list_ping) callback. /// The result of the [`server_list_ping`](Handler::server_list_ping) callback.
#[derive(Debug)] #[derive(Debug)]
pub enum ServerListPing { pub enum ServerListPing<'a> {
/// Responds to the server list ping with the given information. /// Responds to the server list ping with the given information.
Respond { Respond {
online_players: i32, online_players: i32,
@ -210,7 +207,7 @@ pub enum ServerListPing {
/// The image must be 64x64 pixels. /// The image must be 64x64 pixels.
/// ///
/// No icon is used if the value is `None`. /// No icon is used if the value is `None`.
favicon_png: Option<Arc<[u8]>>, favicon_png: Option<&'a [u8]>,
}, },
/// Ignores the query and disconnects from the client. /// Ignores the query and disconnects from the client.
Ignore, Ignore,

View file

@ -67,8 +67,6 @@ pub struct Other {
tick_counter: Ticks, tick_counter: Ticks,
/// The instant the current game tick began. /// The instant the current game tick began.
tick_start: Instant, tick_start: Instant,
/// The time the last keep alive packet was sent to all players.
pub(crate) last_keepalive: Instant,
} }
/// A server handle providing the subset of functionality which can be performed /// A server handle providing the subset of functionality which can be performed
@ -80,7 +78,7 @@ pub struct SharedServer(Arc<SharedServerInner>);
struct SharedServerInner { struct SharedServerInner {
cfg: Box<dyn Config>, cfg: Box<dyn Config>,
address: SocketAddr, address: SocketAddr,
update_duration: Duration, tick_rate: Ticks,
online_mode: bool, online_mode: bool,
max_connections: usize, max_connections: usize,
incoming_packet_capacity: usize, incoming_packet_capacity: usize,
@ -153,8 +151,8 @@ impl SharedServer {
self.0.address self.0.address
} }
pub fn update_duration(&self) -> Duration { pub fn tick_rate(&self) -> Ticks {
self.0.update_duration self.0.tick_rate
} }
pub fn online_mode(&self) -> bool { pub fn online_mode(&self) -> bool {
@ -277,12 +275,9 @@ pub fn start_server(config: impl Config) -> ShutdownResult {
fn setup_server(cfg: impl Config) -> anyhow::Result<Server> { fn setup_server(cfg: impl Config) -> anyhow::Result<Server> {
let max_connections = cfg.max_connections(); let max_connections = cfg.max_connections();
let address = cfg.address(); let address = cfg.address();
let update_duration = cfg.update_duration(); let tick_rate = cfg.tick_rate();
ensure!( ensure!(tick_rate > 0, "tick rate must be greater than zero");
update_duration != Duration::ZERO,
"update duration must be nonzero"
);
let online_mode = cfg.online_mode(); let online_mode = cfg.online_mode();
@ -380,7 +375,7 @@ fn setup_server(cfg: impl Config) -> anyhow::Result<Server> {
let shared = SharedServer(Arc::new(SharedServerInner { let shared = SharedServer(Arc::new(SharedServerInner {
cfg: Box::new(cfg), cfg: Box::new(cfg),
address, address,
update_duration, tick_rate,
online_mode, online_mode,
max_connections, max_connections,
outgoing_packet_capacity, outgoing_packet_capacity,
@ -408,7 +403,6 @@ fn setup_server(cfg: impl Config) -> anyhow::Result<Server> {
tick_counter: 0, tick_counter: 0,
tick_start: Instant::now(), tick_start: Instant::now(),
new_players_rx, new_players_rx,
last_keepalive: Instant::now(),
}, },
}) })
} }
@ -426,21 +420,14 @@ fn do_update_loop(server: &mut Server) -> ShutdownResult {
join_player(server, msg); join_player(server, msg);
} }
const KEEPALIVE_FREQ: Duration = Duration::from_secs(8); server.clients.par_iter_mut().for_each(|(_, client)| {
if server.tick_start().duration_since(server.last_keepalive) >= KEEPALIVE_FREQ { client.update(
server.last_keepalive = server.tick_start(); &server.entities,
} &server.worlds,
&server.chunks,
{ &server.other,
server.clients.par_iter_mut().for_each(|(_, client)| { )
client.update( });
&server.entities,
&server.worlds,
&server.chunks,
&server.other,
)
});
}
server.entities.update(); server.entities.update();
@ -451,7 +438,7 @@ fn do_update_loop(server: &mut Server) -> ShutdownResult {
shared.config().update(server); shared.config().update(server);
// Chunks modified this tick can have their changes applied immediately because // Chunks created this tick can have their changes applied immediately because
// they have not been observed by clients yet. // they have not been observed by clients yet.
server.chunks.par_iter_mut().for_each(|(_, chunk)| { server.chunks.par_iter_mut().for_each(|(_, chunk)| {
if chunk.created_this_tick() { if chunk.created_this_tick() {
@ -461,14 +448,10 @@ fn do_update_loop(server: &mut Server) -> ShutdownResult {
}); });
// Sleep for the remainder of the tick. // Sleep for the remainder of the tick.
thread::sleep( let tick_duration = Duration::from_secs_f64((server.0.tick_rate as f64).recip());
server thread::sleep(tick_duration.saturating_sub(server.tick_start.elapsed()));
.0
.update_duration
.saturating_sub(server.tick_start.elapsed()),
);
server.tick_start = Instant::now();
server.tick_start = Instant::now();
server.tick_counter += 1; server.tick_counter += 1;
} }
} }

View file

@ -59,7 +59,6 @@ impl<T> SlotMap<T> {
pub fn insert(&mut self, val: T) -> Key { pub fn insert(&mut self, val: T) -> Key {
assert!( assert!(
// -1 so that NULL is always invalid.
self.count < u32::MAX, self.count < u32::MAX,
"SlotMap: too many items inserted" "SlotMap: too many items inserted"
); );