minecraft-command-types 0.1.0

Provides an AST like structure for Minecraft commands.
Documentation
use crate::block::BlockState;
use crate::column_position::ColumnPosition;
use crate::command::data::DataTarget;
use crate::command::enums::axis::Axis;
use crate::command::enums::bossbar_store_type::BossbarStoreType;
use crate::command::enums::entity_anchor::EntityAnchor;
use crate::command::enums::heightmap::Heightmap;
use crate::command::enums::if_blocks_mode::IfBlocksMode;
use crate::command::enums::numeric_snbt_type::NumericSNBTType;
use crate::command::enums::relation::Relation;
use crate::command::enums::store_type::StoreType;
use crate::command::item_source::ItemSource;
use crate::command::{Command, PlayerScore};
use crate::coordinate::Coordinates;
use crate::entity_selector::EntitySelector;
use crate::item::ItemPredicate;
use crate::nbt_path::NbtPath;
use crate::range::{FloatRange, IntegerRange};
use crate::resource_location::ResourceLocation;
use crate::rotation::Rotation;
use minecraft_command_types_derive::HasMacro;
use ordered_float::NotNan;
use std::collections::BTreeSet;
use std::fmt::{Display, Formatter};
use strum::Display;

#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
pub enum Facing {
    Position(Coordinates),
    Entity(EntitySelector, EntityAnchor),
}

impl Display for Facing {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Facing::Position(coords) => coords.fmt(f),
            Facing::Entity(selector, anchor) => write!(f, "entity {} {}", selector, anchor),
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
pub enum Positioned {
    Position(Coordinates),
    As(EntitySelector),
    Over(Heightmap),
}

impl Display for Positioned {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Positioned::Position(coords) => coords.fmt(f),
            Positioned::As(selector) => write!(f, "as {}", selector),
            Positioned::Over(heightmap) => write!(f, "over {}", heightmap),
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
pub enum Rotated {
    Rotation(Rotation),
    As(EntitySelector),
}

impl Display for Rotated {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Rotated::Rotation(rotation) => rotation.fmt(f),
            Rotated::As(selector) => write!(f, "as {}", selector),
        }
    }
}

