valence_command/parsers/
entity_selector.rs

1use super::Parser;
2use crate::parsers::{CommandArg, CommandArgParseError, ParseInput};
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum EntitySelector {
6    SimpleSelector(EntitySelectors),
7    ComplexSelector(EntitySelectors, String),
8}
9
10#[derive(Debug, Clone, PartialEq, Eq, Default)]
11pub enum EntitySelectors {
12    AllEntities,
13    SinglePlayer(String),
14    #[default]
15    AllPlayers,
16    SelfPlayer,
17    NearestPlayer,
18    RandomPlayer,
19}
20
21impl CommandArg for EntitySelector {
22    // we want to get either a simple string [`@e`, `@a`, `@p`, `@r`,
23    // `<player_name>`] or a full selector: [`@e[<selector>]`, `@a[<selector>]`,
24    // `@p[<selector>]`, `@r[<selector>]`] the selectors can have spaces in
25    // them, so we need to be careful
26    fn parse_arg(input: &mut ParseInput) -> Result<Self, CommandArgParseError> {
27        input.skip_whitespace();
28        let mut simple_selector = None;
29        while let Some(c) = input.peek() {
30            match c {
31                '@' => {
32                    input.pop(); // pop the '@'
33                    match input.pop() {
34                        Some('e') => simple_selector = Some(EntitySelectors::AllEntities),
35                        Some('a') => simple_selector = Some(EntitySelectors::AllPlayers),
36                        Some('p') => simple_selector = Some(EntitySelectors::NearestPlayer),
37                        Some('r') => simple_selector = Some(EntitySelectors::RandomPlayer),
38                        Some('s') => simple_selector = Some(EntitySelectors::SelfPlayer),
39                        _ => {
40                            return Err(CommandArgParseError::InvalidArgument {
41                                expected: "entity selector".to_owned(),
42                                got: c.to_string(),
43                            })
44                        }
45                    }
46                    if input.peek() != Some('[') {
47                        // if there's no complex selector, we're done
48                        return Ok(EntitySelector::SimpleSelector(simple_selector.unwrap()));
49                    }
50                }
51                '[' => {
52                    input.pop();
53                    if simple_selector.is_none() {
54                        return Err(CommandArgParseError::InvalidArgument {
55                            expected: "entity selector".to_owned(),
56                            got: c.to_string(),
57                        });
58                    }
59                    let mut s = String::new();
60                    while let Some(c) = input.pop() {
61                        if c == ']' {
62                            return Ok(EntitySelector::ComplexSelector(
63                                simple_selector.unwrap(),
64                                s.trim().to_owned(),
65                            ));
66                        }
67
68                        s.push(c);
69                    }
70                }
71                _ => {
72                    return Ok(EntitySelector::SimpleSelector(
73                        EntitySelectors::SinglePlayer(String::parse_arg(input)?),
74                    ))
75                }
76            }
77        }
78        Err(CommandArgParseError::InvalidArgLength)
79    }
80
81    fn display() -> Parser {
82        Parser::Entity {
83            only_players: false,
84            single: false,
85        }
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    #[test]
94    fn test_entity_selector() {
95        let mut input = ParseInput::new("@e");
96        assert_eq!(
97            EntitySelector::parse_arg(&mut input).unwrap(),
98            EntitySelector::SimpleSelector(EntitySelectors::AllEntities)
99        );
100        assert!(input.is_done());
101
102        let mut input = ParseInput::new("@e[distance=..5]");
103        assert_eq!(
104            EntitySelector::parse_arg(&mut input).unwrap(),
105            EntitySelector::ComplexSelector(
106                EntitySelectors::AllEntities,
107                "distance=..5".to_owned()
108            )
109        );
110        assert!(input.is_done());
111
112        let mut input = ParseInput::new("@s[distance=..5");
113        assert!(EntitySelector::parse_arg(&mut input).is_err());
114        assert!(input.is_done());
115
116        let mut input = ParseInput::new("@r[distance=..5] hello");
117        assert_eq!(
118            EntitySelector::parse_arg(&mut input).unwrap(),
119            EntitySelector::ComplexSelector(
120                EntitySelectors::RandomPlayer,
121                "distance=..5".to_owned()
122            )
123        );
124        assert!(!input.is_done());
125
126        let mut input = ParseInput::new("@p[distance=..5]hello");
127        assert_eq!(
128            EntitySelector::parse_arg(&mut input).unwrap(),
129            EntitySelector::ComplexSelector(
130                EntitySelectors::NearestPlayer,
131                "distance=..5".to_owned()
132            )
133        );
134        assert!(!input.is_done());
135
136        let mut input = ParseInput::new("@e[distance=..5] hello world");
137        assert_eq!(
138            EntitySelector::parse_arg(&mut input).unwrap(),
139            EntitySelector::ComplexSelector(
140                EntitySelectors::AllEntities,
141                "distance=..5".to_owned()
142            )
143        );
144        assert!(!input.is_done());
145
146        let mut input = ParseInput::new("@e[distance=..5]hello world");
147        assert_eq!(
148            EntitySelector::parse_arg(&mut input).unwrap(),
149            EntitySelector::ComplexSelector(
150                EntitySelectors::AllEntities,
151                "distance=..5".to_owned()
152            )
153        );
154        assert!(!input.is_done());
155    }
156}