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