pub mod block;
pub mod coordinate;
pub mod entity;
pub mod nbt;
pub mod range;
pub mod resource;
use crate::{
generator::parser::command::{
argument::{
brigadier::parse_unquoted_string, minecraft::entity::MinecraftSelectorParserError,
ArgumentValue, ArgumentValueEnum, MinecraftSelector,
},
resource_location::ResourceLocationRef,
},
utils::Map0,
};
use strum::EnumString;
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftDimension<'l>(pub ResourceLocationRef<&'l str>);
impl<'l> ArgumentValue<'l> for MinecraftDimension<'l> {
fn parse(string: &'l str) -> Result<(Self, usize), String> {
Ok(ResourceLocationRef::parse(string)?.map0(Self))
}
}
#[derive(Clone, Copy, Debug, EnumString, Eq, PartialEq)]
#[strum(serialize_all = "snake_case")]
pub enum MinecraftEntityAnchor {
Eyes,
Feet,
}
impl ArgumentValueEnum for MinecraftEntityAnchor {}
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftFunction<'l>(pub ResourceLocationRef<&'l str>);
impl<'l> ArgumentValue<'l> for MinecraftFunction<'l> {
fn parse(string: &'l str) -> Result<(Self, usize), String> {
Ok(ResourceLocationRef::parse(string)?.map0(Self))
}
}
#[derive(Clone, Copy, Debug, EnumString, Eq, PartialEq)]
#[strum(serialize_all = "snake_case")]
pub enum MinecraftHeightmap {
MotionBlocking,
MotionBlockingNoLeaves,
OceanFloor,
WorldSurface,
}
impl ArgumentValueEnum for MinecraftHeightmap {}
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftMessage<'l> {
pub message: &'l str,
pub selectors: Vec<(MinecraftSelector<'l>, usize, usize)>,
}
impl<'l> ArgumentValue<'l> for MinecraftMessage<'l> {
fn parse(message: &'l str) -> Result<(Self, usize), String> {
let mut index = 0;
let mut selectors = Vec::new();
while let Some(i) = &message[index..].find('@') {
index += i;
match MinecraftSelector::parse(&message[index..]) {
Ok((selector, len)) => {
selectors.push((selector, index, index + len));
index += len;
}
Err(
MinecraftSelectorParserError::MissingSelectorType
| MinecraftSelectorParserError::UnknownSelectorType(..),
) => {
index += 1;
}
Err(e) => return Err(e.to_string()),
}
}
Ok((MinecraftMessage { message, selectors }, message.len()))
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftObjective<'l>(pub &'l str);
impl<'l> ArgumentValue<'l> for MinecraftObjective<'l> {
fn parse(string: &'l str) -> Result<(Self, usize), String> {
Ok(parse_unquoted_string(string).map0(Self))
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftObjectiveCriteria<'l>(&'l str);
impl<'l> ArgumentValue<'l> for MinecraftObjectiveCriteria<'l> {
fn parse(string: &'l str) -> Result<(Self, usize), String> {
let len = string.find(' ').unwrap_or(string.len());
Ok((&string[..len], len).map0(Self))
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MinecraftOperation {
Assignment, Addition, Subtraction, Multiplication, Division, Modulus, Swapping, Minimum, Maximum, }
impl ArgumentValue<'_> for MinecraftOperation {
fn parse(string: &str) -> Result<(Self, usize), String> {
let len = string.find(' ').unwrap_or(string.len());
match &string[..len] {
"=" => Ok((Self::Assignment, len)),
"+=" => Ok((Self::Addition, len)),
"-=" => Ok((Self::Subtraction, len)),
"*=" => Ok((Self::Multiplication, len)),
"/=" => Ok((Self::Division, len)),
"%=" => Ok((Self::Modulus, len)),
">< " => Ok((Self::Swapping, len)),
"<" => Ok((Self::Minimum, len)),
">" => Ok((Self::Maximum, len)),
_ => Err("Invalid operation".to_string()),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum MinecraftScoreHolder<'l> {
Selector(MinecraftSelector<'l>),
Wildcard,
String(&'l str),
}
impl<'l> ArgumentValue<'l> for MinecraftScoreHolder<'l> {
fn parse(string: &'l str) -> Result<(Self, usize), String> {
if string.starts_with('@') {
let (selector, len) = MinecraftSelector::parse(string)?;
Ok((Self::Selector(selector), len))
} else {
let len = string.find(' ').unwrap_or(string.len());
let parsed = &string[..len];
let parsed = if parsed == "*" {
Self::Wildcard
} else {
Self::String(parsed)
};
Ok((parsed, len))
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftScoreboardSlot<'l>(&'l str);
impl<'l> ArgumentValue<'l> for MinecraftScoreboardSlot<'l> {
fn parse(string: &'l str) -> Result<(Self, usize), String> {
Ok(parse_unquoted_string(string).map0(Self))
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftSwizzle;
impl ArgumentValue<'_> for MinecraftSwizzle {
fn parse(string: &str) -> Result<(Self, usize), String> {
let len = string
.find(' ')
.ok_or("Failed to parse swizzle".to_string())?;
Ok((Self, len))
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftTeam<'l>(&'l str);
impl<'l> ArgumentValue<'l> for MinecraftTeam<'l> {
fn parse(string: &'l str) -> Result<(Self, usize), String> {
Ok(parse_unquoted_string(string).map0(Self))
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct MinecraftTime {
pub time: f32,
pub unit: MinecraftTimeUnit,
}
impl ArgumentValue<'_> for MinecraftTime {
fn parse(string: &str) -> Result<(Self, usize), String> {
let float_len = string
.find(|c| c < '0' || c > '9' && c != '.' && c != '-')
.unwrap_or(string.len());
let float_sting = &string[..float_len];
let time = float_sting
.parse()
.map_err(|_| format!("Expected float but got '{}'", &float_sting))?;
let (unit, len) = match string[float_len..].chars().next() {
Some(unit) if unit != ' ' => {
let unit = match unit {
't' => MinecraftTimeUnit::Tick,
's' => MinecraftTimeUnit::Second,
'd' => MinecraftTimeUnit::Day,
unit => return Err(format!("Unknown unit '{}'", unit)),
};
(unit, float_len + 1)
}
_ => (MinecraftTimeUnit::Tick, float_len),
};
Ok((MinecraftTime { time, unit }, len))
}
}
impl MinecraftTime {
pub fn as_ticks(&self) -> u32 {
let ticks = self.time * self.unit.factor() as f32;
ticks.round() as u32
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MinecraftTimeUnit {
Tick,
Second,
Day,
}
impl MinecraftTimeUnit {
pub fn factor(&self) -> u32 {
match self {
MinecraftTimeUnit::Tick => 1,
MinecraftTimeUnit::Second => 20,
MinecraftTimeUnit::Day => 24000,
}
}
}