Skip to main content

EntityRef

Struct EntityRef 

Source
pub struct EntityRef { /* private fields */ }
Expand description

A reference to an entity in a world.

This is different from [Entity], since you can perform actions with just an EntityRef instead of it only being an identifier.

Most functions on EntityRef that return a value will result in a panic if the client has despawned, so if your code involves waiting, you should check Self::is_alive or Self::exists before calling those functions.

Also, since EntityRef stores the Client alongside the entity, this means that it supports interactions such as Self::attack.

Not to be confused with Bevy’s EntityRef.

Implementations§

Source§

impl EntityRef

Source

pub fn position(&self) -> Vec3

Get the entity’s position in the world, which is the same as its feet position.

To get the client’s eye position, use Self::eye_position.

Also see Client::position.

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

impl EntityRef

Source

pub fn dimensions(&self) -> EntityDimensions

Get the bounding box dimensions for the entity, which contains its width, height, and eye height.

Also see Client::dimensions

Source§

impl EntityRef

Source

pub fn eye_position(&self) -> Vec3

Get the position of this entity’s eyes.

Also see Client::eye_position.

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

impl EntityRef

Source

pub fn health(&self) -> f32

Get the health of this entity, typically in the range 0..=20.

Also see Client::health.

Source§

impl EntityRef

Source

pub fn uuid(&self) -> Uuid

Get the Minecraft UUID of this entity.

Also see Client::uuid.

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

impl EntityRef

Source

pub fn minecraft_id(&self) -> MinecraftEntityId

Get the Minecraft UUID of this entity.

See [MinecraftEntityId] for more details. For persistent identifiers, consider using Self::uuid instead.

Also see Client::minecraft_id.

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

impl EntityRef

Source

pub fn attributes(&self) -> Attributes

Returns the attribute values of the entity, which can be used to determine things like its movement speed.

Source§

impl EntityRef

Source

pub fn instance_name(&self) -> WorldName

👎Deprecated: renamed to world_name.
Source§

impl EntityRef

Source

pub fn world_name(&self) -> WorldName

Get the name of the world that the entity is in.

This can be used to check if the entity is in the same world as another entity.

Also see Client::world_name,

Source§

impl EntityRef

Source

pub fn is_alive(&self) -> bool

Returns whether the entity is alive and hasn’t despawned.

Unlike most functions in EntityRef, this one will not panic if the entity is despawned. Because of this, it may be useful to check is_alive before calling functions that request data from the world.

Also see Client::is_alive and Self::exists.

Source§

impl EntityRef

Source

pub fn exists(&self) -> bool

Returns whether the entity is in the world and hasn’t despawned.

Like Self::is_alive, this will not panic.

Also see Client::exists.

Source§

impl EntityRef

Source

pub fn physics(&self) -> Physics

Returns the complete Physics data for this entity, including velocity, bounding box, collisions, etc.

Also see Client::physics.

Source§

impl EntityRef

Source

pub fn new(client: Client, entity: Entity) -> Self

Source

pub fn id(&self) -> Entity

Returns the ECS identifier for the entity.

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

pub fn component<T: Component>(&self) -> MappedRwLockReadGuard<'_, T>

Get a component on the entity.

This allows you to access certain data stored about the entity that isn’t accessible in a simpler way.

See Client::component for more details.

§Panics

This will panic if the component doesn’t exist on the client. Use Self::get_component to avoid this.

§Examples
let world_name = client.component::<WorldName>();
Source

pub fn get_component<T: Component>( &self, ) -> Option<MappedRwLockReadGuard<'_, T>>

Get a component on this client, or None if it doesn’t exist.

If the component is guaranteed to be present, consider using Self::component.

See Client::component for more details.

Source

pub fn query_self<D: QueryData, R>( &self, f: impl FnOnce(QueryItem<'_, '_, D>) -> R, ) -> R

Query the ECS for data from the entity.

You can use this to mutate data on the entity.

Also see Client::query_self and Client::query_entity.

§Panics

This will panic if the entity doesn’t exist or is missing a component required by the query. Consider using Self::try_query_self to avoid this.

Source

pub fn try_query_self<D: QueryData, R>( &self, f: impl FnOnce(QueryItem<'_, '_, D>) -> R, ) -> Result<R, QueryEntityError>

Query the ECS for data from the entity, or return an error if the query fails.

Also see Self::query_self.

Source§

impl EntityRef

Source

pub fn kind(&self) -> EntityKind

Returns the type of entity that this is.

Source§

impl EntityRef

Source

pub fn attack(&self)

Attack this entity from the client that created this EntityRef.

Also see Client::attack.

Examples found in repository?
azalea/examples/testbot/killaura.rs (line 29)
9pub fn tick(bot: Client, state: State) -> anyhow::Result<()> {
10    if !state.killaura {
11        return Ok(());
12    }
13    if bot.has_attack_cooldown() {
14        return Ok(());
15    }
16    let bot_position = bot.eye_position();
17
18    let nearest_entity = bot.nearest_entity_by::<&Position, (
19        With<AbstractMonster>,
20        Without<LocalEntity>,
21        Without<Dead>,
22    )>(|position: &Position| {
23        let distance = bot_position.distance_to(**position);
24        distance < 4.
25    });
26
27    if let Some(nearest_entity) = nearest_entity {
28        println!("attacking {nearest_entity:?}");
29        nearest_entity.attack();
30    }
31
32    Ok(())
33}
Source

pub fn interact(&self)

Right-click this entity from the client that created this EntityRef.

See Client::entity_interact for more information.

Source

pub fn look_at(&self)

Look at this entity from the client that created the EntityRef.

Source

pub fn distance_to_client(&self) -> f64

Returns the distance between the client’s feet position and this entity’s feet position.

Trait Implementations§

Source§

impl Clone for EntityRef

Source§

fn clone(&self) -> EntityRef

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for EntityRef

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> CompatExt for T

§

fn compat(self) -> Compat<T>

Applies the [Compat] adapter by value. Read more
§

fn compat_ref(&self) -> Compat<&T>

Applies the [Compat] adapter by shared reference. Read more
§

fn compat_mut(&mut self) -> Compat<&mut T>

Applies the [Compat] adapter by mutable reference. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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
where T: Any + Send,

§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> IntoResult<T> for T

§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
§

impl<A> Is for A
where A: Any,

§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

§

fn clone_type_data(&self) -> Box<dyn TypeData>

Creates a type-erased clone of this value.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ConditionalSend for T
where T: Send,