Compare commits
10 commits
edb33ebeec
...
1485cf975d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1485cf975d | ||
|
|
75779c6fe9 | ||
|
|
ae432d79e9 | ||
|
|
4f202c8ade | ||
|
|
f835beef10 | ||
|
|
9ff3aad199 | ||
|
|
958a6718eb | ||
|
|
72a0cf8c69 | ||
|
|
2ddd24fc82 | ||
|
|
db3e0f846e |
11 changed files with 272 additions and 32 deletions
|
|
@ -1,30 +1,6 @@
|
||||||
use std::{fmt::Display, io::{self, Read, Write}, net::{TcpStream, ToSocketAddrs}};
|
use std::{fmt::Display, io::{self, Read, Write}, net::{TcpStream, ToSocketAddrs}};
|
||||||
|
mod packet_type;
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
use packet_type::PacketType;
|
||||||
enum PacketType {
|
|
||||||
Login = 3,
|
|
||||||
Command = 2,
|
|
||||||
Response = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PacketType {
|
|
||||||
fn to_le_bytes(self) -> [u8; 4] {
|
|
||||||
(self as i32).to_le_bytes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<i32> for PacketType {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
|
||||||
match value {
|
|
||||||
x if x == Self::Login as i32 => Ok(Self::Login),
|
|
||||||
x if x == Self::Command as i32 => Ok(Self::Command),
|
|
||||||
x if x == Self::Response as i32 => Ok(Self::Response),
|
|
||||||
_ => Err(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RconError {
|
pub enum RconError {
|
||||||
25
src/client/packet_type.rs
Normal file
25
src/client/packet_type.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
pub enum PacketType {
|
||||||
|
Login = 3,
|
||||||
|
Command = 2,
|
||||||
|
Response = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketType {
|
||||||
|
pub fn to_le_bytes(self) -> [u8; 4] {
|
||||||
|
(self as i32).to_le_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<i32> for PacketType {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
x if x == Self::Login as i32 => Ok(Self::Login),
|
||||||
|
x if x == Self::Command as i32 => Ok(Self::Command),
|
||||||
|
x if x == Self::Response as i32 => Ok(Self::Response),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/command/ban.rs
Normal file
33
src/command/ban.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct BanCommand {
|
||||||
|
target: Option<super::Selector>,
|
||||||
|
reason: Option<String>,
|
||||||
|
ip: Option<bool>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BanCommand {
|
||||||
|
pub fn target(mut self, target: super::Selector) -> Self {
|
||||||
|
self.target = Some(target);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reason(mut self, reason: impl Into<String>) -> Self {
|
||||||
|
self.reason = Some(reason.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ip(mut self) -> Self {
|
||||||
|
self.ip = Some(true);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
let target = self.target.unwrap_or(super::Selector::Player("nonexistent".to_string()));
|
||||||
|
let ip = self.ip.unwrap_or(false);
|
||||||
|
let mut s = if ip { format!("ban-ip {target}") } else { format!("ban {target}") };
|
||||||
|
if let Some(reason) = self.reason {
|
||||||
|
s.push_str(&format!(" {reason}"));
|
||||||
|
};
|
||||||
|
super::Command(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/command/banlist.rs
Normal file
40
src/command/banlist.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct BanlistCommand<State> {
|
||||||
|
state: PhantomData<State>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NoFilter;
|
||||||
|
pub struct Ips;
|
||||||
|
pub struct Players;
|
||||||
|
|
||||||
|
impl BanlistCommand<NoFilter> {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Self { state: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn players(self) -> BanlistCommand<Players> {
|
||||||
|
BanlistCommand { state: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ips(self) -> BanlistCommand<Ips> {
|
||||||
|
BanlistCommand { state: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
super::Command::raw("banlist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BanlistCommand<Players> {
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
super::Command::raw("banlist players")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BanlistCommand<Ips> {
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
super::Command::raw("banlist ips")
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/command/defaultgamemode.rs
Normal file
17
src/command/defaultgamemode.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DefaultGamemodeCommand {
|
||||||
|
gamemode: Option<super::Gamemode>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefaultGamemodeCommand {
|
||||||
|
pub fn gamemode(mut self, gamemode: super::Gamemode) -> Self {
|
||||||
|
self.gamemode = Some(gamemode);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
let gamemode = self.gamemode.unwrap_or(super::Gamemode::Survival);
|
||||||
|
let s = format!("defaultgamemode {gamemode}");
|
||||||
|
super::Command(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/command/deop.rs
Normal file
17
src/command/deop.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DeopCommand {
|
||||||
|
target: Option<super::Selector>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeopCommand {
|
||||||
|
pub fn target(mut self, target: super::Selector) -> Self {
|
||||||
|
self.target = Some(target);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
let target = self.target.unwrap_or(super::Selector::Executor);
|
||||||
|
let s = format!("deop {target}");
|
||||||
|
super::Command(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/command/difficulty.rs
Normal file
19
src/command/difficulty.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DifficultyCommand {
|
||||||
|
difficulty: Option<super::Difficulty>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DifficultyCommand {
|
||||||
|
pub fn difficulty(mut self, difficulty: super::Difficulty) -> Self {
|
||||||
|
self.difficulty = Some(difficulty);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
let mut s = format!("difficulty");
|
||||||
|
if let Some(difficulty) = self.difficulty {
|
||||||
|
s.push_str(&format!(" {difficulty}"))
|
||||||
|
};
|
||||||
|
super::Command(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/command/gamemode.rs
Normal file
26
src/command/gamemode.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct GamemodeCommand {
|
||||||
|
gamemode: Option<super::Gamemode>,
|
||||||
|
target: Option<super::Selector>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GamemodeCommand {
|
||||||
|
pub fn gamemode(mut self, gamemode: super::Gamemode) -> Self {
|
||||||
|
self.gamemode = Some(gamemode);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn target(mut self, target: super::Selector) -> Self {
|
||||||
|
self.target = Some(target);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
let gamemode = self.gamemode.unwrap_or(super::Gamemode::Survival);
|
||||||
|
let mut s = format!("defaultgamemode {gamemode}");
|
||||||
|
if let Some(target) = self.target {
|
||||||
|
s.push_str(&format!(" {target}"))
|
||||||
|
}
|
||||||
|
super::Command(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,10 +11,7 @@ impl ListCommand {
|
||||||
|
|
||||||
pub fn build(self) -> super::Command {
|
pub fn build(self) -> super::Command {
|
||||||
let uuids = self.uuids.unwrap_or(false);
|
let uuids = self.uuids.unwrap_or(false);
|
||||||
let mut s = format!("list");
|
let s = format!("list {}", if uuids { "uuids" } else {""} );
|
||||||
if uuids {
|
|
||||||
s.push_str(" uuids");
|
|
||||||
}
|
|
||||||
super::Command(s)
|
super::Command(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,7 +8,8 @@ pub enum Selector {
|
||||||
AllPlayers, // @a
|
AllPlayers, // @a
|
||||||
AllEntities, // @e
|
AllEntities, // @e
|
||||||
Executor, // @s
|
Executor, // @s
|
||||||
NearestEntity // @n
|
NearestEntity, // @n,
|
||||||
|
Player(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Selector {
|
impl Display for Selector {
|
||||||
|
|
@ -19,7 +20,44 @@ impl Display for Selector {
|
||||||
Self::AllPlayers => write!(f, "@a"),
|
Self::AllPlayers => write!(f, "@a"),
|
||||||
Self::AllEntities => write!(f, "@e"),
|
Self::AllEntities => write!(f, "@e"),
|
||||||
Self::Executor => write!(f, "@s"),
|
Self::Executor => write!(f, "@s"),
|
||||||
Self::NearestEntity => write!(f, "@n")
|
Self::NearestEntity => write!(f, "@n"),
|
||||||
|
Self::Player(name) => write!(f, "{name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Gamemode {
|
||||||
|
Survival,
|
||||||
|
Creative,
|
||||||
|
Adventure,
|
||||||
|
Spectator
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Gamemode {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Survival => write!(f, "survival"),
|
||||||
|
Self::Creative => write!(f, "creative"),
|
||||||
|
Self::Adventure => write!(f, "adventure"),
|
||||||
|
Self::Spectator => write!(f, "spectator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Difficulty {
|
||||||
|
Peaceful,
|
||||||
|
Easy,
|
||||||
|
Normal,
|
||||||
|
Hard
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Difficulty {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Peaceful => write!(f, "peaceful"),
|
||||||
|
Self::Easy => write!(f, "easy"),
|
||||||
|
Self::Normal => write!(f, "normal"),
|
||||||
|
Self::Hard => write!(f, "hard")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,6 +65,13 @@ impl Display for Selector {
|
||||||
mod say;
|
mod say;
|
||||||
mod list;
|
mod list;
|
||||||
mod kill;
|
mod kill;
|
||||||
|
mod ban;
|
||||||
|
mod banlist;
|
||||||
|
mod defaultgamemode;
|
||||||
|
mod op;
|
||||||
|
mod deop;
|
||||||
|
mod difficulty;
|
||||||
|
mod gamemode;
|
||||||
|
|
||||||
impl Command {
|
impl Command {
|
||||||
pub fn raw(cmd: &str) -> Self {
|
pub fn raw(cmd: &str) -> Self {
|
||||||
|
|
@ -48,4 +93,32 @@ impl Command {
|
||||||
pub fn kill() -> kill::KillCommand {
|
pub fn kill() -> kill::KillCommand {
|
||||||
kill::KillCommand::default()
|
kill::KillCommand::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ban() -> ban::BanCommand {
|
||||||
|
ban::BanCommand::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn banlist() -> banlist::BanlistCommand<banlist::NoFilter> {
|
||||||
|
banlist::BanlistCommand::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn defaultgamemode() -> defaultgamemode::DefaultGamemodeCommand {
|
||||||
|
defaultgamemode::DefaultGamemodeCommand::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn op() -> op::OpCommand {
|
||||||
|
op::OpCommand::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deop() -> deop::DeopCommand {
|
||||||
|
deop::DeopCommand::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn difficulty() -> difficulty::DifficultyCommand {
|
||||||
|
difficulty::DifficultyCommand::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gamemode() -> gamemode::GamemodeCommand {
|
||||||
|
gamemode::GamemodeCommand::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
17
src/command/op.rs
Normal file
17
src/command/op.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct OpCommand {
|
||||||
|
target: Option<super::Selector>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpCommand {
|
||||||
|
pub fn target(mut self, target: super::Selector) -> Self {
|
||||||
|
self.target = Some(target);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> super::Command {
|
||||||
|
let target = self.target.unwrap_or(super::Selector::Executor);
|
||||||
|
let s = format!("op {target}");
|
||||||
|
super::Command(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue