mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
Add Effects
This commit is contained in:
@@ -51,7 +51,7 @@ rayon = "1.10"
|
||||
parking_lot = { version = "0.12", features = ["send_guard"] }
|
||||
crossbeam = "0.8"
|
||||
|
||||
uuid = { version = "1.13", features = ["serde", "v3", "v4"] }
|
||||
uuid = { version = "1.14", features = ["serde", "v3", "v4"] }
|
||||
derive_more = { version = "2.0", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
@@ -72,6 +72,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi
|
||||
- [ ] Advancements
|
||||
- Entities
|
||||
- [x] Non-Living (Minecart, Eggs...)
|
||||
- [x] Entity Effects
|
||||
- [x] Players
|
||||
- [x] Mobs
|
||||
- [x] Animals
|
||||
|
||||
41
assets/status_effects.json
Normal file
41
assets/status_effects.json
Normal file
@@ -0,0 +1,41 @@
|
||||
[
|
||||
"speed",
|
||||
"slowness",
|
||||
"haste",
|
||||
"mining_fatigue",
|
||||
"strength",
|
||||
"instant_health",
|
||||
"instant_damage",
|
||||
"jump_boost",
|
||||
"nausea",
|
||||
"regeneration",
|
||||
"resistance",
|
||||
"fire_resistance",
|
||||
"water_breathing",
|
||||
"invisibility",
|
||||
"blindness",
|
||||
"night_vision",
|
||||
"hunger",
|
||||
"weakness",
|
||||
"poison",
|
||||
"wither",
|
||||
"health_boost",
|
||||
"absorption",
|
||||
"saturation",
|
||||
"glowing",
|
||||
"levitation",
|
||||
"luck",
|
||||
"unluck",
|
||||
"slow_falling",
|
||||
"conduit_power",
|
||||
"dolphins_grace",
|
||||
"bad_omen",
|
||||
"hero_of_the_village",
|
||||
"darkness",
|
||||
"trial_omen",
|
||||
"raid_omen",
|
||||
"wind_charged",
|
||||
"weaving",
|
||||
"oozing",
|
||||
"infested"
|
||||
]
|
||||
@@ -21,6 +21,7 @@ mod screen;
|
||||
mod sound;
|
||||
mod sound_category;
|
||||
mod spawn_egg;
|
||||
mod status_effect;
|
||||
mod world_event;
|
||||
|
||||
pub fn main() {
|
||||
@@ -42,6 +43,7 @@ pub fn main() {
|
||||
write_generated_file(spawn_egg::build(), "spawn_egg.rs");
|
||||
write_generated_file(item::build(), "item.rs");
|
||||
write_generated_file(fluid::build(), "fluid.rs");
|
||||
write_generated_file(status_effect::build(), "status_effect.rs");
|
||||
}
|
||||
|
||||
pub fn array_to_tokenstream(array: &[String]) -> TokenStream {
|
||||
|
||||
51
pumpkin-data/build/status_effect.rs
Normal file
51
pumpkin-data/build/status_effect.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
use heck::ToPascalCase;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
pub(crate) fn build() -> TokenStream {
|
||||
println!("cargo:rerun-if-changed=../assets/status_effects.json");
|
||||
|
||||
let chunk_status: Vec<String> =
|
||||
serde_json::from_str(include_str!("../../assets/status_effects.json"))
|
||||
.expect("Failed to parse status_effects.json");
|
||||
let mut variants = TokenStream::new();
|
||||
let mut type_from_name = TokenStream::new();
|
||||
let mut type_to_name = TokenStream::new();
|
||||
|
||||
for status in chunk_status.iter() {
|
||||
let const_ident = format_ident!("{}", status.to_pascal_case());
|
||||
let resource_name = status.to_lowercase();
|
||||
|
||||
variants.extend([quote! {
|
||||
#const_ident,
|
||||
}]);
|
||||
type_from_name.extend(quote! {
|
||||
#resource_name => Some(Self::#const_ident),
|
||||
});
|
||||
type_to_name.extend(quote! {
|
||||
Self::#const_ident => #resource_name,
|
||||
});
|
||||
}
|
||||
quote! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum EffectType {
|
||||
#variants
|
||||
}
|
||||
|
||||
impl EffectType {
|
||||
#[doc = r" Try to parse a Effect Type from a resource location string"]
|
||||
pub fn from_name(name: &str) -> Option<Self> {
|
||||
match name {
|
||||
#type_from_name
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn to_name(&self) -> &'static str {
|
||||
match self {
|
||||
#type_to_name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ pub mod game_event {
|
||||
}
|
||||
|
||||
pub mod entity {
|
||||
include!(concat!(env!("OUT_DIR"), "/status_effect.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/spawn_egg.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/entity_type.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/entity_pose.rs"));
|
||||
|
||||
@@ -71,6 +71,7 @@ mod unload_chunk;
|
||||
mod update_entity_pos;
|
||||
mod update_entity_pos_rot;
|
||||
mod update_entity_rot;
|
||||
mod update_mob_effect;
|
||||
mod update_objectives;
|
||||
mod update_score;
|
||||
mod worldevent;
|
||||
@@ -148,6 +149,7 @@ pub use unload_chunk::*;
|
||||
pub use update_entity_pos::*;
|
||||
pub use update_entity_pos_rot::*;
|
||||
pub use update_entity_rot::*;
|
||||
pub use update_mob_effect::*;
|
||||
pub use update_objectives::*;
|
||||
pub use update_score::*;
|
||||
pub use worldevent::*;
|
||||
|
||||
33
pumpkin-protocol/src/client/play/update_mob_effect.rs
Normal file
33
pumpkin-protocol/src/client/play/update_mob_effect.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use pumpkin_data::packet::clientbound::PLAY_UPDATE_MOB_EFFECT;
|
||||
use pumpkin_macros::client_packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::codec::var_int::VarInt;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[client_packet(PLAY_UPDATE_MOB_EFFECT)]
|
||||
pub struct CUpdateMobEffect {
|
||||
entity_id: VarInt,
|
||||
effect_id: VarInt,
|
||||
amplifier: VarInt,
|
||||
duration: VarInt,
|
||||
flags: i8,
|
||||
}
|
||||
|
||||
impl CUpdateMobEffect {
|
||||
pub fn new(
|
||||
entity_id: VarInt,
|
||||
effect_id: VarInt,
|
||||
amplifier: VarInt,
|
||||
duration: VarInt,
|
||||
flags: i8,
|
||||
) -> Self {
|
||||
Self {
|
||||
entity_id,
|
||||
effect_id,
|
||||
amplifier,
|
||||
duration,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ num-traits = "0.2"
|
||||
# Compression
|
||||
flate2 = "1.0"
|
||||
lz4 = "1.28"
|
||||
zstd = "0.13.2"
|
||||
zstd = "0.13.3"
|
||||
|
||||
|
||||
file-guard = "0.2"
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{collections::HashMap, hash::Hash, sync::Arc};
|
||||
use async_trait::async_trait;
|
||||
use bounded_num::{NotInBounds, Number};
|
||||
use pumpkin_data::damage::DamageType;
|
||||
use pumpkin_data::entity::EffectType;
|
||||
use pumpkin_data::particle::Particle;
|
||||
use pumpkin_data::sound::SoundCategory;
|
||||
use pumpkin_protocol::client::play::{ArgumentType, CommandSuggestion, SuggestionProviders};
|
||||
@@ -27,17 +28,15 @@ pub mod bossbar_style;
|
||||
pub mod bounded_num;
|
||||
pub mod command;
|
||||
mod coordinate;
|
||||
pub mod damage_type;
|
||||
pub mod entities;
|
||||
pub mod entity;
|
||||
pub mod gamemode;
|
||||
pub mod item;
|
||||
pub mod message;
|
||||
pub mod particle;
|
||||
pub mod players;
|
||||
pub mod position_2d;
|
||||
pub mod position_3d;
|
||||
pub mod position_block;
|
||||
pub mod resource;
|
||||
pub mod resource_location;
|
||||
pub mod rotation;
|
||||
pub mod simple;
|
||||
@@ -105,6 +104,7 @@ pub enum Arg<'a> {
|
||||
Simple(&'a str),
|
||||
SoundCategory(SoundCategory),
|
||||
DamageType(DamageType),
|
||||
Effect(EffectType),
|
||||
}
|
||||
|
||||
/// see [`crate::commands::tree::builder::argument`] and [`CommandTree::execute`]/[`crate::commands::tree::builder::NonLeafNodeBuilder::execute`]
|
||||
|
||||
@@ -4,7 +4,10 @@ use pumpkin_protocol::client::play::{ArgumentType, CommandSuggestion, Suggestion
|
||||
|
||||
use crate::command::{
|
||||
CommandSender,
|
||||
args::{Arg, ArgumentConsumer, DefaultNameArgConsumer, FindArg, GetClientSideArgParser},
|
||||
args::{
|
||||
Arg, ArgumentConsumer, ConsumedArgs, DefaultNameArgConsumer, FindArg,
|
||||
GetClientSideArgParser,
|
||||
},
|
||||
dispatcher::CommandError,
|
||||
tree::RawArgs,
|
||||
};
|
||||
@@ -59,7 +62,7 @@ impl DefaultNameArgConsumer for DamageTypeArgumentConsumer {
|
||||
impl<'a> FindArg<'a> for DamageTypeArgumentConsumer {
|
||||
type Data = &'a DamageType;
|
||||
|
||||
fn find_arg(args: &'a super::ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
fn find_arg(args: &'a ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
match args.get(name) {
|
||||
Some(Arg::DamageType(data)) => Ok(data),
|
||||
_ => Err(CommandError::InvalidConsumption(Some(name.to_string()))),
|
||||
71
pumpkin/src/command/args/resource/effect.rs
Normal file
71
pumpkin/src/command/args/resource/effect.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::entity::EffectType;
|
||||
use pumpkin_protocol::client::play::{ArgumentType, CommandSuggestion, SuggestionProviders};
|
||||
|
||||
use crate::command::{
|
||||
CommandSender,
|
||||
args::{
|
||||
Arg, ArgumentConsumer, ConsumedArgs, DefaultNameArgConsumer, FindArg,
|
||||
GetClientSideArgParser,
|
||||
},
|
||||
dispatcher::CommandError,
|
||||
tree::RawArgs,
|
||||
};
|
||||
use crate::server::Server;
|
||||
|
||||
pub struct EffectTypeArgumentConsumer;
|
||||
|
||||
impl GetClientSideArgParser for EffectTypeArgumentConsumer {
|
||||
fn get_client_side_parser(&self) -> ArgumentType {
|
||||
ArgumentType::Resource {
|
||||
identifier: "mob_effect",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_client_side_suggestion_type_override(&self) -> Option<SuggestionProviders> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ArgumentConsumer for EffectTypeArgumentConsumer {
|
||||
async fn consume<'a>(
|
||||
&'a self,
|
||||
_sender: &CommandSender<'a>,
|
||||
_server: &'a Server,
|
||||
args: &mut RawArgs<'a>,
|
||||
) -> Option<Arg<'a>> {
|
||||
let name = args.pop()?;
|
||||
|
||||
// Create a static damage type first
|
||||
let damage_type = EffectType::from_name(&name.replace("minecraft:", ""))?;
|
||||
// Find matching static damage type from values array
|
||||
Some(Arg::Effect(damage_type))
|
||||
}
|
||||
|
||||
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 EffectTypeArgumentConsumer {
|
||||
fn default_name(&self) -> &'static str {
|
||||
"mob_effect"
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FindArg<'a> for EffectTypeArgumentConsumer {
|
||||
type Data = &'a EffectType;
|
||||
|
||||
fn find_arg(args: &'a ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
match args.get(name) {
|
||||
Some(Arg::Effect(data)) => Ok(data),
|
||||
_ => Err(CommandError::InvalidConsumption(Some(name.to_string()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,16 @@ use async_trait::async_trait;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_protocol::client::play::{ArgumentType, CommandSuggestion, SuggestionProviders};
|
||||
|
||||
use crate::{command::dispatcher::CommandError, server::Server};
|
||||
|
||||
use super::{
|
||||
super::{
|
||||
CommandSender,
|
||||
args::{ArgumentConsumer, RawArgs},
|
||||
use crate::command::{
|
||||
CommandSender,
|
||||
args::{
|
||||
Arg, ArgumentConsumer, ConsumedArgs, DefaultNameArgConsumer, FindArg,
|
||||
GetClientSideArgParser,
|
||||
},
|
||||
Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser,
|
||||
dispatcher::CommandError,
|
||||
tree::RawArgs,
|
||||
};
|
||||
use crate::server::Server;
|
||||
|
||||
pub struct ItemArgumentConsumer;
|
||||
|
||||
@@ -55,7 +56,7 @@ impl DefaultNameArgConsumer for ItemArgumentConsumer {
|
||||
impl<'a> FindArg<'a> for ItemArgumentConsumer {
|
||||
type Data = (&'a str, Item);
|
||||
|
||||
fn find_arg(args: &'a super::ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
fn find_arg(args: &'a ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
match args.get(name) {
|
||||
Some(Arg::Item(name)) => Item::from_name(&name.replace("minecraft:", "")).map_or_else(
|
||||
|| {
|
||||
4
pumpkin/src/command/args/resource/mod.rs
Normal file
4
pumpkin/src/command/args/resource/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub mod damage_type;
|
||||
pub mod effect;
|
||||
pub mod item;
|
||||
pub mod particle;
|
||||
@@ -4,7 +4,10 @@ use pumpkin_protocol::client::play::{ArgumentType, CommandSuggestion, Suggestion
|
||||
|
||||
use crate::command::{
|
||||
CommandSender,
|
||||
args::{Arg, ArgumentConsumer, DefaultNameArgConsumer, FindArg, GetClientSideArgParser},
|
||||
args::{
|
||||
Arg, ArgumentConsumer, ConsumedArgs, DefaultNameArgConsumer, FindArg,
|
||||
GetClientSideArgParser,
|
||||
},
|
||||
dispatcher::CommandError,
|
||||
tree::RawArgs,
|
||||
};
|
||||
@@ -59,7 +62,7 @@ impl DefaultNameArgConsumer for ParticleArgumentConsumer {
|
||||
impl<'a> FindArg<'a> for ParticleArgumentConsumer {
|
||||
type Data = &'a Particle;
|
||||
|
||||
fn find_arg(args: &'a super::ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
fn find_arg(args: &'a ConsumedArgs, name: &str) -> Result<Self::Data, CommandError> {
|
||||
match args.get(name) {
|
||||
Some(Arg::Particle(data)) => Ok(data),
|
||||
_ => Err(CommandError::InvalidConsumption(Some(name.to_string()))),
|
||||
@@ -20,10 +20,10 @@ const DESCRIPTION: &str = "bans a player";
|
||||
const ARG_TARGET: &str = "player";
|
||||
const ARG_REASON: &str = "reason";
|
||||
|
||||
struct BanNoReasonExecutor;
|
||||
struct NoReasonExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BanNoReasonExecutor {
|
||||
impl CommandExecutor for NoReasonExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -39,10 +39,10 @@ impl CommandExecutor for BanNoReasonExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct BanReasonExecutor;
|
||||
struct ReasonExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BanReasonExecutor {
|
||||
impl CommandExecutor for ReasonExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -107,7 +107,7 @@ async fn ban_player(sender: &CommandSender<'_>, player: &Player, reason: Option<
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_TARGET, PlayersArgumentConsumer)
|
||||
.execute(BanNoReasonExecutor)
|
||||
.then(argument(ARG_REASON, MsgArgConsumer).execute(BanReasonExecutor)),
|
||||
.execute(NoReasonExecutor)
|
||||
.then(argument(ARG_REASON, MsgArgConsumer).execute(ReasonExecutor)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -36,10 +36,10 @@ async fn parse_ip(target: &str, server: &Server) -> Option<IpAddr> {
|
||||
})
|
||||
}
|
||||
|
||||
struct BanIpNoReasonExecutor;
|
||||
struct NoReasonExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BanIpNoReasonExecutor {
|
||||
impl CommandExecutor for NoReasonExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -55,10 +55,10 @@ impl CommandExecutor for BanIpNoReasonExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct BanIpReasonExecutor;
|
||||
struct ReasonExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BanIpReasonExecutor {
|
||||
impl CommandExecutor for ReasonExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -148,7 +148,7 @@ async fn ban_ip(sender: &CommandSender<'_>, server: &Server, target: &str, reaso
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_TARGET, SimpleArgConsumer)
|
||||
.execute(BanIpNoReasonExecutor)
|
||||
.then(argument(ARG_REASON, MsgArgConsumer).execute(BanIpReasonExecutor)),
|
||||
.execute(NoReasonExecutor)
|
||||
.then(argument(ARG_REASON, MsgArgConsumer).execute(ReasonExecutor)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ const DESCRIPTION: &str = "shows the banlist";
|
||||
|
||||
const ARG_LIST_TYPE: &str = "ips|players";
|
||||
|
||||
struct BanListExecutor;
|
||||
struct ListExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BanListExecutor {
|
||||
impl CommandExecutor for ListExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -74,10 +74,10 @@ impl CommandExecutor for BanListExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct BanListAllExecutor;
|
||||
struct ListAllExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BanListAllExecutor {
|
||||
impl CommandExecutor for ListAllExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -138,6 +138,6 @@ async fn handle_banlist(list: Vec<(String, String, String)>, sender: &CommandSen
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.execute(BanListAllExecutor)
|
||||
.then(argument(ARG_LIST_TYPE, SimpleArgConsumer).execute(BanListExecutor))
|
||||
.execute(ListAllExecutor)
|
||||
.then(argument(ARG_LIST_TYPE, SimpleArgConsumer).execute(ListExecutor))
|
||||
}
|
||||
|
||||
@@ -52,10 +52,10 @@ enum CommandValueSet {
|
||||
Visible,
|
||||
}
|
||||
|
||||
struct BossbarAddExecuter;
|
||||
struct AddExecuter;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BossbarAddExecuter {
|
||||
impl CommandExecutor for AddExecuter {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -101,10 +101,10 @@ impl CommandExecutor for BossbarAddExecuter {
|
||||
}
|
||||
}
|
||||
|
||||
struct BossbarGetExecuter(CommandValueGet);
|
||||
struct GetExecuter(CommandValueGet);
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BossbarGetExecuter {
|
||||
impl CommandExecutor for GetExecuter {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -179,10 +179,10 @@ impl CommandExecutor for BossbarGetExecuter {
|
||||
}
|
||||
}
|
||||
|
||||
struct BossbarListExecuter;
|
||||
struct ListExecuter;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BossbarListExecuter {
|
||||
impl CommandExecutor for ListExecuter {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -238,10 +238,10 @@ impl CommandExecutor for BossbarListExecuter {
|
||||
}
|
||||
}
|
||||
|
||||
struct BossbarRemoveExecuter;
|
||||
struct RemoveExecuter;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BossbarRemoveExecuter {
|
||||
impl CommandExecutor for RemoveExecuter {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -289,10 +289,10 @@ impl CommandExecutor for BossbarRemoveExecuter {
|
||||
}
|
||||
}
|
||||
|
||||
struct BossbarSetExecuter(CommandValueSet);
|
||||
struct SetExecuter(CommandValueSet);
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for BossbarSetExecuter {
|
||||
impl CommandExecutor for SetExecuter {
|
||||
#[expect(clippy::too_many_lines)]
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
@@ -591,25 +591,24 @@ fn value_consumer() -> BoundedNumArgumentConsumer<i32> {
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(
|
||||
literal("add")
|
||||
.then(argument_default_name(non_autocomplete_consumer()).then(
|
||||
argument(ARG_NAME, TextComponentArgConsumer).execute(BossbarAddExecuter),
|
||||
)),
|
||||
literal("add").then(
|
||||
argument_default_name(non_autocomplete_consumer())
|
||||
.then(argument(ARG_NAME, TextComponentArgConsumer).execute(AddExecuter)),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
literal("get").then(
|
||||
argument_default_name(autocomplete_consumer())
|
||||
.then(literal("max").execute(BossbarGetExecuter(CommandValueGet::Max)))
|
||||
.then(literal("players").execute(BossbarGetExecuter(CommandValueGet::Players)))
|
||||
.then(literal("value").execute(BossbarGetExecuter(CommandValueGet::Value)))
|
||||
.then(literal("visible").execute(BossbarGetExecuter(CommandValueGet::Visible))),
|
||||
.then(literal("max").execute(GetExecuter(CommandValueGet::Max)))
|
||||
.then(literal("players").execute(GetExecuter(CommandValueGet::Players)))
|
||||
.then(literal("value").execute(GetExecuter(CommandValueGet::Value)))
|
||||
.then(literal("visible").execute(GetExecuter(CommandValueGet::Visible))),
|
||||
),
|
||||
)
|
||||
.then(literal("list").execute(BossbarListExecuter))
|
||||
.then(literal("list").execute(ListExecuter))
|
||||
.then(
|
||||
literal("remove").then(
|
||||
argument_default_name(autocomplete_consumer()).execute(BossbarRemoveExecuter),
|
||||
),
|
||||
literal("remove")
|
||||
.then(argument_default_name(autocomplete_consumer()).execute(RemoveExecuter)),
|
||||
)
|
||||
.then(
|
||||
literal("set").then(
|
||||
@@ -617,45 +616,45 @@ pub fn init_command_tree() -> CommandTree {
|
||||
.then(
|
||||
literal("color").then(
|
||||
argument_default_name(BossbarColorArgumentConsumer)
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Color)),
|
||||
.execute(SetExecuter(CommandValueSet::Color)),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
literal("max").then(
|
||||
argument_default_name(max_value_consumer())
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Max)),
|
||||
.execute(SetExecuter(CommandValueSet::Max)),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
literal("name").then(
|
||||
argument(ARG_NAME, TextComponentArgConsumer)
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Name)),
|
||||
.execute(SetExecuter(CommandValueSet::Name)),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
literal("players")
|
||||
.then(
|
||||
argument_default_name(PlayersArgumentConsumer)
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Players(true))),
|
||||
.execute(SetExecuter(CommandValueSet::Players(true))),
|
||||
)
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Players(false))),
|
||||
.execute(SetExecuter(CommandValueSet::Players(false))),
|
||||
)
|
||||
.then(
|
||||
literal("style").then(
|
||||
argument_default_name(BossbarStyleArgumentConsumer)
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Style)),
|
||||
.execute(SetExecuter(CommandValueSet::Style)),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
literal("value").then(
|
||||
argument_default_name(value_consumer())
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Value)),
|
||||
.execute(SetExecuter(CommandValueSet::Value)),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
literal("visible").then(
|
||||
argument(ARG_VISIBLE, BoolArgConsumer)
|
||||
.execute(BossbarSetExecuter(CommandValueSet::Visible)),
|
||||
.execute(SetExecuter(CommandValueSet::Visible)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -73,10 +73,10 @@ fn clear_command_text_output(item_count: usize, targets: &[Arc<Player>]) -> Text
|
||||
}
|
||||
}
|
||||
|
||||
struct ClearExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for ClearExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -100,10 +100,10 @@ impl CommandExecutor for ClearExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct ClearSelfExecutor;
|
||||
struct SelfExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for ClearSelfExecutor {
|
||||
impl CommandExecutor for SelfExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -126,6 +126,6 @@ impl CommandExecutor for ClearSelfExecutor {
|
||||
#[allow(clippy::redundant_closure_for_method_calls)] // causes lifetime issues
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_TARGET, EntitiesArgumentConsumer).execute(ClearExecutor))
|
||||
.then(require(|sender| sender.is_player()).execute(ClearSelfExecutor))
|
||||
.then(argument(ARG_TARGET, EntitiesArgumentConsumer).execute(Executor))
|
||||
.then(require(|sender| sender.is_player()).execute(SelfExecutor))
|
||||
}
|
||||
|
||||
@@ -9,11 +9,13 @@ use crate::command::{
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
args::{
|
||||
Arg, ConsumedArgs, FindArg, bounded_num::BoundedNumArgumentConsumer,
|
||||
damage_type::DamageTypeArgumentConsumer, entity::EntityArgumentConsumer,
|
||||
position_3d::Position3DArgumentConsumer,
|
||||
entity::EntityArgumentConsumer, position_3d::Position3DArgumentConsumer,
|
||||
resource::damage_type::DamageTypeArgumentConsumer,
|
||||
},
|
||||
tree::{
|
||||
CommandTree,
|
||||
builder::{argument, literal},
|
||||
},
|
||||
tree::CommandTree,
|
||||
tree::builder::{argument, literal},
|
||||
};
|
||||
|
||||
const NAMES: [&str; 1] = ["damage"];
|
||||
@@ -29,8 +31,8 @@ fn amount_consumer() -> BoundedNumArgumentConsumer<f32> {
|
||||
BoundedNumArgumentConsumer::new().name(ARG_AMOUNT).min(0.0)
|
||||
}
|
||||
|
||||
struct DamageLocationExecutor;
|
||||
struct DamageEntityExecutor(bool);
|
||||
struct LocationExecutor;
|
||||
struct EntityExecutor(bool);
|
||||
|
||||
async fn send_damage_result(
|
||||
sender: &mut CommandSender<'_>,
|
||||
@@ -60,7 +62,7 @@ async fn send_damage_result(
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for DamageLocationExecutor {
|
||||
impl CommandExecutor for LocationExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -100,7 +102,7 @@ impl CommandExecutor for DamageLocationExecutor {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for DamageEntityExecutor {
|
||||
impl CommandExecutor for EntityExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -155,28 +157,28 @@ pub fn init_command_tree() -> CommandTree {
|
||||
argument(ARG_TARGET, EntityArgumentConsumer).then(
|
||||
argument(ARG_AMOUNT, amount_consumer())
|
||||
// Basic damage
|
||||
.execute(DamageEntityExecutor(false))
|
||||
.execute(EntityExecutor(false))
|
||||
// With damage type
|
||||
.then(
|
||||
argument(ARG_DAMAGE_TYPE, DamageTypeArgumentConsumer)
|
||||
.execute(DamageEntityExecutor(false))
|
||||
.execute(EntityExecutor(false))
|
||||
// At location
|
||||
.then(
|
||||
literal("at").then(
|
||||
argument(ARG_LOCATION, Position3DArgumentConsumer)
|
||||
.execute(DamageLocationExecutor),
|
||||
.execute(LocationExecutor),
|
||||
),
|
||||
)
|
||||
// By entity
|
||||
.then(
|
||||
literal("by").then(
|
||||
argument(ARG_ENTITY, EntityArgumentConsumer)
|
||||
.execute(DamageEntityExecutor(false))
|
||||
.execute(EntityExecutor(false))
|
||||
// From cause
|
||||
.then(
|
||||
literal("from").then(
|
||||
argument(ARG_CAUSE, EntityArgumentConsumer)
|
||||
.execute(DamageEntityExecutor(true)),
|
||||
.execute(EntityExecutor(true)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -15,10 +15,10 @@ const NAMES: [&str; 1] = ["deop"];
|
||||
const DESCRIPTION: &str = "Revokes operator status from a player.";
|
||||
const ARG_TARGETS: &str = "targets";
|
||||
|
||||
struct DeopExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for DeopExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -61,5 +61,5 @@ impl CommandExecutor for DeopExecutor {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_TARGETS, PlayersArgumentConsumer).execute(DeopExecutor))
|
||||
.then(argument(ARG_TARGETS, PlayersArgumentConsumer).execute(Executor))
|
||||
}
|
||||
|
||||
100
pumpkin/src/command/commands/effect.rs
Normal file
100
pumpkin/src/command/commands/effect.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::command::args::resource::effect::EffectTypeArgumentConsumer;
|
||||
|
||||
use crate::TextComponent;
|
||||
|
||||
use crate::command::args::players::PlayersArgumentConsumer;
|
||||
|
||||
use crate::command::args::{Arg, ConsumedArgs};
|
||||
use crate::command::dispatcher::CommandError;
|
||||
use crate::command::dispatcher::CommandError::InvalidConsumption;
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree::builder::{argument, literal};
|
||||
use crate::command::{CommandExecutor, CommandSender};
|
||||
use crate::server::Server;
|
||||
|
||||
const NAMES: [&str; 1] = ["effect"];
|
||||
|
||||
const DESCRIPTION: &str = "Adds or removes the status effects of players and other entities.";
|
||||
|
||||
// const ARG_CLEAR: &str = "clear";
|
||||
const ARG_GIVE: &str = "give";
|
||||
|
||||
const ARG_TARGET: &str = "target";
|
||||
const ARG_EFFECT: &str = "effect";
|
||||
|
||||
struct GiveExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for GiveExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
_server: &Server,
|
||||
args: &ConsumedArgs<'a>,
|
||||
) -> Result<(), CommandError> {
|
||||
let Some(Arg::Players(targets)) = args.get(ARG_TARGET) else {
|
||||
return Err(InvalidConsumption(Some(ARG_TARGET.into())));
|
||||
};
|
||||
let Some(Arg::Effect(effect)) = args.get(ARG_EFFECT) else {
|
||||
return Err(InvalidConsumption(Some(ARG_EFFECT.into())));
|
||||
};
|
||||
|
||||
let target_count = targets.len();
|
||||
|
||||
for target in targets {
|
||||
target
|
||||
.add_effect(
|
||||
crate::entity::effect::Effect {
|
||||
r#type: *effect,
|
||||
duration: 30,
|
||||
amplifier: 1,
|
||||
ambient: true,
|
||||
show_particles: true,
|
||||
show_icon: true,
|
||||
},
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
let translation_name =
|
||||
TextComponent::translate(format!("effect.minecraft.{}", effect.to_name()), []);
|
||||
if target_count == 1 {
|
||||
// TODO: use entity name
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.effect.give.success.single",
|
||||
[
|
||||
translation_name,
|
||||
TextComponent::text(targets[0].gameprofile.name.clone()),
|
||||
],
|
||||
))
|
||||
.await;
|
||||
} else {
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.effect.give.success.multiple",
|
||||
[
|
||||
translation_name,
|
||||
TextComponent::text(target_count.to_string()),
|
||||
],
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::redundant_closure_for_method_calls)]
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
literal(ARG_GIVE).then(
|
||||
argument(ARG_TARGET, PlayersArgumentConsumer)
|
||||
.then(argument(ARG_EFFECT, EffectTypeArgumentConsumer).execute(GiveExecutor)),
|
||||
),
|
||||
)
|
||||
// TODO: Add more things
|
||||
}
|
||||
@@ -38,12 +38,12 @@ enum ExpType {
|
||||
Levels,
|
||||
}
|
||||
|
||||
struct ExperienceExecutor {
|
||||
struct Executor {
|
||||
mode: Mode,
|
||||
exp_type: Option<ExpType>,
|
||||
}
|
||||
|
||||
impl ExperienceExecutor {
|
||||
impl Executor {
|
||||
async fn handle_query(
|
||||
&self,
|
||||
sender: &mut CommandSender<'_>,
|
||||
@@ -202,7 +202,7 @@ impl ExperienceExecutor {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for ExperienceExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -281,15 +281,15 @@ pub fn init_command_tree() -> CommandTree {
|
||||
literal("add").then(
|
||||
argument(ARG_TARGETS, PlayersArgumentConsumer).then(
|
||||
argument(ARG_AMOUNT, xp_amount())
|
||||
.then(literal("levels").execute(ExperienceExecutor {
|
||||
.then(literal("levels").execute(Executor {
|
||||
mode: Mode::Add,
|
||||
exp_type: Some(ExpType::Levels),
|
||||
}))
|
||||
.then(literal("points").execute(ExperienceExecutor {
|
||||
.then(literal("points").execute(Executor {
|
||||
mode: Mode::Add,
|
||||
exp_type: Some(ExpType::Points),
|
||||
}))
|
||||
.execute(ExperienceExecutor {
|
||||
.execute(Executor {
|
||||
mode: Mode::Add,
|
||||
exp_type: Some(ExpType::Points),
|
||||
}),
|
||||
@@ -300,15 +300,15 @@ pub fn init_command_tree() -> CommandTree {
|
||||
literal("set").then(
|
||||
argument(ARG_TARGETS, PlayersArgumentConsumer).then(
|
||||
argument(ARG_AMOUNT, xp_amount())
|
||||
.then(literal("levels").execute(ExperienceExecutor {
|
||||
.then(literal("levels").execute(Executor {
|
||||
mode: Mode::Set,
|
||||
exp_type: Some(ExpType::Levels),
|
||||
}))
|
||||
.then(literal("points").execute(ExperienceExecutor {
|
||||
.then(literal("points").execute(Executor {
|
||||
mode: Mode::Set,
|
||||
exp_type: Some(ExpType::Points),
|
||||
}))
|
||||
.execute(ExperienceExecutor {
|
||||
.execute(Executor {
|
||||
mode: Mode::Set,
|
||||
exp_type: Some(ExpType::Points),
|
||||
}),
|
||||
@@ -318,11 +318,11 @@ pub fn init_command_tree() -> CommandTree {
|
||||
.then(
|
||||
literal("query").then(
|
||||
argument(ARG_TARGETS, PlayersArgumentConsumer)
|
||||
.then(literal("levels").execute(ExperienceExecutor {
|
||||
.then(literal("levels").execute(Executor {
|
||||
mode: Mode::Query,
|
||||
exp_type: Some(ExpType::Levels),
|
||||
}))
|
||||
.then(literal("points").execute(ExperienceExecutor {
|
||||
.then(literal("points").execute(Executor {
|
||||
mode: Mode::Query,
|
||||
exp_type: Some(ExpType::Points),
|
||||
})),
|
||||
|
||||
@@ -33,11 +33,11 @@ enum Mode {
|
||||
Replace,
|
||||
}
|
||||
|
||||
struct SetblockExecutor(Mode);
|
||||
struct Executor(Mode);
|
||||
|
||||
#[expect(clippy::too_many_lines)]
|
||||
#[async_trait]
|
||||
impl CommandExecutor for SetblockExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -164,12 +164,12 @@ pub fn init_command_tree() -> CommandTree {
|
||||
argument(ARG_FROM, BlockPosArgumentConsumer).then(
|
||||
argument(ARG_TO, BlockPosArgumentConsumer).then(
|
||||
argument(ARG_BLOCK, BlockArgumentConsumer)
|
||||
.then(literal("destroy").execute(SetblockExecutor(Mode::Destroy)))
|
||||
.then(literal("hollow").execute(SetblockExecutor(Mode::Hollow)))
|
||||
.then(literal("keep").execute(SetblockExecutor(Mode::Keep)))
|
||||
.then(literal("outline").execute(SetblockExecutor(Mode::Outline)))
|
||||
.then(literal("replace").execute(SetblockExecutor(Mode::Replace)))
|
||||
.execute(SetblockExecutor(Mode::Replace)),
|
||||
.then(literal("destroy").execute(Executor(Mode::Destroy)))
|
||||
.then(literal("hollow").execute(Executor(Mode::Hollow)))
|
||||
.then(literal("keep").execute(Executor(Mode::Keep)))
|
||||
.then(literal("outline").execute(Executor(Mode::Outline)))
|
||||
.then(literal("replace").execute(Executor(Mode::Replace)))
|
||||
.execute(Executor(Mode::Replace)),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -23,10 +23,10 @@ const DESCRIPTION: &str = "Change a player's gamemode.";
|
||||
const ARG_GAMEMODE: &str = "gamemode";
|
||||
const ARG_TARGET: &str = "target";
|
||||
|
||||
struct GamemodeTargetSelf;
|
||||
struct TargetSelfExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for GamemodeTargetSelf {
|
||||
impl CommandExecutor for TargetSelfExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -56,10 +56,10 @@ impl CommandExecutor for GamemodeTargetSelf {
|
||||
}
|
||||
}
|
||||
|
||||
struct GamemodeTargetPlayer;
|
||||
struct TargetPlayerExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for GamemodeTargetPlayer {
|
||||
impl CommandExecutor for TargetPlayerExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -108,7 +108,7 @@ impl CommandExecutor for GamemodeTargetPlayer {
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_GAMEMODE, GamemodeArgumentConsumer)
|
||||
.then(require(|sender| sender.is_player()).execute(GamemodeTargetSelf))
|
||||
.then(argument(ARG_TARGET, PlayersArgumentConsumer).execute(GamemodeTargetPlayer)),
|
||||
.then(require(|sender| sender.is_player()).execute(TargetSelfExecutor))
|
||||
.then(argument(ARG_TARGET, PlayersArgumentConsumer).execute(TargetPlayerExecutor)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use pumpkin_util::text::color::{Color, NamedColor};
|
||||
use pumpkin_util::text::hover::HoverEvent;
|
||||
|
||||
use crate::command::args::bounded_num::BoundedNumArgumentConsumer;
|
||||
use crate::command::args::item::ItemArgumentConsumer;
|
||||
use crate::command::args::players::PlayersArgumentConsumer;
|
||||
use crate::command::args::resource::item::ItemArgumentConsumer;
|
||||
use crate::command::args::{ConsumedArgs, FindArg, FindArgDefaultName};
|
||||
use crate::command::tree::CommandTree;
|
||||
use crate::command::tree::builder::{argument, argument_default_name};
|
||||
@@ -25,10 +25,10 @@ fn item_count_consumer() -> BoundedNumArgumentConsumer<i32> {
|
||||
.max(i32::MAX)
|
||||
}
|
||||
|
||||
struct GiveExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for GiveExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -112,8 +112,8 @@ pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument_default_name(PlayersArgumentConsumer).then(
|
||||
argument(ARG_ITEM, ItemArgumentConsumer)
|
||||
.execute(GiveExecutor)
|
||||
.then(argument_default_name(item_count_consumer()).execute(GiveExecutor)),
|
||||
.execute(Executor)
|
||||
.then(argument_default_name(item_count_consumer()).execute(Executor)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ fn page_number_consumer() -> BoundedNumArgumentConsumer<i32> {
|
||||
BoundedNumArgumentConsumer::new().name("page").min(1)
|
||||
}
|
||||
|
||||
struct CommandHelpExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for CommandHelpExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -222,7 +222,7 @@ impl CommandExecutor for BaseHelpExecutor {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_COMMAND, CommandTreeArgumentConsumer).execute(CommandHelpExecutor))
|
||||
.then(argument(ARG_COMMAND, CommandTreeArgumentConsumer).execute(Executor))
|
||||
.then(argument_default_name(page_number_consumer()).execute(BaseHelpExecutor))
|
||||
.execute(BaseHelpExecutor)
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ const ARG_TARGETS: &str = "targets";
|
||||
|
||||
const ARG_REASON: &str = "reason";
|
||||
|
||||
struct KickExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for KickExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -52,7 +52,7 @@ impl CommandExecutor for KickExecutor {
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_TARGETS, PlayersArgumentConsumer)
|
||||
.execute(KickExecutor)
|
||||
.then(argument(ARG_REASON, MsgArgConsumer).execute(KickExecutor)),
|
||||
.execute(Executor)
|
||||
.then(argument(ARG_REASON, MsgArgConsumer).execute(Executor)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ const DESCRIPTION: &str = "Kills all target entities.";
|
||||
|
||||
const ARG_TARGET: &str = "target";
|
||||
|
||||
struct KillExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for KillExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -66,10 +66,10 @@ impl CommandExecutor for KillExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct KillSelfExecutor;
|
||||
struct SelfExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for KillSelfExecutor {
|
||||
impl CommandExecutor for SelfExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -104,6 +104,6 @@ impl CommandExecutor for KillSelfExecutor {
|
||||
#[allow(clippy::redundant_closure_for_method_calls)] // causes lifetime issues
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_TARGET, EntitiesArgumentConsumer).execute(KillExecutor))
|
||||
.then(require(|sender| sender.is_player()).execute(KillSelfExecutor))
|
||||
.then(argument(ARG_TARGET, EntitiesArgumentConsumer).execute(Executor))
|
||||
.then(require(|sender| sender.is_player()).execute(SelfExecutor))
|
||||
}
|
||||
|
||||
@@ -15,10 +15,10 @@ const NAMES: [&str; 1] = ["list"];
|
||||
|
||||
const DESCRIPTION: &str = "Print the list of online players.";
|
||||
|
||||
struct ListExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for ListExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -54,5 +54,5 @@ fn get_player_names(players: Vec<Arc<Player>>) -> String {
|
||||
}
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(ListExecutor)
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(Executor)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ const DESCRIPTION: &str = "Broadcasts a narrative message about yourself.";
|
||||
|
||||
const ARG_MESSAGE: &str = "action";
|
||||
|
||||
struct MeExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for MeExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -44,5 +44,5 @@ impl CommandExecutor for MeExecutor {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_MESSAGE, MsgArgConsumer).execute(MeExecutor))
|
||||
.then(argument(ARG_MESSAGE, MsgArgConsumer).execute(Executor))
|
||||
}
|
||||
|
||||
@@ -1,36 +1,90 @@
|
||||
pub mod ban;
|
||||
pub mod banip;
|
||||
pub mod banlist;
|
||||
pub mod bossbar;
|
||||
pub mod clear;
|
||||
pub mod damage;
|
||||
pub mod deop;
|
||||
pub mod experience;
|
||||
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 msg;
|
||||
pub mod op;
|
||||
pub mod pardon;
|
||||
pub mod pardonip;
|
||||
pub mod particle;
|
||||
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 weather;
|
||||
pub mod worldborder;
|
||||
use pumpkin_util::PermissionLvl;
|
||||
|
||||
use super::dispatcher::CommandDispatcher;
|
||||
|
||||
mod ban;
|
||||
mod banip;
|
||||
mod banlist;
|
||||
mod bossbar;
|
||||
mod clear;
|
||||
mod damage;
|
||||
mod deop;
|
||||
mod effect;
|
||||
mod experience;
|
||||
mod fill;
|
||||
mod gamemode;
|
||||
mod give;
|
||||
mod help;
|
||||
mod kick;
|
||||
mod kill;
|
||||
mod list;
|
||||
mod me;
|
||||
mod msg;
|
||||
mod op;
|
||||
mod pardon;
|
||||
mod pardonip;
|
||||
mod particle;
|
||||
mod playsound;
|
||||
mod plugin;
|
||||
mod plugins;
|
||||
mod pumpkin;
|
||||
mod say;
|
||||
mod seed;
|
||||
mod setblock;
|
||||
mod stop;
|
||||
mod summon;
|
||||
mod teleport;
|
||||
mod time;
|
||||
mod title;
|
||||
mod transfer;
|
||||
mod weather;
|
||||
mod worldborder;
|
||||
|
||||
#[must_use]
|
||||
pub fn default_dispatcher() -> CommandDispatcher {
|
||||
let mut dispatcher = CommandDispatcher::default();
|
||||
|
||||
// Zero
|
||||
dispatcher.register(pumpkin::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(help::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(list::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(transfer::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(me::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(msg::init_command_tree(), PermissionLvl::Zero);
|
||||
// Two
|
||||
dispatcher.register(kill::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(worldborder::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(effect::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(clear::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(setblock::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(seed::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(fill::init_command_tree(), PermissionLvl::Two);
|
||||
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.register(experience::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(weather::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(particle::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(damage::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(bossbar::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(say::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(gamemode::init_command_tree(), PermissionLvl::Two);
|
||||
// Three
|
||||
dispatcher.register(op::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(deop::init_command_tree(), PermissionLvl::Three);
|
||||
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(ban::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(banip::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(banlist::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(pardon::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(pardonip::init_command_tree(), PermissionLvl::Three);
|
||||
// Four
|
||||
dispatcher.register(stop::init_command_tree(), PermissionLvl::Four);
|
||||
|
||||
dispatcher
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ const DESCRIPTION: &str = "Sends a private message to one or more players.";
|
||||
|
||||
const ARG_MESSAGE: &str = "message";
|
||||
|
||||
struct MsgExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for MsgExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -81,6 +81,6 @@ impl CommandExecutor for MsgExecutor {
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument_default_name(PlayersArgumentConsumer)
|
||||
.then(argument(ARG_MESSAGE, MsgArgConsumer).execute(MsgExecutor)),
|
||||
.then(argument(ARG_MESSAGE, MsgArgConsumer).execute(Executor)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ const NAMES: [&str; 1] = ["op"];
|
||||
const DESCRIPTION: &str = "Grants operator status to a player.";
|
||||
const ARG_TARGETS: &str = "targets";
|
||||
|
||||
struct OpExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for OpExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -81,5 +81,5 @@ impl CommandExecutor for OpExecutor {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_TARGETS, PlayersArgumentConsumer).execute(OpExecutor))
|
||||
.then(argument(ARG_TARGETS, PlayersArgumentConsumer).execute(Executor))
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ const DESCRIPTION: &str = "unbans a player";
|
||||
|
||||
const ARG_TARGET: &str = "player";
|
||||
|
||||
struct PardonExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for PardonExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -60,5 +60,5 @@ impl CommandExecutor for PardonExecutor {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_TARGET, SimpleArgConsumer).execute(PardonExecutor))
|
||||
.then(argument(ARG_TARGET, SimpleArgConsumer).execute(Executor))
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ const DESCRIPTION: &str = "unbans a ip";
|
||||
|
||||
const ARG_TARGET: &str = "ip";
|
||||
|
||||
struct PardonIpExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for PardonIpExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -64,5 +64,5 @@ impl CommandExecutor for PardonIpExecutor {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_TARGET, SimpleArgConsumer).execute(PardonIpExecutor))
|
||||
.then(argument(ARG_TARGET, SimpleArgConsumer).execute(Executor))
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::command::{
|
||||
CommandError, CommandExecutor, CommandSender,
|
||||
args::{
|
||||
ConsumedArgs, FindArg, bounded_num::BoundedNumArgumentConsumer,
|
||||
particle::ParticleArgumentConsumer, position_3d::Position3DArgumentConsumer,
|
||||
position_3d::Position3DArgumentConsumer, resource::particle::ParticleArgumentConsumer,
|
||||
},
|
||||
tree::{CommandTree, builder::argument},
|
||||
};
|
||||
@@ -20,10 +20,10 @@ const ARG_DELTA: &str = "delta";
|
||||
const ARG_SPEED: &str = "speed";
|
||||
const ARG_COUNT: &str = "count";
|
||||
|
||||
struct ParticleExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for ParticleExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -64,25 +64,25 @@ impl CommandExecutor for ParticleExecutor {
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_NAME, ParticleArgumentConsumer)
|
||||
.execute(ParticleExecutor)
|
||||
.execute(Executor)
|
||||
.then(
|
||||
argument(ARG_POS, Position3DArgumentConsumer)
|
||||
.execute(ParticleExecutor)
|
||||
.execute(Executor)
|
||||
.then(
|
||||
argument(ARG_DELTA, Position3DArgumentConsumer)
|
||||
.execute(ParticleExecutor)
|
||||
.execute(Executor)
|
||||
.then(
|
||||
argument(
|
||||
ARG_SPEED,
|
||||
BoundedNumArgumentConsumer::<f32>::new().min(0.0),
|
||||
)
|
||||
.execute(ParticleExecutor)
|
||||
.execute(Executor)
|
||||
.then(
|
||||
argument(
|
||||
ARG_COUNT,
|
||||
BoundedNumArgumentConsumer::<i32>::new().min(0),
|
||||
)
|
||||
.execute(ParticleExecutor),
|
||||
.execute(Executor),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -57,10 +57,10 @@ fn min_volume_consumer() -> BoundedNumArgumentConsumer<f32> {
|
||||
.max(1.0)
|
||||
}
|
||||
|
||||
struct SoundExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for SoundExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -183,18 +183,18 @@ pub fn init_command_tree() -> CommandTree {
|
||||
ARG_MIN_VOLUME,
|
||||
min_volume_consumer(),
|
||||
)
|
||||
.execute(SoundExecutor),
|
||||
.execute(Executor),
|
||||
)
|
||||
.execute(SoundExecutor),
|
||||
.execute(Executor),
|
||||
)
|
||||
.execute(SoundExecutor),
|
||||
.execute(Executor),
|
||||
)
|
||||
.execute(SoundExecutor),
|
||||
.execute(Executor),
|
||||
)
|
||||
.execute(SoundExecutor),
|
||||
.execute(Executor),
|
||||
)
|
||||
.execute(SoundExecutor),
|
||||
.execute(Executor),
|
||||
)
|
||||
.execute(SoundExecutor),
|
||||
.execute(Executor),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ const NAMES: [&str; 1] = ["plugins"];
|
||||
|
||||
const DESCRIPTION: &str = "List all available plugins.";
|
||||
|
||||
struct ListExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for ListExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -63,5 +63,5 @@ impl CommandExecutor for ListExecutor {
|
||||
}
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(ListExecutor)
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(Executor)
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@ const NAMES: [&str; 2] = ["pumpkin", "version"];
|
||||
|
||||
const DESCRIPTION: &str = "Display information about Pumpkin.";
|
||||
|
||||
struct PumpkinExecutor;
|
||||
struct Executor;
|
||||
|
||||
const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
const CARGO_PKG_DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION");
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for PumpkinExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -98,5 +98,5 @@ impl CommandExecutor for PumpkinExecutor {
|
||||
}
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(PumpkinExecutor)
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(Executor)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ const DESCRIPTION: &str = "Broadcast a message to all Players.";
|
||||
|
||||
const ARG_MESSAGE: &str = "message";
|
||||
|
||||
struct SayExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for SayExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -44,5 +44,5 @@ impl CommandExecutor for SayExecutor {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_MESSAGE, MsgArgConsumer).execute(SayExecutor))
|
||||
.then(argument(ARG_MESSAGE, MsgArgConsumer).execute(Executor))
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ const NAMES: [&str; 1] = ["seed"];
|
||||
|
||||
const DESCRIPTION: &str = "Displays the world seed.";
|
||||
|
||||
struct PumpkinExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for PumpkinExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -54,5 +54,5 @@ impl CommandExecutor for PumpkinExecutor {
|
||||
}
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(PumpkinExecutor)
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(Executor)
|
||||
}
|
||||
|
||||
@@ -27,10 +27,10 @@ enum Mode {
|
||||
Replace,
|
||||
}
|
||||
|
||||
struct SetblockExecutor(Mode);
|
||||
struct Executor(Mode);
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for SetblockExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -90,10 +90,10 @@ pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_BLOCK_POS, BlockPosArgumentConsumer).then(
|
||||
argument(ARG_BLOCK, BlockArgumentConsumer)
|
||||
.then(literal("replace").execute(SetblockExecutor(Mode::Replace)))
|
||||
.then(literal("destroy").execute(SetblockExecutor(Mode::Destroy)))
|
||||
.then(literal("keep").execute(SetblockExecutor(Mode::Keep)))
|
||||
.execute(SetblockExecutor(Mode::Replace)),
|
||||
.then(literal("replace").execute(Executor(Mode::Replace)))
|
||||
.then(literal("destroy").execute(Executor(Mode::Destroy)))
|
||||
.then(literal("keep").execute(Executor(Mode::Keep)))
|
||||
.execute(Executor(Mode::Replace)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ const NAMES: [&str; 1] = ["stop"];
|
||||
|
||||
const DESCRIPTION: &str = "Stop the server.";
|
||||
|
||||
struct StopExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for StopExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -32,5 +32,5 @@ impl CommandExecutor for StopExecutor {
|
||||
}
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(StopExecutor)
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(Executor)
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ const ARG_ENTITY: &str = "entity";
|
||||
|
||||
const ARG_POS: &str = "pos";
|
||||
|
||||
struct SummonExecutor;
|
||||
struct Executor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for SummonExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -54,8 +54,8 @@ impl CommandExecutor for SummonExecutor {
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_ENTITY, SummonableEntitiesArgumentConsumer)
|
||||
.execute(SummonExecutor)
|
||||
.then(argument(ARG_POS, Position3DArgumentConsumer).execute(SummonExecutor)),
|
||||
.execute(Executor)
|
||||
.then(argument(ARG_POS, Position3DArgumentConsumer).execute(Executor)),
|
||||
// TODO: Add NBT
|
||||
)
|
||||
}
|
||||
|
||||
@@ -49,10 +49,10 @@ fn yaw_pitch_facing_position(
|
||||
(yaw_degrees as f32, pitch_degrees as f32)
|
||||
}
|
||||
|
||||
struct TpEntitiesToEntityExecutor;
|
||||
struct EntitiesToEntityExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TpEntitiesToEntityExecutor {
|
||||
impl CommandExecutor for EntitiesToEntityExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
_sender: &mut CommandSender<'a>,
|
||||
@@ -74,10 +74,10 @@ impl CommandExecutor for TpEntitiesToEntityExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct TpEntitiesToPosFacingPosExecutor;
|
||||
struct EntitiesToPosFacingPosExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TpEntitiesToPosFacingPosExecutor {
|
||||
impl CommandExecutor for EntitiesToPosFacingPosExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
_sender: &mut CommandSender<'a>,
|
||||
@@ -99,10 +99,10 @@ impl CommandExecutor for TpEntitiesToPosFacingPosExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct TpEntitiesToPosFacingEntityExecutor;
|
||||
struct EntitiesToPosFacingEntityExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TpEntitiesToPosFacingEntityExecutor {
|
||||
impl CommandExecutor for EntitiesToPosFacingEntityExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
_sender: &mut CommandSender<'a>,
|
||||
@@ -126,10 +126,10 @@ impl CommandExecutor for TpEntitiesToPosFacingEntityExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct TpEntitiesToPosWithRotationExecutor;
|
||||
struct EntitiesToPosWithRotationExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TpEntitiesToPosWithRotationExecutor {
|
||||
impl CommandExecutor for EntitiesToPosWithRotationExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
_sender: &mut CommandSender<'a>,
|
||||
@@ -150,10 +150,10 @@ impl CommandExecutor for TpEntitiesToPosWithRotationExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct TpEntitiesToPosExecutor;
|
||||
struct EntitiesToPosExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TpEntitiesToPosExecutor {
|
||||
impl CommandExecutor for EntitiesToPosExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
_sender: &mut CommandSender<'a>,
|
||||
@@ -174,10 +174,10 @@ impl CommandExecutor for TpEntitiesToPosExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct TpSelfToEntityExecutor;
|
||||
struct SelfToEntityExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TpSelfToEntityExecutor {
|
||||
impl CommandExecutor for SelfToEntityExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -204,10 +204,10 @@ impl CommandExecutor for TpSelfToEntityExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct TpSelfToPosExecutor;
|
||||
struct SelfToPosExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TpSelfToPosExecutor {
|
||||
impl CommandExecutor for SelfToPosExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -234,34 +234,34 @@ impl CommandExecutor for TpSelfToPosExecutor {
|
||||
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(argument(ARG_LOCATION, Position3DArgumentConsumer).execute(TpSelfToPosExecutor))
|
||||
.then(argument(ARG_DESTINATION, EntityArgumentConsumer).execute(TpSelfToEntityExecutor))
|
||||
.then(argument(ARG_LOCATION, Position3DArgumentConsumer).execute(SelfToPosExecutor))
|
||||
.then(argument(ARG_DESTINATION, EntityArgumentConsumer).execute(SelfToEntityExecutor))
|
||||
.then(
|
||||
argument(ARG_TARGETS, EntitiesArgumentConsumer)
|
||||
.then(
|
||||
argument(ARG_LOCATION, Position3DArgumentConsumer)
|
||||
.execute(TpEntitiesToPosExecutor)
|
||||
.execute(EntitiesToPosExecutor)
|
||||
.then(
|
||||
argument(ARG_ROTATION, RotationArgumentConsumer)
|
||||
.execute(TpEntitiesToPosWithRotationExecutor),
|
||||
.execute(EntitiesToPosWithRotationExecutor),
|
||||
)
|
||||
.then(
|
||||
literal("facing")
|
||||
.then(
|
||||
literal("entity").then(
|
||||
argument(ARG_FACING_ENTITY, EntityArgumentConsumer)
|
||||
.execute(TpEntitiesToPosFacingEntityExecutor),
|
||||
.execute(EntitiesToPosFacingEntityExecutor),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
argument(ARG_FACING_LOCATION, Position3DArgumentConsumer)
|
||||
.execute(TpEntitiesToPosFacingPosExecutor),
|
||||
.execute(EntitiesToPosFacingPosExecutor),
|
||||
),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
argument(ARG_DESTINATION, EntityArgumentConsumer)
|
||||
.execute(TpEntitiesToEntityExecutor),
|
||||
.execute(EntitiesToEntityExecutor),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ enum QueryMode {
|
||||
Day,
|
||||
}
|
||||
|
||||
struct TimeQueryExecutor(QueryMode);
|
||||
struct QueryExecutor(QueryMode);
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TimeQueryExecutor {
|
||||
impl CommandExecutor for QueryExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -91,10 +91,10 @@ impl CommandExecutor for TimeQueryExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct TimeChangeExecutor(Mode);
|
||||
struct ChangeExecutor(Mode);
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TimeChangeExecutor {
|
||||
impl CommandExecutor for ChangeExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -153,33 +153,27 @@ impl CommandExecutor for TimeChangeExecutor {
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.then(
|
||||
literal("add").then(
|
||||
argument(ARG_TIME, TimeArgumentConsumer).execute(TimeChangeExecutor(Mode::Add)),
|
||||
),
|
||||
literal("add")
|
||||
.then(argument(ARG_TIME, TimeArgumentConsumer).execute(ChangeExecutor(Mode::Add))),
|
||||
)
|
||||
.then(
|
||||
literal("query")
|
||||
.then(literal("daytime").execute(TimeQueryExecutor(QueryMode::DayTime)))
|
||||
.then(literal("gametime").execute(TimeQueryExecutor(QueryMode::GameTime)))
|
||||
.then(literal("day").execute(TimeQueryExecutor(QueryMode::Day))),
|
||||
.then(literal("daytime").execute(QueryExecutor(QueryMode::DayTime)))
|
||||
.then(literal("gametime").execute(QueryExecutor(QueryMode::GameTime)))
|
||||
.then(literal("day").execute(QueryExecutor(QueryMode::Day))),
|
||||
)
|
||||
.then(
|
||||
literal("set")
|
||||
.then(literal("day").execute(TimeChangeExecutor(Mode::Set(Some(PresetTime::Day)))))
|
||||
.then(
|
||||
literal("noon").execute(TimeChangeExecutor(Mode::Set(Some(PresetTime::Noon)))),
|
||||
)
|
||||
.then(
|
||||
literal("night")
|
||||
.execute(TimeChangeExecutor(Mode::Set(Some(PresetTime::Night)))),
|
||||
)
|
||||
.then(literal("day").execute(ChangeExecutor(Mode::Set(Some(PresetTime::Day)))))
|
||||
.then(literal("noon").execute(ChangeExecutor(Mode::Set(Some(PresetTime::Noon)))))
|
||||
.then(literal("night").execute(ChangeExecutor(Mode::Set(Some(PresetTime::Night)))))
|
||||
.then(
|
||||
literal("midnight")
|
||||
.execute(TimeChangeExecutor(Mode::Set(Some(PresetTime::Midnight)))),
|
||||
.execute(ChangeExecutor(Mode::Set(Some(PresetTime::Midnight)))),
|
||||
)
|
||||
.then(
|
||||
argument(ARG_TIME, TimeArgumentConsumer)
|
||||
.execute(TimeChangeExecutor(Mode::Set(None))),
|
||||
.execute(ChangeExecutor(Mode::Set(None))),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ fn port_consumer() -> BoundedNumArgumentConsumer<i32> {
|
||||
.max(65535)
|
||||
}
|
||||
|
||||
struct TransferTargetSelf;
|
||||
struct TargetSelfExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TransferTargetSelf {
|
||||
impl CommandExecutor for TargetSelfExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -71,10 +71,10 @@ impl CommandExecutor for TransferTargetSelf {
|
||||
}
|
||||
}
|
||||
|
||||
struct TransferTargetPlayer;
|
||||
struct TargetPlayerExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for TransferTargetPlayer {
|
||||
impl CommandExecutor for TargetPlayerExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -121,13 +121,13 @@ impl CommandExecutor for TransferTargetPlayer {
|
||||
pub fn init_command_tree() -> CommandTree {
|
||||
CommandTree::new(NAMES, DESCRIPTION).then(
|
||||
argument(ARG_HOSTNAME, SimpleArgConsumer)
|
||||
.then(require(|sender| sender.is_player()).execute(TransferTargetSelf))
|
||||
.then(require(|sender| sender.is_player()).execute(TargetSelfExecutor))
|
||||
.then(
|
||||
argument_default_name(port_consumer())
|
||||
.then(require(|sender| sender.is_player()).execute(TransferTargetSelf))
|
||||
.then(require(|sender| sender.is_player()).execute(TargetSelfExecutor))
|
||||
.then(
|
||||
argument(ARG_PLAYERS, PlayersArgumentConsumer)
|
||||
.execute(TransferTargetPlayer),
|
||||
.execute(TargetPlayerExecutor),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ const NAMES: [&str; 1] = ["weather"];
|
||||
const DESCRIPTION: &str = "Changes the weather.";
|
||||
const ARG_DURATION: &str = "duration";
|
||||
|
||||
struct WeatherExecutor {
|
||||
struct Executor {
|
||||
mode: WeatherMode,
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ enum WeatherMode {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WeatherExecutor {
|
||||
impl CommandExecutor for Executor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -73,33 +73,33 @@ pub fn init_command_tree() -> CommandTree {
|
||||
.then(
|
||||
literal("clear")
|
||||
.then(
|
||||
argument(ARG_DURATION, TimeArgumentConsumer).execute(WeatherExecutor {
|
||||
argument(ARG_DURATION, TimeArgumentConsumer).execute(Executor {
|
||||
mode: WeatherMode::Clear,
|
||||
}),
|
||||
)
|
||||
.execute(WeatherExecutor {
|
||||
.execute(Executor {
|
||||
mode: WeatherMode::Clear,
|
||||
}),
|
||||
)
|
||||
.then(
|
||||
literal("rain")
|
||||
.then(
|
||||
argument(ARG_DURATION, TimeArgumentConsumer).execute(WeatherExecutor {
|
||||
argument(ARG_DURATION, TimeArgumentConsumer).execute(Executor {
|
||||
mode: WeatherMode::Rain,
|
||||
}),
|
||||
)
|
||||
.execute(WeatherExecutor {
|
||||
.execute(Executor {
|
||||
mode: WeatherMode::Rain,
|
||||
}),
|
||||
)
|
||||
.then(
|
||||
literal("thunder")
|
||||
.then(
|
||||
argument(ARG_DURATION, TimeArgumentConsumer).execute(WeatherExecutor {
|
||||
argument(ARG_DURATION, TimeArgumentConsumer).execute(Executor {
|
||||
mode: WeatherMode::Thunder,
|
||||
}),
|
||||
)
|
||||
.execute(WeatherExecutor {
|
||||
.execute(Executor {
|
||||
mode: WeatherMode::Thunder,
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -48,10 +48,10 @@ fn warning_distance_consumer() -> BoundedNumArgumentConsumer<i32> {
|
||||
BoundedNumArgumentConsumer::new().min(0).name("distance")
|
||||
}
|
||||
|
||||
struct WorldborderGetExecutor;
|
||||
struct GetExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderGetExecutor {
|
||||
impl CommandExecutor for GetExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -76,10 +76,10 @@ impl CommandExecutor for WorldborderGetExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderSetExecutor;
|
||||
struct SetExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderSetExecutor {
|
||||
impl CommandExecutor for SetExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -128,10 +128,10 @@ impl CommandExecutor for WorldborderSetExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderSetTimeExecutor;
|
||||
struct SetTimeExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderSetTimeExecutor {
|
||||
impl CommandExecutor for SetTimeExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -213,10 +213,10 @@ impl CommandExecutor for WorldborderSetTimeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderAddExecutor;
|
||||
struct AddExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderAddExecutor {
|
||||
impl CommandExecutor for AddExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -267,10 +267,10 @@ impl CommandExecutor for WorldborderAddExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderAddTimeExecutor;
|
||||
struct AddTimeExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderAddTimeExecutor {
|
||||
impl CommandExecutor for AddTimeExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -354,10 +354,10 @@ impl CommandExecutor for WorldborderAddTimeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderCenterExecutor;
|
||||
struct CenterExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderCenterExecutor {
|
||||
impl CommandExecutor for CenterExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -387,10 +387,10 @@ impl CommandExecutor for WorldborderCenterExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderDamageAmountExecutor;
|
||||
struct DamageAmountExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderDamageAmountExecutor {
|
||||
impl CommandExecutor for DamageAmountExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -439,10 +439,10 @@ impl CommandExecutor for WorldborderDamageAmountExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderDamageBufferExecutor;
|
||||
struct DamageBufferExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderDamageBufferExecutor {
|
||||
impl CommandExecutor for DamageBufferExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -491,10 +491,10 @@ impl CommandExecutor for WorldborderDamageBufferExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderWarningDistanceExecutor;
|
||||
struct WarningDistanceExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderWarningDistanceExecutor {
|
||||
impl CommandExecutor for WarningDistanceExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -542,10 +542,10 @@ impl CommandExecutor for WorldborderWarningDistanceExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
struct WorldborderWarningTimeExecutor;
|
||||
struct WarningTimeExecutor;
|
||||
|
||||
#[async_trait]
|
||||
impl CommandExecutor for WorldborderWarningTimeExecutor {
|
||||
impl CommandExecutor for WarningTimeExecutor {
|
||||
async fn execute<'a>(
|
||||
&self,
|
||||
sender: &mut CommandSender<'a>,
|
||||
@@ -598,38 +598,32 @@ pub fn init_command_tree() -> CommandTree {
|
||||
.then(
|
||||
literal("add").then(
|
||||
argument_default_name(distance_consumer())
|
||||
.execute(WorldborderAddExecutor)
|
||||
.then(
|
||||
argument_default_name(time_consumer()).execute(WorldborderAddTimeExecutor),
|
||||
),
|
||||
.execute(AddExecutor)
|
||||
.then(argument_default_name(time_consumer()).execute(AddTimeExecutor)),
|
||||
),
|
||||
)
|
||||
.then(literal("center").then(
|
||||
argument_default_name(Position2DArgumentConsumer).execute(WorldborderCenterExecutor),
|
||||
))
|
||||
.then(
|
||||
literal("center")
|
||||
.then(argument_default_name(Position2DArgumentConsumer).execute(CenterExecutor)),
|
||||
)
|
||||
.then(
|
||||
literal("damage")
|
||||
.then(
|
||||
literal("amount").then(
|
||||
argument_default_name(damage_per_block_consumer())
|
||||
.execute(WorldborderDamageAmountExecutor),
|
||||
.execute(DamageAmountExecutor),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
literal("buffer").then(
|
||||
argument_default_name(damage_buffer_consumer())
|
||||
.execute(WorldborderDamageBufferExecutor),
|
||||
),
|
||||
),
|
||||
.then(literal("buffer").then(
|
||||
argument_default_name(damage_buffer_consumer()).execute(DamageBufferExecutor),
|
||||
)),
|
||||
)
|
||||
.then(literal("get").execute(WorldborderGetExecutor))
|
||||
.then(literal("get").execute(GetExecutor))
|
||||
.then(
|
||||
literal("set").then(
|
||||
argument_default_name(distance_consumer())
|
||||
.execute(WorldborderSetExecutor)
|
||||
.then(
|
||||
argument_default_name(time_consumer()).execute(WorldborderSetTimeExecutor),
|
||||
),
|
||||
.execute(SetExecutor)
|
||||
.then(argument_default_name(time_consumer()).execute(SetTimeExecutor)),
|
||||
),
|
||||
)
|
||||
.then(
|
||||
@@ -637,11 +631,12 @@ pub fn init_command_tree() -> CommandTree {
|
||||
.then(
|
||||
literal("distance").then(
|
||||
argument_default_name(warning_distance_consumer())
|
||||
.execute(WorldborderWarningDistanceExecutor),
|
||||
.execute(WarningDistanceExecutor),
|
||||
),
|
||||
)
|
||||
.then(literal("time").then(
|
||||
argument_default_name(time_consumer()).execute(WorldborderWarningTimeExecutor),
|
||||
)),
|
||||
.then(
|
||||
literal("time")
|
||||
.then(argument_default_name(time_consumer()).execute(WarningTimeExecutor)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ impl CommandDispatcher {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::command::{default_dispatcher, tree::CommandTree};
|
||||
use crate::command::{commands::default_dispatcher, tree::CommandTree};
|
||||
use pumpkin_util::permission::PermissionLvl;
|
||||
#[test]
|
||||
fn test_dynamic_command() {
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
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;
|
||||
use crate::world::World;
|
||||
use args::ConsumedArgs;
|
||||
use async_trait::async_trait;
|
||||
use commands::{
|
||||
ban, banip, banlist, clear, damage, deop, experience, fill, gamemode, give, help, kick, kill,
|
||||
list, me, msg, op, pardon, pardonip, particle, playsound, plugin, plugins, pumpkin, say,
|
||||
setblock, stop, summon, teleport, time, title, weather, worldborder,
|
||||
};
|
||||
|
||||
use dispatcher::CommandError;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_util::permission::PermissionLvl;
|
||||
@@ -21,7 +14,7 @@ use pumpkin_util::text::TextComponent;
|
||||
|
||||
pub mod args;
|
||||
pub mod client_suggestions;
|
||||
mod commands;
|
||||
pub mod commands;
|
||||
pub mod dispatcher;
|
||||
pub mod tree;
|
||||
|
||||
@@ -106,54 +99,6 @@ impl CommandSender<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn default_dispatcher() -> CommandDispatcher {
|
||||
let mut dispatcher = CommandDispatcher::default();
|
||||
|
||||
// Zero
|
||||
dispatcher.register(pumpkin::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(help::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(list::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(transfer::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(me::init_command_tree(), PermissionLvl::Zero);
|
||||
dispatcher.register(msg::init_command_tree(), PermissionLvl::Zero);
|
||||
// Two
|
||||
dispatcher.register(kill::init_command_tree(), PermissionLvl::Two);
|
||||
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(clear::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(setblock::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(seed::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(fill::init_command_tree(), PermissionLvl::Two);
|
||||
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.register(experience::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(weather::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(particle::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(damage::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(bossbar::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(say::init_command_tree(), PermissionLvl::Two);
|
||||
dispatcher.register(gamemode::init_command_tree(), PermissionLvl::Two);
|
||||
// Three
|
||||
dispatcher.register(op::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(deop::init_command_tree(), PermissionLvl::Three);
|
||||
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(ban::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(banip::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(banlist::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(pardon::init_command_tree(), PermissionLvl::Three);
|
||||
dispatcher.register(pardonip::init_command_tree(), PermissionLvl::Three);
|
||||
// Four
|
||||
dispatcher.register(stop::init_command_tree(), PermissionLvl::Four);
|
||||
|
||||
dispatcher
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait CommandExecutor: Sync {
|
||||
async fn execute<'a>(
|
||||
|
||||
11
pumpkin/src/entity/effect/mod.rs
Normal file
11
pumpkin/src/entity/effect/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use pumpkin_data::entity::EffectType;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
pub struct Effect {
|
||||
pub r#type: EffectType,
|
||||
pub duration: i32,
|
||||
pub amplifier: u8,
|
||||
pub ambient: bool,
|
||||
pub show_particles: bool,
|
||||
pub show_icon: bool,
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use std::{collections::HashMap, sync::atomic::AtomicI32};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use pumpkin_data::entity::EffectType;
|
||||
use pumpkin_data::{damage::DamageType, sound::Sound};
|
||||
use pumpkin_nbt::tag::NbtTag;
|
||||
use pumpkin_protocol::{
|
||||
@@ -12,8 +13,9 @@ use pumpkin_protocol::{
|
||||
};
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use super::{Entity, EntityId, NBTStorage};
|
||||
use super::{Entity, EntityId, NBTStorage, effect::Effect};
|
||||
|
||||
/// Represents a living entity within the game world.
|
||||
///
|
||||
@@ -31,9 +33,10 @@ pub struct LivingEntity {
|
||||
pub health: AtomicCell<f32>,
|
||||
/// The distance the entity has been falling
|
||||
pub fall_distance: AtomicCell<f32>,
|
||||
pub active_effects: Mutex<HashMap<EffectType, Effect>>,
|
||||
}
|
||||
impl LivingEntity {
|
||||
pub const fn new(entity: Entity) -> Self {
|
||||
pub fn new(entity: Entity) -> Self {
|
||||
Self {
|
||||
entity,
|
||||
last_pos: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)),
|
||||
@@ -41,6 +44,7 @@ impl LivingEntity {
|
||||
last_damage_taken: AtomicCell::new(0.0),
|
||||
health: AtomicCell::new(20.0),
|
||||
fall_distance: AtomicCell::new(0.0),
|
||||
active_effects: Mutex::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +135,22 @@ impl LivingEntity {
|
||||
true
|
||||
}
|
||||
|
||||
pub async fn add_effect(&self, effect: Effect) {
|
||||
let mut effects = self.active_effects.lock().await;
|
||||
effects.insert(effect.r#type, effect);
|
||||
// TODO broadcast metadata
|
||||
}
|
||||
|
||||
pub async fn has_effect(&self, effect: EffectType) -> bool {
|
||||
let effects = self.active_effects.lock().await;
|
||||
effects.contains_key(&effect)
|
||||
}
|
||||
|
||||
pub async fn get_effect(&self, effect: EffectType) -> Option<Effect> {
|
||||
let effects = self.active_effects.lock().await;
|
||||
effects.get(&effect).cloned()
|
||||
}
|
||||
|
||||
pub async fn damage(&self, amount: f32, damage_type: DamageType) -> bool {
|
||||
self.damage_with_context(amount, damage_type, None, None, None)
|
||||
.await
|
||||
|
||||
@@ -32,6 +32,7 @@ use tokio::sync::RwLock;
|
||||
use crate::world::World;
|
||||
|
||||
pub mod ai;
|
||||
pub mod effect;
|
||||
pub mod hunger;
|
||||
pub mod item;
|
||||
pub mod living;
|
||||
|
||||
@@ -13,7 +13,7 @@ use crossbeam::atomic::AtomicCell;
|
||||
use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG};
|
||||
use pumpkin_data::{
|
||||
damage::DamageType,
|
||||
entity::EntityType,
|
||||
entity::{EffectType, EntityType},
|
||||
item::Operation,
|
||||
particle::Particle,
|
||||
sound::{Sound, SoundCategory},
|
||||
@@ -27,7 +27,8 @@ use pumpkin_protocol::{
|
||||
CAcknowledgeBlockChange, CActionBar, CCombatDeath, CDisguisedChatMessage, CEntityStatus,
|
||||
CGameEvent, CHurtAnimation, CKeepAlive, CParticle, CPlayDisconnect, CPlayerAbilities,
|
||||
CPlayerInfoUpdate, CPlayerPosition, CRespawn, CSetExperience, CSetHealth, CSubtitle,
|
||||
CSystemChatMessage, CTitleText, CUnloadChunk, GameEvent, MetaDataType, PlayerAction,
|
||||
CSystemChatMessage, CTitleText, CUnloadChunk, CUpdateMobEffect, GameEvent, MetaDataType,
|
||||
PlayerAction,
|
||||
},
|
||||
server::play::{
|
||||
SChatCommand, SChatMessage, SClientCommand, SClientInformationPlay, SClientTickEnd,
|
||||
@@ -66,6 +67,7 @@ use tokio::sync::{Mutex, Notify, RwLock};
|
||||
use super::{
|
||||
Entity, EntityBase, EntityId, NBTStorage,
|
||||
combat::{self, AttackType, player_attack_sound},
|
||||
effect::Effect,
|
||||
hunger::HungerManager,
|
||||
item::ItemEntity,
|
||||
};
|
||||
@@ -958,13 +960,52 @@ impl Player {
|
||||
.await
|
||||
.get_mining_speed(block_name)
|
||||
.await;
|
||||
// TODO: Handle effects
|
||||
// Haste
|
||||
if self.living_entity.has_effect(EffectType::Haste).await
|
||||
|| self
|
||||
.living_entity
|
||||
.has_effect(EffectType::ConduitPower)
|
||||
.await
|
||||
{
|
||||
speed *= 1.0 + (self.get_haste_amplifier().await + 1) as f32 * 0.2;
|
||||
}
|
||||
// Fatigue
|
||||
if let Some(fatigue) = self
|
||||
.living_entity
|
||||
.get_effect(EffectType::MiningFatigue)
|
||||
.await
|
||||
{
|
||||
let fatigue_speed = match fatigue.amplifier {
|
||||
0 => 0.3,
|
||||
1 => 0.09,
|
||||
2 => 0.0027,
|
||||
_ => 8.1E-4,
|
||||
};
|
||||
speed *= fatigue_speed;
|
||||
}
|
||||
// TODO: Handle when in Water
|
||||
if !self.living_entity.entity.on_ground.load(Ordering::Relaxed) {
|
||||
speed /= 5.0;
|
||||
}
|
||||
speed
|
||||
}
|
||||
|
||||
async fn get_haste_amplifier(&self) -> u32 {
|
||||
let mut i = 0;
|
||||
let mut j = 0;
|
||||
if let Some(effect) = self.living_entity.get_effect(EffectType::Haste).await {
|
||||
i = effect.amplifier;
|
||||
}
|
||||
if let Some(effect) = self
|
||||
.living_entity
|
||||
.get_effect(EffectType::ConduitPower)
|
||||
.await
|
||||
{
|
||||
j = effect.amplifier;
|
||||
}
|
||||
u32::from(i.max(j))
|
||||
}
|
||||
|
||||
pub async fn send_message(
|
||||
&self,
|
||||
message: &TextComponent,
|
||||
@@ -1049,6 +1090,34 @@ impl Player {
|
||||
self.set_experience(new_level, progress, points).await;
|
||||
}
|
||||
|
||||
pub async fn add_effect(&self, effect: Effect, keep_fading: bool) {
|
||||
let mut flag: i8 = 0;
|
||||
|
||||
if effect.ambient {
|
||||
flag |= 1;
|
||||
}
|
||||
if effect.show_particles {
|
||||
flag |= 2;
|
||||
}
|
||||
if effect.show_icon {
|
||||
flag |= 4;
|
||||
}
|
||||
if keep_fading {
|
||||
flag |= 8;
|
||||
}
|
||||
let effect_id = VarInt(effect.r#type as i32);
|
||||
self.client
|
||||
.send_packet(&CUpdateMobEffect::new(
|
||||
self.entity_id().into(),
|
||||
effect_id,
|
||||
effect.amplifier.into(),
|
||||
effect.duration.into(),
|
||||
flag,
|
||||
))
|
||||
.await;
|
||||
self.living_entity.add_effect(effect).await;
|
||||
}
|
||||
|
||||
/// Add experience levels to the player
|
||||
pub async fn add_experience_levels(&self, added_levels: i32) {
|
||||
let current_level = self.experience_level.load(Ordering::Relaxed);
|
||||
|
||||
@@ -31,15 +31,13 @@ use tokio::sync::{Mutex, RwLock};
|
||||
use crate::block::default_block_properties_manager;
|
||||
use crate::block::properties::BlockPropertiesManager;
|
||||
use crate::block::registry::BlockRegistry;
|
||||
use crate::command::commands::default_dispatcher;
|
||||
use crate::entity::{Entity, EntityId};
|
||||
use crate::item::registry::ItemRegistry;
|
||||
use crate::net::EncryptionError;
|
||||
use crate::world::custom_bossbar::CustomBossbars;
|
||||
use crate::{
|
||||
command::{default_dispatcher, dispatcher::CommandDispatcher},
|
||||
entity::player::Player,
|
||||
net::Client,
|
||||
world::World,
|
||||
command::dispatcher::CommandDispatcher, entity::player::Player, net::Client, world::World,
|
||||
};
|
||||
|
||||
mod connection_cache;
|
||||
|
||||
@@ -101,8 +101,8 @@ impl PumpkinError for GetBlockError {
|
||||
/// **Key Responsibilities:**
|
||||
///
|
||||
/// - Manages the `Level` instance for handling chunk-related operations.
|
||||
/// - Stores and tracks active `Player` entities within the world.
|
||||
/// - Provides a central hub for interacting with the world's entities and environment.
|
||||
/// - Active players and entities.
|
||||
/// - World-related systems like the scoreboard, world border, weather, and time.
|
||||
pub struct World {
|
||||
/// The underlying level, responsible for chunk management and terrain generation.
|
||||
pub level: Arc<Level>,
|
||||
@@ -121,7 +121,6 @@ pub struct World {
|
||||
pub dimension_type: DimensionType,
|
||||
/// The world's weather, including rain and thunder levels
|
||||
pub weather: Mutex<Weather>,
|
||||
// TODO: entities
|
||||
}
|
||||
|
||||
impl World {
|
||||
|
||||
Reference in New Issue
Block a user