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

View file

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

View file

@ -10,6 +10,7 @@ use crate::{
block::{BlockType, BLOCK_INFO},
BlockUpdate, Level,
},
packet::server::ServerPacket,
player::Player,
util::neighbors_minus_up,
CONFIG_FILE,
@ -41,6 +42,8 @@ pub struct ServerData {
pub config: ServerConfig,
/// whether the server config needs to be resaved or not
pub config_needs_saving: bool,
/// whether the server should be stopped
pub stop: bool,
}
impl Server {
@ -70,27 +73,34 @@ impl Server {
free_player_ids: Vec::new(),
config,
config_needs_saving: true,
stop: false,
})),
listener,
})
}
/// 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();
tokio::spawn(async move {
handle_ticks(data).await;
});
loop {
let (stream, addr) = self.listener.accept().await?;
let (stream, addr) = self.listener.accept().await.unwrap();
println!("connection from {addr}");
let data = self.data.clone();
let data = data.clone();
tokio::spawn(async move {
network::handle_stream(stream, addr, data)
.await
.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");
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);

View file

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