add play sound command
Its simple and there are many arguments missing but its works
This commit is contained in:
parent
daf3b29bb2
commit
6c78567a83
@ -1,14 +1,27 @@
|
||||
use heck::ToPascalCase;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use crate::array_to_tokenstream;
|
||||
use crate::{array_to_tokenstream, ident};
|
||||
|
||||
pub(crate) fn build() -> TokenStream {
|
||||
println!("cargo:rerun-if-changed=../assets/sounds.json");
|
||||
|
||||
let sound: Vec<String> = serde_json::from_str(include_str!("../../assets/sounds.json"))
|
||||
.expect("Failed to parse sounds.json");
|
||||
let variants = array_to_tokenstream(sound);
|
||||
let variants = array_to_tokenstream(sound.clone());
|
||||
|
||||
let type_from_name = &sound
|
||||
.iter()
|
||||
.map(|sound| {
|
||||
let id = &sound;
|
||||
let name = ident(sound.to_pascal_case());
|
||||
|
||||
quote! {
|
||||
#id => Some(Self::#name),
|
||||
}
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
quote! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@ -16,5 +29,14 @@ pub(crate) fn build() -> TokenStream {
|
||||
pub enum Sound {
|
||||
#variants
|
||||
}
|
||||
|
||||
impl Sound {
|
||||
pub fn from_name(name: &str) -> Option<Self> {
|
||||
match name {
|
||||
#type_from_name
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
74
pumpkin/src/command/args/arg_sound.rs
Normal file
74
pumpkin/src/command/args/arg_sound.rs
Normal file
@ -0,0 +1,74 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::sound::Sound;
|
||||
use pumpkin_protocol::client::play::{
|
||||
CommandSuggestion, ProtoCmdArgParser, ProtoCmdArgSuggestionType,
|
||||
};
|
||||
|
||||
use crate::{command::dispatcher::CommandError, server::Server};
|
||||
|
||||
use super::{
|
||||
super::{
|
||||
args::{ArgumentConsumer, RawArgs},
|
||||
CommandSender,
|
||||
},
|
||||
Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser,
|
||||
};
|
||||
|
||||
pub(crate) struct SoundArgumentConsumer;
|
||||
|
||||
impl GetClientSideArgParser for SoundArgumentConsumer {
|
||||
fn get_client_side_parser(&self) -> ProtoCmdArgParser {
|
||||
ProtoCmdArgParser::ResourceLocation
|
||||
}
|
||||
|
||||
fn get_client_side_suggestion_type_override(&self) -> Option<ProtoCmdArgSuggestionType> {
|
||||
Some(ProtoCmdArgSuggestionType::AvailableSounds)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ArgumentConsumer for SoundArgumentConsumer {
|
||||
async fn consume<'a>(
|
||||
&'a self,
|
||||
_sender: &CommandSender<'a>,
|
||||
_server: &'a Server,
|
||||
args: &mut RawArgs<'a>,
|
||||
) -> Option<Arg<'a>> {
|
||||
let s = args.pop()?;
|
||||
Some(Arg::Block(s))
|
||||
}
|
||||
|
||||
async fn suggest<'a>(
|
||||
&'a self,
|
||||
_sender: &CommandSender<'a>,
|
||||
_server: &'a Server,
|
||||
_input: &'a str,
|
||||
) -> Result<Option<Vec<CommandSuggestion>>, CommandError> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for SoundArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"available_sounds".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FindArg<'a> for SoundArgumentConsumer {
|
||||
type Data = Sound;
|
||||
|
||||
fn find_arg(args: &'a super::ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
match args.get(name) {
|
||||
Some(Arg::Block(name)) => Sound::from_name(&name.replace("minecraft:", ""))
|
||||
.map_or_else(
|
||||
|| {
|
||||
Err(CommandError::GeneralCommandIssue(format!(
|
||||
"Sound {name} does not exist."
|
||||
)))
|
||||
},
|
||||
Result::Ok,
|
||||
),
|
||||
_ => Err(CommandError::InvalidConsumption(Some(name.to_string()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,6 +37,7 @@ pub(crate) mod arg_position_block;
|
||||
pub(crate) mod arg_resource_location;
|
||||
pub(crate) mod arg_rotation;
|
||||
pub(crate) mod arg_simple;
|
||||
pub(crate) mod arg_sound;
|
||||
pub(crate) mod arg_textcomponent;
|
||||
mod coordinate;
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ use CommandError::InvalidConsumption;
|
||||
|
||||
const NAMES: [&str; 1] = ["deop"];
|
||||
const DESCRIPTION: &str = "Revokes operator status from a player.";
|
||||
const ARG_TARGET: &str = "player";
|
||||
const ARG_TARGETS: &str = "targets";
|
||||
|
||||
struct DeopExecutor;
|
||||
|
||||
@ -27,13 +27,11 @@ impl CommandExecutor for DeopExecutor {
|
||||
) -> Result<(), CommandError> {
|
||||
let mut config = OPERATOR_CONFIG.write().await;
|
||||
|
||||
let Some(Arg::Players(targets)) = args.get(&ARG_TARGET) else {
|
||||
return Err(InvalidConsumption(Some(ARG_TARGET.into())));
|
||||
let Some(Arg::Players(targets)) = args.get(&ARG_TARGETS) else {
|
||||
return Err(InvalidConsumption(Some(ARG_TARGETS.into())));
|
||||
};
|
||||
|
||||
// from the command tree, the command can only be executed with one player
|
||||
let player = &targets[0];
|
||||
|
||||
for player in targets {
|
||||
if let Some(op_index) = config
|
||||
.ops
|
||||
.iter()
|
||||
@ -51,14 +49,15 @@ impl CommandExecutor for DeopExecutor {
|
||||
.await;
|
||||
|
||||
let player_name = &player.gameprofile.name;
|
||||
let msg = TextComponent::translate("commands.deop.success", [player_name.clone().into()]);
|
||||
let msg =
|
||||
TextComponent::translate("commands.deop.success", [player_name.clone().into()]);
|
||||
sender.send_message(msg).await;
|
||||
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.with_child(argument(ARG_TARGET, PlayersArgumentConsumer).execute(DeopExecutor))
|
||||
.with_child(argument(ARG_TARGETS, PlayersArgumentConsumer).execute(DeopExecutor))
|
||||
}
|
||||
|
||||
49
pumpkin/src/command/commands/cmd_playsound.rs
Normal file
49
pumpkin/src/command/commands/cmd_playsound.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::sound::SoundCategory;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::command::{
|
||||
args::{arg_sound::SoundArgumentConsumer, ConsumedArgs, FindArg},
|
||||
tree::CommandTree,
|
||||
tree_builder::argument,
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
};
|
||||
const NAMES: [&str; 1] = ["playsound"];
|
||||
|
||||
const DESCRIPTION: &str = "Plays a sound at a position.";
|
||||
|
||||
const ARG_SOUND: &str = "sound";
|
||||
|
||||
struct SoundExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for SoundExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
_server: &crate::server::Server,
|
||||
args: &ConsumedArgs<'a>,
|
||||
) -> Result<(), CommandError> {
|
||||
let sound = SoundArgumentConsumer::find_arg(args, ARG_SOUND)?;
|
||||
|
||||
if let Some(player) = sender.as_player() {
|
||||
let seed = thread_rng().gen::<f64>();
|
||||
player
|
||||
.play_sound(
|
||||
sound as u16,
|
||||
SoundCategory::Master,
|
||||
&player.living_entity.entity.pos.load(),
|
||||
1.0,
|
||||
1.0,
|
||||
seed,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.with_child(argument(ARG_SOUND, SoundArgumentConsumer).execute(SoundExecutor))
|
||||
}
|
||||
@ -13,7 +13,7 @@ const NAMES: [&str; 1] = ["setblock"];
|
||||
const DESCRIPTION: &str = "Place a block.";
|
||||
|
||||
const ARG_BLOCK: &str = "block";
|
||||
const ARG_BLOCK_POS: &str = "position";
|
||||
const ARG_BLOCK_POS: &str = "pos";
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Mode {
|
||||
|
||||
@ -10,6 +10,7 @@ pub mod cmd_kill;
|
||||
pub mod cmd_list;
|
||||
pub mod cmd_me;
|
||||
pub mod cmd_op;
|
||||
pub mod cmd_playsound;
|
||||
pub mod cmd_pumpkin;
|
||||
pub mod cmd_say;
|
||||
pub mod cmd_seed;
|
||||
|
||||
@ -11,8 +11,8 @@ use args::ConsumedArgs;
|
||||
use async_trait::async_trait;
|
||||
use commands::{
|
||||
cmd_clear, cmd_deop, cmd_fill, cmd_gamemode, cmd_give, cmd_help, cmd_kick, cmd_kill, cmd_list,
|
||||
cmd_me, cmd_op, cmd_pumpkin, cmd_say, cmd_setblock, cmd_stop, cmd_teleport, cmd_time,
|
||||
cmd_worldborder,
|
||||
cmd_me, cmd_op, cmd_playsound, cmd_pumpkin, cmd_say, cmd_setblock, cmd_stop, cmd_teleport,
|
||||
cmd_time, cmd_worldborder,
|
||||
};
|
||||
use dispatcher::CommandError;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
@ -133,6 +133,7 @@ pub fn default_dispatcher() -> CommandDispatcher {
|
||||
dispatcher.register(cmd_op::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(cmd_deop::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(cmd_me::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(cmd_playsound::init_command_tree(), PermissionLvl::Two);
|
||||
|
||||
dispatcher
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user