#[derive(Display, Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
pub enum ScoreComparisonOperator {
    #[strum(serialize = "<")]
    LessThan,
    #[strum(serialize = "<=")]
    LessThanOrEqualTo,
    #[strum(serialize = "=")]
    EqualTo,
    #[strum(serialize = ">")]
    GreaterThan,
    #[strum(serialize = ">=")]
    GreaterThanOrEqualTo,
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
pub enum ScoreComparison {
    Range(IntegerRange),
    Score(ScoreComparisonOperator, PlayerScore),
}

impl Display for ScoreComparison {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ScoreComparison::Range(range) => write!(f, "matches {}", range),
            ScoreComparison::Score(operator, right) => {
                write!(f, "{} {}", operator, right)
            }
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
pub enum ExecuteIfSubcommand {
    Biome(
        Coordinates,
        ResourceLocation,
        Option<Box<ExecuteSubcommand>>,
    ),
    Block(Coordinates, BlockState, Option<Box<ExecuteSubcommand>>),
    Blocks(
        Coordinates,
        Coordinates,
        Coordinates,
        IfBlocksMode,
        Option<Box<ExecuteSubcommand>>,
    ),
    Data(DataTarget, NbtPath, Option<Box<ExecuteSubcommand>>),
    Dimension(ResourceLocation, Option<Box<ExecuteSubcommand>>),
    Entity(EntitySelector, Option<Box<ExecuteSubcommand>>),
    Function(ResourceLocation, Box<ExecuteSubcommand>),
    Items(
        ItemSource,
        String,
        ItemPredicate,
        Option<Box<ExecuteSubcommand>>,
    ),
    Loaded(ColumnPosition, Option<Box<ExecuteSubcommand>>),
    Predicate(ResourceLocation, Option<Box<ExecuteSubcommand>>),
    Score(PlayerScore, ScoreComparison, Option<Box<ExecuteSubcommand>>),
    Stopwatch(ResourceLocation, FloatRange),
}

impl Display for ExecuteIfSubcommand {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ExecuteIfSubcommand::Biome(coords, id, next) => {
                write!(f, "biome {} {}", coords, id)?;

                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Block(coords, predicate, next) => {
                write!(f, "block {} {}", coords, predicate)?;

                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Blocks(start, end, dest, mode, next) => {
                write!(f, "blocks {} {} {} {}", start, end, dest, mode)?;

                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Data(target, path, next) => {
                write!(f, "data {} {}", target, path)?;

                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Dimension(id, next) => {
                write!(f, "dimension {}", id)?;

                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Entity(selector, next) => {
                write!(f, "entity {}", selector)?;

                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Function(id, next) => {
                write!(f, "function {} {}", id, next)
            }
            ExecuteIfSubcommand::Items(source, slot, predicate, next) => {
                write!(f, "items {} {} {}", source, slot, predicate)?;

                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Loaded(coords, next) => {
                write!(f, "loaded {}", coords)?;
                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Predicate(id, next) => {
                write!(f, "predicate {}", id)?;
                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Score(score, comparison, next) => {
                write!(f, "score {} {}", score, comparison)?;
                if let Some(next_sub) = next {
                    write!(f, " {}", next_sub)?;
                }

                Ok(())
            }
            ExecuteIfSubcommand::Stopwatch(location, range) => {
                write!(f, "stopwatch {} {}", location, range)
            }
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
pub enum ExecuteStoreSubcommand {
    Block(
        Coordinates,
        NbtPath,
        NumericSNBTType,
        NotNan<f32>,
        Box<ExecuteSubcommand>,
    ),
    Bossbar(ResourceLocation, BossbarStoreType, Box<ExecuteSubcommand>),
    Entity(
        EntitySelector,
        NbtPath,
        NumericSNBTType,
        NotNan<f32>,
        Box<ExecuteSubcommand>,
    ),
    Score(PlayerScore, Box<ExecuteSubcommand>),
    Storage(
        ResourceLocation,
        NbtPath,
        NumericSNBTType,
        NotNan<f32>,
        Box<ExecuteSubcommand>,
    ),
}

impl Display for ExecuteStoreSubcommand {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ExecuteStoreSubcommand::Block(coords, path, num_type, scale, next) => {
                write!(
                    f,
                    "block {} {} {} {} {}",
                    coords, path, num_type, scale, next
                )?;

                Ok(())
            }
            ExecuteStoreSubcommand::Bossbar(id, store_type, next) => {
                write!(f, "bossbar {} {} {}", id, store_type, next)?;

                Ok(())
            }
            ExecuteStoreSubcommand::Entity(selector, path, num_type, scale, next) => {
                write!(
                    f,
                    "entity {} {} {} {} {}",
                    selector, path, num_type, scale, next
                )?;

                Ok(())
            }
            ExecuteStoreSubcommand::Score(score, next) => {
                write!(f, "score {} {}", score, next)?;

                Ok(())
            }
            ExecuteStoreSubcommand::Storage(id, path, num_type, scale, next) => {
                write!(f, "storage {} {} {} {} {}", id, path, num_type, scale, next)?;

                Ok(())
            }
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
pub enum ExecuteSubcommand {
    Align(BTreeSet<Axis>, Box<ExecuteSubcommand>),
    Anchored(EntityAnchor, Box<ExecuteSubcommand>),
    As(EntitySelector, Box<ExecuteSubcommand>),
    At(EntitySelector, Box<ExecuteSubcommand>),
    Facing(Facing, Box<ExecuteSubcommand>),
    In(ResourceLocation, Box<ExecuteSubcommand>),
    On(Relation, Box<ExecuteSubcommand>),
    Positioned(Positioned, Box<ExecuteSubcommand>),
    Rotated(Rotated, Box<ExecuteSubcommand>),
    Summon(ResourceLocation, Box<ExecuteSubcommand>),
    If(bool, ExecuteIfSubcommand),
    Store(StoreType, ExecuteStoreSubcommand),
    Run(Box<Command>),
}

impl Display for ExecuteSubcommand {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ExecuteSubcommand::Align(axes, next) => {
                let axes_str: String = axes.iter().map(|a| a.to_string()).collect();
                write!(f, "align {} {}", axes_str, next)?;

                Ok(())
            }
            ExecuteSubcommand::Anchored(anchor, next) => {
                write!(f, "anchored {} {}", anchor, next)?;

                Ok(())
            }
            ExecuteSubcommand::As(selector, next) => {
                write!(f, "as {} {}", selector, next)?;

                Ok(())
            }
            ExecuteSubcommand::At(selector, next) => {
                write!(f, "at {} {}", selector, next)?;

                Ok(())
            }
            ExecuteSubcommand::Facing(facing, next) => {
                write!(f, "facing {} {}", facing, next)?;

                Ok(())
            }
            ExecuteSubcommand::In(dimension, next) => {
                write!(f, "in {} {}", dimension, next)?;

                Ok(())
            }
            ExecuteSubcommand::On(relation, next) => {
                write!(f, "on {} {}", relation, next)?;

                Ok(())
            }
            ExecuteSubcommand::Positioned(positioned, next) => {
                write!(f, "positioned {} {}", positioned, next)?;

                Ok(())
            }
            ExecuteSubcommand::Rotated(rotated, next) => {
                write!(f, "rotated {} {}", rotated, next)?;

                Ok(())
            }
            ExecuteSubcommand::Summon(entity_id, next) => {
                write!(f, "summon {} {}", entity_id, next)?;

                Ok(())
            }
            ExecuteSubcommand::If(is_inverted, subcommand) => {
                let keyword = if *is_inverted { "unless" } else { "if" };

                write!(f, "{} {}", keyword, subcommand)
            }
            ExecuteSubcommand::Store(store_type, subcommand) => {
                write!(f, "store {} {}", store_type, subcommand)
            }
            ExecuteSubcommand::Run(command) => {
                write!(f, "run {}", command)
            }
        }
    }
}