Add MakeNPC admin command

This commit is contained in:
juliancoffee 2021-08-15 14:45:50 +03:00
parent e3798e5d2a
commit e9dde3ecec
3 changed files with 55 additions and 18 deletions

View File

@ -1,6 +1,7 @@
use crate::{
assets,
comp::{self, buff::BuffKind, inventory::item::try_all_item_defs, AdminRole as Role, Skill},
generation::try_all_entity_configs,
npc, terrain,
};
use assets::AssetExt;
@ -76,6 +77,7 @@ pub enum ChatCommand {
Lantern,
Light,
MakeBlock,
MakeNpc,
MakeSprite,
Motd,
Object,
@ -242,6 +244,15 @@ lazy_static! {
items
};
/// List of all entity configs. Useful for tab completing
static ref ENTITY_CONFIGS: Vec<String> = {
try_all_entity_configs()
.unwrap_or_else(|e| {
warn!(?e, "Failed to load entity configs");
Vec::new()
})
};
static ref KITS: Vec<String> = {
if let Ok(kits) = KitManifest::load(KIT_MANIFEST_PATH) {
kits.read().0.keys().cloned().collect()
@ -461,6 +472,14 @@ impl ChatCommand {
"Make a block at your location with a color",
Some(Admin),
),
ChatCommand::MakeNpc => cmd(
vec![
Enum("entity_config", ENTITY_CONFIGS.clone(), Required),
Integer("num", 1, Optional),
],
"Spawn entity from config near you",
Some(Admin),
),
ChatCommand::MakeSprite => cmd(
vec![Enum("sprite", SPRITE_KINDS.clone(), Required)],
"Make a sprite at your location",
@ -521,8 +540,8 @@ impl ChatCommand {
"Set the server description",
Some(Admin),
),
// Uses Message because site names can contain spaces, which would be assumed to be
// separators otherwise
// 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",
@ -634,6 +653,7 @@ impl ChatCommand {
ChatCommand::Lantern => "lantern",
ChatCommand::Light => "light",
ChatCommand::MakeBlock => "make_block",
ChatCommand::MakeNpc => "make_npc",
ChatCommand::MakeSprite => "make_sprite",
ChatCommand::Motd => "motd",
ChatCommand::Object => "object",
@ -788,7 +808,6 @@ pub enum ArgumentSpec {
}
impl ArgumentSpec {
#[allow(clippy::nonstandard_macro_braces)] //tmp as of false positive !?
pub fn usage_string(&self) -> String {
match self {
ArgumentSpec::PlayerName(req) => {
@ -836,9 +855,9 @@ impl ArgumentSpec {
ArgumentSpec::SubCommand => "<[/]command> [args...]".to_string(),
ArgumentSpec::Enum(label, _, req) => {
if &Requirement::Required == req {
format! {"<{}>", label}
format!("<{}>", label)
} else {
format! {"[{}]", label}
format!("[{}]", label)
}
},
ArgumentSpec::Boolean(label, _, req) => {

View File

@ -1,5 +1,5 @@
use crate::{
assets::{self, AssetExt},
assets::{self, AssetExt, Error},
comp::{
self, agent, humanoid,
inventory::loadout_builder::{ItemSpec, LoadoutBuilder},
@ -140,6 +140,12 @@ impl EntityConfig {
}
}
/// Return all entity config specifiers
pub fn try_all_entity_configs() -> Result<Vec<String>, Error> {
let configs = assets::load_dir::<EntityConfig>("common.entity", true)?;
Ok(configs.ids().map(|id| id.to_owned()).collect())
}
#[derive(Clone)]
pub struct EntityInfo {
pub pos: Vec3<f32>,
@ -554,10 +560,10 @@ mod tests {
#[test]
fn test_all_entity_assets() {
// It just load everything that could
let entity_configs = assets::load_dir::<EntityConfig>("common.entity", true)
.expect("Failed to access entity directory");
for config_asset in entity_configs.ids() {
// Get list of entity configs, load everything, validate content.
let entity_configs =
try_all_entity_configs().expect("Failed to access entity configs directory");
for config_asset in entity_configs {
// print asset name so we don't need to find errors everywhere
// it'll be ignored by default so you'll see it only in case of errors
//
@ -568,7 +574,7 @@ mod tests {
// 2) Add try_from_asset() for LoadoutBuilder and
// SkillSet builder which will return Result and we will happily
// panic in validate_meta() with the name of config_asset
println!("{}:", config_asset);
println!("{}:", &config_asset);
let EntityConfig {
hands,
@ -577,12 +583,12 @@ mod tests {
loot,
meta,
alignment: _alignment, // can't fail if serialized, it's a boring enum
} = EntityConfig::from_asset_expect(config_asset);
} = EntityConfig::from_asset_expect(&config_asset);
validate_hands(hands, config_asset);
validate_body_and_name(body, name, config_asset);
validate_loot(loot, config_asset);
validate_meta(meta, config_asset);
validate_hands(hands, &config_asset);
validate_body_and_name(body, name, &config_asset);
validate_loot(loot, &config_asset);
validate_meta(meta, &config_asset);
}
}
}

View File

@ -1,6 +1,6 @@
//! # Implementing new commands.
//! To implement a new command, add an instance of `ChatCommand` to
//! `CHAT_COMMANDS` and provide a handler function.
//! To implement a new command provide a handler function
//! in [do_command].
use crate::{
settings::{
@ -68,6 +68,7 @@ impl ChatCommandExt for ChatCommand {
}
type CmdResult<T> = Result<T, String>;
/// Handler function called when the command is executed.
/// # Arguments
/// * `&mut Server` - the `Server` instance executing the command.
@ -140,6 +141,7 @@ fn do_command(
ChatCommand::Lantern => handle_lantern,
ChatCommand::Light => handle_light,
ChatCommand::MakeBlock => handle_make_block,
ChatCommand::MakeNpc => handle_make_npc,
ChatCommand::MakeSprite => handle_make_sprite,
ChatCommand::Motd => handle_motd,
ChatCommand::Object => handle_object,
@ -547,6 +549,16 @@ fn handle_make_block(
}
}
fn handle_make_npc(
_server: &mut Server,
_client: EcsEntity,
_target: EcsEntity,
_args: Vec<String>,
_action: &ChatCommand,
) -> CmdResult<()> {
Err("Not implemented".to_owned())
}
fn handle_make_sprite(
server: &mut Server,
_client: EcsEntity,