testbot/commands/
movement.rs1use std::time::Duration;
2
3use azalea::{
4 BlockPos, SprintDirection, WalkDirection,
5 brigadier::prelude::*,
6 entity::Position,
7 pathfinder::goals::{BlockPosGoal, RadiusGoal, XZGoal},
8 prelude::*,
9};
10use azalea_entity::dimensions::EntityDimensions;
11use parking_lot::Mutex;
12
13use super::{CommandSource, Ctx};
14use crate::BotTask;
15
16pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
17 commands.register(
18 literal("goto")
19 .executes(|ctx: &Ctx| {
20 let mut source = ctx.source.lock();
21 println!("got goto");
22 let Some(entity) = source.entity() else {
24 source.reply("I can't see you!");
25 return 0;
26 };
27 let Some(position) = source.bot.get_entity_component::<Position>(entity) else {
28 source.reply("I can't see you!");
29 return 0;
30 };
31 source.reply("ok");
32 source
33 .bot
34 .start_goto(BlockPosGoal(BlockPos::from(position)));
35 1
36 })
37 .then(literal("xz").then(argument("x", integer()).then(
38 argument("z", integer()).executes(|ctx: &Ctx| {
39 let source = ctx.source.lock();
40 let x = get_integer(ctx, "x").unwrap();
41 let z = get_integer(ctx, "z").unwrap();
42 println!("goto xz {x} {z}");
43 source.reply("ok");
44 source.bot.start_goto(XZGoal { x, z });
45 1
46 }),
47 )))
48 .then(literal("radius").then(argument("radius", float()).then(
49 argument("x", integer()).then(argument("y", integer()).then(
50 argument("z", integer()).executes(|ctx: &Ctx| {
51 let source = ctx.source.lock();
52 let radius = get_float(ctx, "radius").unwrap();
53 let x = get_integer(ctx, "x").unwrap();
54 let y = get_integer(ctx, "y").unwrap();
55 let z = get_integer(ctx, "z").unwrap();
56 println!("goto radius {radius}, position: {x} {y} {z}");
57 source.reply("ok");
58 source.bot.start_goto(RadiusGoal {
59 pos: BlockPos::new(x, y, z).center(),
60 radius,
61 });
62 1
63 }),
64 )),
65 )))
66 .then(argument("x", integer()).then(argument("y", integer()).then(
67 argument("z", integer()).executes(|ctx: &Ctx| {
68 let source = ctx.source.lock();
69 let x = get_integer(ctx, "x").unwrap();
70 let y = get_integer(ctx, "y").unwrap();
71 let z = get_integer(ctx, "z").unwrap();
72 println!("goto xyz {x} {y} {z}");
73 source.reply("ok");
74 source.bot.start_goto(BlockPosGoal(BlockPos::new(x, y, z)));
75 1
76 }),
77 ))),
78 );
79
80 commands.register(literal("down").executes(|ctx: &Ctx| {
81 let source = ctx.source.clone();
82 tokio::spawn(async move {
83 let bot = source.lock().bot.clone();
84 let position = BlockPos::from(bot.position());
85 source.lock().reply("mining...");
86 bot.mine(position.down(1)).await;
87 source.lock().reply("done");
88 });
89 1
90 }));
91
92 commands.register(
93 literal("look")
94 .executes(|ctx: &Ctx| {
95 let mut source = ctx.source.lock();
97 let Some(entity) = source.entity() else {
98 source.reply("I can't see you!");
99 return 0;
100 };
101 let Some(position) = source.bot.get_entity_component::<Position>(entity) else {
102 source.reply("I can't see you!");
103 return 0;
104 };
105 let eye_height = source
106 .bot
107 .get_entity_component::<EntityDimensions>(entity)
108 .map(|h| h.eye_height)
109 .unwrap_or_default();
110 source.bot.look_at(position.up(eye_height as f64));
111 1
112 })
113 .then(argument("x", integer()).then(argument("y", integer()).then(
114 argument("z", integer()).executes(|ctx: &Ctx| {
115 let pos = BlockPos::new(
116 get_integer(ctx, "x").unwrap(),
117 get_integer(ctx, "y").unwrap(),
118 get_integer(ctx, "z").unwrap(),
119 );
120 println!("{pos:?}");
121 let source = ctx.source.lock();
122 source.bot.look_at(pos.center());
123 1
124 }),
125 ))),
126 );
127
128 commands.register(
129 literal("walk").then(argument("seconds", float()).executes(|ctx: &Ctx| {
130 let mut seconds = get_float(ctx, "seconds").unwrap();
131 let source = ctx.source.lock();
132 let bot = source.bot.clone();
133
134 if seconds < 0. {
135 bot.walk(WalkDirection::Backward);
136 seconds = -seconds;
137 } else {
138 bot.walk(WalkDirection::Forward);
139 }
140
141 tokio::spawn(async move {
142 tokio::time::sleep(Duration::from_secs_f32(seconds)).await;
143 bot.walk(WalkDirection::None);
144 });
145 source.reply(format!("ok, walking for {seconds} seconds"));
146 1
147 })),
148 );
149 commands.register(
150 literal("sprint").then(argument("seconds", float()).executes(|ctx: &Ctx| {
151 let seconds = get_float(ctx, "seconds").unwrap();
152 let source = ctx.source.lock();
153 let bot = source.bot.clone();
154 bot.sprint(SprintDirection::Forward);
155 tokio::spawn(async move {
156 tokio::time::sleep(Duration::from_secs_f32(seconds)).await;
157 bot.walk(WalkDirection::None);
158 });
159 source.reply(format!("ok, sprinting for {seconds} seconds"));
160 1
161 })),
162 );
163
164 commands.register(literal("north").executes(|ctx: &Ctx| {
165 let source = ctx.source.lock();
166 source.bot.set_direction(180., 0.);
167 source.reply("ok");
168 1
169 }));
170 commands.register(literal("south").executes(|ctx: &Ctx| {
171 let source = ctx.source.lock();
172 source.bot.set_direction(0., 0.);
173 source.reply("ok");
174 1
175 }));
176 commands.register(literal("east").executes(|ctx: &Ctx| {
177 let source = ctx.source.lock();
178 source.bot.set_direction(-90., 0.);
179 source.reply("ok");
180 1
181 }));
182 commands.register(literal("west").executes(|ctx: &Ctx| {
183 let source = ctx.source.lock();
184 source.bot.set_direction(90., 0.);
185 source.reply("ok");
186 1
187 }));
188 commands.register(
189 literal("jump")
190 .executes(|ctx: &Ctx| {
191 let source = ctx.source.lock();
192 source.bot.jump();
193 source.reply("ok");
194 1
195 })
196 .then(argument("enabled", bool()).executes(|ctx: &Ctx| {
197 let jumping = get_bool(ctx, "enabled").unwrap();
198 let source = ctx.source.lock();
199 source.bot.set_jumping(jumping);
200 1
201 })),
202 );
203
204 let sneak = |ctx: &Ctx| {
205 let source = ctx.source.lock();
206 source.bot.set_crouching(!source.bot.crouching());
207 source.reply("ok");
208 1
209 };
210 let sneak_enabled = argument("enabled", bool()).executes(|ctx: &Ctx| {
211 let sneaking = get_bool(ctx, "enabled").unwrap();
212 let source = ctx.source.lock();
213 source.bot.set_crouching(sneaking);
214 1
215 });
216 commands.register(literal("sneak").executes(sneak).then(sneak_enabled.clone()));
217 commands.register(literal("crouch").executes(sneak).then(sneak_enabled));
218
219 commands.register(literal("stop").executes(|ctx: &Ctx| {
220 let source = ctx.source.lock();
221 source.bot.stop_pathfinding();
222 source.reply("ok");
223 *source.state.task.lock() = BotTask::None;
224 1
225 }));
226}