aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUbuntu <github@matdoes.dev>2022-01-12 00:40:43 +0000
committerUbuntu <github@matdoes.dev>2022-01-12 00:40:43 +0000
commit270507736af57aae6801dc9eb3c3132139d0d07b (patch)
treea8fa1d1b8d038eb9d7e2061342026d23ddbd9027
parentcc4fe62fc82842e0bde628437a45d55c6a82f1f3 (diff)
downloadazalea-drasl-270507736af57aae6801dc9eb3c3132139d0d07b.tar.xz
a
-rw-r--r--Cargo.lock28
-rw-r--r--azalea-brigadier/Cargo.toml1
-rw-r--r--azalea-brigadier/README.md1
-rw-r--r--azalea-brigadier/src/arguments/argument_type.rs28
-rw-r--r--azalea-brigadier/src/arguments/bool_argument_type.rs1
-rw-r--r--azalea-brigadier/src/builder/argument_builder.rs8
-rw-r--r--azalea-brigadier/src/builder/literal_argument_builder.rs15
-rw-r--r--azalea-brigadier/src/builder/required_argument_builder.rs11
-rw-r--r--azalea-brigadier/src/command.rs4
-rw-r--r--azalea-brigadier/src/command_dispatcher.rs17
-rw-r--r--azalea-brigadier/src/context/command_context_builder.rs16
-rw-r--r--azalea-brigadier/src/context/parsed_command_node.rs9
-rw-r--r--azalea-brigadier/src/redirect_modifier.rs5
-rw-r--r--azalea-brigadier/src/suggestion/integer_suggestion.rs1
-rw-r--r--azalea-brigadier/src/suggestion/suggestions.rs86
-rw-r--r--azalea-brigadier/src/suggestion/suggestions_builder.rs4
-rw-r--r--azalea-brigadier/src/tree/argument_command_node.rs17
-rw-r--r--azalea-brigadier/src/tree/command_node.rs59
-rw-r--r--azalea-brigadier/src/tree/literal_command_node.rs20
-rw-r--r--azalea-brigadier/src/tree/root_command_node.rs19
20 files changed, 307 insertions, 43 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0eeb6520..a0ca81fb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -71,6 +71,7 @@ dependencies = [
name = "azalea-brigadier"
version = "0.1.0"
dependencies = [
+ "dyn-clonable",
"lazy_static",
]
@@ -337,6 +338,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
[[package]]
+name = "dyn-clonable"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4"
+dependencies = [
+ "dyn-clonable-impl",
+ "dyn-clone",
+]
+
+[[package]]
+name = "dyn-clonable-impl"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "dyn-clone"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf"
+
+[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/azalea-brigadier/Cargo.toml b/azalea-brigadier/Cargo.toml
index 3694a4b7..4e8968d7 100644
--- a/azalea-brigadier/Cargo.toml
+++ b/azalea-brigadier/Cargo.toml
@@ -7,3 +7,4 @@ version = "0.1.0"
[dependencies]
lazy_static = "^1.4"
+dyn-clonable = "^0.9"
diff --git a/azalea-brigadier/README.md b/azalea-brigadier/README.md
index 92c0d27e..df69b5c0 100644
--- a/azalea-brigadier/README.md
+++ b/azalea-brigadier/README.md
@@ -1,3 +1,4 @@
# Azalea Brigadier
A Rustier port of Mojang's [Brigadier](https://github.com/Mojang/brigadier) command parsing and dispatching library.
+
diff --git a/azalea-brigadier/src/arguments/argument_type.rs b/azalea-brigadier/src/arguments/argument_type.rs
index 46026735..890cdea0 100644
--- a/azalea-brigadier/src/arguments/argument_type.rs
+++ b/azalea-brigadier/src/arguments/argument_type.rs
@@ -5,11 +5,19 @@ use crate::{
string_reader::StringReader,
suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder},
};
+use dyn_clonable::*;
-pub trait Types {
+#[clonable]
+// This should be applied to an Enum
+pub trait Types: Clone {
fn bool(value: bool) -> Self
where
Self: Sized;
+
+ /// Get the less specific ArgumentType from this enum
+ fn inner<T>(&self) -> Box<dyn ArgumentType<T>>
+ where
+ Self: Sized;
}
/*
@@ -25,12 +33,21 @@ enum BrigadierTypes {
Entity(EntityArgumentType)
}
+
+impl Types for BrigadierTypes {
+ fn inner(&self) -> dyn ArgumentType<dyn Types> {
+ match self {
+ Bool(t) => t,
+ Entity(t) => t
+ }
+ }
+}
*/
-pub trait ArgumentType<T>
+#[clonable]
+pub trait ArgumentType<T: ?Sized>: Clone
where
- Self: Sized,
- T: Types + ?Sized,
+ T: Types,
{
// T parse(StringReader reader) throws CommandSyntaxException;
@@ -42,7 +59,7 @@ where
// return Collections.emptyList();
// }
- fn parse(&self, reader: &mut StringReader) -> Result<T, CommandSyntaxException>;
+ fn parse(&self, reader: &mut StringReader) -> Result<Box<T>, CommandSyntaxException>;
fn list_suggestions<S>(
&self,
@@ -50,6 +67,7 @@ where
builder: &mut SuggestionsBuilder,
) -> Result<Suggestions, CommandSyntaxException>
where
+ Self: Sized,
S: Sized,
T: Sized;
diff --git a/azalea-brigadier/src/arguments/bool_argument_type.rs b/azalea-brigadier/src/arguments/bool_argument_type.rs
index 1237caa0..b04488c1 100644
--- a/azalea-brigadier/src/arguments/bool_argument_type.rs
+++ b/azalea-brigadier/src/arguments/bool_argument_type.rs
@@ -7,6 +7,7 @@ use crate::{
use super::argument_type::{ArgumentType, Types};
+#[derive(Clone)]
pub struct BoolArgumentType {}
impl<T> ArgumentType<T> for BoolArgumentType
diff --git a/azalea-brigadier/src/builder/argument_builder.rs b/azalea-brigadier/src/builder/argument_builder.rs
index bd2a2c15..0360b05a 100644
--- a/azalea-brigadier/src/builder/argument_builder.rs
+++ b/azalea-brigadier/src/builder/argument_builder.rs
@@ -1,4 +1,5 @@
use crate::{
+ arguments::argument_type::{ArgumentType, Types},
command::Command,
redirect_modifier::RedirectModifier,
single_redirect_modifier::SingleRedirectModifier,
@@ -8,7 +9,7 @@ use crate::{
pub struct BaseArgumentBuilder<'a, S, T>
where
S: Sized,
- T: Sized,
+ T: Sized + ArgumentType<dyn Types>,
{
arguments: RootCommandNode<'a, S, T>,
command: Option<&'a dyn Command<S, T>>,
@@ -22,7 +23,10 @@ pub trait ArgumentBuilder<S, T> {
fn build(self) -> dyn CommandNode<S, T>;
}
-impl<S, T> BaseArgumentBuilder<'_, S, T> {
+impl<S, T> BaseArgumentBuilder<'_, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
pub fn then(&mut self, command: dyn CommandNode<S, T>) -> Result<&mut T, String> {
if self.target.is_some() {
return Err("Cannot add children to a redirected node".to_string());
diff --git a/azalea-brigadier/src/builder/literal_argument_builder.rs b/azalea-brigadier/src/builder/literal_argument_builder.rs
index cf9f1ee9..a4cb3f84 100644
--- a/azalea-brigadier/src/builder/literal_argument_builder.rs
+++ b/azalea-brigadier/src/builder/literal_argument_builder.rs
@@ -1,14 +1,23 @@
-use crate::tree::literal_command_node::LiteralCommandNode;
+use crate::{
+ arguments::argument_type::{ArgumentType, Types},
+ tree::literal_command_node::LiteralCommandNode,
+};
use super::argument_builder::BaseArgumentBuilder;
-pub struct LiteralArgumentBuilder<'a, S, T> {
+pub struct LiteralArgumentBuilder<'a, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
literal: String,
pub base: BaseArgumentBuilder<'a, S, T>,
}
-impl<'a, S, T> LiteralArgumentBuilder<'a, S, T> {
+impl<'a, S, T> LiteralArgumentBuilder<'a, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
pub fn new(literal: String) -> Self {
Self {
literal,
diff --git a/azalea-brigadier/src/builder/required_argument_builder.rs b/azalea-brigadier/src/builder/required_argument_builder.rs
index 6f6fa8eb..b5f99828 100644
--- a/azalea-brigadier/src/builder/required_argument_builder.rs
+++ b/azalea-brigadier/src/builder/required_argument_builder.rs
@@ -1,11 +1,15 @@
use crate::{
+ arguments::argument_type::{ArgumentType, Types},
suggestion::suggestion_provider::SuggestionProvider,
tree::{argument_command_node::ArgumentCommandNode, command_node::BaseCommandNode},
};
use super::argument_builder::BaseArgumentBuilder;
-pub struct RequiredArgumentBuilder<'a, S, T> {
+pub struct RequiredArgumentBuilder<'a, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
// private final String name;
// private final ArgumentType<T> type;
// private SuggestionProvider<S> suggestionsProvider = null;
@@ -16,7 +20,10 @@ pub struct RequiredArgumentBuilder<'a, S, T> {
pub base: BaseArgumentBuilder<'a, S, T>,
}
-impl<'a, S, T> RequiredArgumentBuilder<'a, S, T> {
+impl<'a, S, T> RequiredArgumentBuilder<'a, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
pub fn new(name: String, type_: T) -> Self {
Self {
name,
diff --git a/azalea-brigadier/src/command.rs b/azalea-brigadier/src/command.rs
index 520c8a52..dcbf3ffd 100644
--- a/azalea-brigadier/src/command.rs
+++ b/azalea-brigadier/src/command.rs
@@ -2,9 +2,11 @@ use crate::{
context::command_context::CommandContext,
exceptions::command_syntax_exception::CommandSyntaxException,
};
+use dyn_clonable::*;
pub const SINGLE_SUCCESS: i32 = 1;
-pub trait Command<S, T> {
+#[clonable]
+pub trait Command<S, T>: Clone {
fn run(&self, context: &mut CommandContext<S, T>) -> Result<i32, CommandSyntaxException>;
}
diff --git a/azalea-brigadier/src/command_dispatcher.rs b/azalea-brigadier/src/command_dispatcher.rs
index d0351547..f2fc7528 100644
--- a/azalea-brigadier/src/command_dispatcher.rs
+++ b/azalea-brigadier/src/command_dispatcher.rs
@@ -1,13 +1,22 @@
-use crate::tree::root_command_node::RootCommandNode;
+use crate::{
+ arguments::argument_type::{ArgumentType, Types},
+ tree::root_command_node::RootCommandNode,
+};
/// The core command dispatcher, for registering, parsing, and executing commands.
/// The `S` generic is a custom "source" type, such as a user or originator of a command
-#[derive(Default)]
-pub struct CommandDispatcher<'a, S, T> {
+#[derive(Default, Clone)]
+pub struct CommandDispatcher<'a, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
root: RootCommandNode<'a, S, T>,
}
-impl<S, T> CommandDispatcher<'_, S, T> {
+impl<S, T> CommandDispatcher<'_, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
/// The string required to separate individual arguments in an input string
///
/// See: [`ARGUMENT_SEPARATOR_CHAR`]
diff --git a/azalea-brigadier/src/context/command_context_builder.rs b/azalea-brigadier/src/context/command_context_builder.rs
index 88e26343..639a97ee 100644
--- a/azalea-brigadier/src/context/command_context_builder.rs
+++ b/azalea-brigadier/src/context/command_context_builder.rs
@@ -1,8 +1,10 @@
use std::collections::HashMap;
use crate::{
- arguments::argument_type::ArgumentType, command::Command,
- command_dispatcher::CommandDispatcher, redirect_modifier::RedirectModifier,
+ arguments::argument_type::{ArgumentType, Types},
+ command::Command,
+ command_dispatcher::CommandDispatcher,
+ redirect_modifier::RedirectModifier,
tree::command_node::CommandNode,
};
@@ -25,7 +27,10 @@ use super::{
// private boolean forks;
#[derive(Clone)]
-pub struct CommandContextBuilder<'a, S, T> {
+pub struct CommandContextBuilder<'a, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
arguments: HashMap<String, ParsedArgument<T>>,
root_node: &'a dyn CommandNode<S, T>,
nodes: Vec<ParsedCommandNode<S, T>>,
@@ -45,7 +50,10 @@ pub struct CommandContextBuilder<'a, S, T> {
// this.range = StringRange.at(start);
// }
-impl<S, T> CommandContextBuilder<'_, S, T> {
+impl<S, T> CommandContextBuilder<'_, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
pub fn new(
dispatcher: CommandDispatcher<S, T>,
source: S,
diff --git a/azalea-brigadier/src/context/parsed_command_node.rs b/azalea-brigadier/src/context/parsed_command_node.rs
index 14168a06..c0be355c 100644
--- a/azalea-brigadier/src/context/parsed_command_node.rs
+++ b/azalea-brigadier/src/context/parsed_command_node.rs
@@ -19,3 +19,12 @@ impl<S, T> ParsedCommandNode<S, T> {
&self.range
}
}
+
+impl<S, T> Clone for ParsedCommandNode<S, T> {
+ fn clone_from(&mut self, source: &Self) {
+ Self {
+ node: self.node.clone(),
+ range: self.range.clone(),
+ }
+ }
+}
diff --git a/azalea-brigadier/src/redirect_modifier.rs b/azalea-brigadier/src/redirect_modifier.rs
index fd2e1bf7..fdb0a080 100644
--- a/azalea-brigadier/src/redirect_modifier.rs
+++ b/azalea-brigadier/src/redirect_modifier.rs
@@ -1,8 +1,11 @@
+use dyn_clonable::*;
+
use crate::{
context::command_context::CommandContext,
exceptions::command_syntax_exception::CommandSyntaxException,
};
-pub trait RedirectModifier<S, T> {
+#[clonable]
+pub trait RedirectModifier<S, T>: Clone {
fn apply(&self, context: CommandContext<S, T>) -> Result<Vec<S>, CommandSyntaxException>;
}
diff --git a/azalea-brigadier/src/suggestion/integer_suggestion.rs b/azalea-brigadier/src/suggestion/integer_suggestion.rs
index e69de29b..acee2329 100644
--- a/azalea-brigadier/src/suggestion/integer_suggestion.rs
+++ b/azalea-brigadier/src/suggestion/integer_suggestion.rs
@@ -0,0 +1 @@
+pub struct IntegerSuggestion {}
diff --git a/azalea-brigadier/src/suggestion/suggestions.rs b/azalea-brigadier/src/suggestion/suggestions.rs
index 18572d20..778c5de8 100644
--- a/azalea-brigadier/src/suggestion/suggestions.rs
+++ b/azalea-brigadier/src/suggestion/suggestions.rs
@@ -1,8 +1,90 @@
-use std::cmp;
+use std::{cmp, collections::HashSet};
use crate::{context::string_range::StringRange, message::Message};
-pub struct Suggestions {}
+use super::suggestion::Suggestion;
+
+#[derive(PartialEq, Eq, Hash, Default)]
+pub struct Suggestions {
+ range: StringRange,
+ suggestions: Vec<Suggestions>,
+}
+
+impl Suggestions {
+ fn range(&self) -> &StringRange {
+ &self.range
+ }
+
+ fn list(&self) -> &Vec<Suggestions> {
+ &self.suggestions
+ }
+
+ fn is_empty(&self) -> bool {
+ self.suggestions.is_empty()
+ }
+
+ fn merge(command: &str, input: &Vec<Suggestions>) {
+ if input.is_empty() {
+ return Self::default();
+ } else if input.len() == 1 {
+ return input.iter().next();
+ }
+ let texts = HashSet::new();
+ for suggestions in input {
+ texts.extend(suggestions.list())
+ }
+ Self::new(command, texts)
+ }
+
+ // public static Suggestions create(final String command, final Collection<Suggestion> suggestions) {
+ // if (suggestions.isEmpty()) {
+ // return EMPTY;
+ // }
+ // int start = Integer.MAX_VALUE;
+ // int end = Integer.MIN_VALUE;
+ // for (final Suggestion suggestion : suggestions) {
+ // start = Math.min(suggestion.getRange().getStart(), start);
+ // end = Math.max(suggestion.getRange().getEnd(), end);
+ // }
+ // final StringRange range = new StringRange(start, end);
+ // final Set<Suggestion> texts = new HashSet<>();
+ // for (final Suggestion suggestion : suggestions) {
+ // texts.add(suggestion.expand(command, range));
+ // }
+ // final List<Suggestion> sorted = new ArrayList<>(texts);
+ // sorted.sort((a, b) -> a.compareToIgnoreCase(b));
+ // return new Suggestions(range, sorted);
+ pub fn new(command: String, suggestions: Vec<Suggestion>) -> Self {
+ if suggestions.is_empty() {
+ return Self::default();
+ }
+ let mut start = usize::MAX;
+ let mut end = usize::MIN;
+ for suggestion in suggestions {
+ let start = cmp::min(suggestion.range().start(), start);
+ let end = cmp::max(suggestion.range().end(), end);
+ }
+ let range = StringRange::new(start, end);
+ let texts = HashSet::new();
+ for suggestion in suggestions {
+ texts.insert(suggestion.expand(command, range));
+ }
+ let sorted = texts.sort_by(|a, b| a.compare_ignore_case(b));
+ Suggestions {
+ range,
+ suggestions: sorted,
+ }
+ }
+}
+
+impl Default for Suggestions {
+ fn default() -> Self {
+ Self {
+ range: StringRange::at(0),
+ suggestions: vec![],
+ }
+ }
+}
// #[cfg(test)]
// mod tests {
diff --git a/azalea-brigadier/src/suggestion/suggestions_builder.rs b/azalea-brigadier/src/suggestion/suggestions_builder.rs
index 7853a3a2..bc8f6f5d 100644
--- a/azalea-brigadier/src/suggestion/suggestions_builder.rs
+++ b/azalea-brigadier/src/suggestion/suggestions_builder.rs
@@ -1,6 +1,8 @@
use crate::context::string_range::StringRange;
-use super::{suggestion::Suggestion, suggestions::Suggestions};
+use super::{
+ integer_suggestion::IntegerSuggestion, suggestion::Suggestion, suggestions::Suggestions,
+};
pub struct SuggestionsBuilder {
input: String,
diff --git a/azalea-brigadier/src/tree/argument_command_node.rs b/azalea-brigadier/src/tree/argument_command_node.rs
index 647b6c35..3fc1bb50 100644
--- a/azalea-brigadier/src/tree/argument_command_node.rs
+++ b/azalea-brigadier/src/tree/argument_command_node.rs
@@ -21,6 +21,7 @@ use super::command_node::{BaseCommandNode, CommandNode};
const USAGE_ARGUMENT_OPEN: &str = "<";
const USAGE_ARGUMENT_CLOSE: &str = ">";
+#[derive(Clone)]
pub struct ArgumentCommandNode<'a, S, T>
where
// each argument command node has its own different type
@@ -34,7 +35,10 @@ where
pub base: BaseCommandNode<'a, S, T>,
}
-impl<S, T> ArgumentCommandNode<'_, S, T> {
+impl<S, T> ArgumentCommandNode<'_, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
fn get_type(&self) -> &T {
&self.type_
}
@@ -44,7 +48,11 @@ impl<S, T> ArgumentCommandNode<'_, S, T> {
}
}
-impl<'a, S, T> CommandNode<S, T> for ArgumentCommandNode<'a, S, T> {
+impl<'a, S, T> CommandNode<S, T> for ArgumentCommandNode<'a, S, T>
+where
+ T: ArgumentType<dyn Types> + Clone,
+ S: Clone,
+{
fn name(&self) -> &str {
&self.name
}
@@ -117,7 +125,10 @@ impl<'a, S, T> CommandNode<S, T> for ArgumentCommandNode<'a, S, T> {
}
}
-impl Display for ArgumentCommandNode<'_, (), (), ()> {
+impl<S, T> Display for ArgumentCommandNode<'_, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "<argument {}: {}>", self.name, self.type_)
}
diff --git a/azalea-brigadier/src/tree/command_node.rs b/azalea-brigadier/src/tree/command_node.rs
index 8e262f0b..f3be1597 100644
--- a/azalea-brigadier/src/tree/command_node.rs
+++ b/azalea-brigadier/src/tree/command_node.rs
@@ -1,7 +1,6 @@
-use std::collections::HashMap;
-
+use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode};
use crate::{
- arguments::argument_type::ArgumentType,
+ arguments::argument_type::{ArgumentType, Types},
builder::argument_builder::ArgumentBuilder,
command::Command,
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
@@ -10,10 +9,14 @@ use crate::{
string_reader::StringReader,
suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder},
};
+use dyn_clonable::*;
+use std::{collections::HashMap, fmt::Debug};
-use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode};
-
-pub struct BaseCommandNode<'a, S, T> {
+#[derive(Default)]
+pub struct BaseCommandNode<'a, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
children: HashMap<String, &'a dyn CommandNode<S, T>>,
literals: HashMap<String, LiteralCommandNode<'a, S, T>>,
arguments: HashMap<String, ArgumentCommandNode<'a, S, T>>,
@@ -24,9 +27,49 @@ pub struct BaseCommandNode<'a, S, T> {
command: Option<&'a dyn Command<S, T>>,
}
-impl<S, T> BaseCommandNode<'_, S, T> {}
+impl<S, T> BaseCommandNode<'_, S, T> where T: ArgumentType<dyn Types> {}
+
+impl<S, T> Clone for BaseCommandNode<'_, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
+ fn clone(&self) -> Self {
+ Self {
+ children: self.children.clone(),
+ literals: self.literals.clone(),
+ arguments: self.arguments.clone(),
+ requirement: self.requirement.clone(),
+ redirect: self.redirect.clone(),
+ modifier: self.modifier.clone(),
+ forks: self.forks.clone(),
+ command: self.command.clone(),
+ }
+ }
+}
+
+impl<S, T> Debug for BaseCommandNode<'_, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("BaseCommandNode")
+ .field("children", &self.children)
+ .field("literals", &self.literals)
+ .field("arguments", &self.arguments)
+ .field("requirement", &self.requirement)
+ .field("redirect", &self.redirect)
+ .field("modifier", &self.modifier)
+ .field("forks", &self.forks)
+ .field("command", &self.command)
+ .finish()
+ }
+}
-pub trait CommandNode<S, T> {
+#[clonable]
+pub trait CommandNode<S, T>: Clone
+where
+ T: ArgumentType<dyn Types>,
+{
fn name(&self) -> &str;
fn usage_text(&self) -> &str;
fn parse(
diff --git a/azalea-brigadier/src/tree/literal_command_node.rs b/azalea-brigadier/src/tree/literal_command_node.rs
index fe933669..021a3ea6 100644
--- a/azalea-brigadier/src/tree/literal_command_node.rs
+++ b/azalea-brigadier/src/tree/literal_command_node.rs
@@ -1,4 +1,5 @@
use crate::{
+ arguments::argument_type::{ArgumentType, Types},
builder::literal_argument_builder::LiteralArgumentBuilder,
command::Command,
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
@@ -12,15 +13,22 @@ use crate::{
use super::command_node::{BaseCommandNode, CommandNode};
-#[derive(Hash, PartialEq, Eq, Debug, Clone)]
-pub struct LiteralCommandNode<'a, S, T> {
+#[derive(Debug, Clone)]
+pub struct LiteralCommandNode<'a, S, T>
+where
+ // each argument command node has its own different type
+ T: ArgumentType<dyn Types>,
+{
literal: String,
literal_lowercase: String,
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
pub base: BaseCommandNode<'a, S, T>,
}
-impl<'a, S, T> LiteralCommandNode<'a, S, T> {
+impl<'a, S, T> LiteralCommandNode<'a, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
pub fn new(literal: String, base: BaseCommandNode<S, T>) -> Self {
let literal_lowercase = literal.to_lowercase();
Self {
@@ -51,7 +59,11 @@ impl<'a, S, T> LiteralCommandNode<'a, S, T> {
}
}
-impl<S, T> CommandNode<S, T> for LiteralCommandNode<'_, S, T> {
+impl<S, T> CommandNode<S, T> for LiteralCommandNode<'_, S, T>
+where
+ T: ArgumentType<dyn Types> + Clone,
+ S: Clone,
+{
fn name(&self) -> &str {
&self.literal
}
diff --git a/azalea-brigadier/src/tree/root_command_node.rs b/azalea-brigadier/src/tree/root_command_node.rs
index 36787340..ded5fa77 100644
--- a/azalea-brigadier/src/tree/root_command_node.rs
+++ b/azalea-brigadier/src/tree/root_command_node.rs
@@ -1,6 +1,7 @@
use std::fmt::{Display, Formatter};
use crate::{
+ arguments::argument_type::{ArgumentType, Types},
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
exceptions::{
builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException,
@@ -11,12 +12,21 @@ use crate::{
use super::command_node::{BaseCommandNode, CommandNode};
-pub struct RootCommandNode<'a, S, T> {
+#[derive(Clone, Default)]
+pub struct RootCommandNode<'a, S, T>
+where
+ // each argument command node has its own different type
+ T: ArgumentType<dyn Types>,
+{
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
pub base: BaseCommandNode<'a, S, T>,
}
-impl<S, T> CommandNode<S, T> for RootCommandNode<'_, S, T> {
+impl<S, T> CommandNode<S, T> for RootCommandNode<'_, S, T>
+where
+ T: ArgumentType<dyn Types> + Clone,
+ S: Clone,
+{
fn name(&self) -> &str {
""
}
@@ -53,7 +63,10 @@ impl<S, T> CommandNode<S, T> for RootCommandNode<'_, S, T> {
}
}
-impl<S, T> Display for RootCommandNode<'_, S, T> {
+impl<S, T> Display for RootCommandNode<'_, S, T>
+where
+ T: ArgumentType<dyn Types>,
+{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "<root>")
}