pub struct BlockPos {
pub x: i32,
pub y: i32,
pub z: i32,
}Expand description
The coordinates of a block in the world.
For entities (if the coordinates are floating-point), use Vec3 instead.
Fields§
§x: i32§y: i32§z: i32Implementations§
Source§impl BlockPos
impl BlockPos
Sourcepub const fn new(x: i32, y: i32, z: i32) -> BlockPos
pub const fn new(x: i32, y: i32, z: i32) -> BlockPos
Examples found in repository?
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 // look for the sender
23 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 // look for the sender
96 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}More examples
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 mut 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 = source.bot.entity_component::<Position>(entity);
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 mut 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 = source.bot.entity_component::<MinecraftEntityId>(entity);
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.component::<LookDirection>();
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.component::<HitResultComponent>();
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 ocmponent");
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
193 commands.register(literal("startuseitem").executes(|ctx: &Ctx| {
194 let source = ctx.source.lock();
195 source.bot.start_use_item();
196 source.reply("Ok!");
197 1
198 }));
199 commands.register(literal("maxstacksize").executes(|ctx: &Ctx| {
200 let source = ctx.source.lock();
201 let max_stack_size = source
202 .bot
203 .get_held_item()
204 .get_component::<MaxStackSize>()
205 .map_or(-1, |s| s.count);
206 source.reply(format!("{max_stack_size}"));
207 1
208 }));
209
210 commands.register(literal("dimensions").executes(|ctx: &Ctx| {
211 let source = ctx.source.lock();
212 let bot_dimensions = source.bot.dimensions();
213 source.reply(format!("{bot_dimensions:?}"));
214 1
215 }));
216
217 commands.register(literal("players").executes(|ctx: &Ctx| {
218 let source = ctx.source.lock();
219 let player_entities = source
220 .bot
221 .nearest_entities_by::<(), With<metadata::Player>>(|_: ()| true);
222 let tab_list = source.bot.tab_list();
223 for player_entity in player_entities {
224 let uuid = source.bot.entity_component::<EntityUuid>(player_entity);
225 source.reply(format!(
226 "{} - {} ({:?})",
227 player_entity,
228 tab_list.get(&uuid).map_or("?", |p| p.profile.name.as_str()),
229 uuid
230 ));
231 }
232 1
233 }));
234
235 commands.register(literal("enchants").executes(|ctx: &Ctx| {
236 let source = ctx.source.lock();
237 source.bot.with_registry_holder(|r| {
238 let enchants = &r.enchantment;
239 println!("enchants: {enchants:?}");
240 });
241 1
242 }));
243
244 commands.register(literal("attributes").executes(|ctx: &Ctx| {
245 let source = ctx.source.lock();
246 let attributes = source.bot.component::<Attributes>();
247 println!("attributes: {attributes:?}");
248 1
249 }));
250
251 commands.register(literal("debugecsleak").executes(|ctx: &Ctx| {
252 let source = ctx.source.lock();
253
254 source.reply("Ok!");
255
256
257
258 source.bot.disconnect();
259
260 let ecs = source.bot.ecs.clone();
261 thread::spawn(move || {
262 thread::sleep(Duration::from_secs(1));
263 // dump the ecs
264
265 let mut ecs = ecs.lock();
266
267
268
269 let report_path = env::temp_dir().join("azalea-ecs-leak-report.txt");
270 let mut report = File::create(&report_path).unwrap();
271
272 let mut query = ecs.query::<EntityRef>();
273 for entity in query.iter(& ecs) {
274 writeln!(report, "Entity: {}", entity.id()).unwrap();
275 let archetype = entity.archetype();
276 let component_count = archetype.component_count();
277
278 let component_names = archetype
279 .components()
280 .iter()
281 .map(|c| ecs.components().get_info(*c).unwrap().name().to_string())
282 .collect::<Vec<_>>();
283 writeln!(
284 report,
285 "- {component_count} components: {}",
286 component_names.join(", ")
287 )
288 .unwrap();
289 }
290
291 writeln!(report).unwrap();
292
293
294 for (info, _) in ecs.iter_resources() {
295 let name = info.name().to_string();
296 writeln!(report, "Resource: {name}").unwrap();
297 // writeln!(report, "- Size: {} bytes",
298 // info.layout().size()).unwrap();
299
300 match name.as_ref() {
301 "azalea_world::container::InstanceContainer" => {
302 let instance_container = ecs.resource::<InstanceContainer>();
303
304 for (instance_name, instance) in &instance_container.instances {
305 writeln!(report, "- Name: {instance_name}").unwrap();
306 writeln!(report, "- Reference count: {}", instance.strong_count())
307 .unwrap();
308 if let Some(instance) = instance.upgrade() {
309 let instance = instance.read();
310 let strong_chunks = instance
311 .chunks
312 .map
313 .iter()
314 .filter(|(_, v)| v.strong_count() > 0)
315 .count();
316 writeln!(
317 report,
318 "- Chunks: {} strongly referenced, {} in map",
319 strong_chunks,
320 instance.chunks.map.len()
321 )
322 .unwrap();
323 writeln!(
324 report,
325 "- Entities: {}",
326 instance.entities_by_chunk.len()
327 )
328 .unwrap();
329 }
330 }
331 }
332 "bevy_ecs::message::Messages<azalea_client::packet::game::ReceivePacketEvent>" => {
333 let events = ecs.resource::<Messages<game::ReceiveGamePacketEvent>>();
334 writeln!(report, "- Event count: {}", events.len()).unwrap();
335 }
336 "bevy_ecs::message::Messages<azalea_client::chunks::ReceiveChunkEvent>" => {
337 let events = ecs.resource::<Messages<ReceiveChunkEvent>>();
338 writeln!(report, "- Event count: {}", events.len()).unwrap();
339 }
340
341 _ => {}
342 }
343 }
344
345 println!("\x1b[1mWrote report to {}\x1b[m", report_path.display());
346 });
347
348 1
349 }));
350
351 commands.register(literal("exit").executes(|ctx: &Ctx| {
352 let source = ctx.source.lock();
353 source.reply("bye!");
354
355 source.bot.disconnect();
356
357 let source = ctx.source.clone();
358 thread::spawn(move || {
359 thread::sleep(Duration::from_secs(1));
360
361 source.lock().bot.ecs.lock().write_message(AppExit::Success);
362 });
363
364 1
365 }));
366}Sourcepub fn length_squared(&self) -> i32
pub fn length_squared(&self) -> i32
Get the distance of this vector to the origin by doing x^2 + y^2 + z^2.
Sourcepub fn distance_squared_to(self, other: BlockPos) -> i32
pub fn distance_squared_to(self, other: BlockPos) -> i32
Get the squared distance from this position to another position.
Equivalent to (self - other).length_squared().
pub fn horizontal_distance_squared(&self) -> i32
pub fn horizontal_distance_squared_to(self, other: BlockPos) -> i32
Sourcepub fn down(&self, y: i32) -> BlockPos
pub fn down(&self, y: i32) -> BlockPos
Return a new instance of this position with the y coordinate decreased by the given number.
Examples found in repository?
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 // look for the sender
23 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 // look for the sender
96 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}Sourcepub fn up(&self, y: i32) -> BlockPos
pub fn up(&self, y: i32) -> BlockPos
Return a new instance of this position with the y coordinate increased by the given number.
Sourcepub fn north(&self, z: i32) -> BlockPos
pub fn north(&self, z: i32) -> BlockPos
Return a new instance of this position with the z coordinate subtracted by the given number.
Sourcepub fn east(&self, x: i32) -> BlockPos
pub fn east(&self, x: i32) -> BlockPos
Return a new instance of this position with the x coordinate increased by the given number.
Sourcepub fn south(&self, z: i32) -> BlockPos
pub fn south(&self, z: i32) -> BlockPos
Return a new instance of this position with the z coordinate increased by the given number.
Sourcepub fn west(&self, x: i32) -> BlockPos
pub fn west(&self, x: i32) -> BlockPos
Return a new instance of this position with the x coordinate subtracted by the given number.
pub fn dot(&self, other: BlockPos) -> i32
Sourcepub fn min(&self, other: BlockPos) -> BlockPos
pub fn min(&self, other: BlockPos) -> BlockPos
Make a new position with the lower coordinates for each axis.
Sourcepub fn max(&self, other: BlockPos) -> BlockPos
pub fn max(&self, other: BlockPos) -> BlockPos
Make a new position with the higher coordinates for each axis.
pub fn with_x(&self, x: i32) -> BlockPos
pub fn with_y(&self, y: i32) -> BlockPos
pub fn with_z(&self, z: i32) -> BlockPos
Source§impl BlockPos
impl BlockPos
Sourcepub fn center(&self) -> Vec3
pub fn center(&self) -> Vec3
Get the absolute center of a block position by adding 0.5 to each coordinate.
Examples found in repository?
42async fn steal(bot: Client, state: State) -> anyhow::Result<()> {
43 {
44 let mut is_stealing = state.is_stealing.lock();
45 if *is_stealing {
46 bot.chat("Already stealing");
47 return Ok(());
48 }
49 *is_stealing = true;
50 }
51
52 state.checked_chests.lock().clear();
53
54 loop {
55 let chest_block = bot
56 .world()
57 .read()
58 .find_blocks(bot.position(), &BlockKind::Chest.into())
59 .find(
60 // find the closest chest that hasn't been checked
61 |block_pos| !state.checked_chests.lock().contains(block_pos),
62 );
63 let Some(chest_block) = chest_block else {
64 break;
65 };
66
67 state.checked_chests.lock().push(chest_block);
68
69 bot.goto(RadiusGoal::new(chest_block.center(), 3.)).await;
70
71 let Some(chest) = bot.open_container_at(chest_block).await else {
72 println!("Couldn't open chest at {chest_block:?}");
73 continue;
74 };
75
76 println!("Getting contents of chest at {chest_block:?}");
77 for (index, slot) in chest.contents().unwrap_or_default().iter().enumerate() {
78 println!("Checking slot {index}: {slot:?}");
79 let ItemStack::Present(item) = slot else {
80 continue;
81 };
82 if item.kind == ItemKind::Diamond {
83 println!("clicking slot ^");
84 chest.click(QuickMoveClick::Left { slot: index as u16 });
85 }
86 }
87 }
88
89 bot.chat("Done");
90
91 *state.is_stealing.lock() = false;
92
93 Ok(())
94}More examples
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 // look for the sender
23 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 // look for the sender
96 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}Sourcepub fn center_bottom(&self) -> Vec3
pub fn center_bottom(&self) -> Vec3
Get the center of the bottom of a block position by adding 0.5 to the x and z coordinates.
Sourcepub fn to_vec3_floored(&self) -> Vec3
pub fn to_vec3_floored(&self) -> Vec3
Convert the block position into a Vec3 without centering it.
Sourcepub fn length_manhattan(&self) -> u32
pub fn length_manhattan(&self) -> u32
Get the distance of this vector from the origin by doing x + y + z.
pub fn offset_with_direction(self, direction: Direction) -> BlockPos
Sourcepub fn length(&self) -> f64
pub fn length(&self) -> f64
Get the distance (as an f64) of this BlockPos to the origin by
doing sqrt(x^2 + y^2 + z^2).
Sourcepub fn distance_to(self, other: BlockPos) -> f64
pub fn distance_to(self, other: BlockPos) -> f64
Get the distance (as an f64) from this position to another position.
Equivalent to (self - other).length().
Note that if you’re using this in a hot path, it may be more performant
to use BlockPos::distance_squared_to instead (by squaring the other
side in the comparison).
Trait Implementations§
Source§impl AddAssign for BlockPos
impl AddAssign for BlockPos
Source§fn add_assign(&mut self, rhs: BlockPos)
fn add_assign(&mut self, rhs: BlockPos)
+= operation. Read moreSource§impl AzaleaRead for BlockPos
impl AzaleaRead for BlockPos
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<BlockPos, BufReadError>
Source§impl AzaleaWrite for BlockPos
impl AzaleaWrite for BlockPos
Source§impl<'de> Deserialize<'de> for BlockPos
impl<'de> Deserialize<'de> for BlockPos
Source§fn deserialize<D>(
deserializer: D,
) -> Result<BlockPos, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<BlockPos, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl DivAssign<i32> for BlockPos
impl DivAssign<i32> for BlockPos
Source§fn div_assign(&mut self, divisor: i32)
fn div_assign(&mut self, divisor: i32)
/= operation. Read moreSource§impl From<&LastSentPosition> for BlockPos
impl From<&LastSentPosition> for BlockPos
Source§fn from(value: &LastSentPosition) -> BlockPos
fn from(value: &LastSentPosition) -> BlockPos
Source§impl From<LastSentPosition> for BlockPos
impl From<LastSentPosition> for BlockPos
Source§fn from(value: LastSentPosition) -> BlockPos
fn from(value: LastSentPosition) -> BlockPos
Source§impl FromStr for BlockPos
Parses a string in the format “X Y Z” into a BlockPos.
impl FromStr for BlockPos
Parses a string in the format “X Y Z” into a BlockPos.
The input string should contain three integer values separated by spaces,
representing the x, y, and z components of the vector respectively.
This can be used to parse user input or from BlockPos::to_string.
Source§impl MulAssign<i32> for BlockPos
impl MulAssign<i32> for BlockPos
Source§fn mul_assign(&mut self, multiplier: i32)
fn mul_assign(&mut self, multiplier: i32)
*= operation. Read moreSource§impl Serialize for BlockPos
impl Serialize for BlockPos
Source§fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
impl Copy for BlockPos
impl Eq for BlockPos
impl StructuralPartialEq for BlockPos
Auto Trait Implementations§
impl Freeze for BlockPos
impl RefUnwindSafe for BlockPos
impl Send for BlockPos
impl Sync for BlockPos
impl Unpin for BlockPos
impl UnwindSafe for BlockPos
Blanket Implementations§
§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§unsafe fn clone_to_uninit(&self, dest: *mut u8)
unsafe fn clone_to_uninit(&self, dest: *mut u8)
clone_to_uninit)§impl<T> CompatExt for T
impl<T> CompatExt for T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DynEq for T
impl<T> DynEq for T
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> Serialize for T
impl<T> Serialize for T
fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>
fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>
§impl<T> ToCompactString for Twhere
T: Display,
impl<T> ToCompactString for Twhere
T: Display,
§fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
fn try_to_compact_string(&self) -> Result<CompactString, ToCompactStringError>
ToCompactString::to_compact_string()] Read more§fn to_compact_string(&self) -> CompactString
fn to_compact_string(&self) -> CompactString
CompactString]. Read more§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.