2021-05-04 13:22:10 +00:00
|
|
|
use crate::{
|
|
|
|
assets,
|
|
|
|
comp::{self, buff::BuffKind},
|
|
|
|
npc, terrain,
|
|
|
|
};
|
2021-04-12 18:07:34 +00:00
|
|
|
use assets::AssetExt;
|
2020-12-12 01:45:46 +00:00
|
|
|
use hashbrown::HashMap;
|
2020-05-09 02:42:51 +00:00
|
|
|
use lazy_static::lazy_static;
|
2021-04-12 18:07:34 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2020-06-05 18:12:18 +00:00
|
|
|
use std::{
|
|
|
|
fmt::{self, Display},
|
|
|
|
path::Path,
|
|
|
|
str::FromStr,
|
|
|
|
};
|
2021-05-04 13:22:10 +00:00
|
|
|
use strum::IntoEnumIterator;
|
2020-06-24 03:29:46 +00:00
|
|
|
use tracing::warn;
|
2020-05-05 04:06:36 +00:00
|
|
|
|
|
|
|
/// Struct representing a command that a user can run from server chat.
|
2020-05-05 22:33:16 +00:00
|
|
|
pub struct ChatCommandData {
|
2020-05-11 22:02:21 +00:00
|
|
|
/// A list of arguments useful for both tab completion and parsing
|
2020-05-05 22:33:16 +00:00
|
|
|
pub args: Vec<ArgumentSpec>,
|
2020-05-05 04:06:36 +00:00
|
|
|
/// A one-line message that explains what the command does
|
|
|
|
pub description: &'static str,
|
2020-06-01 04:33:39 +00:00
|
|
|
/// Whether the command requires administrator permissions.
|
|
|
|
pub needs_admin: IsAdminOnly,
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 22:33:16 +00:00
|
|
|
impl ChatCommandData {
|
2020-06-01 04:33:39 +00:00
|
|
|
pub fn new(
|
|
|
|
args: Vec<ArgumentSpec>,
|
|
|
|
description: &'static str,
|
|
|
|
needs_admin: IsAdminOnly,
|
|
|
|
) -> Self {
|
2020-05-05 04:06:36 +00:00
|
|
|
Self {
|
|
|
|
args,
|
|
|
|
description,
|
|
|
|
needs_admin,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-05 22:33:16 +00:00
|
|
|
// Please keep this sorted alphabetically :-)
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub enum ChatCommand {
|
|
|
|
Adminify,
|
2021-03-11 16:48:59 +00:00
|
|
|
Airship,
|
2020-05-05 22:33:16 +00:00
|
|
|
Alias,
|
2021-05-02 21:42:54 +00:00
|
|
|
ApplyBuff,
|
2020-07-15 23:36:03 +00:00
|
|
|
Ban,
|
2020-05-05 22:33:16 +00:00
|
|
|
Build,
|
2021-03-24 07:58:42 +00:00
|
|
|
BuildAreaAdd,
|
2021-03-27 05:53:33 +00:00
|
|
|
BuildAreaList,
|
2021-03-24 07:58:42 +00:00
|
|
|
BuildAreaRemove,
|
2020-07-31 09:34:26 +00:00
|
|
|
Campfire,
|
2020-05-05 22:33:16 +00:00
|
|
|
DebugColumn,
|
2021-04-13 22:05:47 +00:00
|
|
|
DisconnectAllPlayers,
|
2021-01-08 19:12:09 +00:00
|
|
|
DropAll,
|
2020-07-02 21:53:01 +00:00
|
|
|
Dummy,
|
2020-05-05 22:33:16 +00:00
|
|
|
Explosion,
|
2020-06-01 04:33:39 +00:00
|
|
|
Faction,
|
2020-05-05 22:33:16 +00:00
|
|
|
GiveItem,
|
|
|
|
Goto,
|
2020-06-01 04:33:39 +00:00
|
|
|
Group,
|
2020-12-04 02:18:42 +00:00
|
|
|
GroupInvite,
|
|
|
|
GroupKick,
|
|
|
|
GroupLeave,
|
|
|
|
GroupPromote,
|
2020-05-05 22:33:16 +00:00
|
|
|
Health,
|
|
|
|
Help,
|
2020-11-03 23:53:46 +00:00
|
|
|
Home,
|
2020-06-04 09:40:05 +00:00
|
|
|
JoinFaction,
|
2020-05-05 22:33:16 +00:00
|
|
|
Jump,
|
2020-07-15 23:36:03 +00:00
|
|
|
Kick,
|
2020-05-05 22:33:16 +00:00
|
|
|
Kill,
|
|
|
|
KillNpcs,
|
2021-04-12 16:49:08 +00:00
|
|
|
Kit,
|
2020-05-05 22:33:16 +00:00
|
|
|
Lantern,
|
|
|
|
Light,
|
2020-06-27 18:39:16 +00:00
|
|
|
MakeBlock,
|
2020-09-21 15:39:20 +00:00
|
|
|
MakeSprite,
|
2020-06-25 12:07:01 +00:00
|
|
|
Motd,
|
2020-05-05 22:33:16 +00:00
|
|
|
Object,
|
2021-03-23 08:37:29 +00:00
|
|
|
PermitBuild,
|
2020-05-05 22:33:16 +00:00
|
|
|
Players,
|
2020-06-01 04:33:39 +00:00
|
|
|
Region,
|
2020-05-05 22:33:16 +00:00
|
|
|
RemoveLights,
|
2021-03-24 07:58:42 +00:00
|
|
|
RevokeBuild,
|
|
|
|
RevokeBuildAll,
|
2021-02-28 23:14:59 +00:00
|
|
|
Safezone,
|
2020-06-01 04:33:39 +00:00
|
|
|
Say,
|
2021-04-17 17:44:22 +00:00
|
|
|
ServerPhysics,
|
2020-06-25 13:56:21 +00:00
|
|
|
SetMotd,
|
2021-03-27 00:38:56 +00:00
|
|
|
Site,
|
2021-01-06 01:26:21 +00:00
|
|
|
SkillPoint,
|
2020-05-05 22:33:16 +00:00
|
|
|
Spawn,
|
|
|
|
Sudo,
|
|
|
|
Tell,
|
|
|
|
Time,
|
|
|
|
Tp,
|
2020-07-15 23:36:03 +00:00
|
|
|
Unban,
|
2020-05-05 22:33:16 +00:00
|
|
|
Version,
|
|
|
|
Waypoint,
|
2021-04-15 16:28:16 +00:00
|
|
|
Wiring,
|
2020-06-30 12:21:36 +00:00
|
|
|
Whitelist,
|
2020-06-01 04:33:39 +00:00
|
|
|
World,
|
2020-05-05 22:33:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Thank you for keeping this sorted alphabetically :-)
|
2020-06-08 18:37:41 +00:00
|
|
|
pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Adminify,
|
2021-03-11 16:48:59 +00:00
|
|
|
ChatCommand::Airship,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Alias,
|
2021-05-02 21:42:54 +00:00
|
|
|
ChatCommand::ApplyBuff,
|
2020-07-15 23:36:03 +00:00
|
|
|
ChatCommand::Ban,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Build,
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::BuildAreaAdd,
|
2021-03-27 05:53:33 +00:00
|
|
|
ChatCommand::BuildAreaList,
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::BuildAreaRemove,
|
2020-07-31 09:34:26 +00:00
|
|
|
ChatCommand::Campfire,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::DebugColumn,
|
2021-04-13 22:05:47 +00:00
|
|
|
ChatCommand::DisconnectAllPlayers,
|
2021-01-08 19:12:09 +00:00
|
|
|
ChatCommand::DropAll,
|
2020-07-02 21:53:01 +00:00
|
|
|
ChatCommand::Dummy,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Explosion,
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Faction,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::GiveItem,
|
|
|
|
ChatCommand::Goto,
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Group,
|
2020-12-04 02:18:42 +00:00
|
|
|
ChatCommand::GroupInvite,
|
|
|
|
ChatCommand::GroupKick,
|
|
|
|
ChatCommand::GroupLeave,
|
|
|
|
ChatCommand::GroupPromote,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Health,
|
|
|
|
ChatCommand::Help,
|
2020-11-03 23:53:46 +00:00
|
|
|
ChatCommand::Home,
|
2020-06-04 09:40:05 +00:00
|
|
|
ChatCommand::JoinFaction,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Jump,
|
2020-07-15 23:36:03 +00:00
|
|
|
ChatCommand::Kick,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Kill,
|
|
|
|
ChatCommand::KillNpcs,
|
2021-04-12 16:49:08 +00:00
|
|
|
ChatCommand::Kit,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Lantern,
|
|
|
|
ChatCommand::Light,
|
2020-06-27 18:39:16 +00:00
|
|
|
ChatCommand::MakeBlock,
|
2020-09-21 15:39:20 +00:00
|
|
|
ChatCommand::MakeSprite,
|
2020-06-25 12:07:01 +00:00
|
|
|
ChatCommand::Motd,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Object,
|
2021-03-23 08:37:29 +00:00
|
|
|
ChatCommand::PermitBuild,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Players,
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Region,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::RemoveLights,
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::RevokeBuild,
|
|
|
|
ChatCommand::RevokeBuildAll,
|
2021-02-28 23:14:59 +00:00
|
|
|
ChatCommand::Safezone,
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Say,
|
2021-04-17 17:44:22 +00:00
|
|
|
ChatCommand::ServerPhysics,
|
2020-06-25 13:56:21 +00:00
|
|
|
ChatCommand::SetMotd,
|
2021-03-27 00:38:56 +00:00
|
|
|
ChatCommand::Site,
|
2021-01-06 01:26:21 +00:00
|
|
|
ChatCommand::SkillPoint,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Spawn,
|
|
|
|
ChatCommand::Sudo,
|
|
|
|
ChatCommand::Tell,
|
|
|
|
ChatCommand::Time,
|
|
|
|
ChatCommand::Tp,
|
2020-07-15 23:36:03 +00:00
|
|
|
ChatCommand::Unban,
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Version,
|
|
|
|
ChatCommand::Waypoint,
|
2021-04-15 16:28:16 +00:00
|
|
|
ChatCommand::Wiring,
|
2020-06-30 12:21:36 +00:00
|
|
|
ChatCommand::Whitelist,
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::World,
|
2020-05-05 22:33:16 +00:00
|
|
|
];
|
|
|
|
|
2021-04-12 18:07:34 +00:00
|
|
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
|
|
|
pub struct KitManifest(pub HashMap<String, Vec<(String, u32)>>);
|
|
|
|
impl assets::Asset for KitManifest {
|
|
|
|
type Loader = assets::RonLoader;
|
|
|
|
|
|
|
|
const EXTENSION: &'static str = "ron";
|
|
|
|
}
|
|
|
|
|
2020-05-09 02:42:51 +00:00
|
|
|
lazy_static! {
|
2020-06-05 18:12:18 +00:00
|
|
|
pub static ref CHAT_SHORTCUTS: HashMap<char, ChatCommand> = [
|
|
|
|
('f', ChatCommand::Faction),
|
|
|
|
('g', ChatCommand::Group),
|
|
|
|
('r', ChatCommand::Region),
|
|
|
|
('s', ChatCommand::Say),
|
|
|
|
('t', ChatCommand::Tell),
|
|
|
|
('w', ChatCommand::World),
|
|
|
|
].iter().cloned().collect();
|
|
|
|
|
2020-05-09 02:42:51 +00:00
|
|
|
static ref ALIGNMENTS: Vec<String> = vec!["wild", "enemy", "npc", "pet"]
|
|
|
|
.iter()
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
.collect();
|
2021-01-06 01:26:21 +00:00
|
|
|
static ref SKILL_TREES: Vec<String> = vec!["general", "sword", "axe", "hammer", "bow", "staff", "sceptre"]
|
|
|
|
.iter()
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
.collect();
|
2020-12-12 22:14:24 +00:00
|
|
|
/// TODO: Make this use hot-reloading
|
2020-05-09 02:42:51 +00:00
|
|
|
static ref ENTITIES: Vec<String> = {
|
2020-12-12 22:14:24 +00:00
|
|
|
let npc_names = &*npc::NPC_NAMES.read();
|
2020-05-09 02:42:51 +00:00
|
|
|
npc::ALL_NPCS
|
|
|
|
.iter()
|
|
|
|
.map(|&npc| npc_names[npc].keyword.clone())
|
|
|
|
.collect()
|
|
|
|
};
|
|
|
|
static ref OBJECTS: Vec<String> = comp::object::ALL_OBJECTS
|
|
|
|
.iter()
|
|
|
|
.map(|o| o.to_string().to_string())
|
|
|
|
.collect();
|
|
|
|
static ref TIMES: Vec<String> = vec![
|
|
|
|
"midnight", "night", "dawn", "morning", "day", "noon", "dusk"
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
.collect();
|
2020-05-11 22:02:21 +00:00
|
|
|
|
2021-05-04 13:22:10 +00:00
|
|
|
pub static ref BUFF_PARSER: HashMap<String, BuffKind> = {
|
|
|
|
let string_from_buff = |kind| match kind {
|
|
|
|
BuffKind::Burning => "burning",
|
|
|
|
BuffKind::Regeneration => "regeration",
|
|
|
|
BuffKind::Saturation => "saturation",
|
|
|
|
BuffKind::Bleeding => "bleeding",
|
|
|
|
BuffKind::Cursed => "cursed",
|
|
|
|
BuffKind::Potion => "potion",
|
|
|
|
BuffKind::CampfireHeal => "campfire_heal",
|
|
|
|
BuffKind::IncreaseMaxEnergy => "increase_max_energy",
|
|
|
|
BuffKind::IncreaseMaxHealth => "increase_max_health",
|
|
|
|
BuffKind::Invulnerability => "invulnerability",
|
|
|
|
BuffKind::ProtectingWard => "protecting_ward",
|
|
|
|
BuffKind::Frenzied => "frenzied",
|
|
|
|
BuffKind::Crippled => "crippled",
|
|
|
|
};
|
|
|
|
let mut buff_parser = HashMap::new();
|
|
|
|
BuffKind::iter().for_each(|kind| {buff_parser.insert(string_from_buff(kind).to_string(), kind);});
|
|
|
|
buff_parser
|
|
|
|
};
|
|
|
|
|
|
|
|
pub static ref BUFF_PACK: Vec<String> = {
|
|
|
|
let mut buff_pack: Vec<_> = BUFF_PARSER.keys().cloned().collect();
|
|
|
|
// Remove invulnerability as it removes debuffs
|
|
|
|
buff_pack.retain(|kind| kind != "invulnerability");
|
|
|
|
buff_pack
|
|
|
|
};
|
|
|
|
|
|
|
|
static ref BUFFS: Vec<String> = {
|
|
|
|
let mut buff_pack: Vec<_> = BUFF_PARSER.keys().cloned().collect();
|
|
|
|
// Add all as valid command
|
|
|
|
buff_pack.push("all".to_string());
|
|
|
|
buff_pack
|
|
|
|
};
|
2021-05-02 21:42:54 +00:00
|
|
|
|
2020-06-27 18:39:16 +00:00
|
|
|
static ref BLOCK_KINDS: Vec<String> = terrain::block::BLOCK_KINDS
|
|
|
|
.keys()
|
|
|
|
.cloned()
|
|
|
|
.collect();
|
|
|
|
|
2020-09-21 15:39:20 +00:00
|
|
|
static ref SPRITE_KINDS: Vec<String> = terrain::sprite::SPRITE_KINDS
|
|
|
|
.keys()
|
|
|
|
.cloned()
|
|
|
|
.collect();
|
|
|
|
|
2020-05-11 22:02:21 +00:00
|
|
|
/// List of item specifiers. Useful for tab completing
|
|
|
|
static ref ITEM_SPECS: Vec<String> = {
|
|
|
|
let path = assets::ASSETS_PATH.join("common").join("items");
|
|
|
|
let mut items = vec![];
|
|
|
|
fn list_items (path: &Path, base: &Path, mut items: &mut Vec<String>) -> std::io::Result<()>{
|
|
|
|
for entry in std::fs::read_dir(path)? {
|
|
|
|
let path = entry?.path();
|
|
|
|
if path.is_dir(){
|
|
|
|
list_items(&path, &base, &mut items)?;
|
2020-06-08 18:37:41 +00:00
|
|
|
} else if let Ok(path) = path.strip_prefix(base) {
|
|
|
|
let path = path.to_string_lossy().trim_end_matches(".ron").replace('/', ".");
|
|
|
|
items.push(path);
|
2020-05-11 22:02:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
if list_items(&path, &assets::ASSETS_PATH, &mut items).is_err() {
|
|
|
|
warn!("There was a problem listing item assets");
|
|
|
|
}
|
|
|
|
items.sort();
|
|
|
|
items
|
|
|
|
};
|
2021-04-12 18:07:34 +00:00
|
|
|
|
|
|
|
static ref KITS: Vec<String> = {
|
|
|
|
if let Ok(kits) = KitManifest::load("server.manifests.kits") {
|
|
|
|
kits.read().0.keys().cloned().collect()
|
|
|
|
} else {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
};
|
2020-05-09 02:42:51 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 22:33:16 +00:00
|
|
|
impl ChatCommand {
|
|
|
|
pub fn data(&self) -> ChatCommandData {
|
|
|
|
use ArgumentSpec::*;
|
2020-06-01 04:33:39 +00:00
|
|
|
use IsAdminOnly::*;
|
2020-05-09 02:42:51 +00:00
|
|
|
use Requirement::*;
|
2020-05-05 22:33:16 +00:00
|
|
|
let cmd = ChatCommandData::new;
|
|
|
|
match self {
|
|
|
|
ChatCommand::Adminify => cmd(
|
2020-05-09 02:42:51 +00:00
|
|
|
vec![PlayerName(Required)],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Temporarily gives a player admin permissions or removes them",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
2021-03-12 22:14:08 +00:00
|
|
|
ChatCommand::Airship => cmd(
|
|
|
|
vec![Float("destination_degrees_ccw_of_east", 90.0, Optional)],
|
|
|
|
"Spawns an airship",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Alias => cmd(vec![Any("name", Required)], "Change your alias", NoAdmin),
|
2021-05-02 21:42:54 +00:00
|
|
|
ChatCommand::ApplyBuff => cmd(
|
|
|
|
vec![
|
|
|
|
Enum("buff", BUFFS.clone(), Required),
|
|
|
|
Float("strength", 0.01, Optional),
|
|
|
|
Float("duration", 10.0, Optional),
|
|
|
|
],
|
|
|
|
"Cast a buff on player",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-07-15 23:36:03 +00:00
|
|
|
ChatCommand::Ban => cmd(
|
2020-07-16 00:03:22 +00:00
|
|
|
vec![Any("username", Required), Message(Optional)],
|
2020-07-15 23:36:03 +00:00
|
|
|
"Ban a player with a given username",
|
2020-08-09 15:14:44 +00:00
|
|
|
Admin,
|
2020-07-15 23:36:03 +00:00
|
|
|
),
|
2021-03-23 08:37:29 +00:00
|
|
|
ChatCommand::Build => cmd(vec![], "Toggles build mode on and off", NoAdmin),
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::BuildAreaAdd => cmd(
|
|
|
|
vec![
|
|
|
|
Any("name", Required),
|
|
|
|
Integer("xlo", 0, Required),
|
|
|
|
Integer("xhi", 10, Required),
|
|
|
|
Integer("ylo", 0, Required),
|
|
|
|
Integer("yhi", 10, Required),
|
|
|
|
Integer("zlo", 0, Required),
|
|
|
|
Integer("zhi", 10, Required),
|
|
|
|
],
|
|
|
|
"Adds a new build area",
|
|
|
|
Admin,
|
|
|
|
),
|
2021-03-27 05:53:33 +00:00
|
|
|
ChatCommand::BuildAreaList => cmd(vec![], "List all build areas", Admin),
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::BuildAreaRemove => cmd(
|
|
|
|
vec![Any("name", Required)],
|
|
|
|
"Removes specified build area",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-07-31 09:34:26 +00:00
|
|
|
ChatCommand::Campfire => cmd(vec![], "Spawns a campfire", Admin),
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::DebugColumn => cmd(
|
2020-05-09 20:41:29 +00:00
|
|
|
vec![Integer("x", 15000, Required), Integer("y", 15000, Required)],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Prints some debug information about a column",
|
2020-06-01 04:33:39 +00:00
|
|
|
NoAdmin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
2021-04-13 22:05:47 +00:00
|
|
|
ChatCommand::DisconnectAllPlayers => cmd(
|
|
|
|
vec![Any("confirm", Required)],
|
|
|
|
"Disconnects all players from the server",
|
|
|
|
Admin,
|
|
|
|
),
|
2021-01-08 19:12:09 +00:00
|
|
|
ChatCommand::DropAll => cmd(vec![], "Drops all your items on the ground", Admin),
|
2020-09-05 14:12:35 +00:00
|
|
|
ChatCommand::Dummy => cmd(vec![], "Spawns a training dummy", Admin),
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Explosion => cmd(
|
2020-05-09 02:42:51 +00:00
|
|
|
vec![Float("radius", 5.0, Required)],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Explodes the ground around you",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
|
|
|
),
|
|
|
|
ChatCommand::Faction => cmd(
|
|
|
|
vec![Message(Optional)],
|
|
|
|
"Send messages to your faction",
|
|
|
|
NoAdmin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
|
|
|
ChatCommand::GiveItem => cmd(
|
2020-05-09 20:41:29 +00:00
|
|
|
vec![
|
2020-05-11 22:02:21 +00:00
|
|
|
Enum("item", ITEM_SPECS.clone(), Required),
|
2020-05-09 20:41:29 +00:00
|
|
|
Integer("num", 1, Optional),
|
|
|
|
],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Give yourself some items",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
|
|
|
ChatCommand::Goto => cmd(
|
|
|
|
vec![
|
2020-05-09 02:42:51 +00:00
|
|
|
Float("x", 0.0, Required),
|
|
|
|
Float("y", 0.0, Required),
|
|
|
|
Float("z", 0.0, Required),
|
2020-05-05 22:33:16 +00:00
|
|
|
],
|
|
|
|
"Teleport to a position",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
|
|
|
),
|
|
|
|
ChatCommand::Group => cmd(
|
|
|
|
vec![Message(Optional)],
|
|
|
|
"Send messages to your group",
|
|
|
|
NoAdmin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
2020-12-04 02:18:42 +00:00
|
|
|
ChatCommand::GroupInvite => cmd(
|
|
|
|
vec![PlayerName(Required)],
|
|
|
|
"Invite a player to join a group",
|
|
|
|
NoAdmin,
|
|
|
|
),
|
|
|
|
ChatCommand::GroupKick => cmd(
|
|
|
|
vec![PlayerName(Required)],
|
|
|
|
"Remove a player from a group",
|
|
|
|
NoAdmin,
|
|
|
|
),
|
|
|
|
ChatCommand::GroupLeave => cmd(vec![], "Leave the current group", NoAdmin),
|
|
|
|
ChatCommand::GroupPromote => cmd(
|
|
|
|
vec![PlayerName(Required)],
|
|
|
|
"Promote a player to group leader",
|
|
|
|
NoAdmin,
|
|
|
|
),
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Health => cmd(
|
2020-05-09 02:42:51 +00:00
|
|
|
vec![Integer("hp", 100, Required)],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Set your current health",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
|
|
|
ChatCommand::Help => ChatCommandData::new(
|
2020-05-09 02:42:51 +00:00
|
|
|
vec![Command(Optional)],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Display information about commands",
|
2020-06-01 04:33:39 +00:00
|
|
|
NoAdmin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
2020-11-03 23:53:46 +00:00
|
|
|
ChatCommand::Home => cmd(vec![], "Return to the home town", NoAdmin),
|
2020-06-04 09:40:05 +00:00
|
|
|
ChatCommand::JoinFaction => ChatCommandData::new(
|
|
|
|
vec![Any("faction", Optional)],
|
|
|
|
"Join/leave the specified faction",
|
|
|
|
NoAdmin,
|
|
|
|
),
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Jump => cmd(
|
|
|
|
vec![
|
2020-05-09 02:42:51 +00:00
|
|
|
Float("x", 0.0, Required),
|
|
|
|
Float("y", 0.0, Required),
|
|
|
|
Float("z", 0.0, Required),
|
2020-05-05 22:33:16 +00:00
|
|
|
],
|
|
|
|
"Offset your current position",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
2020-07-15 23:36:03 +00:00
|
|
|
ChatCommand::Kick => cmd(
|
2020-07-16 00:03:22 +00:00
|
|
|
vec![Any("username", Required), Message(Optional)],
|
2020-07-15 23:36:03 +00:00
|
|
|
"Kick a player with a given username",
|
2020-08-09 15:14:44 +00:00
|
|
|
Admin,
|
2020-07-15 23:36:03 +00:00
|
|
|
),
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Kill => cmd(vec![], "Kill yourself", NoAdmin),
|
|
|
|
ChatCommand::KillNpcs => cmd(vec![], "Kill the NPCs", Admin),
|
2021-04-12 16:49:08 +00:00
|
|
|
ChatCommand::Kit => cmd(
|
2021-04-12 18:07:34 +00:00
|
|
|
vec![Enum("kit_name", KITS.to_vec(), Required)],
|
2021-04-12 16:49:08 +00:00
|
|
|
"Place a set of items into your inventory.",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Lantern => cmd(
|
|
|
|
vec![
|
2020-05-09 02:42:51 +00:00
|
|
|
Float("strength", 5.0, Required),
|
|
|
|
Float("r", 1.0, Optional),
|
|
|
|
Float("g", 1.0, Optional),
|
|
|
|
Float("b", 1.0, Optional),
|
2020-05-05 22:33:16 +00:00
|
|
|
],
|
|
|
|
"Change your lantern's strength and color",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
|
|
|
ChatCommand::Light => cmd(
|
|
|
|
vec![
|
2020-05-09 02:42:51 +00:00
|
|
|
Float("r", 1.0, Optional),
|
|
|
|
Float("g", 1.0, Optional),
|
|
|
|
Float("b", 1.0, Optional),
|
|
|
|
Float("x", 0.0, Optional),
|
|
|
|
Float("y", 0.0, Optional),
|
|
|
|
Float("z", 0.0, Optional),
|
|
|
|
Float("strength", 5.0, Optional),
|
2020-05-05 22:33:16 +00:00
|
|
|
],
|
|
|
|
"Spawn entity with light",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
2020-06-27 18:39:16 +00:00
|
|
|
ChatCommand::MakeBlock => cmd(
|
|
|
|
vec![Enum("block", BLOCK_KINDS.clone(), Required)],
|
2020-09-21 15:39:20 +00:00
|
|
|
"Make a block at your location",
|
|
|
|
Admin,
|
|
|
|
),
|
|
|
|
ChatCommand::MakeSprite => cmd(
|
|
|
|
vec![Enum("sprite", SPRITE_KINDS.clone(), Required)],
|
|
|
|
"Make a sprite at your location",
|
2020-06-27 18:39:16 +00:00
|
|
|
Admin,
|
|
|
|
),
|
2020-06-27 23:12:12 +00:00
|
|
|
ChatCommand::Motd => cmd(
|
|
|
|
vec![Message(Optional)],
|
|
|
|
"View the server description",
|
|
|
|
NoAdmin,
|
|
|
|
),
|
2020-05-09 02:42:51 +00:00
|
|
|
ChatCommand::Object => cmd(
|
|
|
|
vec![Enum("object", OBJECTS.clone(), Required)],
|
|
|
|
"Spawn an object",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-09 02:42:51 +00:00
|
|
|
),
|
2021-03-23 08:37:29 +00:00
|
|
|
ChatCommand::PermitBuild => cmd(
|
2021-03-27 05:53:33 +00:00
|
|
|
vec![Any("area_name", Required)],
|
2021-03-23 08:37:29 +00:00
|
|
|
"Grants player a bounded box they can build in",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Players => cmd(vec![], "Lists players currently online", NoAdmin),
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::RemoveLights => cmd(
|
2020-05-09 02:42:51 +00:00
|
|
|
vec![Float("radius", 20.0, Optional)],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Removes all lights spawned by players",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
|
|
|
),
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::RevokeBuild => cmd(
|
2021-03-27 05:53:33 +00:00
|
|
|
vec![Any("area_name", Required)],
|
|
|
|
"Revokes build area permission for player",
|
2021-03-24 07:58:42 +00:00
|
|
|
Admin,
|
|
|
|
),
|
|
|
|
ChatCommand::RevokeBuildAll => cmd(
|
2021-03-27 05:53:33 +00:00
|
|
|
vec![],
|
|
|
|
"Revokes all build area permissions for player",
|
2021-03-24 07:58:42 +00:00
|
|
|
Admin,
|
|
|
|
),
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Region => cmd(
|
|
|
|
vec![Message(Optional)],
|
|
|
|
"Send messages to everyone in your region of the world",
|
|
|
|
NoAdmin,
|
|
|
|
),
|
2021-02-28 23:14:59 +00:00
|
|
|
ChatCommand::Safezone => cmd(
|
|
|
|
vec![Float("range", 100.0, Optional)],
|
|
|
|
"Creates a safezone",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Say => cmd(
|
|
|
|
vec![Message(Optional)],
|
|
|
|
"Send messages to everyone within shouting distance",
|
|
|
|
NoAdmin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
2021-04-17 17:44:22 +00:00
|
|
|
ChatCommand::ServerPhysics => cmd(
|
|
|
|
vec![
|
|
|
|
Any("username", Required),
|
|
|
|
Boolean("enabled", "true".to_string(), Optional),
|
|
|
|
],
|
|
|
|
"Set/unset server-authoritative physics for an account",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-06-27 23:12:12 +00:00
|
|
|
ChatCommand::SetMotd => {
|
|
|
|
cmd(vec![Message(Optional)], "Set the server description", Admin)
|
|
|
|
},
|
2021-03-27 00:38:56 +00:00
|
|
|
// Uses Message because site names can contain spaces, which would be assumed to be
|
|
|
|
// separators otherwise
|
|
|
|
ChatCommand::Site => cmd(vec![Message(Required)], "Teleport to a site", Admin),
|
2021-01-06 01:26:21 +00:00
|
|
|
ChatCommand::SkillPoint => cmd(
|
|
|
|
vec![
|
|
|
|
Enum("skill tree", SKILL_TREES.clone(), Required),
|
|
|
|
Integer("amount", 1, Optional),
|
|
|
|
],
|
|
|
|
"Give yourself skill points for a particular skill tree",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-05-09 02:42:51 +00:00
|
|
|
ChatCommand::Spawn => cmd(
|
|
|
|
vec![
|
|
|
|
Enum("alignment", ALIGNMENTS.clone(), Required),
|
|
|
|
Enum("entity", ENTITIES.clone(), Required),
|
|
|
|
Integer("amount", 1, Optional),
|
2020-07-02 21:53:01 +00:00
|
|
|
Boolean("ai", "true".to_string(), Optional),
|
2020-05-09 02:42:51 +00:00
|
|
|
],
|
|
|
|
"Spawn a test entity",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-09 02:42:51 +00:00
|
|
|
),
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Sudo => cmd(
|
2020-05-09 02:42:51 +00:00
|
|
|
vec![PlayerName(Required), SubCommand],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Run command as if you were another player",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
|
|
|
ChatCommand::Tell => cmd(
|
2020-06-01 04:33:39 +00:00
|
|
|
vec![PlayerName(Required), Message(Optional)],
|
2020-05-05 22:33:16 +00:00
|
|
|
"Send a message to another player",
|
2020-06-01 04:33:39 +00:00
|
|
|
NoAdmin,
|
2020-05-05 22:33:16 +00:00
|
|
|
),
|
2020-05-09 02:42:51 +00:00
|
|
|
ChatCommand::Time => cmd(
|
|
|
|
vec![Enum("time", TIMES.clone(), Optional)],
|
|
|
|
"Set the time of day",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-09 02:42:51 +00:00
|
|
|
),
|
|
|
|
ChatCommand::Tp => cmd(
|
|
|
|
vec![PlayerName(Optional)],
|
|
|
|
"Teleport to another player",
|
2020-06-01 04:33:39 +00:00
|
|
|
Admin,
|
2020-05-09 02:42:51 +00:00
|
|
|
),
|
2020-08-09 15:14:44 +00:00
|
|
|
ChatCommand::Unban => cmd(
|
2020-07-15 23:36:03 +00:00
|
|
|
vec![Any("username", Required)],
|
|
|
|
"Remove the ban for the given username",
|
2020-08-09 15:14:44 +00:00
|
|
|
Admin,
|
2020-07-15 23:36:03 +00:00
|
|
|
),
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Version => cmd(vec![], "Prints server version", NoAdmin),
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Waypoint => {
|
2020-06-01 04:33:39 +00:00
|
|
|
cmd(vec![], "Set your waypoint to your current position", Admin)
|
2020-05-05 22:33:16 +00:00
|
|
|
},
|
2021-04-15 16:28:16 +00:00
|
|
|
ChatCommand::Wiring => cmd(vec![], "Create wiring element", Admin),
|
2020-06-30 12:21:36 +00:00
|
|
|
ChatCommand::Whitelist => cmd(
|
|
|
|
vec![Any("add/remove", Required), Any("username", Required)],
|
|
|
|
"Adds/removes username to whitelist",
|
|
|
|
Admin,
|
|
|
|
),
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::World => cmd(
|
|
|
|
vec![Message(Optional)],
|
|
|
|
"Send messages to everyone on the server",
|
|
|
|
NoAdmin,
|
|
|
|
),
|
2020-05-05 22:33:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-11 22:02:21 +00:00
|
|
|
/// The keyword used to invoke the command, omitting the leading '/'.
|
2020-05-05 22:33:16 +00:00
|
|
|
pub fn keyword(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
ChatCommand::Adminify => "adminify",
|
2021-03-11 16:48:59 +00:00
|
|
|
ChatCommand::Airship => "airship",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Alias => "alias",
|
2021-05-02 21:42:54 +00:00
|
|
|
ChatCommand::ApplyBuff => "buff",
|
2020-07-15 23:36:03 +00:00
|
|
|
ChatCommand::Ban => "ban",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Build => "build",
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::BuildAreaAdd => "build_area_add",
|
2021-03-27 05:53:33 +00:00
|
|
|
ChatCommand::BuildAreaList => "build_area_list",
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::BuildAreaRemove => "build_area_remove",
|
2020-07-31 09:34:26 +00:00
|
|
|
ChatCommand::Campfire => "campfire",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::DebugColumn => "debug_column",
|
2021-04-13 22:05:47 +00:00
|
|
|
ChatCommand::DisconnectAllPlayers => "disconnect_all_players",
|
2021-01-08 19:12:09 +00:00
|
|
|
ChatCommand::DropAll => "dropall",
|
2020-07-02 21:53:01 +00:00
|
|
|
ChatCommand::Dummy => "dummy",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Explosion => "explosion",
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Faction => "faction",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::GiveItem => "give_item",
|
|
|
|
ChatCommand::Goto => "goto",
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Group => "group",
|
2020-12-04 02:18:42 +00:00
|
|
|
ChatCommand::GroupInvite => "group_invite",
|
|
|
|
ChatCommand::GroupKick => "group_kick",
|
|
|
|
ChatCommand::GroupPromote => "group_promote",
|
|
|
|
ChatCommand::GroupLeave => "group_leave",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Health => "health",
|
2020-06-04 09:40:05 +00:00
|
|
|
ChatCommand::JoinFaction => "join_faction",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Help => "help",
|
2020-11-03 23:53:46 +00:00
|
|
|
ChatCommand::Home => "home",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Jump => "jump",
|
2020-07-15 23:36:03 +00:00
|
|
|
ChatCommand::Kick => "kick",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Kill => "kill",
|
2021-04-12 16:49:08 +00:00
|
|
|
ChatCommand::Kit => "kit",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::KillNpcs => "kill_npcs",
|
|
|
|
ChatCommand::Lantern => "lantern",
|
|
|
|
ChatCommand::Light => "light",
|
2020-06-27 18:39:16 +00:00
|
|
|
ChatCommand::MakeBlock => "make_block",
|
2020-09-21 15:39:20 +00:00
|
|
|
ChatCommand::MakeSprite => "make_sprite",
|
2020-06-25 12:07:01 +00:00
|
|
|
ChatCommand::Motd => "motd",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Object => "object",
|
2021-03-23 08:37:29 +00:00
|
|
|
ChatCommand::PermitBuild => "permit_build",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Players => "players",
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Region => "region",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::RemoveLights => "remove_lights",
|
2021-03-24 07:58:42 +00:00
|
|
|
ChatCommand::RevokeBuild => "revoke_build",
|
|
|
|
ChatCommand::RevokeBuildAll => "revoke_build_all",
|
2021-02-28 23:14:59 +00:00
|
|
|
ChatCommand::Safezone => "safezone",
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::Say => "say",
|
2021-04-17 17:44:22 +00:00
|
|
|
ChatCommand::ServerPhysics => "server_physics",
|
2020-06-25 13:56:21 +00:00
|
|
|
ChatCommand::SetMotd => "set_motd",
|
2021-03-27 00:38:56 +00:00
|
|
|
ChatCommand::Site => "site",
|
2021-01-06 01:26:21 +00:00
|
|
|
ChatCommand::SkillPoint => "skill_point",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Spawn => "spawn",
|
|
|
|
ChatCommand::Sudo => "sudo",
|
|
|
|
ChatCommand::Tell => "tell",
|
|
|
|
ChatCommand::Time => "time",
|
|
|
|
ChatCommand::Tp => "tp",
|
2020-07-15 23:36:03 +00:00
|
|
|
ChatCommand::Unban => "unban",
|
2020-05-05 22:33:16 +00:00
|
|
|
ChatCommand::Version => "version",
|
|
|
|
ChatCommand::Waypoint => "waypoint",
|
2021-04-15 16:28:16 +00:00
|
|
|
ChatCommand::Wiring => "wiring",
|
2020-06-30 12:21:36 +00:00
|
|
|
ChatCommand::Whitelist => "whitelist",
|
2020-06-01 04:33:39 +00:00
|
|
|
ChatCommand::World => "world",
|
2020-05-05 22:33:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-11 22:02:21 +00:00
|
|
|
/// A message that explains what the command does
|
2020-05-05 22:33:16 +00:00
|
|
|
pub fn help_string(&self) -> String {
|
|
|
|
let data = self.data();
|
|
|
|
let usage = std::iter::once(format!("/{}", self.keyword()))
|
|
|
|
.chain(data.args.iter().map(|arg| arg.usage_string()))
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(" ");
|
|
|
|
format!("{}: {}", usage, data.description)
|
|
|
|
}
|
|
|
|
|
2020-05-11 22:02:21 +00:00
|
|
|
/// A boolean that is used to check whether the command requires
|
|
|
|
/// administrator permissions or not.
|
2020-06-12 17:44:29 +00:00
|
|
|
pub fn needs_admin(&self) -> bool { IsAdminOnly::Admin == self.data().needs_admin }
|
2020-05-05 22:33:16 +00:00
|
|
|
|
2020-05-11 22:02:21 +00:00
|
|
|
/// Returns a format string for parsing arguments with scan_fmt
|
2020-05-05 22:33:16 +00:00
|
|
|
pub fn arg_fmt(&self) -> String {
|
|
|
|
self.data()
|
|
|
|
.args
|
|
|
|
.iter()
|
|
|
|
.map(|arg| match arg {
|
|
|
|
ArgumentSpec::PlayerName(_) => "{}",
|
2020-05-08 21:38:58 +00:00
|
|
|
ArgumentSpec::Float(_, _, _) => "{}",
|
2020-05-05 22:33:16 +00:00
|
|
|
ArgumentSpec::Integer(_, _, _) => "{d}",
|
|
|
|
ArgumentSpec::Any(_, _) => "{}",
|
|
|
|
ArgumentSpec::Command(_) => "{}",
|
2020-06-01 04:33:39 +00:00
|
|
|
ArgumentSpec::Message(_) => "{/.*/}",
|
2020-05-08 21:38:58 +00:00
|
|
|
ArgumentSpec::SubCommand => "{} {/.*/}",
|
2020-06-05 18:12:18 +00:00
|
|
|
ArgumentSpec::Enum(_, _, _) => "{}",
|
2020-07-02 21:53:01 +00:00
|
|
|
ArgumentSpec::Boolean(_, _, _) => "{}",
|
2020-05-05 22:33:16 +00:00
|
|
|
})
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(" ")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-05 18:12:18 +00:00
|
|
|
impl Display for ChatCommand {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
write!(f, "{}", self.keyword())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-09 02:42:51 +00:00
|
|
|
impl FromStr for ChatCommand {
|
2020-05-05 22:33:16 +00:00
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(keyword: &str) -> Result<ChatCommand, ()> {
|
2021-01-08 19:12:09 +00:00
|
|
|
let kwd = if let Some(stripped) = keyword.strip_prefix('/') {
|
|
|
|
stripped
|
2020-05-05 22:33:16 +00:00
|
|
|
} else {
|
2021-01-08 19:12:09 +00:00
|
|
|
&keyword
|
2020-05-05 22:33:16 +00:00
|
|
|
};
|
2020-06-05 18:12:18 +00:00
|
|
|
if keyword.len() == 1 {
|
|
|
|
if let Some(c) = keyword
|
|
|
|
.chars()
|
2020-06-24 05:46:29 +00:00
|
|
|
.next()
|
2020-06-05 18:12:18 +00:00
|
|
|
.as_ref()
|
|
|
|
.and_then(|k| CHAT_SHORTCUTS.get(k))
|
|
|
|
{
|
2020-05-05 22:33:16 +00:00
|
|
|
return Ok(*c);
|
|
|
|
}
|
2020-06-05 18:12:18 +00:00
|
|
|
} else {
|
|
|
|
for c in CHAT_COMMANDS {
|
|
|
|
if kwd == c.keyword() {
|
|
|
|
return Ok(*c);
|
|
|
|
}
|
|
|
|
}
|
2020-05-05 22:33:16 +00:00
|
|
|
}
|
2020-06-08 18:37:41 +00:00
|
|
|
Err(())
|
2020-05-05 22:33:16 +00:00
|
|
|
}
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
|
2020-06-12 17:44:29 +00:00
|
|
|
#[derive(Eq, PartialEq, Debug)]
|
2020-06-01 04:33:39 +00:00
|
|
|
pub enum IsAdminOnly {
|
|
|
|
Admin,
|
|
|
|
NoAdmin,
|
|
|
|
}
|
|
|
|
|
2020-06-12 17:44:29 +00:00
|
|
|
#[derive(Eq, PartialEq, Debug)]
|
2020-05-09 02:42:51 +00:00
|
|
|
pub enum Requirement {
|
|
|
|
Required,
|
|
|
|
Optional,
|
|
|
|
}
|
|
|
|
|
2020-05-05 04:06:36 +00:00
|
|
|
/// Representation for chat command arguments
|
2020-05-05 22:33:16 +00:00
|
|
|
pub enum ArgumentSpec {
|
2020-05-05 04:06:36 +00:00
|
|
|
/// The argument refers to a player by alias
|
2020-05-09 02:42:51 +00:00
|
|
|
PlayerName(Requirement),
|
2020-05-05 04:06:36 +00:00
|
|
|
/// The argument is a float. The associated values are
|
|
|
|
/// * label
|
2020-05-09 02:42:51 +00:00
|
|
|
/// * suggested tab-completion
|
2020-05-05 04:06:36 +00:00
|
|
|
/// * whether it's optional
|
2020-05-09 02:42:51 +00:00
|
|
|
Float(&'static str, f32, Requirement),
|
2020-05-05 04:06:36 +00:00
|
|
|
/// The argument is a float. The associated values are
|
|
|
|
/// * label
|
2020-05-09 02:42:51 +00:00
|
|
|
/// * suggested tab-completion
|
2020-05-05 04:06:36 +00:00
|
|
|
/// * whether it's optional
|
2020-05-09 02:42:51 +00:00
|
|
|
Integer(&'static str, i32, Requirement),
|
2020-05-05 22:33:16 +00:00
|
|
|
/// The argument is any string that doesn't contain spaces
|
2020-05-09 02:42:51 +00:00
|
|
|
Any(&'static str, Requirement),
|
|
|
|
/// The argument is a command name (such as in /help)
|
|
|
|
Command(Requirement),
|
2020-05-05 22:33:16 +00:00
|
|
|
/// This is the final argument, consuming all characters until the end of
|
|
|
|
/// input.
|
2020-06-01 04:33:39 +00:00
|
|
|
Message(Requirement),
|
2020-05-08 05:35:07 +00:00
|
|
|
/// This command is followed by another command (such as in /sudo)
|
|
|
|
SubCommand,
|
2020-05-05 04:06:36 +00:00
|
|
|
/// The argument is likely an enum. The associated values are
|
|
|
|
/// * label
|
|
|
|
/// * Predefined string completions
|
|
|
|
/// * whether it's optional
|
2020-05-09 02:42:51 +00:00
|
|
|
Enum(&'static str, Vec<String>, Requirement),
|
2020-07-02 21:53:01 +00:00
|
|
|
/// The argument is likely a boolean. The associated values are
|
|
|
|
/// * label
|
|
|
|
/// * suggested tab-completion
|
|
|
|
/// * whether it's optional
|
|
|
|
Boolean(&'static str, String, Requirement),
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 22:33:16 +00:00
|
|
|
impl ArgumentSpec {
|
|
|
|
pub fn usage_string(&self) -> String {
|
|
|
|
match self {
|
2020-05-09 02:42:51 +00:00
|
|
|
ArgumentSpec::PlayerName(req) => {
|
2020-06-12 17:44:29 +00:00
|
|
|
if &Requirement::Required == req {
|
2020-05-05 04:06:36 +00:00
|
|
|
"<player>".to_string()
|
|
|
|
} else {
|
2020-05-09 02:42:51 +00:00
|
|
|
"[player]".to_string()
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
},
|
2020-05-09 02:42:51 +00:00
|
|
|
ArgumentSpec::Float(label, _, req) => {
|
2020-06-12 17:44:29 +00:00
|
|
|
if &Requirement::Required == req {
|
2020-05-05 04:06:36 +00:00
|
|
|
format!("<{}>", label)
|
2020-05-09 02:42:51 +00:00
|
|
|
} else {
|
|
|
|
format!("[{}]", label)
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
},
|
2020-05-09 02:42:51 +00:00
|
|
|
ArgumentSpec::Integer(label, _, req) => {
|
2020-06-12 17:44:29 +00:00
|
|
|
if &Requirement::Required == req {
|
2020-05-05 04:06:36 +00:00
|
|
|
format!("<{}>", label)
|
2020-05-09 02:42:51 +00:00
|
|
|
} else {
|
|
|
|
format!("[{}]", label)
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
},
|
2020-05-09 02:42:51 +00:00
|
|
|
ArgumentSpec::Any(label, req) => {
|
2020-06-12 17:44:29 +00:00
|
|
|
if &Requirement::Required == req {
|
2020-05-05 22:33:16 +00:00
|
|
|
format!("<{}>", label)
|
2020-05-09 02:42:51 +00:00
|
|
|
} else {
|
|
|
|
format!("[{}]", label)
|
2020-05-05 22:33:16 +00:00
|
|
|
}
|
|
|
|
},
|
2020-05-09 02:42:51 +00:00
|
|
|
ArgumentSpec::Command(req) => {
|
2020-06-12 17:44:29 +00:00
|
|
|
if &Requirement::Required == req {
|
2020-05-05 04:06:36 +00:00
|
|
|
"<[/]command>".to_string()
|
2020-05-09 02:42:51 +00:00
|
|
|
} else {
|
|
|
|
"[[/]command]".to_string()
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
},
|
2020-06-01 04:33:39 +00:00
|
|
|
ArgumentSpec::Message(req) => {
|
2020-06-12 17:44:29 +00:00
|
|
|
if &Requirement::Required == req {
|
2020-06-01 04:33:39 +00:00
|
|
|
"<message>".to_string()
|
|
|
|
} else {
|
2020-06-12 17:44:29 +00:00
|
|
|
"[message]".to_string()
|
2020-06-01 04:33:39 +00:00
|
|
|
}
|
|
|
|
},
|
2020-05-08 05:35:07 +00:00
|
|
|
ArgumentSpec::SubCommand => "<[/]command> [args...]".to_string(),
|
2020-05-09 02:42:51 +00:00
|
|
|
ArgumentSpec::Enum(label, _, req) => {
|
2020-06-12 17:44:29 +00:00
|
|
|
if &Requirement::Required == req {
|
2020-05-05 04:06:36 +00:00
|
|
|
format! {"<{}>", label}
|
2020-05-09 02:42:51 +00:00
|
|
|
} else {
|
|
|
|
format! {"[{}]", label}
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
},
|
2020-07-02 21:53:01 +00:00
|
|
|
ArgumentSpec::Boolean(label, _, req) => {
|
|
|
|
if &Requirement::Required == req {
|
|
|
|
format!("<{}>", label)
|
|
|
|
} else {
|
|
|
|
format!("[{}]", label)
|
|
|
|
}
|
|
|
|
},
|
2020-05-05 04:06:36 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-08 05:35:07 +00:00
|
|
|
}
|