From 760816c81fab414cc42ab1e75506fc816bcf9681 Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 13 Jan 2022 20:08:53 -0600 Subject: stuff --- azalea-brigadier/src/tree/command_node.rs | 119 +++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 11 deletions(-) (limited to 'azalea-brigadier/src/tree/command_node.rs') diff --git a/azalea-brigadier/src/tree/command_node.rs b/azalea-brigadier/src/tree/command_node.rs index b8f416eb..f59b1cef 100644 --- a/azalea-brigadier/src/tree/command_node.rs +++ b/azalea-brigadier/src/tree/command_node.rs @@ -1,4 +1,7 @@ -use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode}; +use super::{ + argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode, + root_command_node::RootCommandNode, +}; use crate::{ arguments::argument_type::ArgumentType, builder::argument_builder::ArgumentBuilder, @@ -12,19 +15,98 @@ use crate::{ use dyn_clonable::*; use std::{any::Any, collections::HashMap, fmt::Debug}; -#[derive(Default)] pub struct BaseCommandNode<'a, S> { - children: HashMap>, + children: HashMap>>, literals: HashMap>, arguments: HashMap>, - requirement: Option<&'a dyn Fn(&S) -> bool>, - redirect: Option<&'a dyn CommandNode>, - modifier: Option<&'a dyn RedirectModifier>, + requirement: Box bool>, + redirect: Option>>, + modifier: Option>>, forks: bool, - command: Option<&'a dyn Command>, + command: Option>>, } -impl BaseCommandNode<'_, S> {} +impl BaseCommandNode<'_, S> { + pub fn command(&self) -> &Option>> { + &self.command + } + + pub fn children(&self) -> &HashMap>> { + &self.children + } + + pub fn child(&self, name: &str) -> Option<&dyn CommandNode> { + self.children.get(name).map(|child| child.as_ref()) + } + + pub fn redirect(&self) -> Option<&dyn CommandNode> { + self.redirect.as_ref().map(|redirect| redirect.as_ref()) + } + + pub fn redirect_modifier(&self) -> Option<&dyn RedirectModifier> { + self.modifier.as_ref().map(|modifier| modifier.as_ref()) + } + + pub fn can_use(&self, source: S) -> bool { + (self.requirement)(&source) + } + + // public void addChild(final CommandNode node) { + // if (node instanceof RootCommandNode) { + // throw new UnsupportedOperationException("Cannot add a RootCommandNode as a child to any other CommandNode"); + // } + + // final CommandNode child = children.get(node.getName()); + // if (child != null) { + // // We've found something to merge onto + // if (node.getCommand() != null) { + // child.command = node.getCommand(); + // } + // for (final CommandNode grandchild : node.getChildren()) { + // child.addChild(grandchild); + // } + // } else { + // children.put(node.getName(), node); + // if (node instanceof LiteralCommandNode) { + // literals.put(node.getName(), (LiteralCommandNode) node); + // } else if (node instanceof ArgumentCommandNode) { + // arguments.put(node.getName(), (ArgumentCommandNode) node); + // } + // } + // } + + pub fn add_child(&self, node: &dyn CommandNode) -> Result<(), String> { + if (&node as &dyn Any).is::>() { + return Err(String::from( + "Cannot add a RootCommandNode as a child to any other CommandNode", + )); + } + + let child = self.children.get(node.name()); + if let Some(child) = child { + // We've found something to merge onto + if let Some(command) = node.base.command() { + child.command = Some(command); + } + for grandchild in node.children() { + child.add_child(grandchild)?; + } + } else { + self.children.insert(node.name().to_string(), node); + if let Some(literal) = + &node.clone_boxed() as &dyn Any as &dyn Any as &LiteralCommandNode + { + self.literals + .insert(node.name().to_string(), literal.clone_boxed()); + } else if let Some(argument) = + &node.clone_boxed() as &dyn Any as &dyn Any as &ArgumentCommandNode + { + self.arguments + .insert(node.name().to_string(), argument.clone_boxed()); + } + } + } +} impl Clone for BaseCommandNode<'_, S> { fn clone(&self) -> Self { @@ -56,8 +138,22 @@ impl Debug for BaseCommandNode<'_, S> { } } -#[clonable] -pub trait CommandNode: Clone { +impl Default for BaseCommandNode<'_, S> { + fn default() -> Self { + Self { + children: HashMap::new(), + literals: HashMap::new(), + arguments: HashMap::new(), + requirement: Box::new(|_| true), + redirect: None, + modifier: None, + forks: false, + command: None, + } + } +} + +pub trait CommandNode { fn name(&self) -> &str; fn usage_text(&self) -> &str; fn parse( @@ -68,9 +164,10 @@ pub trait CommandNode: Clone { fn list_suggestions( &self, context: CommandContext, - builder: SuggestionsBuilder, + builder: &SuggestionsBuilder, ) -> Result; fn is_valid_input(&self, input: &str) -> bool; fn create_builder(&self) -> dyn ArgumentBuilder; fn get_examples(&self) -> Vec; + fn base(&self) -> &BaseCommandNode; } -- cgit v1.2.3