1use crate::block::BlockState;
2use crate::column_position::ColumnPosition;
3use crate::command::data::DataTarget;
4use crate::command::enums::axis::Axis;
5use crate::command::enums::bossbar_store_type::BossbarStoreType;
6use crate::command::enums::entity_anchor::EntityAnchor;
7use crate::command::enums::heightmap::Heightmap;
8use crate::command::enums::if_blocks_mode::IfBlocksMode;
9use crate::command::enums::numeric_snbt_type::NumericSNBTType;
10use crate::command::enums::relation::Relation;
11use crate::command::enums::store_type::StoreType;
12use crate::command::item_source::ItemSource;
13use crate::command::{Command, PlayerScore};
14use crate::coordinate::Coordinates;
15use crate::entity_selector::EntitySelector;
16use crate::item::ItemPredicate;
17use crate::nbt_path::NbtPath;
18use crate::range::{FloatRange, IntegerRange};
19use crate::resource_location::ResourceLocation;
20use crate::rotation::Rotation;
21use minecraft_command_types_derive::HasMacro;
22use ordered_float::NotNan;
23use std::collections::BTreeSet;
24use std::fmt::{Display, Formatter};
25use strum::Display;
26
27#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
28pub enum Facing {
29 Position(Coordinates),
30 Entity(EntitySelector, EntityAnchor),
31}
32
33impl Display for Facing {
34 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35 match self {
36 Facing::Position(coords) => coords.fmt(f),
37 Facing::Entity(selector, anchor) => write!(f, "entity {} {}", selector, anchor),
38 }
39 }
40}
41
42#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
43pub enum Positioned {
44 Position(Coordinates),
45 As(EntitySelector),
46 Over(Heightmap),
47}
48
49impl Display for Positioned {
50 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
51 match self {
52 Positioned::Position(coords) => coords.fmt(f),
53 Positioned::As(selector) => write!(f, "as {}", selector),
54 Positioned::Over(heightmap) => write!(f, "over {}", heightmap),
55 }
56 }
57}
58
59#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
60pub enum Rotated {
61 Rotation(Rotation),
62 As(EntitySelector),
63}
64
65impl Display for Rotated {
66 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
67 match self {
68 Rotated::Rotation(rotation) => rotation.fmt(f),
69 Rotated::As(selector) => write!(f, "as {}", selector),
70 }
71 }
72}
73
74#[derive(Display, Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
75pub enum ScoreComparisonOperator {
76 #[strum(serialize = "<")]
77 LessThan,
78 #[strum(serialize = "<=")]
79 LessThanOrEqualTo,
80 #[strum(serialize = "=")]
81 EqualTo,
82 #[strum(serialize = ">")]
83 GreaterThan,
84 #[strum(serialize = ">=")]
85 GreaterThanOrEqualTo,
86}
87
88#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
89pub enum ScoreComparison {
90 Range(IntegerRange),
91 Score(ScoreComparisonOperator, PlayerScore),
92}
93
94impl Display for ScoreComparison {
95 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
96 match self {
97 ScoreComparison::Range(range) => write!(f, "matches {}", range),
98 ScoreComparison::Score(operator, right) => {
99 write!(f, "{} {}", operator, right)
100 }
101 }
102 }
103}
104
105#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
106pub enum ExecuteIfSubcommand {
107 Biome(
108 Coordinates,
109 ResourceLocation,
110 Option<Box<ExecuteSubcommand>>,
111 ),
112 Block(Coordinates, BlockState, Option<Box<ExecuteSubcommand>>),
113 Blocks(
114 Coordinates,
115 Coordinates,
116 Coordinates,
117 IfBlocksMode,
118 Option<Box<ExecuteSubcommand>>,
119 ),
120 Data(DataTarget, NbtPath, Option<Box<ExecuteSubcommand>>),
121 Dimension(ResourceLocation, Option<Box<ExecuteSubcommand>>),
122 Entity(EntitySelector, Option<Box<ExecuteSubcommand>>),
123 Function(ResourceLocation, Box<ExecuteSubcommand>),
124 Items(
125 ItemSource,
126 String,
127 ItemPredicate,
128 Option<Box<ExecuteSubcommand>>,
129 ),
130 Loaded(ColumnPosition, Option<Box<ExecuteSubcommand>>),
131 Predicate(ResourceLocation, Option<Box<ExecuteSubcommand>>),
132 Score(PlayerScore, ScoreComparison, Option<Box<ExecuteSubcommand>>),
133 Stopwatch(ResourceLocation, FloatRange),
134}
135
136impl Display for ExecuteIfSubcommand {
137 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
138 match self {
139 ExecuteIfSubcommand::Biome(coords, id, next) => {
140 write!(f, "biome {} {}", coords, id)?;
141
142 if let Some(next_sub) = next {
143 write!(f, " {}", next_sub)?;
144 }
145
146 Ok(())
147 }
148 ExecuteIfSubcommand::Block(coords, predicate, next) => {
149 write!(f, "block {} {}", coords, predicate)?;
150
151 if let Some(next_sub) = next {
152 write!(f, " {}", next_sub)?;
153 }
154
155 Ok(())
156 }
157 ExecuteIfSubcommand::Blocks(start, end, dest, mode, next) => {
158 write!(f, "blocks {} {} {} {}", start, end, dest, mode)?;
159
160 if let Some(next_sub) = next {
161 write!(f, " {}", next_sub)?;
162 }
163
164 Ok(())
165 }
166 ExecuteIfSubcommand::Data(target, path, next) => {
167 write!(f, "data {} {}", target, path)?;
168
169 if let Some(next_sub) = next {
170 write!(f, " {}", next_sub)?;
171 }
172
173 Ok(())
174 }
175 ExecuteIfSubcommand::Dimension(id, next) => {
176 write!(f, "dimension {}", id)?;
177
178 if let Some(next_sub) = next {
179 write!(f, " {}", next_sub)?;
180 }
181
182 Ok(())
183 }
184 ExecuteIfSubcommand::Entity(selector, next) => {
185 write!(f, "entity {}", selector)?;
186
187 if let Some(next_sub) = next {
188 write!(f, " {}", next_sub)?;
189 }
190
191 Ok(())
192 }
193 ExecuteIfSubcommand::Function(id, next) => {
194 write!(f, "function {} {}", id, next)
195 }
196 ExecuteIfSubcommand::Items(source, slot, predicate, next) => {
197 write!(f, "items {} {} {}", source, slot, predicate)?;
198
199 if let Some(next_sub) = next {
200 write!(f, " {}", next_sub)?;
201 }
202
203 Ok(())
204 }
205 ExecuteIfSubcommand::Loaded(coords, next) => {
206 write!(f, "loaded {}", coords)?;
207 if let Some(next_sub) = next {
208 write!(f, " {}", next_sub)?;
209 }
210
211 Ok(())
212 }
213 ExecuteIfSubcommand::Predicate(id, next) => {
214 write!(f, "predicate {}", id)?;
215 if let Some(next_sub) = next {
216 write!(f, " {}", next_sub)?;
217 }
218
219 Ok(())
220 }
221 ExecuteIfSubcommand::Score(score, comparison, next) => {
222 write!(f, "score {} {}", score, comparison)?;
223 if let Some(next_sub) = next {
224 write!(f, " {}", next_sub)?;
225 }
226
227 Ok(())
228 }
229 ExecuteIfSubcommand::Stopwatch(location, range) => {
230 write!(f, "stopwatch {} {}", location, range)
231 }
232 }
233 }
234}
235
236#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
237pub enum ExecuteStoreSubcommand {
238 Block(
239 Coordinates,
240 NbtPath,
241 NumericSNBTType,
242 NotNan<f32>,
243 Box<ExecuteSubcommand>,
244 ),
245 Bossbar(ResourceLocation, BossbarStoreType, Box<ExecuteSubcommand>),
246 Entity(
247 EntitySelector,
248 NbtPath,
249 NumericSNBTType,
250 NotNan<f32>,
251 Box<ExecuteSubcommand>,
252 ),
253 Score(PlayerScore, Box<ExecuteSubcommand>),
254 Storage(
255 ResourceLocation,
256 NbtPath,
257 NumericSNBTType,
258 NotNan<f32>,
259 Box<ExecuteSubcommand>,
260 ),
261}
262
263impl Display for ExecuteStoreSubcommand {
264 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
265 match self {
266 ExecuteStoreSubcommand::Block(coords, path, num_type, scale, next) => {
267 write!(
268 f,
269 "block {} {} {} {} {}",
270 coords, path, num_type, scale, next
271 )?;
272
273 Ok(())
274 }
275 ExecuteStoreSubcommand::Bossbar(id, store_type, next) => {
276 write!(f, "bossbar {} {} {}", id, store_type, next)?;
277
278 Ok(())
279 }
280 ExecuteStoreSubcommand::Entity(selector, path, num_type, scale, next) => {
281 write!(
282 f,
283 "entity {} {} {} {} {}",
284 selector, path, num_type, scale, next
285 )?;
286
287 Ok(())
288 }
289 ExecuteStoreSubcommand::Score(score, next) => {
290 write!(f, "score {} {}", score, next)?;
291
292 Ok(())
293 }
294 ExecuteStoreSubcommand::Storage(id, path, num_type, scale, next) => {
295 write!(f, "storage {} {} {} {} {}", id, path, num_type, scale, next)?;
296
297 Ok(())
298 }
299 }
300 }
301}
302
303#[derive(Debug, Clone, Eq, PartialEq, Hash, HasMacro)]
304pub enum ExecuteSubcommand {
305 Align(BTreeSet<Axis>, Box<ExecuteSubcommand>),
306 Anchored(EntityAnchor, Box<ExecuteSubcommand>),
307 As(EntitySelector, Box<ExecuteSubcommand>),
308 At(EntitySelector, Box<ExecuteSubcommand>),
309 Facing(Facing, Box<ExecuteSubcommand>),
310 In(ResourceLocation, Box<ExecuteSubcommand>),
311 On(Relation, Box<ExecuteSubcommand>),
312 Positioned(Positioned, Box<ExecuteSubcommand>),
313 Rotated(Rotated, Box<ExecuteSubcommand>),
314 Summon(ResourceLocation, Box<ExecuteSubcommand>),
315 If(bool, ExecuteIfSubcommand),
316 Store(StoreType, ExecuteStoreSubcommand),
317 Run(Box<Command>),
318}
319
320impl Display for ExecuteSubcommand {
321 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
322 match self {
323 ExecuteSubcommand::Align(axes, next) => {
324 let axes_str: String = axes.iter().map(|a| a.to_string()).collect();
325 write!(f, "align {} {}", axes_str, next)?;
326
327 Ok(())
328 }
329 ExecuteSubcommand::Anchored(anchor, next) => {
330 write!(f, "anchored {} {}", anchor, next)?;
331
332 Ok(())
333 }
334 ExecuteSubcommand::As(selector, next) => {
335 write!(f, "as {} {}", selector, next)?;
336
337 Ok(())
338 }
339 ExecuteSubcommand::At(selector, next) => {
340 write!(f, "at {} {}", selector, next)?;
341
342 Ok(())
343 }
344 ExecuteSubcommand::Facing(facing, next) => {
345 write!(f, "facing {} {}", facing, next)?;
346
347 Ok(())
348 }
349 ExecuteSubcommand::In(dimension, next) => {
350 write!(f, "in {} {}", dimension, next)?;
351
352 Ok(())
353 }
354 ExecuteSubcommand::On(relation, next) => {
355 write!(f, "on {} {}", relation, next)?;
356
357 Ok(())
358 }
359 ExecuteSubcommand::Positioned(positioned, next) => {
360 write!(f, "positioned {} {}", positioned, next)?;
361
362 Ok(())
363 }
364 ExecuteSubcommand::Rotated(rotated, next) => {
365 write!(f, "rotated {} {}", rotated, next)?;
366
367 Ok(())
368 }
369 ExecuteSubcommand::Summon(entity_id, next) => {
370 write!(f, "summon {} {}", entity_id, next)?;
371
372 Ok(())
373 }
374 ExecuteSubcommand::If(is_inverted, subcommand) => {
375 let keyword = if *is_inverted { "unless" } else { "if" };
376
377 write!(f, "{} {}", keyword, subcommand)
378 }
379 ExecuteSubcommand::Store(store_type, subcommand) => {
380 write!(f, "store {} {}", store_type, subcommand)
381 }
382 ExecuteSubcommand::Run(command) => {
383 write!(f, "run {}", command)
384 }
385 }
386 }
387}