add /stop command

This commit is contained in:
Zoey 2024-04-23 01:14:17 -07:00
parent e49e35fe82
commit d5530a1449
No known key found for this signature in database
GPG key ID: 8611B896D1AAFAF2
4 changed files with 44 additions and 13 deletions

View file

@ -4,6 +4,7 @@ const CMD_ME: &str = "me";
const CMD_SAY: &str = "say"; const CMD_SAY: &str = "say";
const CMD_SET_PERM: &str = "setperm"; const CMD_SET_PERM: &str = "setperm";
const CMD_KICK: &str = "kick"; const CMD_KICK: &str = "kick";
const CMD_STOP: &str = "stop";
/// enum for possible commands /// enum for possible commands
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -19,10 +20,13 @@ pub enum Command<'m> {
player_username: &'m str, player_username: &'m str,
permissions: PlayerType, permissions: PlayerType,
}, },
/// kicks a player from the server
Kick { Kick {
username: &'m str, username: &'m str,
message: Option<&'m str>, message: Option<&'m str>,
}, },
/// command to stop the server
Stop,
} }
impl<'m> Command<'m> { impl<'m> Command<'m> {
@ -45,6 +49,7 @@ impl<'m> Command<'m> {
let message = (!message.is_empty()).then_some(message); let message = (!message.is_empty()).then_some(message);
Self::Kick { username, message } Self::Kick { username, message }
} }
CMD_STOP => Self::Stop,
_ => return Err(format!("Unknown command: {command_name}")), _ => return Err(format!("Unknown command: {command_name}")),
}) })
} }
@ -53,6 +58,7 @@ impl<'m> Command<'m> {
pub fn perms_required(&self) -> PlayerType { pub fn perms_required(&self) -> PlayerType {
match self { match self {
Self::Me { .. } => PlayerType::Normal, Self::Me { .. } => PlayerType::Normal,
Self::Stop => PlayerType::Operator,
_ => PlayerType::Moderator, _ => PlayerType::Moderator,
} }
} }

View file

@ -29,7 +29,7 @@ async fn main() -> std::io::Result<()> {
println!("starting server with config: {config:#?}"); println!("starting server with config: {config:#?}");
let mut server = Server::new(config).await?; let server = Server::new(config).await?;
server.run().await?; server.run().await?;

View file

@ -10,6 +10,7 @@ use crate::{
block::{BlockType, BLOCK_INFO}, block::{BlockType, BLOCK_INFO},
BlockUpdate, Level, BlockUpdate, Level,
}, },
packet::server::ServerPacket,
player::Player, player::Player,
util::neighbors_minus_up, util::neighbors_minus_up,
CONFIG_FILE, CONFIG_FILE,
@ -41,6 +42,8 @@ pub struct ServerData {
pub config: ServerConfig, pub config: ServerConfig,
/// whether the server config needs to be resaved or not /// whether the server config needs to be resaved or not
pub config_needs_saving: bool, pub config_needs_saving: bool,
/// whether the server should be stopped
pub stop: bool,
} }
impl Server { impl Server {
@ -70,27 +73,34 @@ impl Server {
free_player_ids: Vec::new(), free_player_ids: Vec::new(),
config, config,
config_needs_saving: true, config_needs_saving: true,
stop: false,
})), })),
listener, listener,
}) })
} }
/// starts the server /// starts the server
pub async fn run(&mut self) -> std::io::Result<()> { pub async fn run(self) -> std::io::Result<()> {
let data = self.data.clone(); let data = self.data.clone();
tokio::spawn(async move { tokio::spawn(async move {
handle_ticks(data).await;
});
loop { loop {
let (stream, addr) = self.listener.accept().await?; let (stream, addr) = self.listener.accept().await.unwrap();
println!("connection from {addr}"); println!("connection from {addr}");
let data = self.data.clone(); let data = data.clone();
tokio::spawn(async move { tokio::spawn(async move {
network::handle_stream(stream, addr, data) network::handle_stream(stream, addr, data)
.await .await
.expect("failed to handle client stream"); .expect("failed to handle client stream");
}); });
} }
});
handle_ticks(self.data).await;
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
// TODO: cancel pending tasks/send out "Server is stopping" messages *here* instead of elsewhere
// rn the message isn't guaranteed to actually go out........
Ok(())
} }
} }
@ -111,6 +121,17 @@ async fn handle_ticks(data: Arc<RwLock<ServerData>>) {
.expect("failed to save config file"); .expect("failed to save config file");
data.config_needs_saving = false; data.config_needs_saving = false;
} }
if data.stop {
let packet = ServerPacket::DisconnectPlayer {
disconnect_reason: "Server is stopping!".to_string(),
};
for player in &mut data.players {
player.packets_to_send.push(packet.clone());
}
// TODO: save level before exiting
break;
}
} }
current_tick = current_tick.wrapping_add(1); current_tick = current_tick.wrapping_add(1);

View file

@ -467,6 +467,10 @@ async fn handle_stream_inner(
); );
} }
} }
Command::Stop => {
data.stop = true;
}
} }
} }
Err(msg) => { Err(msg) => {