Add Summon Command
Also refactor some things: - Remove cmd_ prefix from commands - Remove arg_ prefix from arguments
This commit is contained in:
parent
69cb3bb4f0
commit
2fdf0777f6
@ -40,8 +40,20 @@ pub(crate) fn build() -> TokenStream {
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
let type_from_name = json
|
||||
.iter()
|
||||
.map(|sound| {
|
||||
let id = &sound.0;
|
||||
let name = ident(sound.0.to_pascal_case());
|
||||
|
||||
quote! {
|
||||
#[derive(Clone, Copy)]
|
||||
#id => Some(Self::#name),
|
||||
}
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
|
||||
quote! {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(u8)]
|
||||
pub enum EntityType {
|
||||
#variants
|
||||
@ -54,6 +66,13 @@ pub(crate) fn build() -> TokenStream {
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_name(name: &str) -> Option<Self> {
|
||||
match name {
|
||||
#type_from_name
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +76,6 @@ async-trait = "0.1.83"
|
||||
|
||||
# plugins
|
||||
libloading = "0.8.5"
|
||||
oneshot = "0.1.8"
|
||||
[build-dependencies]
|
||||
git-version = "0.3.9"
|
||||
# This makes it so the entire project doesn't recompile on each build on linux.
|
||||
|
||||
@ -49,8 +49,8 @@ impl ArgumentConsumer for BlockArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for BlockArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"block".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"block"
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,8 +62,8 @@ impl ArgumentConsumer for BossbarColorArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for BossbarColorArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"color".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"color"
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,8 +66,8 @@ impl ArgumentConsumer for BossbarStyleArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for BossbarStyleArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"style".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"style"
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,8 +238,8 @@ impl<T: ToFromNumber> DefaultNameArgConsumer for BoundedNumArgumentConsumer<T>
|
||||
where
|
||||
Self: ArgumentConsumer,
|
||||
{
|
||||
fn default_name(&self) -> String {
|
||||
fn default_name(&self) -> &'static str {
|
||||
// setting a single default name for all BoundedNumArgumentConsumer variants is probably a bad idea since it would lead to confusion
|
||||
self.name.expect("Only use *_default variants of methods with a BoundedNumArgumentConsumer that has a name.").to_string()
|
||||
self.name.expect("Only use *_default variants of methods with a BoundedNumArgumentConsumer that has a name.")
|
||||
}
|
||||
}
|
||||
@ -65,8 +65,8 @@ impl ArgumentConsumer for CommandTreeArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for CommandTreeArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"cmd".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"cmd"
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
|
||||
use super::super::args::ArgumentConsumer;
|
||||
use super::arg_players::PlayersArgumentConsumer;
|
||||
use super::players::PlayersArgumentConsumer;
|
||||
use super::{Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser};
|
||||
|
||||
/// todo: implement (currently just calls [`super::arg_player::PlayerArgumentConsumer`])
|
||||
@ -55,8 +55,8 @@ impl ArgumentConsumer for EntitiesArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for EntitiesArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"targets".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"targets"
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,8 +77,8 @@ impl ArgumentConsumer for EntityArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for EntityArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"target".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"target"
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,8 +57,8 @@ impl ArgumentConsumer for GamemodeArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for GamemodeArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"gamemode".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"gamemode"
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,8 +47,8 @@ impl ArgumentConsumer for ItemArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for ItemArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"item".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"item"
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,8 +55,8 @@ impl ArgumentConsumer for MsgArgConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for MsgArgConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"msg".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"msg"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::{collections::HashMap, hash::Hash, sync::Arc};
|
||||
|
||||
use arg_bounded_num::{NotInBounds, Number};
|
||||
use async_trait::async_trait;
|
||||
use bounded_num::{NotInBounds, Number};
|
||||
use pumpkin_protocol::client::play::{ArgumentType, CommandSuggestion, SuggestionProviders};
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_util::{
|
||||
@ -17,27 +17,28 @@ use super::{
|
||||
use crate::world::bossbar::{BossbarColor, BossbarDivisions};
|
||||
use crate::{entity::player::Player, server::Server};
|
||||
|
||||
pub mod arg_block;
|
||||
pub mod arg_bool;
|
||||
pub mod arg_bossbar_color;
|
||||
pub mod arg_bossbar_style;
|
||||
pub mod arg_bounded_num;
|
||||
pub mod arg_command;
|
||||
pub mod arg_entities;
|
||||
pub mod arg_entity;
|
||||
pub mod arg_gamemode;
|
||||
pub mod arg_item;
|
||||
pub mod arg_message;
|
||||
pub mod arg_players;
|
||||
pub mod arg_position_2d;
|
||||
pub mod arg_position_3d;
|
||||
pub mod arg_position_block;
|
||||
pub mod arg_resource_location;
|
||||
pub mod arg_rotation;
|
||||
pub mod arg_simple;
|
||||
pub mod arg_sound;
|
||||
pub mod arg_textcomponent;
|
||||
pub mod block;
|
||||
pub mod bool;
|
||||
pub mod bossbar_color;
|
||||
pub mod bossbar_style;
|
||||
pub mod bounded_num;
|
||||
pub mod command;
|
||||
mod coordinate;
|
||||
pub mod entities;
|
||||
pub mod entity;
|
||||
pub mod gamemode;
|
||||
pub mod item;
|
||||
pub mod message;
|
||||
pub mod players;
|
||||
pub mod position_2d;
|
||||
pub mod position_3d;
|
||||
pub mod position_block;
|
||||
pub mod resource_location;
|
||||
pub mod rotation;
|
||||
pub mod simple;
|
||||
pub mod sound;
|
||||
pub mod summonable_entities;
|
||||
pub mod textcomponent;
|
||||
|
||||
/// see [`crate::commands::tree_builder::argument`]
|
||||
#[async_trait]
|
||||
@ -68,7 +69,7 @@ pub trait GetClientSideArgParser {
|
||||
}
|
||||
|
||||
pub trait DefaultNameArgConsumer: ArgumentConsumer {
|
||||
fn default_name(&self) -> String;
|
||||
fn default_name(&self) -> &str;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -120,7 +121,7 @@ pub(crate) trait FindArgDefaultName<'a, T> {
|
||||
|
||||
impl<'a, T, C: FindArg<'a, Data = T> + DefaultNameArgConsumer> FindArgDefaultName<'a, T> for C {
|
||||
fn find_arg_default_name(&self, args: &'a ConsumedArgs) -> Result<T, CommandError> {
|
||||
C::find_arg(args, &self.default_name())
|
||||
C::find_arg(args, self.default_name())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -71,8 +71,8 @@ impl ArgumentConsumer for PlayersArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for PlayersArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"player".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"player"
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,8 +71,8 @@ impl MaybeRelativePosition2D {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for Position2DArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"pos2d".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"pos"
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,8 +74,8 @@ impl MaybeRelativePosition3D {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for Position3DArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"pos".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"pos"
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,8 +75,8 @@ impl MaybeRelativeBlockPos {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for BlockPosArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"block_pos".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"block_pos"
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,8 +58,8 @@ impl ArgumentConsumer for ResourceLocationArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for ResourceLocationArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"id".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"id"
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,8 +59,8 @@ impl ArgumentConsumer for RotationArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for RotationArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"rotation".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"rotation"
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,8 +47,8 @@ impl ArgumentConsumer for SoundArgumentConsumer {
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for SoundArgumentConsumer {
|
||||
fn default_name(&self) -> String {
|
||||
"available_sounds".to_string()
|
||||
fn default_name(&self) -> &'static str {
|
||||
"available_sounds"
|
||||
}
|
||||
}
|
||||
|
||||
72
pumpkin/src/command/args/summonable_entities.rs
Normal file
72
pumpkin/src/command/args/summonable_entities.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_protocol::client::play::{ArgumentType, CommandSuggestion, SuggestionProviders};
|
||||
|
||||
use crate::{command::dispatcher::CommandError, server::Server};
|
||||
|
||||
use super::{
|
||||
super::{
|
||||
args::{ArgumentConsumer, RawArgs},
|
||||
CommandSender,
|
||||
},
|
||||
Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser,
|
||||
};
|
||||
|
||||
pub(crate) struct SummonableEntitiesArgumentConsumer;
|
||||
|
||||
impl GetClientSideArgParser for SummonableEntitiesArgumentConsumer {
|
||||
fn get_client_side_parser(&self) -> ArgumentType {
|
||||
ArgumentType::ResourceLocation
|
||||
}
|
||||
|
||||
fn get_client_side_suggestion_type_override(&self) -> Option<SuggestionProviders> {
|
||||
Some(SuggestionProviders::SummonableEntities)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ArgumentConsumer for SummonableEntitiesArgumentConsumer {
|
||||
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 SummonableEntitiesArgumentConsumer {
|
||||
fn default_name(&self) -> &'static str {
|
||||
"summonable_entities"
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FindArg<'a> for SummonableEntitiesArgumentConsumer {
|
||||
type Data = EntityType;
|
||||
|
||||
fn find_arg(args: &'a super::ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
match args.get(name) {
|
||||
Some(Arg::Block(name)) => EntityType::from_name(&name.replace("minecraft:", ""))
|
||||
.map_or_else(
|
||||
|| {
|
||||
Err(CommandError::GeneralCommandIssue(format!(
|
||||
"Entity {name} does not exist."
|
||||
)))
|
||||
},
|
||||
Result::Ok,
|
||||
),
|
||||
_ => Err(CommandError::InvalidConsumption(Some(name.to_string()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,14 @@
|
||||
use crate::command::args::arg_bool::BoolArgConsumer;
|
||||
use crate::command::args::arg_bossbar_color::BossbarColorArgumentConsumer;
|
||||
use crate::command::args::arg_bossbar_style::BossbarStyleArgumentConsumer;
|
||||
use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::arg_players::PlayersArgumentConsumer;
|
||||
use crate::command::args::arg_resource_location::ResourceLocationArgumentConsumer;
|
||||
use crate::command::args::bool::BoolArgConsumer;
|
||||
use crate::command::args::bossbar_color::BossbarColorArgumentConsumer;
|
||||
use crate::command::args::bossbar_style::BossbarStyleArgumentConsumer;
|
||||
use crate::command::args::bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::players::PlayersArgumentConsumer;
|
||||
use crate::command::args::resource_location::ResourceLocationArgumentConsumer;
|
||||
|
||||
use crate::command::args::{ConsumedArgs, DefaultNameArgConsumer, FindArg, FindArgDefaultName};
|
||||
use crate::command::dispatcher::CommandError;
|
||||
|
||||
use crate::command::args::arg_textcomponent::TextComponentArgConsumer;
|
||||
use crate::command::args::textcomponent::TextComponentArgConsumer;
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree_builder::{argument, argument_default_name, literal};
|
||||
use crate::command::{CommandExecutor, CommandSender};
|
||||
@ -5,7 +5,7 @@ use pumpkin_inventory::Container;
|
||||
use pumpkin_util::text::color::NamedColor;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_entities::EntitiesArgumentConsumer;
|
||||
use crate::command::args::entities::EntitiesArgumentConsumer;
|
||||
use crate::command::args::{Arg, ConsumedArgs};
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree_builder::{argument, require};
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
command::{
|
||||
args::{arg_players::PlayersArgumentConsumer, Arg, ConsumedArgs},
|
||||
args::{players::PlayersArgumentConsumer, Arg, ConsumedArgs},
|
||||
tree::CommandTree,
|
||||
tree_builder::argument,
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::command::args::arg_block::BlockArgumentConsumer;
|
||||
use crate::command::args::arg_position_block::BlockPosArgumentConsumer;
|
||||
use crate::command::args::block::BlockArgumentConsumer;
|
||||
use crate::command::args::position_block::BlockPosArgumentConsumer;
|
||||
use crate::command::args::{ConsumedArgs, FindArg};
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree_builder::{argument, literal};
|
||||
@ -1,11 +1,11 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::command::args::arg_gamemode::GamemodeArgumentConsumer;
|
||||
use crate::command::args::gamemode::GamemodeArgumentConsumer;
|
||||
use crate::command::args::GetCloned;
|
||||
|
||||
use crate::TextComponent;
|
||||
|
||||
use crate::command::args::arg_players::PlayersArgumentConsumer;
|
||||
use crate::command::args::players::PlayersArgumentConsumer;
|
||||
|
||||
use crate::command::args::{Arg, ConsumedArgs};
|
||||
use crate::command::dispatcher::CommandError;
|
||||
@ -2,9 +2,9 @@ use async_trait::async_trait;
|
||||
use pumpkin_util::text::color::{Color, NamedColor};
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::arg_item::ItemArgumentConsumer;
|
||||
use crate::command::args::arg_players::PlayersArgumentConsumer;
|
||||
use crate::command::args::bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::item::ItemArgumentConsumer;
|
||||
use crate::command::args::players::PlayersArgumentConsumer;
|
||||
use crate::command::args::{ConsumedArgs, FindArg, FindArgDefaultName};
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree_builder::{argument, argument_default_name};
|
||||
@ -3,8 +3,8 @@ use pumpkin_util::text::click::ClickEvent;
|
||||
use pumpkin_util::text::color::{Color, NamedColor};
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::arg_command::CommandTreeArgumentConsumer;
|
||||
use crate::command::args::bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::command::CommandTreeArgumentConsumer;
|
||||
use crate::command::args::{Arg, ConsumedArgs, FindArgDefaultName};
|
||||
use crate::command::dispatcher::CommandError;
|
||||
use crate::command::dispatcher::CommandError::InvalidConsumption;
|
||||
@ -2,8 +2,8 @@ use async_trait::async_trait;
|
||||
use pumpkin_util::text::color::NamedColor;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_message::MsgArgConsumer;
|
||||
use crate::command::args::arg_players::PlayersArgumentConsumer;
|
||||
use crate::command::args::message::MsgArgConsumer;
|
||||
use crate::command::args::players::PlayersArgumentConsumer;
|
||||
use crate::command::args::{Arg, ConsumedArgs};
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree_builder::argument;
|
||||
@ -2,7 +2,7 @@ use async_trait::async_trait;
|
||||
use pumpkin_util::text::color::NamedColor;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_entities::EntitiesArgumentConsumer;
|
||||
use crate::command::args::entities::EntitiesArgumentConsumer;
|
||||
use crate::command::args::{Arg, ConsumedArgs};
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree_builder::{argument, require};
|
||||
@ -3,7 +3,7 @@ use pumpkin_data::world::EMOTE_COMMAND;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::{
|
||||
args::{arg_message::MsgArgConsumer, Arg, ConsumedArgs},
|
||||
args::{message::MsgArgConsumer, Arg, ConsumedArgs},
|
||||
tree::CommandTree,
|
||||
tree_builder::argument,
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
@ -1,25 +1,26 @@
|
||||
pub mod cmd_bossbar;
|
||||
pub mod cmd_clear;
|
||||
pub mod cmd_deop;
|
||||
pub mod cmd_fill;
|
||||
pub mod cmd_gamemode;
|
||||
pub mod cmd_give;
|
||||
pub mod cmd_help;
|
||||
pub mod cmd_kick;
|
||||
pub mod cmd_kill;
|
||||
pub mod cmd_list;
|
||||
pub mod cmd_me;
|
||||
pub mod cmd_op;
|
||||
pub mod cmd_playsound;
|
||||
pub mod cmd_plugin;
|
||||
pub mod cmd_plugins;
|
||||
pub mod cmd_pumpkin;
|
||||
pub mod cmd_say;
|
||||
pub mod cmd_seed;
|
||||
pub mod cmd_setblock;
|
||||
pub mod cmd_stop;
|
||||
pub mod cmd_teleport;
|
||||
pub mod cmd_time;
|
||||
pub mod cmd_title;
|
||||
pub mod cmd_transfer;
|
||||
pub mod cmd_worldborder;
|
||||
pub mod bossbar;
|
||||
pub mod clear;
|
||||
pub mod deop;
|
||||
pub mod fill;
|
||||
pub mod gamemode;
|
||||
pub mod give;
|
||||
pub mod help;
|
||||
pub mod kick;
|
||||
pub mod kill;
|
||||
pub mod list;
|
||||
pub mod me;
|
||||
pub mod op;
|
||||
pub mod playsound;
|
||||
pub mod plugin;
|
||||
pub mod plugins;
|
||||
pub mod pumpkin;
|
||||
pub mod say;
|
||||
pub mod seed;
|
||||
pub mod setblock;
|
||||
pub mod stop;
|
||||
pub mod summon;
|
||||
pub mod teleport;
|
||||
pub mod time;
|
||||
pub mod title;
|
||||
pub mod transfer;
|
||||
pub mod worldborder;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
command::{
|
||||
args::{arg_players::PlayersArgumentConsumer, Arg, ConsumedArgs},
|
||||
args::{players::PlayersArgumentConsumer, Arg, ConsumedArgs},
|
||||
tree::CommandTree,
|
||||
tree_builder::argument,
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
@ -3,7 +3,7 @@ use pumpkin_data::sound::SoundCategory;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::command::{
|
||||
args::{arg_sound::SoundArgumentConsumer, ConsumedArgs, FindArg},
|
||||
args::{sound::SoundArgumentConsumer, ConsumedArgs, FindArg},
|
||||
tree::CommandTree,
|
||||
tree_builder::argument,
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
@ -6,7 +6,7 @@ use pumpkin_util::{
|
||||
|
||||
use crate::{
|
||||
command::{
|
||||
args::{arg_simple::SimpleArgConsumer, Arg, ConsumedArgs},
|
||||
args::{simple::SimpleArgConsumer, Arg, ConsumedArgs},
|
||||
tree::CommandTree,
|
||||
tree_builder::{argument, literal, require},
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
@ -3,7 +3,7 @@ use pumpkin_data::world::SAY_COMMAND;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::{
|
||||
args::{arg_message::MsgArgConsumer, Arg, ConsumedArgs},
|
||||
args::{message::MsgArgConsumer, Arg, ConsumedArgs},
|
||||
tree::CommandTree,
|
||||
tree_builder::argument,
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
@ -36,19 +36,17 @@ impl CommandExecutor for PumpkinExecutor {
|
||||
let seed = (seed as i64).to_string();
|
||||
|
||||
sender
|
||||
.send_message(
|
||||
TextComponent::text("Seed: [")
|
||||
.add_child(
|
||||
TextComponent::text(seed.clone())
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.seed.success",
|
||||
[TextComponent::text(seed.clone())
|
||||
.hover_event(HoverEvent::show_text(TextComponent::translate(
|
||||
Cow::from("chat.copy.click"),
|
||||
vec![],
|
||||
)))
|
||||
.click_event(ClickEvent::CopyToClipboard(Cow::from(seed)))
|
||||
.color_named(NamedColor::Green),
|
||||
)
|
||||
.add_child(TextComponent::text("]")),
|
||||
)
|
||||
.color_named(NamedColor::Green)]
|
||||
.into(),
|
||||
))
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_block::BlockArgumentConsumer;
|
||||
use crate::command::args::arg_position_block::BlockPosArgumentConsumer;
|
||||
use crate::command::args::block::BlockArgumentConsumer;
|
||||
use crate::command::args::position_block::BlockPosArgumentConsumer;
|
||||
use crate::command::args::{ConsumedArgs, FindArg};
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree_builder::{argument, literal};
|
||||
64
pumpkin/src/command/commands/summon.rs
Normal file
64
pumpkin/src/command/commands/summon.rs
Normal file
@ -0,0 +1,64 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::{
|
||||
command::{
|
||||
args::{
|
||||
position_3d::Position3DArgumentConsumer,
|
||||
summonable_entities::SummonableEntitiesArgumentConsumer, ConsumedArgs, FindArg,
|
||||
},
|
||||
tree::CommandTree,
|
||||
tree_builder::argument,
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
},
|
||||
entity::mob,
|
||||
};
|
||||
const NAMES: [&str; 1] = ["summon"];
|
||||
|
||||
const DESCRIPTION: &str = "Spawns a Entity at position.";
|
||||
|
||||
const ARG_ENTITY: &str = "entity";
|
||||
|
||||
const ARG_POS: &str = "pos";
|
||||
|
||||
struct SummonExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for SummonExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
server: &crate::server::Server,
|
||||
args: &ConsumedArgs<'a>,
|
||||
) -> Result<(), CommandError> {
|
||||
let entity = SummonableEntitiesArgumentConsumer::find_arg(args, ARG_ENTITY)?;
|
||||
let pos = Position3DArgumentConsumer::find_arg(args, ARG_POS);
|
||||
|
||||
// TODO: Make this work in console
|
||||
if let Some(player) = sender.as_player() {
|
||||
let pos = pos.unwrap_or(player.living_entity.entity.pos.load());
|
||||
let (mob, uuid) = mob::from_type(entity, server, pos, player.world()).await;
|
||||
player
|
||||
.world()
|
||||
.broadcast_packet_all(&mob.living_entity.entity.create_spawn_packet(uuid))
|
||||
.await;
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.summon.success",
|
||||
[TextComponent::text(format!("{entity:?}"))].into(),
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_ENTITY, SummonableEntitiesArgumentConsumer)
|
||||
.execute(SummonExecutor)
|
||||
.then(argument(ARG_POS, Position3DArgumentConsumer).execute(SummonExecutor)),
|
||||
// TODO: Add NBT
|
||||
)
|
||||
}
|
||||
@ -2,10 +2,10 @@ use async_trait::async_trait;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_entities::EntitiesArgumentConsumer;
|
||||
use crate::command::args::arg_entity::EntityArgumentConsumer;
|
||||
use crate::command::args::arg_position_3d::Position3DArgumentConsumer;
|
||||
use crate::command::args::arg_rotation::RotationArgumentConsumer;
|
||||
use crate::command::args::entities::EntitiesArgumentConsumer;
|
||||
use crate::command::args::entity::EntityArgumentConsumer;
|
||||
use crate::command::args::position_3d::Position3DArgumentConsumer;
|
||||
use crate::command::args::rotation::RotationArgumentConsumer;
|
||||
use crate::command::args::ConsumedArgs;
|
||||
use crate::command::args::FindArg;
|
||||
use crate::command::tree::CommandTree;
|
||||
@ -2,7 +2,7 @@ use async_trait::async_trait;
|
||||
use pumpkin_util::text::color::{Color, NamedColor};
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::FindArgDefaultName;
|
||||
use crate::command::tree_builder::{argument_default_name, literal};
|
||||
use crate::command::{
|
||||
@ -5,7 +5,7 @@ use pumpkin_util::text::TextComponent;
|
||||
use crate::{
|
||||
command::{
|
||||
args::{
|
||||
arg_players::PlayersArgumentConsumer, arg_textcomponent::TextComponentArgConsumer, Arg,
|
||||
players::PlayersArgumentConsumer, textcomponent::TextComponentArgConsumer, Arg,
|
||||
ConsumedArgs, FindArg,
|
||||
},
|
||||
tree::CommandTree,
|
||||
@ -4,9 +4,9 @@ use pumpkin_protocol::codec::var_int::VarInt;
|
||||
use pumpkin_util::text::color::{Color, NamedColor};
|
||||
use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::command::args::arg_bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::arg_players::PlayersArgumentConsumer;
|
||||
use crate::command::args::arg_simple::SimpleArgConsumer;
|
||||
use crate::command::args::bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::players::PlayersArgumentConsumer;
|
||||
use crate::command::args::simple::SimpleArgConsumer;
|
||||
use crate::command::args::{Arg, FindArgDefaultName};
|
||||
use crate::command::dispatcher::CommandError::{InvalidConsumption, InvalidRequirement};
|
||||
use crate::command::tree_builder::{argument, argument_default_name, require};
|
||||
@ -10,9 +10,8 @@ use pumpkin_util::{
|
||||
use crate::{
|
||||
command::{
|
||||
args::{
|
||||
arg_bounded_num::BoundedNumArgumentConsumer,
|
||||
arg_position_2d::Position2DArgumentConsumer, ConsumedArgs, DefaultNameArgConsumer,
|
||||
FindArgDefaultName,
|
||||
bounded_num::BoundedNumArgumentConsumer, position_2d::Position2DArgumentConsumer,
|
||||
ConsumedArgs, DefaultNameArgConsumer, FindArgDefaultName,
|
||||
},
|
||||
tree::CommandTree,
|
||||
tree_builder::{argument_default_name, literal},
|
||||
@ -1,8 +1,8 @@
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::command::commands::cmd_seed;
|
||||
use crate::command::commands::{cmd_bossbar, cmd_transfer};
|
||||
use crate::command::commands::seed;
|
||||
use crate::command::commands::{bossbar, transfer};
|
||||
use crate::command::dispatcher::CommandDispatcher;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
@ -10,9 +10,8 @@ use crate::world::World;
|
||||
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_playsound, cmd_plugin, cmd_plugins, cmd_pumpkin, cmd_say, cmd_setblock,
|
||||
cmd_stop, cmd_teleport, cmd_time, cmd_title, cmd_worldborder,
|
||||
clear, deop, fill, gamemode, give, help, kick, kill, list, me, op, playsound, plugin, plugins,
|
||||
pumpkin, say, setblock, stop, summon, teleport, time, title, worldborder,
|
||||
};
|
||||
use dispatcher::CommandError;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
@ -112,31 +111,32 @@ impl CommandSender<'_> {
|
||||
pub fn default_dispatcher() -> CommandDispatcher {
|
||||
let mut dispatcher = CommandDispatcher::default();
|
||||
|
||||
dispatcher.register(cmd_pumpkin::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(cmd_bossbar::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_say::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_gamemode::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_stop::init_command_tree(), PermissionLvl::Four);
|
||||
dispatcher.register(cmd_help::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(cmd_kill::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_kick::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(cmd_plugin::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(cmd_plugins::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(cmd_worldborder::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_teleport::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_time::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_give::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_list::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(cmd_clear::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_setblock::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_seed::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(cmd_transfer::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(cmd_fill::init_command_tree(), PermissionLvl::Two);
|
||||
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.register(cmd_title::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(pumpkin::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(bossbar::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(say::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(gamemode::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(stop::init_command_tree(), PermissionLvl::Four);
|
||||
dispatcher.register(help::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(kill::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(kick::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(plugin::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(plugins::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(worldborder::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(teleport::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(time::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(give::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(list::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(clear::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(setblock::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(seed::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(transfer::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(fill::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(op::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(deop::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(me::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(playsound::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(title::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(summon::init_command_tree(), PermissionLvl::Two);
|
||||
|
||||
dispatcher
|
||||
}
|
||||
|
||||
@ -168,7 +168,7 @@ pub fn argument_default_name(
|
||||
) -> NonLeafNodeBuilder {
|
||||
NonLeafNodeBuilder {
|
||||
node_type: NodeType::Argument {
|
||||
name: consumer.default_name(),
|
||||
name: consumer.default_name().to_string(),
|
||||
consumer: Arc::new(consumer),
|
||||
},
|
||||
child_nodes: Vec::new(),
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_protocol::{client::play::CSpawnEntity, codec::var_int::VarInt};
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use tokio::sync::Mutex;
|
||||
use uuid::Uuid;
|
||||
@ -61,25 +60,4 @@ impl MobEntity {
|
||||
pub async fn goal<T: Goal + 'static>(&self, goal: T) {
|
||||
self.goals.lock().await.push((Arc::new(goal), false));
|
||||
}
|
||||
|
||||
pub fn create_spawn_entity_packet(&self, uuid: Uuid) -> CSpawnEntity {
|
||||
let e = &self.living_entity.entity;
|
||||
let entity_loc = e.pos.load();
|
||||
let entity_vel = e.velocity.load();
|
||||
CSpawnEntity::new(
|
||||
VarInt(e.entity_id),
|
||||
uuid,
|
||||
VarInt((e.entity_type) as i32),
|
||||
entity_loc.x,
|
||||
entity_loc.y,
|
||||
entity_loc.z,
|
||||
e.pitch.load(),
|
||||
e.yaw.load(),
|
||||
e.yaw.load(), // todo: head_yaw and yaw are swapped, find out why
|
||||
0.into(),
|
||||
entity_vel.x as f32,
|
||||
entity_vel.y as f32,
|
||||
entity_vel.z as f32,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,9 @@ use crossbeam::atomic::AtomicCell;
|
||||
use pumpkin_data::entity::{EntityPose, EntityType};
|
||||
use pumpkin_nbt::{compound::NbtCompound, tag::NbtTag};
|
||||
use pumpkin_protocol::{
|
||||
client::play::{CHeadRot, CSetEntityMetadata, CTeleportEntity, CUpdateEntityRot, Metadata},
|
||||
client::play::{
|
||||
CHeadRot, CSetEntityMetadata, CSpawnEntity, CTeleportEntity, CUpdateEntityRot, Metadata,
|
||||
},
|
||||
codec::var_int::VarInt,
|
||||
};
|
||||
use pumpkin_util::math::{
|
||||
@ -17,6 +19,7 @@ use pumpkin_util::math::{
|
||||
vector3::Vector3,
|
||||
wrap_degrees,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::world::World;
|
||||
|
||||
@ -206,6 +209,26 @@ impl Entity {
|
||||
self.world.remove_entity(self).await;
|
||||
}
|
||||
|
||||
pub fn create_spawn_packet(&self, uuid: Uuid) -> CSpawnEntity {
|
||||
let entity_loc = self.pos.load();
|
||||
let entity_vel = self.velocity.load();
|
||||
CSpawnEntity::new(
|
||||
VarInt(self.entity_id),
|
||||
uuid,
|
||||
VarInt((self.entity_type) as i32),
|
||||
entity_loc.x,
|
||||
entity_loc.y,
|
||||
entity_loc.z,
|
||||
self.pitch.load(),
|
||||
self.yaw.load(),
|
||||
self.head_yaw.load(), // todo: head_yaw and yaw are swapped, find out why
|
||||
0.into(),
|
||||
entity_vel.x as f32,
|
||||
entity_vel.y as f32,
|
||||
entity_vel.z as f32,
|
||||
)
|
||||
}
|
||||
|
||||
/// Applies knockback to the entity, following vanilla Minecraft's mechanics.
|
||||
///
|
||||
/// This function calculates the entity's new velocity based on the specified knockback strength and direction.
|
||||
|
||||
@ -538,7 +538,7 @@ impl Player {
|
||||
let mobs = world.current_living_mobs.lock().await.clone();
|
||||
for (uuid, mob) in mobs {
|
||||
self.client
|
||||
.send_packet(&mob.create_spawn_entity_packet(uuid))
|
||||
.send_packet(&mob.living_entity.entity.create_spawn_packet(uuid))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1095,12 +1095,13 @@ impl Player {
|
||||
// create rotation like Vanilla
|
||||
let yaw = wrap_degrees(rand::random::<f32>() * 360.0) % 360.0;
|
||||
|
||||
let world = self.world();
|
||||
// create new mob and uuid based on spawn egg id
|
||||
let (mob, uuid) = mob::from_type(
|
||||
EntityType::from_raw(*spawn_item_id).unwrap(),
|
||||
server,
|
||||
pos,
|
||||
self.world(),
|
||||
world,
|
||||
)
|
||||
.await;
|
||||
|
||||
@ -1108,8 +1109,8 @@ impl Player {
|
||||
mob.living_entity.entity.set_rotation(yaw, 0.0);
|
||||
|
||||
// broadcast new mob to all players
|
||||
server
|
||||
.broadcast_packet_all(&mob.create_spawn_entity_packet(uuid))
|
||||
world
|
||||
.broadcast_packet_all(&mob.living_entity.entity.create_spawn_packet(uuid))
|
||||
.await;
|
||||
|
||||
// TODO: send/configure additional commands/data based on type of entity (horse, slime, etc)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user