Skip to main content

literal

Function literal 

Source
pub fn literal<S>(value: &str) -> ArgumentBuilder<S>
Expand description

Shortcut for creating a new literal builder node.

Examples found in repository?
azalea/examples/testbot/commands/combat.rs (line 9)
7pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
8    commands.register(
9        literal("killaura").then(argument("enabled", bool()).executes(|ctx: &Ctx| {
10            let enabled = get_bool(ctx, "enabled").unwrap();
11            let source = ctx.source.lock();
12            let bot = source.bot.clone();
13            bot.query_self::<&mut State, _>(|mut state| state.killaura = enabled);
14            source.reply(if enabled {
15                "Enabled killaura"
16            } else {
17                "Disabled killaura"
18            });
19            1
20        })),
21    );
22}
More examples
Hide additional examples
azalea/examples/testbot/commands/movement.rs (line 16)
14pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
15    commands.register(
16        literal("goto")
17            .executes(|ctx: &Ctx| {
18                let source = ctx.source.lock();
19                println!("got goto");
20                // look for the sender
21                let Some(entity) = source.entity() else {
22                    source.reply("I can't see you!");
23                    return 0;
24                };
25                let position = entity.position();
26                source.reply("ok");
27                source
28                    .bot
29                    .start_goto(BlockPosGoal(BlockPos::from(position.up(0.5))));
30                1
31            })
32            .then(literal("xz").then(argument("x", integer()).then(
33                argument("z", integer()).executes(|ctx: &Ctx| {
34                    let source = ctx.source.lock();
35                    let x = get_integer(ctx, "x").unwrap();
36                    let z = get_integer(ctx, "z").unwrap();
37                    println!("goto xz {x} {z}");
38                    source.reply("ok");
39                    source.bot.start_goto(XZGoal { x, z });
40                    1
41                }),
42            )))
43            .then(literal("radius").then(argument("radius", float()).then(
44                argument("x", integer()).then(argument("y", integer()).then(
45                    argument("z", integer()).executes(|ctx: &Ctx| {
46                        let source = ctx.source.lock();
47                        let radius = get_float(ctx, "radius").unwrap();
48                        let x = get_integer(ctx, "x").unwrap();
49                        let y = get_integer(ctx, "y").unwrap();
50                        let z = get_integer(ctx, "z").unwrap();
51                        println!("goto radius {radius}, position: {x} {y} {z}");
52                        source.reply("ok");
53                        source.bot.start_goto(RadiusGoal {
54                            pos: BlockPos::new(x, y, z).center(),
55                            radius,
56                        });
57                        1
58                    }),
59                )),
60            )))
61            .then(argument("x", integer()).then(argument("y", integer()).then(
62                argument("z", integer()).executes(|ctx: &Ctx| {
63                    let source = ctx.source.lock();
64                    let x = get_integer(ctx, "x").unwrap();
65                    let y = get_integer(ctx, "y").unwrap();
66                    let z = get_integer(ctx, "z").unwrap();
67                    println!("goto xyz {x} {y} {z}");
68                    source.reply("ok");
69                    source.bot.start_goto(BlockPosGoal(BlockPos::new(x, y, z)));
70                    1
71                }),
72            ))),
73    );
74
75    commands.register(literal("down").executes(|ctx: &Ctx| {
76        let source = ctx.source.clone();
77        tokio::spawn(async move {
78            let bot = source.lock().bot.clone();
79            let position = BlockPos::from(bot.position());
80            source.lock().reply("mining...");
81            bot.mine(position.down(1)).await;
82            source.lock().reply("done");
83        });
84        1
85    }));
86
87    commands.register(
88        literal("look")
89            .executes(|ctx: &Ctx| {
90                // look for the sender
91                let source = ctx.source.lock();
92                let Some(entity) = source.entity() else {
93                    source.reply("I can't see you!");
94                    return 0;
95                };
96                let eye_position = entity.eye_position();
97                source.bot.look_at(eye_position);
98                1
99            })
100            .then(argument("x", integer()).then(argument("y", integer()).then(
101                argument("z", integer()).executes(|ctx: &Ctx| {
102                    let pos = BlockPos::new(
103                        get_integer(ctx, "x").unwrap(),
104                        get_integer(ctx, "y").unwrap(),
105                        get_integer(ctx, "z").unwrap(),
106                    );
107                    println!("{pos:?}");
108                    let source = ctx.source.lock();
109                    source.bot.look_at(pos.center());
110                    1
111                }),
112            ))),
113    );
114
115    commands.register(
116        literal("walk").then(argument("seconds", float()).executes(|ctx: &Ctx| {
117            let mut seconds = get_float(ctx, "seconds").unwrap();
118            let source = ctx.source.lock();
119            let bot = source.bot.clone();
120
121            if seconds < 0. {
122                bot.walk(WalkDirection::Backward);
123                seconds = -seconds;
124            } else {
125                bot.walk(WalkDirection::Forward);
126            }
127
128            tokio::spawn(async move {
129                tokio::time::sleep(Duration::from_secs_f32(seconds)).await;
130                bot.walk(WalkDirection::None);
131            });
132            source.reply(format!("ok, walking for {seconds} seconds"));
133            1
134        })),
135    );
136    commands.register(
137        literal("sprint").then(argument("seconds", float()).executes(|ctx: &Ctx| {
138            let seconds = get_float(ctx, "seconds").unwrap();
139            let source = ctx.source.lock();
140            let bot = source.bot.clone();
141            bot.sprint(SprintDirection::Forward);
142            tokio::spawn(async move {
143                tokio::time::sleep(Duration::from_secs_f32(seconds)).await;
144                bot.walk(WalkDirection::None);
145            });
146            source.reply(format!("ok, sprinting for {seconds} seconds"));
147            1
148        })),
149    );
150
151    commands.register(literal("north").executes(|ctx: &Ctx| {
152        let source = ctx.source.lock();
153        source.bot.set_direction(180., 0.);
154        source.reply("ok");
155        1
156    }));
157    commands.register(literal("south").executes(|ctx: &Ctx| {
158        let source = ctx.source.lock();
159        source.bot.set_direction(0., 0.);
160        source.reply("ok");
161        1
162    }));
163    commands.register(literal("east").executes(|ctx: &Ctx| {
164        let source = ctx.source.lock();
165        source.bot.set_direction(-90., 0.);
166        source.reply("ok");
167        1
168    }));
169    commands.register(literal("west").executes(|ctx: &Ctx| {
170        let source = ctx.source.lock();
171        source.bot.set_direction(90., 0.);
172        source.reply("ok");
173        1
174    }));
175    commands.register(
176        literal("jump")
177            .executes(|ctx: &Ctx| {
178                let source = ctx.source.lock();
179                source.bot.jump();
180                source.reply("ok");
181                1
182            })
183            .then(argument("enabled", bool()).executes(|ctx: &Ctx| {
184                let jumping = get_bool(ctx, "enabled").unwrap();
185                let source = ctx.source.lock();
186                source.bot.set_jumping(jumping);
187                1
188            })),
189    );
190
191    let sneak = |ctx: &Ctx| {
192        let source = ctx.source.lock();
193        source.bot.set_crouching(!source.bot.crouching());
194        source.reply("ok");
195        1
196    };
197    let sneak_enabled = argument("enabled", bool()).executes(|ctx: &Ctx| {
198        let sneaking = get_bool(ctx, "enabled").unwrap();
199        let source = ctx.source.lock();
200        source.bot.set_crouching(sneaking);
201        1
202    });
203    commands.register(literal("sneak").executes(sneak).then(sneak_enabled.clone()));
204    commands.register(literal("crouch").executes(sneak).then(sneak_enabled));
205
206    commands.register(literal("stop").executes(|ctx: &Ctx| {
207        let source = ctx.source.lock();
208        source.bot.stop_pathfinding();
209        source.reply("ok");
210        *source.state.task.lock() = BotTask::None;
211        1
212    }));
213    commands.register(literal("forcestop").executes(|ctx: &Ctx| {
214        let source = ctx.source.lock();
215        source.bot.force_stop_pathfinding();
216        source.reply("ok");
217        *source.state.task.lock() = BotTask::None;
218        1
219    }));
220}
azalea/examples/testbot/commands/debug.rs (line 27)
26pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
27    commands.register(literal("ping").executes(|ctx: &Ctx| {
28        let source = ctx.source.lock();
29        source.reply("pong!");
30        1
31    }));
32
33    commands.register(literal("disconnect").executes(|ctx: &Ctx| {
34        let source = ctx.source.lock();
35        source.bot.disconnect();
36        1
37    }));
38
39    commands.register(literal("whereami").executes(|ctx: &Ctx| {
40        let source = ctx.source.lock();
41        let Some(entity) = source.entity() else {
42            source.reply("You aren't in render distance!");
43            return 0;
44        };
45        let position = entity.position();
46        source.reply(format!(
47            "You are at {}, {}, {}",
48            position.x, position.y, position.z
49        ));
50        1
51    }));
52
53    commands.register(literal("entityid").executes(|ctx: &Ctx| {
54        let source = ctx.source.lock();
55        let Some(entity) = source.entity() else {
56            source.reply("You aren't in render distance!");
57            return 0;
58        };
59        let entity_id = entity.minecraft_id();
60        source.reply(format!(
61            "Your Minecraft ID is {} and your ECS ID is {entity:?}",
62            *entity_id
63        ));
64        1
65    }));
66
67    let whereareyou = |ctx: &Ctx| {
68        let source = ctx.source.lock();
69        let position = source.bot.position();
70        source.reply(format!(
71            "I'm at {}, {}, {}",
72            position.x, position.y, position.z
73        ));
74        1
75    };
76    commands.register(literal("whereareyou").executes(whereareyou));
77    commands.register(literal("pos").executes(whereareyou));
78
79    commands.register(literal("whoareyou").executes(|ctx: &Ctx| {
80        let source = ctx.source.lock();
81        source.reply(format!(
82            "I am {} ({}, {})",
83            source.bot.username(),
84            source.bot.uuid(),
85            source.bot.entity
86        ));
87        1
88    }));
89
90    commands.register(literal("getdirection").executes(|ctx: &Ctx| {
91        let source = ctx.source.lock();
92        let direction = source.bot.direction();
93        source.reply(format!(
94            "I'm looking at {}, {}",
95            direction.y_rot(),
96            direction.x_rot()
97        ));
98        1
99    }));
100
101    commands.register(literal("health").executes(|ctx: &Ctx| {
102        let source = ctx.source.lock();
103
104        let health = source.bot.health();
105        source.reply(format!("I have {health} health"));
106        1
107    }));
108
109    commands.register(literal("lookingat").executes(|ctx: &Ctx| {
110        let source = ctx.source.lock();
111
112        let hit_result = source.bot.hit_result();
113
114        match &hit_result {
115            HitResult::Block(r) => {
116                if r.miss {
117                    source.reply("I'm not looking at anything");
118                    return 0;
119                }
120                let block_pos = r.block_pos;
121                let block = source.bot.world().read().get_block_state(block_pos);
122                source.reply(format!("I'm looking at {block:?} at {block_pos:?}"));
123            }
124            HitResult::Entity(r) => {
125                let entity_kind = **source.bot.entity_component::<EntityKindComponent>(r.entity);
126                source.reply(format!(
127                    "I'm looking at {entity_kind} ({:?}) at {}",
128                    r.entity, r.location
129                ));
130            }
131        }
132
133        1
134    }));
135
136    commands.register(literal("getblock").then(argument("x", integer()).then(
137        argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
138            let source = ctx.source.lock();
139            let x = get_integer(ctx, "x").unwrap();
140            let y = get_integer(ctx, "y").unwrap();
141            let z = get_integer(ctx, "z").unwrap();
142            println!("getblock xyz {x} {y} {z}");
143            let block_pos = BlockPos::new(x, y, z);
144            let block = source.bot.world().read().get_block_state(block_pos);
145            source.reply(format!("BlockKind at {block_pos} is {block:?}"));
146            1
147        })),
148    )));
149    commands.register(literal("getfluid").then(argument("x", integer()).then(
150        argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
151            let source = ctx.source.lock();
152            let x = get_integer(ctx, "x").unwrap();
153            let y = get_integer(ctx, "y").unwrap();
154            let z = get_integer(ctx, "z").unwrap();
155            println!("getfluid xyz {x} {y} {z}");
156            let block_pos = BlockPos::new(x, y, z);
157            let block = source.bot.world().read().get_fluid_state(block_pos);
158            source.reply(format!("Fluid at {block_pos} is {block:?}"));
159            1
160        })),
161    )));
162
163    commands.register(literal("pathfinderstate").executes(|ctx: &Ctx| {
164        let source = ctx.source.lock();
165        let pathfinder = source.bot.get_component::<Pathfinder>();
166        let Some(pathfinder) = pathfinder else {
167            source.reply("I don't have the Pathfinder component");
168            return 1;
169        };
170        source.reply(format!(
171            "pathfinder.is_calculating: {}",
172            pathfinder.is_calculating
173        ));
174
175        let executing_path = source.bot.get_component::<ExecutingPath>();
176        let Some(executing_path) = executing_path else {
177            source.reply("I'm not executing a path");
178            return 1;
179        };
180        source.reply(format!(
181            "is_path_partial: {}, path.len: {}, queued_path.len: {}",
182            executing_path.is_path_partial,
183            executing_path.path.len(),
184            if let Some(queued) = &executing_path.queued_path {
185                queued.len().to_string()
186            } else {
187                "n/a".to_owned()
188            },
189        ));
190        1
191    }));
192    commands.register(literal("pathfindermoves").executes(|ctx: &Ctx| {
193        let source = ctx.source.lock();
194
195        let Some(entity) = source.entity() else {
196            source.reply("You aren't in render distance!");
197            return 0;
198        };
199        let position = entity.position();
200        let position = BlockPos::from(position);
201
202        let mut edges = Vec::new();
203        let cached_world = CachedWorld::new(source.bot.world(), position);
204        let mining_cache = MiningCache::new(Some(Menu::Player(inventory::Player::default())));
205        let custom_state = CustomPathfinderStateRef::default();
206
207        azalea::pathfinder::moves::default_move(
208            &mut MovesCtx {
209                edges: &mut edges,
210                world: &cached_world,
211                mining_cache: &mining_cache,
212                custom_state: &custom_state,
213            },
214            RelBlockPos::from_origin(position, position),
215        );
216
217        if edges.is_empty() {
218            source.reply("No possible moves.");
219        } else {
220            source.reply("Moves:");
221            for (i, edge) in edges.iter().enumerate() {
222                source.reply(format!("{}) {edge:?}", i + 1));
223            }
224        }
225
226        1
227    }));
228
229    commands.register(literal("startuseitem").executes(|ctx: &Ctx| {
230        let source = ctx.source.lock();
231        source.bot.start_use_item();
232        source.reply("Ok!");
233        1
234    }));
235    commands.register(literal("maxstacksize").executes(|ctx: &Ctx| {
236        let source = ctx.source.lock();
237        let max_stack_size = source
238            .bot
239            .get_held_item()
240            .get_component::<MaxStackSize>()
241            .map_or(-1, |s| s.count);
242        source.reply(format!("{max_stack_size}"));
243        1
244    }));
245
246    commands.register(literal("dimensions").executes(|ctx: &Ctx| {
247        let source = ctx.source.lock();
248        let bot_dimensions = source.bot.dimensions();
249        source.reply(format!("{bot_dimensions:?}"));
250        1
251    }));
252
253    commands.register(literal("players").executes(|ctx: &Ctx| {
254        let source = ctx.source.lock();
255        let player_entities = source
256            .bot
257            .nearest_entities_by::<(), With<metadata::Player>>(|_: ()| true);
258        let tab_list = source.bot.tab_list();
259        for player_entity in player_entities {
260            let uuid = player_entity.uuid();
261            source.reply(format!(
262                "{} - {} ({:?})",
263                player_entity.id(),
264                tab_list.get(&uuid).map_or("?", |p| p.profile.name.as_str()),
265                uuid
266            ));
267        }
268        1
269    }));
270
271    commands.register(literal("enchants").executes(|ctx: &Ctx| {
272        let source = ctx.source.lock();
273        source.bot.with_registry_holder(|r| {
274            let enchants = &r.enchantment;
275            println!("enchants: {enchants:?}");
276        });
277        1
278    }));
279
280    commands.register(literal("attributes").executes(|ctx: &Ctx| {
281        let source = ctx.source.lock();
282        let attributes = source.bot.attributes();
283        println!("attributes: {attributes:?}");
284        1
285    }));
286
287    commands.register(literal("debugecsleak").executes(|ctx: &Ctx| {
288        let source = ctx.source.lock();
289
290        source.reply("Ok!");
291
292
293
294        source.bot.disconnect();
295
296        let ecs = source.bot.ecs.clone();
297        thread::spawn(move || {
298            thread::sleep(Duration::from_secs(1));
299            // dump the ecs
300
301            let mut ecs = ecs.write();
302
303            let report_path = env::temp_dir().join("azalea-ecs-leak-report.txt");
304            let mut report = File::create(&report_path).unwrap();
305
306            let mut query = ecs.query::<EntityRef>();
307            for entity in query.iter(& ecs) {
308                writeln!(report, "Entity: {}", entity.id()).unwrap();
309                let archetype = entity.archetype();
310                let component_count = archetype.component_count();
311
312                let component_names = archetype
313                    .components()
314                    .iter()
315                    .map(|c| ecs.components().get_info(*c).unwrap().name().to_string())
316                    .collect::<Vec<_>>();
317                writeln!(
318                    report,
319                    "- {component_count} components: {}",
320                    component_names.join(", ")
321                )
322                .unwrap();
323            }
324
325            writeln!(report).unwrap();
326
327
328            for (info, _) in ecs.iter_resources() {
329                let name = info.name().to_string();
330                writeln!(report, "Resource: {name}").unwrap();
331                // writeln!(report, "- Size: {} bytes",
332                // info.layout().size()).unwrap();
333
334                match name.as_ref() {
335                    "azalea_world::container::Worlds" => {
336                        let worlds = ecs.resource::<Worlds>();
337
338                        for (world_name, world) in &worlds.map {
339                            writeln!(report, "- Name: {world_name}").unwrap();
340                            writeln!(report, "- Reference count: {}", world.strong_count())
341                                .unwrap();
342                            if let Some(world) = world.upgrade() {
343                                let world = world.read();
344                                let strong_chunks = world
345                                    .chunks
346                                    .map
347                                    .iter()
348                                    .filter(|(_, v)| v.strong_count() > 0)
349                                    .count();
350                                writeln!(
351                                    report,
352                                    "- Chunks: {} strongly referenced, {} in map",
353                                    strong_chunks,
354                                    world.chunks.map.len()
355                                )
356                                .unwrap();
357                                writeln!(
358                                    report,
359                                    "- Entities: {}",
360                                    world.entities_by_chunk.len()
361                                )
362                                .unwrap();
363                            }
364                        }
365                    }
366                    "bevy_ecs::message::Messages<azalea_client::packet::game::ReceivePacketEvent>" => {
367                        let events = ecs.resource::<Messages<game::ReceiveGamePacketEvent>>();
368                        writeln!(report, "- Event count: {}", events.len()).unwrap();
369                    }
370                    "bevy_ecs::message::Messages<azalea_client::chunks::ReceiveChunkEvent>" => {
371                        let events = ecs.resource::<Messages<ReceiveChunkEvent>>();
372                        writeln!(report, "- Event count: {}", events.len()).unwrap();
373                    }
374
375                    _ => {}
376                }
377            }
378
379            println!("\x1b[1mWrote report to {}\x1b[m", report_path.display());
380        });
381
382        1
383    }));
384
385    commands.register(literal("exit").executes(|ctx: &Ctx| {
386        let source = ctx.source.lock();
387        source.reply("bye!");
388
389        source.bot.disconnect();
390
391        let source = ctx.source.clone();
392        thread::spawn(move || {
393            thread::sleep(Duration::from_secs(1));
394
395            source
396                .lock()
397                .bot
398                .ecs
399                .write()
400                .write_message(AppExit::Success);
401        });
402
403        1
404    }));
405}