diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2022-04-20 01:34:12 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-20 01:34:12 +0000 |
| commit | 5fd87615cf1514c7f9a0358988964768ded3f06e (patch) | |
| tree | 001c3c760fdae8fe7b72cacb1f87d3703cc4e82c /azalea-brigadier/src/builder | |
| parent | d09762f5d38ab1200fb08ca3b1178813b4e47081 (diff) | |
| parent | be194c1ca136100fd8f53ed068d82c9f7ae32870 (diff) | |
| download | azalea-drasl-5fd87615cf1514c7f9a0358988964768ded3f06e.tar.xz | |
Merge pull request #1 from mat-1/brigadier
azalea-brigadier
Diffstat (limited to 'azalea-brigadier/src/builder')
| -rw-r--r-- | azalea-brigadier/src/builder/argument_builder.rs | 137 | ||||
| -rw-r--r-- | azalea-brigadier/src/builder/literal_argument_builder.rs | 24 | ||||
| -rw-r--r-- | azalea-brigadier/src/builder/mod.rs | 3 | ||||
| -rw-r--r-- | azalea-brigadier/src/builder/required_argument_builder.rs | 45 |
4 files changed, 209 insertions, 0 deletions
diff --git a/azalea-brigadier/src/builder/argument_builder.rs b/azalea-brigadier/src/builder/argument_builder.rs new file mode 100644 index 00000000..d26b2a8a --- /dev/null +++ b/azalea-brigadier/src/builder/argument_builder.rs @@ -0,0 +1,137 @@ +use crate::{context::CommandContext, modifier::RedirectModifier, tree::CommandNode}; + +use super::{literal_argument_builder::Literal, required_argument_builder::Argument}; +use std::{cell::RefCell, fmt::Debug, rc::Rc}; + +#[derive(Debug, Clone)] +pub enum ArgumentBuilderType { + Literal(Literal), + Argument(Argument), +} + +/// A node that hasn't yet been built. +pub struct ArgumentBuilder<S> { + arguments: CommandNode<S>, + + command: Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>, + requirement: Rc<dyn Fn(Rc<S>) -> bool>, + target: Option<Rc<RefCell<CommandNode<S>>>>, + + forks: bool, + modifier: Option<Rc<RedirectModifier<S>>>, +} + +impl<S> Clone for ArgumentBuilder<S> { + fn clone(&self) -> Self { + Self { + arguments: self.arguments.clone(), + command: self.command.clone(), + requirement: self.requirement.clone(), + target: self.target.clone(), + forks: self.forks, + modifier: self.modifier.clone(), + } + } +} + +/// A node that isn't yet built. +impl<S> ArgumentBuilder<S> { + pub fn new(value: ArgumentBuilderType) -> Self { + Self { + arguments: CommandNode { + value, + ..Default::default() + }, + command: None, + requirement: Rc::new(|_| true), + forks: false, + modifier: None, + target: None, + } + } + + pub fn then(&mut self, argument: ArgumentBuilder<S>) -> Self { + self.then_built(argument.build()) + } + + pub fn then_built(&mut self, argument: CommandNode<S>) -> Self { + self.arguments.add_child(&Rc::new(RefCell::new(argument))); + self.clone() + } + + pub fn executes<F>(&mut self, f: F) -> Self + where + F: Fn(&CommandContext<S>) -> i32 + 'static, + { + self.command = Some(Rc::new(f)); + self.clone() + } + + pub fn requires<F>(&mut self, requirement: F) -> Self + where + F: Fn(Rc<S>) -> bool + 'static, + { + self.requirement = Rc::new(requirement); + self.clone() + } + + pub fn redirect(&mut self, target: Rc<RefCell<CommandNode<S>>>) -> Self { + self.forward(target, None, false) + } + + pub fn fork( + &mut self, + target: Rc<RefCell<CommandNode<S>>>, + modifier: Rc<RedirectModifier<S>>, + ) -> Self { + self.forward(target, Some(modifier), true) + } + + pub fn forward( + &mut self, + target: Rc<RefCell<CommandNode<S>>>, + modifier: Option<Rc<RedirectModifier<S>>>, + fork: bool, + ) -> Self { + if !self.arguments.children.is_empty() { + panic!("Cannot forward a node with children"); + } + self.target = Some(target); + self.modifier = modifier; + self.forks = fork; + self.clone() + } + + pub fn build(self) -> CommandNode<S> { + let mut result = CommandNode { + value: self.arguments.value, + command: self.command, + requirement: self.requirement, + redirect: self.target, + modifier: self.modifier, + forks: self.forks, + arguments: Default::default(), + children: Default::default(), + literals: Default::default(), + }; + + for argument in self.arguments.children.values() { + result.add_child(argument); + } + + result + } +} + +impl<S> Debug for ArgumentBuilder<S> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ArgumentBuilder") + .field("arguments", &self.arguments) + // .field("command", &self.command) + // .field("requirement", &self.requirement) + .field("target", &self.target) + .field("forks", &self.forks) + // .field("modifier", &self.modifier) + .finish() + } +} diff --git a/azalea-brigadier/src/builder/literal_argument_builder.rs b/azalea-brigadier/src/builder/literal_argument_builder.rs new file mode 100644 index 00000000..6627ffdc --- /dev/null +++ b/azalea-brigadier/src/builder/literal_argument_builder.rs @@ -0,0 +1,24 @@ +use super::argument_builder::{ArgumentBuilder, ArgumentBuilderType}; + +#[derive(Debug, Clone, Default)] +pub struct Literal { + pub value: String, +} +impl Literal { + pub fn new(value: &str) -> Self { + Self { + value: value.to_string(), + } + } +} + +impl From<Literal> for ArgumentBuilderType { + fn from(literal: Literal) -> Self { + Self::Literal(literal) + } +} + +/// Shortcut for creating a new literal builder node. +pub fn literal<S>(value: &str) -> ArgumentBuilder<S> { + ArgumentBuilder::new(ArgumentBuilderType::Literal(Literal::new(value))) +} diff --git a/azalea-brigadier/src/builder/mod.rs b/azalea-brigadier/src/builder/mod.rs new file mode 100644 index 00000000..26f2f644 --- /dev/null +++ b/azalea-brigadier/src/builder/mod.rs @@ -0,0 +1,3 @@ +pub mod argument_builder; +pub mod literal_argument_builder; +pub mod required_argument_builder; diff --git a/azalea-brigadier/src/builder/required_argument_builder.rs b/azalea-brigadier/src/builder/required_argument_builder.rs new file mode 100644 index 00000000..9d4d9e0a --- /dev/null +++ b/azalea-brigadier/src/builder/required_argument_builder.rs @@ -0,0 +1,45 @@ +use super::argument_builder::{ArgumentBuilder, ArgumentBuilderType}; +use crate::{ + arguments::ArgumentType, exceptions::CommandSyntaxException, string_reader::StringReader, +}; +use std::{any::Any, fmt::Debug, rc::Rc}; + +/// An argument node type. The `T` type parameter is the type of the argument, +/// which can be anything. +#[derive(Clone)] +pub struct Argument { + pub name: String, + parser: Rc<dyn ArgumentType>, +} +impl Argument { + pub fn new(name: &str, parser: Rc<dyn ArgumentType>) -> Self { + Self { + name: name.to_string(), + parser, + } + } + + pub fn parse(&self, reader: &mut StringReader) -> Result<Rc<dyn Any>, CommandSyntaxException> { + self.parser.parse(reader) + } +} + +impl From<Argument> for ArgumentBuilderType { + fn from(argument: Argument) -> Self { + Self::Argument(argument) + } +} + +impl Debug for Argument { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Argument") + .field("name", &self.name) + // .field("parser", &self.parser) + .finish() + } +} + +/// Shortcut for creating a new argument builder node. +pub fn argument<S>(name: &str, parser: impl ArgumentType + 'static) -> ArgumentBuilder<S> { + ArgumentBuilder::new(Argument::new(name, Rc::new(parser)).into()) +} |
