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.
To convert a BlockPos to a Vec3, you’ll usually want Self::center.
Fields§
§x: i32§y: i32§z: i32Implementations§
Source§impl BlockPos
impl BlockPos
Sourcepub const fn new(x: i32, y: i32, z: i32) -> Self
pub const fn new(x: i32, y: i32, z: i32) -> Self
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 let position = position.clone();
32 source.reply("ok");
33 source
34 .bot
35 .start_goto(BlockPosGoal(BlockPos::from(position)));
36 1
37 })
38 .then(literal("xz").then(argument("x", integer()).then(
39 argument("z", integer()).executes(|ctx: &Ctx| {
40 let source = ctx.source.lock();
41 let x = get_integer(ctx, "x").unwrap();
42 let z = get_integer(ctx, "z").unwrap();
43 println!("goto xz {x} {z}");
44 source.reply("ok");
45 source.bot.start_goto(XZGoal { x, z });
46 1
47 }),
48 )))
49 .then(literal("radius").then(argument("radius", float()).then(
50 argument("x", integer()).then(argument("y", integer()).then(
51 argument("z", integer()).executes(|ctx: &Ctx| {
52 let source = ctx.source.lock();
53 let radius = get_float(ctx, "radius").unwrap();
54 let x = get_integer(ctx, "x").unwrap();
55 let y = get_integer(ctx, "y").unwrap();
56 let z = get_integer(ctx, "z").unwrap();
57 println!("goto radius {radius}, position: {x} {y} {z}");
58 source.reply("ok");
59 source.bot.start_goto(RadiusGoal {
60 pos: BlockPos::new(x, y, z).center(),
61 radius,
62 });
63 1
64 }),
65 )),
66 )))
67 .then(argument("x", integer()).then(argument("y", integer()).then(
68 argument("z", integer()).executes(|ctx: &Ctx| {
69 let source = ctx.source.lock();
70 let x = get_integer(ctx, "x").unwrap();
71 let y = get_integer(ctx, "y").unwrap();
72 let z = get_integer(ctx, "z").unwrap();
73 println!("goto xyz {x} {y} {z}");
74 source.reply("ok");
75 source.bot.start_goto(BlockPosGoal(BlockPos::new(x, y, z)));
76 1
77 }),
78 ))),
79 );
80
81 commands.register(literal("down").executes(|ctx: &Ctx| {
82 let source = ctx.source.clone();
83 tokio::spawn(async move {
84 let bot = source.lock().bot.clone();
85 let position = BlockPos::from(bot.position());
86 source.lock().reply("mining...");
87 bot.mine(position.down(1)).await;
88 source.lock().reply("done");
89 });
90 1
91 }));
92
93 commands.register(
94 literal("look")
95 .executes(|ctx: &Ctx| {
96 // look for the sender
97 let mut source = ctx.source.lock();
98 let Some(entity) = source.entity() else {
99 source.reply("I can't see you!");
100 return 0;
101 };
102 let Some(position) = source.bot.get_entity_component::<Position>(entity) else {
103 source.reply("I can't see you!");
104 return 0;
105 };
106 let eye_height = source
107 .bot
108 .get_entity_component::<EntityDimensions>(entity)
109 .map(|h| h.eye_height)
110 .unwrap_or_default();
111 source.bot.look_at(position.up(eye_height as f64));
112 1
113 })
114 .then(argument("x", integer()).then(argument("y", integer()).then(
115 argument("z", integer()).executes(|ctx: &Ctx| {
116 let pos = BlockPos::new(
117 get_integer(ctx, "x").unwrap(),
118 get_integer(ctx, "y").unwrap(),
119 get_integer(ctx, "z").unwrap(),
120 );
121 println!("{pos:?}");
122 let source = ctx.source.lock();
123 source.bot.look_at(pos.center());
124 1
125 }),
126 ))),
127 );
128
129 commands.register(
130 literal("walk").then(argument("seconds", float()).executes(|ctx: &Ctx| {
131 let mut seconds = get_float(ctx, "seconds").unwrap();
132 let source = ctx.source.lock();
133 let bot = source.bot.clone();
134
135 if seconds < 0. {
136 bot.walk(WalkDirection::Backward);
137 seconds = -seconds;
138 } else {
139 bot.walk(WalkDirection::Forward);
140 }
141
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, walking for {seconds} seconds"));
147 1
148 })),
149 );
150 commands.register(
151 literal("sprint").then(argument("seconds", float()).executes(|ctx: &Ctx| {
152 let seconds = get_float(ctx, "seconds").unwrap();
153 let source = ctx.source.lock();
154 let bot = source.bot.clone();
155 bot.sprint(SprintDirection::Forward);
156 tokio::spawn(async move {
157 tokio::time::sleep(Duration::from_secs_f32(seconds)).await;
158 bot.walk(WalkDirection::None);
159 });
160 source.reply(format!("ok, sprinting for {seconds} seconds"));
161 1
162 })),
163 );
164
165 commands.register(literal("north").executes(|ctx: &Ctx| {
166 let source = ctx.source.lock();
167 source.bot.set_direction(180., 0.);
168 source.reply("ok");
169 1
170 }));
171 commands.register(literal("south").executes(|ctx: &Ctx| {
172 let source = ctx.source.lock();
173 source.bot.set_direction(0., 0.);
174 source.reply("ok");
175 1
176 }));
177 commands.register(literal("east").executes(|ctx: &Ctx| {
178 let source = ctx.source.lock();
179 source.bot.set_direction(-90., 0.);
180 source.reply("ok");
181 1
182 }));
183 commands.register(literal("west").executes(|ctx: &Ctx| {
184 let source = ctx.source.lock();
185 source.bot.set_direction(90., 0.);
186 source.reply("ok");
187 1
188 }));
189 commands.register(
190 literal("jump")
191 .executes(|ctx: &Ctx| {
192 let source = ctx.source.lock();
193 source.bot.jump();
194 source.reply("ok");
195 1
196 })
197 .then(argument("enabled", bool()).executes(|ctx: &Ctx| {
198 let jumping = get_bool(ctx, "enabled").unwrap();
199 let source = ctx.source.lock();
200 source.bot.set_jumping(jumping);
201 1
202 })),
203 );
204
205 let sneak = |ctx: &Ctx| {
206 let source = ctx.source.lock();
207 source.bot.set_crouching(!source.bot.crouching());
208 source.reply("ok");
209 1
210 };
211 let sneak_enabled = argument("enabled", bool()).executes(|ctx: &Ctx| {
212 let sneaking = get_bool(ctx, "enabled").unwrap();
213 let source = ctx.source.lock();
214 source.bot.set_crouching(sneaking);
215 1
216 });
217 commands.register(literal("sneak").executes(sneak).then(sneak_enabled.clone()));
218 commands.register(literal("crouch").executes(sneak).then(sneak_enabled));
219
220 commands.register(literal("stop").executes(|ctx: &Ctx| {
221 let source = ctx.source.lock();
222 source.bot.stop_pathfinding();
223 source.reply("ok");
224 *source.state.task.lock() = BotTask::None;
225 1
226 }));
227}More examples
24pub fn register(commands: &mut CommandDispatcher<Mutex<CommandSource>>) {
25 commands.register(literal("ping").executes(|ctx: &Ctx| {
26 let source = ctx.source.lock();
27 source.reply("pong!");
28 1
29 }));
30
31 commands.register(literal("disconnect").executes(|ctx: &Ctx| {
32 let source = ctx.source.lock();
33 source.bot.disconnect();
34 1
35 }));
36
37 commands.register(literal("whereami").executes(|ctx: &Ctx| {
38 let mut source = ctx.source.lock();
39 let Some(entity) = source.entity() else {
40 source.reply("You aren't in render distance!");
41 return 0;
42 };
43 let position = source.bot.entity_component::<Position>(entity);
44 source.reply(format!(
45 "You are at {}, {}, {}",
46 position.x, position.y, position.z
47 ));
48 1
49 }));
50
51 commands.register(literal("entityid").executes(|ctx: &Ctx| {
52 let mut source = ctx.source.lock();
53 let Some(entity) = source.entity() else {
54 source.reply("You aren't in render distance!");
55 return 0;
56 };
57 let entity_id = source.bot.entity_component::<MinecraftEntityId>(entity);
58 source.reply(format!(
59 "Your Minecraft ID is {} and your ECS ID is {entity:?}",
60 *entity_id
61 ));
62 1
63 }));
64
65 let whereareyou = |ctx: &Ctx| {
66 let source = ctx.source.lock();
67 let position = source.bot.position();
68 source.reply(format!(
69 "I'm at {}, {}, {}",
70 position.x, position.y, position.z
71 ));
72 1
73 };
74 commands.register(literal("whereareyou").executes(whereareyou));
75 commands.register(literal("pos").executes(whereareyou));
76
77 commands.register(literal("whoareyou").executes(|ctx: &Ctx| {
78 let source = ctx.source.lock();
79 source.reply(format!(
80 "I am {} ({}, {})",
81 source.bot.username(),
82 source.bot.uuid(),
83 source.bot.entity
84 ));
85 1
86 }));
87
88 commands.register(literal("getdirection").executes(|ctx: &Ctx| {
89 let source = ctx.source.lock();
90 let direction = source.bot.direction();
91 source.reply(format!(
92 "I'm looking at {}, {}",
93 direction.y_rot(),
94 direction.x_rot()
95 ));
96 1
97 }));
98
99 commands.register(literal("health").executes(|ctx: &Ctx| {
100 let source = ctx.source.lock();
101
102 let health = source.bot.health();
103 source.reply(format!("I have {health} health"));
104 1
105 }));
106
107 commands.register(literal("lookingat").executes(|ctx: &Ctx| {
108 let source = ctx.source.lock();
109
110 let hit_result = source.bot.hit_result();
111
112 match &hit_result {
113 HitResult::Block(r) => {
114 if r.miss {
115 source.reply("I'm not looking at anything");
116 return 0;
117 }
118 let block_pos = r.block_pos;
119 let block = source.bot.world().read().get_block_state(block_pos);
120 source.reply(format!("I'm looking at {block:?} at {block_pos:?}"));
121 }
122 HitResult::Entity(r) => {
123 let entity_kind = **source.bot.entity_component::<EntityKindComponent>(r.entity);
124 source.reply(format!(
125 "I'm looking at {entity_kind} ({:?}) at {}",
126 r.entity, r.location
127 ));
128 }
129 }
130
131 1
132 }));
133
134 commands.register(literal("getblock").then(argument("x", integer()).then(
135 argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
136 let source = ctx.source.lock();
137 let x = get_integer(ctx, "x").unwrap();
138 let y = get_integer(ctx, "y").unwrap();
139 let z = get_integer(ctx, "z").unwrap();
140 println!("getblock xyz {x} {y} {z}");
141 let block_pos = BlockPos::new(x, y, z);
142 let block = source.bot.world().read().get_block_state(block_pos);
143 source.reply(format!("BlockKind at {block_pos} is {block:?}"));
144 1
145 })),
146 )));
147 commands.register(literal("getfluid").then(argument("x", integer()).then(
148 argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
149 let source = ctx.source.lock();
150 let x = get_integer(ctx, "x").unwrap();
151 let y = get_integer(ctx, "y").unwrap();
152 let z = get_integer(ctx, "z").unwrap();
153 println!("getfluid xyz {x} {y} {z}");
154 let block_pos = BlockPos::new(x, y, z);
155 let block = source.bot.world().read().get_fluid_state(block_pos);
156 source.reply(format!("Fluid at {block_pos} is {block:?}"));
157 1
158 })),
159 )));
160
161 commands.register(literal("pathfinderstate").executes(|ctx: &Ctx| {
162 let source = ctx.source.lock();
163 let pathfinder = source.bot.get_component::<Pathfinder>();
164 let Some(pathfinder) = pathfinder else {
165 source.reply("I don't have the Pathfinder ocmponent");
166 return 1;
167 };
168 source.reply(format!(
169 "pathfinder.is_calculating: {}",
170 pathfinder.is_calculating
171 ));
172
173 let executing_path = source.bot.get_component::<ExecutingPath>();
174 let Some(executing_path) = executing_path else {
175 source.reply("I'm not executing a path");
176 return 1;
177 };
178 source.reply(format!(
179 "is_path_partial: {}, path.len: {}, queued_path.len: {}",
180 executing_path.is_path_partial,
181 executing_path.path.len(),
182 if let Some(queued) = &executing_path.queued_path {
183 queued.len().to_string()
184 } else {
185 "n/a".to_owned()
186 },
187 ));
188 1
189 }));
190
191 commands.register(literal("startuseitem").executes(|ctx: &Ctx| {
192 let source = ctx.source.lock();
193 source.bot.start_use_item();
194 source.reply("Ok!");
195 1
196 }));
197 commands.register(literal("maxstacksize").executes(|ctx: &Ctx| {
198 let source = ctx.source.lock();
199 let max_stack_size = source
200 .bot
201 .get_held_item()
202 .get_component::<MaxStackSize>()
203 .map_or(-1, |s| s.count);
204 source.reply(format!("{max_stack_size}"));
205 1
206 }));
207
208 commands.register(literal("dimensions").executes(|ctx: &Ctx| {
209 let source = ctx.source.lock();
210 let bot_dimensions = source.bot.dimensions();
211 source.reply(format!("{bot_dimensions:?}"));
212 1
213 }));
214
215 commands.register(literal("players").executes(|ctx: &Ctx| {
216 let source = ctx.source.lock();
217 let player_entities = source
218 .bot
219 .nearest_entities_by::<(), With<metadata::Player>>(|_: ()| true);
220 let tab_list = source.bot.tab_list();
221 for player_entity in player_entities {
222 let uuid = source.bot.entity_component::<EntityUuid>(player_entity);
223 source.reply(format!(
224 "{} - {} ({:?})",
225 player_entity,
226 tab_list.get(&uuid).map_or("?", |p| p.profile.name.as_str()),
227 uuid
228 ));
229 }
230 1
231 }));
232
233 commands.register(literal("enchants").executes(|ctx: &Ctx| {
234 let source = ctx.source.lock();
235 source.bot.with_registry_holder(|r| {
236 let enchants = &r.enchantment;
237 println!("enchants: {enchants:?}");
238 });
239 1
240 }));
241
242 commands.register(literal("attributes").executes(|ctx: &Ctx| {
243 let source = ctx.source.lock();
244 let attributes = source.bot.attributes();
245 println!("attributes: {attributes:?}");
246 1
247 }));
248
249 commands.register(literal("debugecsleak").executes(|ctx: &Ctx| {
250 let source = ctx.source.lock();
251
252 source.reply("Ok!");
253
254
255
256 source.bot.disconnect();
257
258 let ecs = source.bot.ecs.clone();
259 thread::spawn(move || {
260 thread::sleep(Duration::from_secs(1));
261 // dump the ecs
262
263 let mut ecs = ecs.write();
264
265 let report_path = env::temp_dir().join("azalea-ecs-leak-report.txt");
266 let mut report = File::create(&report_path).unwrap();
267
268 let mut query = ecs.query::<EntityRef>();
269 for entity in query.iter(& ecs) {
270 writeln!(report, "Entity: {}", entity.id()).unwrap();
271 let archetype = entity.archetype();
272 let component_count = archetype.component_count();
273
274 let component_names = archetype
275 .components()
276 .iter()
277 .map(|c| ecs.components().get_info(*c).unwrap().name().to_string())
278 .collect::<Vec<_>>();
279 writeln!(
280 report,
281 "- {component_count} components: {}",
282 component_names.join(", ")
283 )
284 .unwrap();
285 }
286
287 writeln!(report).unwrap();
288
289
290 for (info, _) in ecs.iter_resources() {
291 let name = info.name().to_string();
292 writeln!(report, "Resource: {name}").unwrap();
293 // writeln!(report, "- Size: {} bytes",
294 // info.layout().size()).unwrap();
295
296 match name.as_ref() {
297 "azalea_world::container::InstanceContainer" => {
298 let instance_container = ecs.resource::<InstanceContainer>();
299
300 for (instance_name, instance) in &instance_container.instances {
301 writeln!(report, "- Name: {instance_name}").unwrap();
302 writeln!(report, "- Reference count: {}", instance.strong_count())
303 .unwrap();
304 if let Some(instance) = instance.upgrade() {
305 let instance = instance.read();
306 let strong_chunks = instance
307 .chunks
308 .map
309 .iter()
310 .filter(|(_, v)| v.strong_count() > 0)
311 .count();
312 writeln!(
313 report,
314 "- Chunks: {} strongly referenced, {} in map",
315 strong_chunks,
316 instance.chunks.map.len()
317 )
318 .unwrap();
319 writeln!(
320 report,
321 "- Entities: {}",
322 instance.entities_by_chunk.len()
323 )
324 .unwrap();
325 }
326 }
327 }
328 "bevy_ecs::message::Messages<azalea_client::packet::game::ReceivePacketEvent>" => {
329 let events = ecs.resource::<Messages<game::ReceiveGamePacketEvent>>();
330 writeln!(report, "- Event count: {}", events.len()).unwrap();
331 }
332 "bevy_ecs::message::Messages<azalea_client::chunks::ReceiveChunkEvent>" => {
333 let events = ecs.resource::<Messages<ReceiveChunkEvent>>();
334 writeln!(report, "- Event count: {}", events.len()).unwrap();
335 }
336
337 _ => {}
338 }
339 }
340
341 println!("\x1b[1mWrote report to {}\x1b[m", report_path.display());
342 });
343
344 1
345 }));
346
347 commands.register(literal("exit").executes(|ctx: &Ctx| {
348 let source = ctx.source.lock();
349 source.reply("bye!");
350
351 source.bot.disconnect();
352
353 let source = ctx.source.clone();
354 thread::spawn(move || {
355 thread::sleep(Duration::from_secs(1));
356
357 source
358 .lock()
359 .bot
360 .ecs
361 .write()
362 .write_message(AppExit::Success);
363 });
364
365 1
366 }));
367}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: Self) -> i32
pub fn distance_squared_to(self, other: Self) -> 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: Self) -> i32
Sourcepub fn down(&self, y: i32) -> Self
pub fn down(&self, y: i32) -> Self
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 let position = position.clone();
32 source.reply("ok");
33 source
34 .bot
35 .start_goto(BlockPosGoal(BlockPos::from(position)));
36 1
37 })
38 .then(literal("xz").then(argument("x", integer()).then(
39 argument("z", integer()).executes(|ctx: &Ctx| {
40 let source = ctx.source.lock();
41 let x = get_integer(ctx, "x").unwrap();
42 let z = get_integer(ctx, "z").unwrap();
43 println!("goto xz {x} {z}");
44 source.reply("ok");
45 source.bot.start_goto(XZGoal { x, z });
46 1
47 }),
48 )))
49 .then(literal("radius").then(argument("radius", float()).then(
50 argument("x", integer()).then(argument("y", integer()).then(
51 argument("z", integer()).executes(|ctx: &Ctx| {
52 let source = ctx.source.lock();
53 let radius = get_float(ctx, "radius").unwrap();
54 let x = get_integer(ctx, "x").unwrap();
55 let y = get_integer(ctx, "y").unwrap();
56 let z = get_integer(ctx, "z").unwrap();
57 println!("goto radius {radius}, position: {x} {y} {z}");
58 source.reply("ok");
59 source.bot.start_goto(RadiusGoal {
60 pos: BlockPos::new(x, y, z).center(),
61 radius,
62 });
63 1
64 }),
65 )),
66 )))
67 .then(argument("x", integer()).then(argument("y", integer()).then(
68 argument("z", integer()).executes(|ctx: &Ctx| {
69 let source = ctx.source.lock();
70 let x = get_integer(ctx, "x").unwrap();
71 let y = get_integer(ctx, "y").unwrap();
72 let z = get_integer(ctx, "z").unwrap();
73 println!("goto xyz {x} {y} {z}");
74 source.reply("ok");
75 source.bot.start_goto(BlockPosGoal(BlockPos::new(x, y, z)));
76 1
77 }),
78 ))),
79 );
80
81 commands.register(literal("down").executes(|ctx: &Ctx| {
82 let source = ctx.source.clone();
83 tokio::spawn(async move {
84 let bot = source.lock().bot.clone();
85 let position = BlockPos::from(bot.position());
86 source.lock().reply("mining...");
87 bot.mine(position.down(1)).await;
88 source.lock().reply("done");
89 });
90 1
91 }));
92
93 commands.register(
94 literal("look")
95 .executes(|ctx: &Ctx| {
96 // look for the sender
97 let mut source = ctx.source.lock();
98 let Some(entity) = source.entity() else {
99 source.reply("I can't see you!");
100 return 0;
101 };
102 let Some(position) = source.bot.get_entity_component::<Position>(entity) else {
103 source.reply("I can't see you!");
104 return 0;
105 };
106 let eye_height = source
107 .bot
108 .get_entity_component::<EntityDimensions>(entity)
109 .map(|h| h.eye_height)
110 .unwrap_or_default();
111 source.bot.look_at(position.up(eye_height as f64));
112 1
113 })
114 .then(argument("x", integer()).then(argument("y", integer()).then(
115 argument("z", integer()).executes(|ctx: &Ctx| {
116 let pos = BlockPos::new(
117 get_integer(ctx, "x").unwrap(),
118 get_integer(ctx, "y").unwrap(),
119 get_integer(ctx, "z").unwrap(),
120 );
121 println!("{pos:?}");
122 let source = ctx.source.lock();
123 source.bot.look_at(pos.center());
124 1
125 }),
126 ))),
127 );
128
129 commands.register(
130 literal("walk").then(argument("seconds", float()).executes(|ctx: &Ctx| {
131 let mut seconds = get_float(ctx, "seconds").unwrap();
132 let source = ctx.source.lock();
133 let bot = source.bot.clone();
134
135 if seconds < 0. {
136 bot.walk(WalkDirection::Backward);
137 seconds = -seconds;
138 } else {
139 bot.walk(WalkDirection::Forward);
140 }
141
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, walking for {seconds} seconds"));
147 1
148 })),
149 );
150 commands.register(
151 literal("sprint").then(argument("seconds", float()).executes(|ctx: &Ctx| {
152 let seconds = get_float(ctx, "seconds").unwrap();
153 let source = ctx.source.lock();
154 let bot = source.bot.clone();
155 bot.sprint(SprintDirection::Forward);
156 tokio::spawn(async move {
157 tokio::time::sleep(Duration::from_secs_f32(seconds)).await;
158 bot.walk(WalkDirection::None);
159 });
160 source.reply(format!("ok, sprinting for {seconds} seconds"));
161 1
162 })),
163 );
164
165 commands.register(literal("north").executes(|ctx: &Ctx| {
166 let source = ctx.source.lock();
167 source.bot.set_direction(180., 0.);
168 source.reply("ok");
169 1
170 }));
171 commands.register(literal("south").executes(|ctx: &Ctx| {
172 let source = ctx.source.lock();
173 source.bot.set_direction(0., 0.);
174 source.reply("ok");
175 1
176 }));
177 commands.register(literal("east").executes(|ctx: &Ctx| {
178 let source = ctx.source.lock();
179 source.bot.set_direction(-90., 0.);
180 source.reply("ok");
181 1
182 }));
183 commands.register(literal("west").executes(|ctx: &Ctx| {
184 let source = ctx.source.lock();
185 source.bot.set_direction(90., 0.);
186 source.reply("ok");
187 1
188 }));
189 commands.register(
190 literal("jump")
191 .executes(|ctx: &Ctx| {
192 let source = ctx.source.lock();
193 source.bot.jump();
194 source.reply("ok");
195 1
196 })
197 .then(argument("enabled", bool()).executes(|ctx: &Ctx| {
198 let jumping = get_bool(ctx, "enabled").unwrap();
199 let source = ctx.source.lock();
200 source.bot.set_jumping(jumping);
201 1
202 })),
203 );
204
205 let sneak = |ctx: &Ctx| {
206 let source = ctx.source.lock();
207 source.bot.set_crouching(!source.bot.crouching());
208 source.reply("ok");
209 1
210 };
211 let sneak_enabled = argument("enabled", bool()).executes(|ctx: &Ctx| {
212 let sneaking = get_bool(ctx, "enabled").unwrap();
213 let source = ctx.source.lock();
214 source.bot.set_crouching(sneaking);
215 1
216 });
217 commands.register(literal("sneak").executes(sneak).then(sneak_enabled.clone()));
218 commands.register(literal("crouch").executes(sneak).then(sneak_enabled));
219
220 commands.register(literal("stop").executes(|ctx: &Ctx| {
221 let source = ctx.source.lock();
222 source.bot.stop_pathfinding();
223 source.reply("ok");
224 *source.state.task.lock() = BotTask::None;
225 1
226 }));
227}Sourcepub fn up(&self, y: i32) -> Self
pub fn up(&self, y: i32) -> Self
Return a new instance of this position with the y coordinate increased by the given number.
Sourcepub fn north(&self, z: i32) -> Self
pub fn north(&self, z: i32) -> Self
Return a new instance of this position with the z coordinate subtracted by the given number.
Sourcepub fn east(&self, x: i32) -> Self
pub fn east(&self, x: i32) -> Self
Return a new instance of this position with the x coordinate increased by the given number.
Sourcepub fn south(&self, z: i32) -> Self
pub fn south(&self, z: i32) -> Self
Return a new instance of this position with the z coordinate increased by the given number.
Sourcepub fn west(&self, x: i32) -> Self
pub fn west(&self, x: i32) -> Self
Return a new instance of this position with the x coordinate subtracted by the given number.
pub fn dot(&self, other: Self) -> i32
Sourcepub fn min(&self, other: Self) -> Self
pub fn min(&self, other: Self) -> Self
Make a new position with the lower coordinates for each axis.
Sourcepub fn max(&self, other: Self) -> Self
pub fn max(&self, other: Self) -> Self
Make a new position with the higher coordinates for each axis.
pub fn with_x(&self, x: i32) -> Self
pub fn with_y(&self, y: i32) -> Self
pub fn with_z(&self, z: i32) -> Self
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.left_click(index);
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 let position = position.clone();
32 source.reply("ok");
33 source
34 .bot
35 .start_goto(BlockPosGoal(BlockPos::from(position)));
36 1
37 })
38 .then(literal("xz").then(argument("x", integer()).then(
39 argument("z", integer()).executes(|ctx: &Ctx| {
40 let source = ctx.source.lock();
41 let x = get_integer(ctx, "x").unwrap();
42 let z = get_integer(ctx, "z").unwrap();
43 println!("goto xz {x} {z}");
44 source.reply("ok");
45 source.bot.start_goto(XZGoal { x, z });
46 1
47 }),
48 )))
49 .then(literal("radius").then(argument("radius", float()).then(
50 argument("x", integer()).then(argument("y", integer()).then(
51 argument("z", integer()).executes(|ctx: &Ctx| {
52 let source = ctx.source.lock();
53 let radius = get_float(ctx, "radius").unwrap();
54 let x = get_integer(ctx, "x").unwrap();
55 let y = get_integer(ctx, "y").unwrap();
56 let z = get_integer(ctx, "z").unwrap();
57 println!("goto radius {radius}, position: {x} {y} {z}");
58 source.reply("ok");
59 source.bot.start_goto(RadiusGoal {
60 pos: BlockPos::new(x, y, z).center(),
61 radius,
62 });
63 1
64 }),
65 )),
66 )))
67 .then(argument("x", integer()).then(argument("y", integer()).then(
68 argument("z", integer()).executes(|ctx: &Ctx| {
69 let source = ctx.source.lock();
70 let x = get_integer(ctx, "x").unwrap();
71 let y = get_integer(ctx, "y").unwrap();
72 let z = get_integer(ctx, "z").unwrap();
73 println!("goto xyz {x} {y} {z}");
74 source.reply("ok");
75 source.bot.start_goto(BlockPosGoal(BlockPos::new(x, y, z)));
76 1
77 }),
78 ))),
79 );
80
81 commands.register(literal("down").executes(|ctx: &Ctx| {
82 let source = ctx.source.clone();
83 tokio::spawn(async move {
84 let bot = source.lock().bot.clone();
85 let position = BlockPos::from(bot.position());
86 source.lock().reply("mining...");
87 bot.mine(position.down(1)).await;
88 source.lock().reply("done");
89 });
90 1
91 }));
92
93 commands.register(
94 literal("look")
95 .executes(|ctx: &Ctx| {
96 // look for the sender
97 let mut source = ctx.source.lock();
98 let Some(entity) = source.entity() else {
99 source.reply("I can't see you!");
100 return 0;
101 };
102 let Some(position) = source.bot.get_entity_component::<Position>(entity) else {
103 source.reply("I can't see you!");
104 return 0;
105 };
106 let eye_height = source
107 .bot
108 .get_entity_component::<EntityDimensions>(entity)
109 .map(|h| h.eye_height)
110 .unwrap_or_default();
111 source.bot.look_at(position.up(eye_height as f64));
112 1
113 })
114 .then(argument("x", integer()).then(argument("y", integer()).then(
115 argument("z", integer()).executes(|ctx: &Ctx| {
116 let pos = BlockPos::new(
117 get_integer(ctx, "x").unwrap(),
118 get_integer(ctx, "y").unwrap(),
119 get_integer(ctx, "z").unwrap(),
120 );
121 println!("{pos:?}");
122 let source = ctx.source.lock();
123 source.bot.look_at(pos.center());
124 1
125 }),
126 ))),
127 );
128
129 commands.register(
130 literal("walk").then(argument("seconds", float()).executes(|ctx: &Ctx| {
131 let mut seconds = get_float(ctx, "seconds").unwrap();
132 let source = ctx.source.lock();
133 let bot = source.bot.clone();
134
135 if seconds < 0. {
136 bot.walk(WalkDirection::Backward);
137 seconds = -seconds;
138 } else {
139 bot.walk(WalkDirection::Forward);
140 }
141
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, walking for {seconds} seconds"));
147 1
148 })),
149 );
150 commands.register(
151 literal("sprint").then(argument("seconds", float()).executes(|ctx: &Ctx| {
152 let seconds = get_float(ctx, "seconds").unwrap();
153 let source = ctx.source.lock();
154 let bot = source.bot.clone();
155 bot.sprint(SprintDirection::Forward);
156 tokio::spawn(async move {
157 tokio::time::sleep(Duration::from_secs_f32(seconds)).await;
158 bot.walk(WalkDirection::None);
159 });
160 source.reply(format!("ok, sprinting for {seconds} seconds"));
161 1
162 })),
163 );
164
165 commands.register(literal("north").executes(|ctx: &Ctx| {
166 let source = ctx.source.lock();
167 source.bot.set_direction(180., 0.);
168 source.reply("ok");
169 1
170 }));
171 commands.register(literal("south").executes(|ctx: &Ctx| {
172 let source = ctx.source.lock();
173 source.bot.set_direction(0., 0.);
174 source.reply("ok");
175 1
176 }));
177 commands.register(literal("east").executes(|ctx: &Ctx| {
178 let source = ctx.source.lock();
179 source.bot.set_direction(-90., 0.);
180 source.reply("ok");
181 1
182 }));
183 commands.register(literal("west").executes(|ctx: &Ctx| {
184 let source = ctx.source.lock();
185 source.bot.set_direction(90., 0.);
186 source.reply("ok");
187 1
188 }));
189 commands.register(
190 literal("jump")
191 .executes(|ctx: &Ctx| {
192 let source = ctx.source.lock();
193 source.bot.jump();
194 source.reply("ok");
195 1
196 })
197 .then(argument("enabled", bool()).executes(|ctx: &Ctx| {
198 let jumping = get_bool(ctx, "enabled").unwrap();
199 let source = ctx.source.lock();
200 source.bot.set_jumping(jumping);
201 1
202 })),
203 );
204
205 let sneak = |ctx: &Ctx| {
206 let source = ctx.source.lock();
207 source.bot.set_crouching(!source.bot.crouching());
208 source.reply("ok");
209 1
210 };
211 let sneak_enabled = argument("enabled", bool()).executes(|ctx: &Ctx| {
212 let sneaking = get_bool(ctx, "enabled").unwrap();
213 let source = ctx.source.lock();
214 source.bot.set_crouching(sneaking);
215 1
216 });
217 commands.register(literal("sneak").executes(sneak).then(sneak_enabled.clone()));
218 commands.register(literal("crouch").executes(sneak).then(sneak_enabled));
219
220 commands.register(literal("stop").executes(|ctx: &Ctx| {
221 let source = ctx.source.lock();
222 source.bot.stop_pathfinding();
223 source.reply("ok");
224 *source.state.task.lock() = BotTask::None;
225 1
226 }));
227}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.
Sourcepub fn offset_with_direction(self, direction: Direction) -> Self
pub fn offset_with_direction(self, direction: Direction) -> Self
Add or subtract 1 to one of this position’s coordinates, depending on
the direction.
let pos = BlockPos::new(10, 10, 10);
assert_eq!(
pos.offset_with_direction(Direction::North),
BlockPos::new(10, 10, 9)
);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: Self) -> f64
pub fn distance_to(self, other: Self) -> 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: Self)
fn add_assign(&mut self, rhs: Self)
+= operation. Read moreSource§impl AzaleaRead for BlockPos
impl AzaleaRead for BlockPos
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, 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<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::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<&BlockPos> for ChunkBiomePos
impl From<&BlockPos> for ChunkBiomePos
Source§impl From<&BlockPos> for ChunkBlockPos
impl From<&BlockPos> for ChunkBlockPos
Source§impl From<&BlockPos> for ChunkSectionPos
impl From<&BlockPos> for ChunkSectionPos
Source§impl From<BlockPos> for ChunkBiomePos
impl From<BlockPos> for ChunkBiomePos
Source§impl From<BlockPos> for ChunkBlockPos
impl From<BlockPos> for ChunkBlockPos
Source§impl From<BlockPos> for ChunkSectionBlockPos
impl From<BlockPos> for ChunkSectionBlockPos
Source§impl From<BlockPos> for ChunkSectionPos
impl From<BlockPos> for ChunkSectionPos
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 moreimpl 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§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§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>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> 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>
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