Add Game mode Command

This commit is contained in:
Snowiiii 2024-08-05 23:11:40 +02:00
parent cb3cb760ac
commit 1e114c008e
3 changed files with 112 additions and 12 deletions

View File

@ -0,0 +1,47 @@
use super::Command;
pub struct GamemodeCommand {}
impl GamemodeCommand {
pub fn new() -> Self {
Self {}
}
}
impl<'a> Command<'a> for GamemodeCommand {
const NAME: &'a str = "gamemode";
const DESCRIPTION: &'a str = "Changes the gamemode for a Player";
fn on_execute(
sender: &mut super::CommandSender<'a>,
command: String,
_server: &mut crate::server::Server,
) {
let player = sender.as_mut_player().unwrap();
let args: Vec<&str> = command.split_whitespace().collect();
if args.len() != 2 {
// todo red
player.send_message("Usage: /gamemode <mode>".into());
return;
}
let mode_str = args[1].to_lowercase();
match mode_str.parse() {
Ok(mode) => {
player.set_gamemode(mode);
player.send_message(format!("Set own game mode to {mode_str}").into());
}
Err(_) => {
// todo red
player.send_message("Invalid gamemode".into());
}
}
}
// todo: support console, (name required)
fn player_required() -> bool {
true
}
}

View File

@ -1,8 +1,10 @@
use gamemode::GamemodeCommand;
use pumpkin::PumpkinCommand; use pumpkin::PumpkinCommand;
use pumpkin_protocol::text::TextComponent; use pumpkin_protocol::text::TextComponent;
use crate::{client::Client, server::Server}; use crate::{client::Client, server::Server};
mod gamemode;
mod pumpkin; mod pumpkin;
/// I think it would be great to split this up into a seperate crate, But idk how i should do that, Because we have to rely on Client and Server /// I think it would be great to split this up into a seperate crate, But idk how i should do that, Because we have to rely on Client and Server
@ -12,6 +14,11 @@ pub trait Command<'a> {
const DESCRIPTION: &'a str; const DESCRIPTION: &'a str;
fn on_execute(sender: &mut CommandSender<'a>, command: String, server: &mut Server); fn on_execute(sender: &mut CommandSender<'a>, command: String, server: &mut Server);
/// Specifies wether the Command Sender has to be a Player
fn player_required() -> bool {
false
}
} }
pub enum CommandSender<'a> { pub enum CommandSender<'a> {
@ -27,13 +34,38 @@ impl<'a> CommandSender<'a> {
CommandSender::Player(c) => c.send_message(text), CommandSender::Player(c) => c.send_message(text),
} }
} }
pub fn is_player(&mut self) -> bool {
match self {
CommandSender::Console => false,
CommandSender::Player(_) => true,
}
}
pub fn is_console(&mut self) -> bool {
match self {
CommandSender::Console => true,
CommandSender::Player(_) => false,
}
}
pub fn as_mut_player(&mut self) -> Option<&mut Client> {
match self {
CommandSender::Player(client) => Some(client),
CommandSender::Console => None,
}
}
} }
pub fn handle_command(sender: &mut CommandSender, command: String, server: &mut Server) { pub fn handle_command(sender: &mut CommandSender, command: String, server: &mut Server) {
let command = command.to_lowercase(); let command = command.to_lowercase();
// an ugly mess i know
if command.starts_with(PumpkinCommand::NAME) { if command.starts_with(PumpkinCommand::NAME) {
PumpkinCommand::on_execute(sender, command, server); PumpkinCommand::on_execute(sender, command, server);
return; return;
} }
if command.starts_with(GamemodeCommand::NAME) {
GamemodeCommand::on_execute(sender, command, server);
return;
}
// todo: red color // todo: red color
sender.send_message("Command not Found".into()); sender.send_message("Command not Found".into());
} }

View File

@ -1,3 +1,5 @@
use std::str::FromStr;
use pumpkin_protocol::VarInt; use pumpkin_protocol::VarInt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -42,13 +44,13 @@ pub enum Hand {
Off, Off,
} }
impl Hand { impl From<VarInt> for Hand {
pub fn from_varint(varint: VarInt) -> Self { fn from(value: VarInt) -> Self {
match varint { match value {
0 => Self::Off, 0 => Self::Off,
1 => Self::Main, 1 => Self::Main,
_ => { _ => {
log::info!("Unexpected Hand {}", varint); log::info!("Unexpected Hand {}", value);
Self::Main Self::Main
} }
} }
@ -61,14 +63,14 @@ pub enum ChatMode {
Hidden, Hidden,
} }
impl ChatMode { impl From<VarInt> for ChatMode {
pub fn from_varint(varint: VarInt) -> Self { fn from(value: VarInt) -> Self {
match varint { match value {
0 => Self::Enabled, 0 => Self::Enabled,
1 => Self::CommandsOnly, 1 => Self::CommandsOnly,
2 => Self::Hidden, 2 => Self::Hidden,
_ => { _ => {
log::info!("Unexpected ChatMode {}", varint); log::info!("Unexpected ChatMode {}", value);
Self::Enabled Self::Enabled
} }
} }
@ -84,21 +86,40 @@ pub enum GameMode {
Spectator, Spectator,
} }
impl GameMode { #[derive(Debug, PartialEq, Eq)]
pub fn from_byte(byte: i8) -> Self { pub struct ParseGameModeError;
match byte {
impl FromStr for GameMode {
type Err = ParseGameModeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"survival" => Ok(Self::Survival),
"creative" => Ok(Self::Creative),
"adventure" => Ok(Self::Adventure),
"spectator" => Ok(Self::Spectator),
_ => Err(ParseGameModeError),
}
}
}
impl From<i8> for GameMode {
fn from(value: i8) -> Self {
match value {
-1 => GameMode::Undefined, -1 => GameMode::Undefined,
0 => GameMode::Survival, 0 => GameMode::Survival,
1 => GameMode::Creative, 1 => GameMode::Creative,
2 => GameMode::Adventure, 2 => GameMode::Adventure,
3 => GameMode::Spectator, 3 => GameMode::Spectator,
_ => { _ => {
log::info!("Unexpected GameMode {}", byte); log::info!("Unexpected GameMode {}", value);
Self::Survival Self::Survival
} }
} }
} }
}
impl GameMode {
pub fn to_byte(self) -> i8 { pub fn to_byte(self) -> i8 {
match self { match self {
Self::Undefined => -1, Self::Undefined => -1,