pub struct ItemFrameItem(pub ItemStack);Expand description
A metadata field for ItemFrame.
Tuple Fields§
§0: ItemStackMethods from Deref<Target = ItemStack>§
pub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Check if the slot is ItemStack::Empty, if the count is <= 0, or if the item is air.
This is the opposite of [ItemStack::is_present].
Examples found in repository?
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 commands.register(
33 literal("say").then(argument("message", greedy_string()).executes(|ctx: &Ctx| {
34 let source = ctx.source.lock();
35 let message = get_string(ctx, "message").unwrap();
36 source.bot.chat(message);
37 1
38 })),
39 );
40
41 commands.register(literal("disconnect").executes(|ctx: &Ctx| {
42 let source = ctx.source.lock();
43 source.bot.disconnect();
44 1
45 }));
46
47 commands.register(literal("whereami").executes(|ctx: &Ctx| {
48 let source = ctx.source.lock();
49 let Some(entity) = source.entity() else {
50 source.reply("You aren't in render distance!");
51 return 0;
52 };
53 let position = entity.position();
54 source.reply(format!(
55 "You are at {}, {}, {}",
56 position.x, position.y, position.z
57 ));
58 1
59 }));
60
61 commands.register(literal("entityid").executes(|ctx: &Ctx| {
62 let source = ctx.source.lock();
63 let Some(entity) = source.entity() else {
64 source.reply("You aren't in render distance!");
65 return 0;
66 };
67 let entity_id = entity.minecraft_id();
68 source.reply(format!(
69 "Your Minecraft ID is {} and your ECS ID is {entity:?}",
70 *entity_id
71 ));
72 1
73 }));
74
75 let whereareyou = |ctx: &Ctx| {
76 let source = ctx.source.lock();
77 let position = source.bot.position();
78 source.reply(format!(
79 "I'm at {}, {}, {}",
80 position.x, position.y, position.z
81 ));
82 1
83 };
84 commands.register(literal("whereareyou").executes(whereareyou));
85 commands.register(literal("pos").executes(whereareyou));
86
87 commands.register(literal("whoareyou").executes(|ctx: &Ctx| {
88 let source = ctx.source.lock();
89 source.reply(format!(
90 "I am {} ({}, {})",
91 source.bot.username(),
92 source.bot.uuid(),
93 source.bot.entity
94 ));
95 1
96 }));
97
98 commands.register(literal("getdirection").executes(|ctx: &Ctx| {
99 let source = ctx.source.lock();
100 let direction = source.bot.direction();
101 source.reply(format!(
102 "I'm looking at {}, {}",
103 direction.y_rot(),
104 direction.x_rot()
105 ));
106 1
107 }));
108
109 commands.register(literal("health").executes(|ctx: &Ctx| {
110 let source = ctx.source.lock();
111
112 let health = source.bot.health();
113 source.reply(format!("I have {health} health"));
114 1
115 }));
116
117 commands.register(literal("lookingat").executes(|ctx: &Ctx| {
118 let source = ctx.source.lock();
119
120 let hit_result = source.bot.hit_result();
121
122 match &hit_result {
123 HitResult::Block(r) => {
124 if r.miss {
125 source.reply("I'm not looking at anything");
126 return 0;
127 }
128 let block_pos = r.block_pos;
129 let block = source.bot.world().read().get_block_state(block_pos);
130 source.reply(format!("I'm looking at {block:?} at {block_pos:?}"));
131 }
132 HitResult::Entity(r) => {
133 let entity_kind = **source.bot.entity_component::<EntityKindComponent>(r.entity);
134 source.reply(format!(
135 "I'm looking at {entity_kind} ({:?}) at {}",
136 r.entity, r.location
137 ));
138 }
139 }
140
141 1
142 }));
143
144 commands.register(literal("getblock").then(argument("x", integer()).then(
145 argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
146 let source = ctx.source.lock();
147 let x = get_integer(ctx, "x").unwrap();
148 let y = get_integer(ctx, "y").unwrap();
149 let z = get_integer(ctx, "z").unwrap();
150 println!("getblock xyz {x} {y} {z}");
151 let block_pos = BlockPos::new(x, y, z);
152 let block = source.bot.world().read().get_block_state(block_pos);
153 source.reply(format!("BlockKind at {block_pos} is {block:?}"));
154 1
155 })),
156 )));
157 commands.register(literal("getfluid").then(argument("x", integer()).then(
158 argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
159 let source = ctx.source.lock();
160 let x = get_integer(ctx, "x").unwrap();
161 let y = get_integer(ctx, "y").unwrap();
162 let z = get_integer(ctx, "z").unwrap();
163 println!("getfluid xyz {x} {y} {z}");
164 let block_pos = BlockPos::new(x, y, z);
165 let block = source.bot.world().read().get_fluid_state(block_pos);
166 source.reply(format!("Fluid at {block_pos} is {block:?}"));
167 1
168 })),
169 )));
170
171 commands.register(literal("inventory").executes(|ctx: &Ctx| {
172 let source = ctx.source.lock();
173 for item in source.bot.menu().slots() {
174 if item.is_empty() {
175 continue;
176 }
177 println!("{item:?}");
178 for (kind, data) in item.component_patch().iter() {
179 if let Some(data) = data {
180 println!("- {kind} {data:?}");
181 }
182 }
183 }
184 1
185 }));
186
187 commands.register(literal("pathfinderstate").executes(|ctx: &Ctx| {
188 let source = ctx.source.lock();
189 let pathfinder = source.bot.get_component::<Pathfinder>();
190 let Some(pathfinder) = pathfinder else {
191 source.reply("I don't have the Pathfinder component");
192 return 1;
193 };
194 source.reply(format!(
195 "pathfinder.is_calculating: {}",
196 pathfinder.is_calculating
197 ));
198
199 let executing_path = source.bot.get_component::<ExecutingPath>();
200 let Some(executing_path) = executing_path else {
201 source.reply("I'm not executing a path");
202 return 1;
203 };
204 source.reply(format!(
205 "is_path_partial: {}, path.len: {}, queued_path.len: {}",
206 executing_path.is_path_partial,
207 executing_path.path.len(),
208 if let Some(queued) = &executing_path.queued_path {
209 queued.len().to_string()
210 } else {
211 "n/a".to_owned()
212 },
213 ));
214 1
215 }));
216 commands.register(literal("pathfindermoves").executes(|ctx: &Ctx| {
217 let source = ctx.source.lock();
218
219 let Some(entity) = source.entity() else {
220 source.reply("You aren't in render distance!");
221 return 0;
222 };
223 let position = entity.position();
224 let position = BlockPos::from(position);
225
226 let mut edges = Vec::new();
227 let cached_world = CachedWorld::new(source.bot.world(), position);
228 let mining_cache = MiningCache::new(Some(Menu::Player(inventory::Player::default())));
229 let custom_state = CustomPathfinderStateRef::default();
230
231 azalea::pathfinder::moves::default_move(
232 &mut MovesCtx {
233 edges: &mut edges,
234 world: &cached_world,
235 mining_cache: &mining_cache,
236 custom_state: &custom_state,
237 },
238 RelBlockPos::from_origin(position, position),
239 );
240
241 if edges.is_empty() {
242 source.reply("No possible moves.");
243 } else {
244 source.reply("Moves:");
245 for (i, edge) in edges.iter().enumerate() {
246 source.reply(format!("{}) {edge:?}", i + 1));
247 }
248 }
249
250 1
251 }));
252
253 commands.register(literal("startuseitem").executes(|ctx: &Ctx| {
254 let source = ctx.source.lock();
255 source.bot.start_use_item();
256 source.reply("Ok!");
257 1
258 }));
259 commands.register(literal("maxstacksize").executes(|ctx: &Ctx| {
260 let source = ctx.source.lock();
261 let max_stack_size = source
262 .bot
263 .get_held_item()
264 .get_component::<MaxStackSize>()
265 .map_or(-1, |s| s.count);
266 source.reply(format!("{max_stack_size}"));
267 1
268 }));
269
270 commands.register(literal("dimensions").executes(|ctx: &Ctx| {
271 let source = ctx.source.lock();
272 let bot_dimensions = source.bot.dimensions();
273 source.reply(format!("{bot_dimensions:?}"));
274 1
275 }));
276
277 commands.register(literal("players").executes(|ctx: &Ctx| {
278 let source = ctx.source.lock();
279 let player_entities = source
280 .bot
281 .nearest_entities_by::<(), With<metadata::Player>>(|_: ()| true);
282 let tab_list = source.bot.tab_list();
283 for player_entity in player_entities {
284 let uuid = player_entity.uuid();
285 source.reply(format!(
286 "{} - {} ({:?})",
287 player_entity.id(),
288 tab_list.get(&uuid).map_or("?", |p| p.profile.name.as_str()),
289 uuid
290 ));
291 }
292 1
293 }));
294
295 commands.register(literal("enchants").executes(|ctx: &Ctx| {
296 let source = ctx.source.lock();
297 source.bot.with_registry_holder(|r| {
298 let enchants = &r.enchantment;
299 println!("enchants: {enchants:?}");
300 });
301 1
302 }));
303
304 commands.register(literal("attributes").executes(|ctx: &Ctx| {
305 let source = ctx.source.lock();
306 let attributes = source.bot.attributes();
307 println!("attributes: {attributes:?}");
308 1
309 }));
310
311 commands.register(literal("debugecsleak").executes(|ctx: &Ctx| {
312 let source = ctx.source.lock();
313
314 source.reply("Ok!");
315
316
317
318 source.bot.disconnect();
319
320 let ecs = source.bot.ecs.clone();
321 thread::spawn(move || {
322 thread::sleep(Duration::from_secs(1));
323 // dump the ecs
324
325 let mut ecs = ecs.write();
326
327 let report_path = env::temp_dir().join("azalea-ecs-leak-report.txt");
328 let mut report = File::create(&report_path).unwrap();
329
330 let mut query = ecs.query::<EntityRef>();
331 for entity in query.iter(& ecs) {
332 writeln!(report, "Entity: {}", entity.id()).unwrap();
333 let archetype = entity.archetype();
334 let component_count = archetype.component_count();
335
336 let component_names = archetype
337 .components()
338 .iter()
339 .map(|c| ecs.components().get_info(*c).unwrap().name().to_string())
340 .collect::<Vec<_>>();
341 writeln!(
342 report,
343 "- {component_count} components: {}",
344 component_names.join(", ")
345 )
346 .unwrap();
347 }
348
349 writeln!(report).unwrap();
350
351
352 for (info, _) in ecs.iter_resources() {
353 let name = info.name().to_string();
354 writeln!(report, "Resource: {name}").unwrap();
355 // writeln!(report, "- Size: {} bytes",
356 // info.layout().size()).unwrap();
357
358 match name.as_ref() {
359 "azalea_world::container::Worlds" => {
360 let worlds = ecs.resource::<Worlds>();
361
362 for (world_name, world) in &worlds.map {
363 writeln!(report, "- Name: {world_name}").unwrap();
364 writeln!(report, "- Reference count: {}", world.strong_count())
365 .unwrap();
366 if let Some(world) = world.upgrade() {
367 let world = world.read();
368 let chunks = &world.chunks;
369 let chunks = (chunks as &dyn Any).downcast_ref::<WeakChunkStorage>();
370 if let Some(chunks) = chunks {
371 let strong_chunks = chunks
372 .map
373 .iter()
374 .filter(|(_, v)| v.strong_count() > 0)
375 .count();
376 writeln!(
377 report,
378 "- Chunks: {} strongly referenced, {} in map",
379 strong_chunks,
380 chunks.map.len()
381 )
382 .unwrap();
383 }
384 writeln!(
385 report,
386 "- Entities: {}",
387 world.entities_by_chunk.len()
388 )
389 .unwrap();
390 }
391 }
392 }
393 "bevy_ecs::message::Messages<azalea_client::packet::game::ReceivePacketEvent>" => {
394 let events = ecs.resource::<Messages<game::ReceiveGamePacketEvent>>();
395 writeln!(report, "- Event count: {}", events.len()).unwrap();
396 }
397 "bevy_ecs::message::Messages<azalea_client::chunks::ReceiveChunkEvent>" => {
398 let events = ecs.resource::<Messages<ReceiveChunkEvent>>();
399 writeln!(report, "- Event count: {}", events.len()).unwrap();
400 }
401
402 _ => {}
403 }
404 }
405
406 println!("\x1b[1mWrote report to {}\x1b[m", report_path.display());
407 });
408
409 1
410 }));
411
412 commands.register(literal("exit").executes(|ctx: &Ctx| {
413 let source = ctx.source.lock();
414 source.reply("bye!");
415
416 source.bot.disconnect();
417
418 let source = ctx.source.clone();
419 thread::spawn(move || {
420 thread::sleep(Duration::from_secs(1));
421
422 source
423 .lock()
424 .bot
425 .ecs
426 .write()
427 .write_message(AppExit::Success);
428 });
429
430 1
431 }));
432}pub fn is_present(&self) -> bool
pub fn is_present(&self) -> bool
Check if the slot is not ItemStack::Empty, if the count is > 0, and if the item is not air.
This is the opposite of [ItemStack::is_empty].
pub fn count(&self) -> i32
pub fn count(&self) -> i32
Return the amount of the item in the slot, or 0 if the slot is empty.
Note that it’s possible for the count to be zero or negative when the slot is present.
pub fn split(&mut self, count: u32) -> ItemStack
pub fn split(&mut self, count: u32) -> ItemStack
Remove count items from this slot, returning the removed items.
pub fn kind(&self) -> ItemKind
pub fn kind(&self) -> ItemKind
Get the kind of the item in this slot, or ItemKind::Air
Examples found in repository?
63fn log_nearby_item_drops(
64 bots: Query<Entity, With<Bot>>,
65 entities: EntityFinder<With<ItemItem>>,
66 item_drops: Query<&ItemItem>,
67) {
68 for bot_id in bots.iter() {
69 for (entity, distance) in entities.nearby_entities_to_entity(bot_id, 8.0) {
70 let item_drop = item_drops.get(entity).unwrap();
71 let kind = item_drop.kind();
72
73 println!("Bot {bot_id:?} can see an {kind:?} {distance:.1} meters away.");
74 }
75 }
76}pub fn update_empty(&mut self)
pub fn update_empty(&mut self)
Update whether this slot is empty, based on the count.
pub fn as_present(&self) -> Option<&ItemStackData>
pub fn as_present(&self) -> Option<&ItemStackData>
Convert this slot into an [ItemStackData], if it’s present.
pub fn as_present_mut(&mut self) -> Option<&mut ItemStackData>
pub fn component_patch(&self) -> &DataComponentPatch
pub fn component_patch(&self) -> &DataComponentPatch
Examples found in repository?
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 commands.register(
33 literal("say").then(argument("message", greedy_string()).executes(|ctx: &Ctx| {
34 let source = ctx.source.lock();
35 let message = get_string(ctx, "message").unwrap();
36 source.bot.chat(message);
37 1
38 })),
39 );
40
41 commands.register(literal("disconnect").executes(|ctx: &Ctx| {
42 let source = ctx.source.lock();
43 source.bot.disconnect();
44 1
45 }));
46
47 commands.register(literal("whereami").executes(|ctx: &Ctx| {
48 let source = ctx.source.lock();
49 let Some(entity) = source.entity() else {
50 source.reply("You aren't in render distance!");
51 return 0;
52 };
53 let position = entity.position();
54 source.reply(format!(
55 "You are at {}, {}, {}",
56 position.x, position.y, position.z
57 ));
58 1
59 }));
60
61 commands.register(literal("entityid").executes(|ctx: &Ctx| {
62 let source = ctx.source.lock();
63 let Some(entity) = source.entity() else {
64 source.reply("You aren't in render distance!");
65 return 0;
66 };
67 let entity_id = entity.minecraft_id();
68 source.reply(format!(
69 "Your Minecraft ID is {} and your ECS ID is {entity:?}",
70 *entity_id
71 ));
72 1
73 }));
74
75 let whereareyou = |ctx: &Ctx| {
76 let source = ctx.source.lock();
77 let position = source.bot.position();
78 source.reply(format!(
79 "I'm at {}, {}, {}",
80 position.x, position.y, position.z
81 ));
82 1
83 };
84 commands.register(literal("whereareyou").executes(whereareyou));
85 commands.register(literal("pos").executes(whereareyou));
86
87 commands.register(literal("whoareyou").executes(|ctx: &Ctx| {
88 let source = ctx.source.lock();
89 source.reply(format!(
90 "I am {} ({}, {})",
91 source.bot.username(),
92 source.bot.uuid(),
93 source.bot.entity
94 ));
95 1
96 }));
97
98 commands.register(literal("getdirection").executes(|ctx: &Ctx| {
99 let source = ctx.source.lock();
100 let direction = source.bot.direction();
101 source.reply(format!(
102 "I'm looking at {}, {}",
103 direction.y_rot(),
104 direction.x_rot()
105 ));
106 1
107 }));
108
109 commands.register(literal("health").executes(|ctx: &Ctx| {
110 let source = ctx.source.lock();
111
112 let health = source.bot.health();
113 source.reply(format!("I have {health} health"));
114 1
115 }));
116
117 commands.register(literal("lookingat").executes(|ctx: &Ctx| {
118 let source = ctx.source.lock();
119
120 let hit_result = source.bot.hit_result();
121
122 match &hit_result {
123 HitResult::Block(r) => {
124 if r.miss {
125 source.reply("I'm not looking at anything");
126 return 0;
127 }
128 let block_pos = r.block_pos;
129 let block = source.bot.world().read().get_block_state(block_pos);
130 source.reply(format!("I'm looking at {block:?} at {block_pos:?}"));
131 }
132 HitResult::Entity(r) => {
133 let entity_kind = **source.bot.entity_component::<EntityKindComponent>(r.entity);
134 source.reply(format!(
135 "I'm looking at {entity_kind} ({:?}) at {}",
136 r.entity, r.location
137 ));
138 }
139 }
140
141 1
142 }));
143
144 commands.register(literal("getblock").then(argument("x", integer()).then(
145 argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
146 let source = ctx.source.lock();
147 let x = get_integer(ctx, "x").unwrap();
148 let y = get_integer(ctx, "y").unwrap();
149 let z = get_integer(ctx, "z").unwrap();
150 println!("getblock xyz {x} {y} {z}");
151 let block_pos = BlockPos::new(x, y, z);
152 let block = source.bot.world().read().get_block_state(block_pos);
153 source.reply(format!("BlockKind at {block_pos} is {block:?}"));
154 1
155 })),
156 )));
157 commands.register(literal("getfluid").then(argument("x", integer()).then(
158 argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
159 let source = ctx.source.lock();
160 let x = get_integer(ctx, "x").unwrap();
161 let y = get_integer(ctx, "y").unwrap();
162 let z = get_integer(ctx, "z").unwrap();
163 println!("getfluid xyz {x} {y} {z}");
164 let block_pos = BlockPos::new(x, y, z);
165 let block = source.bot.world().read().get_fluid_state(block_pos);
166 source.reply(format!("Fluid at {block_pos} is {block:?}"));
167 1
168 })),
169 )));
170
171 commands.register(literal("inventory").executes(|ctx: &Ctx| {
172 let source = ctx.source.lock();
173 for item in source.bot.menu().slots() {
174 if item.is_empty() {
175 continue;
176 }
177 println!("{item:?}");
178 for (kind, data) in item.component_patch().iter() {
179 if let Some(data) = data {
180 println!("- {kind} {data:?}");
181 }
182 }
183 }
184 1
185 }));
186
187 commands.register(literal("pathfinderstate").executes(|ctx: &Ctx| {
188 let source = ctx.source.lock();
189 let pathfinder = source.bot.get_component::<Pathfinder>();
190 let Some(pathfinder) = pathfinder else {
191 source.reply("I don't have the Pathfinder component");
192 return 1;
193 };
194 source.reply(format!(
195 "pathfinder.is_calculating: {}",
196 pathfinder.is_calculating
197 ));
198
199 let executing_path = source.bot.get_component::<ExecutingPath>();
200 let Some(executing_path) = executing_path else {
201 source.reply("I'm not executing a path");
202 return 1;
203 };
204 source.reply(format!(
205 "is_path_partial: {}, path.len: {}, queued_path.len: {}",
206 executing_path.is_path_partial,
207 executing_path.path.len(),
208 if let Some(queued) = &executing_path.queued_path {
209 queued.len().to_string()
210 } else {
211 "n/a".to_owned()
212 },
213 ));
214 1
215 }));
216 commands.register(literal("pathfindermoves").executes(|ctx: &Ctx| {
217 let source = ctx.source.lock();
218
219 let Some(entity) = source.entity() else {
220 source.reply("You aren't in render distance!");
221 return 0;
222 };
223 let position = entity.position();
224 let position = BlockPos::from(position);
225
226 let mut edges = Vec::new();
227 let cached_world = CachedWorld::new(source.bot.world(), position);
228 let mining_cache = MiningCache::new(Some(Menu::Player(inventory::Player::default())));
229 let custom_state = CustomPathfinderStateRef::default();
230
231 azalea::pathfinder::moves::default_move(
232 &mut MovesCtx {
233 edges: &mut edges,
234 world: &cached_world,
235 mining_cache: &mining_cache,
236 custom_state: &custom_state,
237 },
238 RelBlockPos::from_origin(position, position),
239 );
240
241 if edges.is_empty() {
242 source.reply("No possible moves.");
243 } else {
244 source.reply("Moves:");
245 for (i, edge) in edges.iter().enumerate() {
246 source.reply(format!("{}) {edge:?}", i + 1));
247 }
248 }
249
250 1
251 }));
252
253 commands.register(literal("startuseitem").executes(|ctx: &Ctx| {
254 let source = ctx.source.lock();
255 source.bot.start_use_item();
256 source.reply("Ok!");
257 1
258 }));
259 commands.register(literal("maxstacksize").executes(|ctx: &Ctx| {
260 let source = ctx.source.lock();
261 let max_stack_size = source
262 .bot
263 .get_held_item()
264 .get_component::<MaxStackSize>()
265 .map_or(-1, |s| s.count);
266 source.reply(format!("{max_stack_size}"));
267 1
268 }));
269
270 commands.register(literal("dimensions").executes(|ctx: &Ctx| {
271 let source = ctx.source.lock();
272 let bot_dimensions = source.bot.dimensions();
273 source.reply(format!("{bot_dimensions:?}"));
274 1
275 }));
276
277 commands.register(literal("players").executes(|ctx: &Ctx| {
278 let source = ctx.source.lock();
279 let player_entities = source
280 .bot
281 .nearest_entities_by::<(), With<metadata::Player>>(|_: ()| true);
282 let tab_list = source.bot.tab_list();
283 for player_entity in player_entities {
284 let uuid = player_entity.uuid();
285 source.reply(format!(
286 "{} - {} ({:?})",
287 player_entity.id(),
288 tab_list.get(&uuid).map_or("?", |p| p.profile.name.as_str()),
289 uuid
290 ));
291 }
292 1
293 }));
294
295 commands.register(literal("enchants").executes(|ctx: &Ctx| {
296 let source = ctx.source.lock();
297 source.bot.with_registry_holder(|r| {
298 let enchants = &r.enchantment;
299 println!("enchants: {enchants:?}");
300 });
301 1
302 }));
303
304 commands.register(literal("attributes").executes(|ctx: &Ctx| {
305 let source = ctx.source.lock();
306 let attributes = source.bot.attributes();
307 println!("attributes: {attributes:?}");
308 1
309 }));
310
311 commands.register(literal("debugecsleak").executes(|ctx: &Ctx| {
312 let source = ctx.source.lock();
313
314 source.reply("Ok!");
315
316
317
318 source.bot.disconnect();
319
320 let ecs = source.bot.ecs.clone();
321 thread::spawn(move || {
322 thread::sleep(Duration::from_secs(1));
323 // dump the ecs
324
325 let mut ecs = ecs.write();
326
327 let report_path = env::temp_dir().join("azalea-ecs-leak-report.txt");
328 let mut report = File::create(&report_path).unwrap();
329
330 let mut query = ecs.query::<EntityRef>();
331 for entity in query.iter(& ecs) {
332 writeln!(report, "Entity: {}", entity.id()).unwrap();
333 let archetype = entity.archetype();
334 let component_count = archetype.component_count();
335
336 let component_names = archetype
337 .components()
338 .iter()
339 .map(|c| ecs.components().get_info(*c).unwrap().name().to_string())
340 .collect::<Vec<_>>();
341 writeln!(
342 report,
343 "- {component_count} components: {}",
344 component_names.join(", ")
345 )
346 .unwrap();
347 }
348
349 writeln!(report).unwrap();
350
351
352 for (info, _) in ecs.iter_resources() {
353 let name = info.name().to_string();
354 writeln!(report, "Resource: {name}").unwrap();
355 // writeln!(report, "- Size: {} bytes",
356 // info.layout().size()).unwrap();
357
358 match name.as_ref() {
359 "azalea_world::container::Worlds" => {
360 let worlds = ecs.resource::<Worlds>();
361
362 for (world_name, world) in &worlds.map {
363 writeln!(report, "- Name: {world_name}").unwrap();
364 writeln!(report, "- Reference count: {}", world.strong_count())
365 .unwrap();
366 if let Some(world) = world.upgrade() {
367 let world = world.read();
368 let chunks = &world.chunks;
369 let chunks = (chunks as &dyn Any).downcast_ref::<WeakChunkStorage>();
370 if let Some(chunks) = chunks {
371 let strong_chunks = chunks
372 .map
373 .iter()
374 .filter(|(_, v)| v.strong_count() > 0)
375 .count();
376 writeln!(
377 report,
378 "- Chunks: {} strongly referenced, {} in map",
379 strong_chunks,
380 chunks.map.len()
381 )
382 .unwrap();
383 }
384 writeln!(
385 report,
386 "- Entities: {}",
387 world.entities_by_chunk.len()
388 )
389 .unwrap();
390 }
391 }
392 }
393 "bevy_ecs::message::Messages<azalea_client::packet::game::ReceivePacketEvent>" => {
394 let events = ecs.resource::<Messages<game::ReceiveGamePacketEvent>>();
395 writeln!(report, "- Event count: {}", events.len()).unwrap();
396 }
397 "bevy_ecs::message::Messages<azalea_client::chunks::ReceiveChunkEvent>" => {
398 let events = ecs.resource::<Messages<ReceiveChunkEvent>>();
399 writeln!(report, "- Event count: {}", events.len()).unwrap();
400 }
401
402 _ => {}
403 }
404 }
405
406 println!("\x1b[1mWrote report to {}\x1b[m", report_path.display());
407 });
408
409 1
410 }));
411
412 commands.register(literal("exit").executes(|ctx: &Ctx| {
413 let source = ctx.source.lock();
414 source.reply("bye!");
415
416 source.bot.disconnect();
417
418 let source = ctx.source.clone();
419 thread::spawn(move || {
420 thread::sleep(Duration::from_secs(1));
421
422 source
423 .lock()
424 .bot
425 .ecs
426 .write()
427 .write_message(AppExit::Success);
428 });
429
430 1
431 }));
432}pub fn get_component<'a, T>(&'a self) -> Option<Cow<'a, T>>where
T: DataComponentTrait,
pub fn get_component<'a, T>(&'a self) -> Option<Cow<'a, T>>where
T: DataComponentTrait,
Get the value of a data component for this item.
This is used for things like getting the damage of an item, or seeing how much food it replenishes.
Examples found in repository?
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 commands.register(
33 literal("say").then(argument("message", greedy_string()).executes(|ctx: &Ctx| {
34 let source = ctx.source.lock();
35 let message = get_string(ctx, "message").unwrap();
36 source.bot.chat(message);
37 1
38 })),
39 );
40
41 commands.register(literal("disconnect").executes(|ctx: &Ctx| {
42 let source = ctx.source.lock();
43 source.bot.disconnect();
44 1
45 }));
46
47 commands.register(literal("whereami").executes(|ctx: &Ctx| {
48 let source = ctx.source.lock();
49 let Some(entity) = source.entity() else {
50 source.reply("You aren't in render distance!");
51 return 0;
52 };
53 let position = entity.position();
54 source.reply(format!(
55 "You are at {}, {}, {}",
56 position.x, position.y, position.z
57 ));
58 1
59 }));
60
61 commands.register(literal("entityid").executes(|ctx: &Ctx| {
62 let source = ctx.source.lock();
63 let Some(entity) = source.entity() else {
64 source.reply("You aren't in render distance!");
65 return 0;
66 };
67 let entity_id = entity.minecraft_id();
68 source.reply(format!(
69 "Your Minecraft ID is {} and your ECS ID is {entity:?}",
70 *entity_id
71 ));
72 1
73 }));
74
75 let whereareyou = |ctx: &Ctx| {
76 let source = ctx.source.lock();
77 let position = source.bot.position();
78 source.reply(format!(
79 "I'm at {}, {}, {}",
80 position.x, position.y, position.z
81 ));
82 1
83 };
84 commands.register(literal("whereareyou").executes(whereareyou));
85 commands.register(literal("pos").executes(whereareyou));
86
87 commands.register(literal("whoareyou").executes(|ctx: &Ctx| {
88 let source = ctx.source.lock();
89 source.reply(format!(
90 "I am {} ({}, {})",
91 source.bot.username(),
92 source.bot.uuid(),
93 source.bot.entity
94 ));
95 1
96 }));
97
98 commands.register(literal("getdirection").executes(|ctx: &Ctx| {
99 let source = ctx.source.lock();
100 let direction = source.bot.direction();
101 source.reply(format!(
102 "I'm looking at {}, {}",
103 direction.y_rot(),
104 direction.x_rot()
105 ));
106 1
107 }));
108
109 commands.register(literal("health").executes(|ctx: &Ctx| {
110 let source = ctx.source.lock();
111
112 let health = source.bot.health();
113 source.reply(format!("I have {health} health"));
114 1
115 }));
116
117 commands.register(literal("lookingat").executes(|ctx: &Ctx| {
118 let source = ctx.source.lock();
119
120 let hit_result = source.bot.hit_result();
121
122 match &hit_result {
123 HitResult::Block(r) => {
124 if r.miss {
125 source.reply("I'm not looking at anything");
126 return 0;
127 }
128 let block_pos = r.block_pos;
129 let block = source.bot.world().read().get_block_state(block_pos);
130 source.reply(format!("I'm looking at {block:?} at {block_pos:?}"));
131 }
132 HitResult::Entity(r) => {
133 let entity_kind = **source.bot.entity_component::<EntityKindComponent>(r.entity);
134 source.reply(format!(
135 "I'm looking at {entity_kind} ({:?}) at {}",
136 r.entity, r.location
137 ));
138 }
139 }
140
141 1
142 }));
143
144 commands.register(literal("getblock").then(argument("x", integer()).then(
145 argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
146 let source = ctx.source.lock();
147 let x = get_integer(ctx, "x").unwrap();
148 let y = get_integer(ctx, "y").unwrap();
149 let z = get_integer(ctx, "z").unwrap();
150 println!("getblock xyz {x} {y} {z}");
151 let block_pos = BlockPos::new(x, y, z);
152 let block = source.bot.world().read().get_block_state(block_pos);
153 source.reply(format!("BlockKind at {block_pos} is {block:?}"));
154 1
155 })),
156 )));
157 commands.register(literal("getfluid").then(argument("x", integer()).then(
158 argument("y", integer()).then(argument("z", integer()).executes(|ctx: &Ctx| {
159 let source = ctx.source.lock();
160 let x = get_integer(ctx, "x").unwrap();
161 let y = get_integer(ctx, "y").unwrap();
162 let z = get_integer(ctx, "z").unwrap();
163 println!("getfluid xyz {x} {y} {z}");
164 let block_pos = BlockPos::new(x, y, z);
165 let block = source.bot.world().read().get_fluid_state(block_pos);
166 source.reply(format!("Fluid at {block_pos} is {block:?}"));
167 1
168 })),
169 )));
170
171 commands.register(literal("inventory").executes(|ctx: &Ctx| {
172 let source = ctx.source.lock();
173 for item in source.bot.menu().slots() {
174 if item.is_empty() {
175 continue;
176 }
177 println!("{item:?}");
178 for (kind, data) in item.component_patch().iter() {
179 if let Some(data) = data {
180 println!("- {kind} {data:?}");
181 }
182 }
183 }
184 1
185 }));
186
187 commands.register(literal("pathfinderstate").executes(|ctx: &Ctx| {
188 let source = ctx.source.lock();
189 let pathfinder = source.bot.get_component::<Pathfinder>();
190 let Some(pathfinder) = pathfinder else {
191 source.reply("I don't have the Pathfinder component");
192 return 1;
193 };
194 source.reply(format!(
195 "pathfinder.is_calculating: {}",
196 pathfinder.is_calculating
197 ));
198
199 let executing_path = source.bot.get_component::<ExecutingPath>();
200 let Some(executing_path) = executing_path else {
201 source.reply("I'm not executing a path");
202 return 1;
203 };
204 source.reply(format!(
205 "is_path_partial: {}, path.len: {}, queued_path.len: {}",
206 executing_path.is_path_partial,
207 executing_path.path.len(),
208 if let Some(queued) = &executing_path.queued_path {
209 queued.len().to_string()
210 } else {
211 "n/a".to_owned()
212 },
213 ));
214 1
215 }));
216 commands.register(literal("pathfindermoves").executes(|ctx: &Ctx| {
217 let source = ctx.source.lock();
218
219 let Some(entity) = source.entity() else {
220 source.reply("You aren't in render distance!");
221 return 0;
222 };
223 let position = entity.position();
224 let position = BlockPos::from(position);
225
226 let mut edges = Vec::new();
227 let cached_world = CachedWorld::new(source.bot.world(), position);
228 let mining_cache = MiningCache::new(Some(Menu::Player(inventory::Player::default())));
229 let custom_state = CustomPathfinderStateRef::default();
230
231 azalea::pathfinder::moves::default_move(
232 &mut MovesCtx {
233 edges: &mut edges,
234 world: &cached_world,
235 mining_cache: &mining_cache,
236 custom_state: &custom_state,
237 },
238 RelBlockPos::from_origin(position, position),
239 );
240
241 if edges.is_empty() {
242 source.reply("No possible moves.");
243 } else {
244 source.reply("Moves:");
245 for (i, edge) in edges.iter().enumerate() {
246 source.reply(format!("{}) {edge:?}", i + 1));
247 }
248 }
249
250 1
251 }));
252
253 commands.register(literal("startuseitem").executes(|ctx: &Ctx| {
254 let source = ctx.source.lock();
255 source.bot.start_use_item();
256 source.reply("Ok!");
257 1
258 }));
259 commands.register(literal("maxstacksize").executes(|ctx: &Ctx| {
260 let source = ctx.source.lock();
261 let max_stack_size = source
262 .bot
263 .get_held_item()
264 .get_component::<MaxStackSize>()
265 .map_or(-1, |s| s.count);
266 source.reply(format!("{max_stack_size}"));
267 1
268 }));
269
270 commands.register(literal("dimensions").executes(|ctx: &Ctx| {
271 let source = ctx.source.lock();
272 let bot_dimensions = source.bot.dimensions();
273 source.reply(format!("{bot_dimensions:?}"));
274 1
275 }));
276
277 commands.register(literal("players").executes(|ctx: &Ctx| {
278 let source = ctx.source.lock();
279 let player_entities = source
280 .bot
281 .nearest_entities_by::<(), With<metadata::Player>>(|_: ()| true);
282 let tab_list = source.bot.tab_list();
283 for player_entity in player_entities {
284 let uuid = player_entity.uuid();
285 source.reply(format!(
286 "{} - {} ({:?})",
287 player_entity.id(),
288 tab_list.get(&uuid).map_or("?", |p| p.profile.name.as_str()),
289 uuid
290 ));
291 }
292 1
293 }));
294
295 commands.register(literal("enchants").executes(|ctx: &Ctx| {
296 let source = ctx.source.lock();
297 source.bot.with_registry_holder(|r| {
298 let enchants = &r.enchantment;
299 println!("enchants: {enchants:?}");
300 });
301 1
302 }));
303
304 commands.register(literal("attributes").executes(|ctx: &Ctx| {
305 let source = ctx.source.lock();
306 let attributes = source.bot.attributes();
307 println!("attributes: {attributes:?}");
308 1
309 }));
310
311 commands.register(literal("debugecsleak").executes(|ctx: &Ctx| {
312 let source = ctx.source.lock();
313
314 source.reply("Ok!");
315
316
317
318 source.bot.disconnect();
319
320 let ecs = source.bot.ecs.clone();
321 thread::spawn(move || {
322 thread::sleep(Duration::from_secs(1));
323 // dump the ecs
324
325 let mut ecs = ecs.write();
326
327 let report_path = env::temp_dir().join("azalea-ecs-leak-report.txt");
328 let mut report = File::create(&report_path).unwrap();
329
330 let mut query = ecs.query::<EntityRef>();
331 for entity in query.iter(& ecs) {
332 writeln!(report, "Entity: {}", entity.id()).unwrap();
333 let archetype = entity.archetype();
334 let component_count = archetype.component_count();
335
336 let component_names = archetype
337 .components()
338 .iter()
339 .map(|c| ecs.components().get_info(*c).unwrap().name().to_string())
340 .collect::<Vec<_>>();
341 writeln!(
342 report,
343 "- {component_count} components: {}",
344 component_names.join(", ")
345 )
346 .unwrap();
347 }
348
349 writeln!(report).unwrap();
350
351
352 for (info, _) in ecs.iter_resources() {
353 let name = info.name().to_string();
354 writeln!(report, "Resource: {name}").unwrap();
355 // writeln!(report, "- Size: {} bytes",
356 // info.layout().size()).unwrap();
357
358 match name.as_ref() {
359 "azalea_world::container::Worlds" => {
360 let worlds = ecs.resource::<Worlds>();
361
362 for (world_name, world) in &worlds.map {
363 writeln!(report, "- Name: {world_name}").unwrap();
364 writeln!(report, "- Reference count: {}", world.strong_count())
365 .unwrap();
366 if let Some(world) = world.upgrade() {
367 let world = world.read();
368 let chunks = &world.chunks;
369 let chunks = (chunks as &dyn Any).downcast_ref::<WeakChunkStorage>();
370 if let Some(chunks) = chunks {
371 let strong_chunks = chunks
372 .map
373 .iter()
374 .filter(|(_, v)| v.strong_count() > 0)
375 .count();
376 writeln!(
377 report,
378 "- Chunks: {} strongly referenced, {} in map",
379 strong_chunks,
380 chunks.map.len()
381 )
382 .unwrap();
383 }
384 writeln!(
385 report,
386 "- Entities: {}",
387 world.entities_by_chunk.len()
388 )
389 .unwrap();
390 }
391 }
392 }
393 "bevy_ecs::message::Messages<azalea_client::packet::game::ReceivePacketEvent>" => {
394 let events = ecs.resource::<Messages<game::ReceiveGamePacketEvent>>();
395 writeln!(report, "- Event count: {}", events.len()).unwrap();
396 }
397 "bevy_ecs::message::Messages<azalea_client::chunks::ReceiveChunkEvent>" => {
398 let events = ecs.resource::<Messages<ReceiveChunkEvent>>();
399 writeln!(report, "- Event count: {}", events.len()).unwrap();
400 }
401
402 _ => {}
403 }
404 }
405
406 println!("\x1b[1mWrote report to {}\x1b[m", report_path.display());
407 });
408
409 1
410 }));
411
412 commands.register(literal("exit").executes(|ctx: &Ctx| {
413 let source = ctx.source.lock();
414 source.reply("bye!");
415
416 source.bot.disconnect();
417
418 let source = ctx.source.clone();
419 thread::spawn(move || {
420 thread::sleep(Duration::from_secs(1));
421
422 source
423 .lock()
424 .bot
425 .ecs
426 .write()
427 .write_message(AppExit::Success);
428 });
429
430 1
431 }));
432}Trait Implementations§
Source§impl Clone for ItemFrameItem
impl Clone for ItemFrameItem
Source§fn clone(&self) -> ItemFrameItem
fn clone(&self) -> ItemFrameItem
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Component for ItemFrameItem
impl Component for ItemFrameItem
Source§const STORAGE_TYPE: StorageType = bevy_ecs::component::StorageType::Table
const STORAGE_TYPE: StorageType = bevy_ecs::component::StorageType::Table
Source§type Mutability = Mutable
type Mutability = Mutable
Component<Mutability = Mutable>],
while immutable components will instead have [Component<Mutability = Immutable>]. Read moreSource§fn register_required_components(
_requiree: ComponentId,
required_components: &mut RequiredComponentsRegistrator<'_, '_>,
)
fn register_required_components( _requiree: ComponentId, required_components: &mut RequiredComponentsRegistrator<'_, '_>, )
Source§fn clone_behavior() -> ComponentCloneBehavior
fn clone_behavior() -> ComponentCloneBehavior
Source§fn relationship_accessor() -> Option<ComponentRelationshipAccessor<Self>>
fn relationship_accessor() -> Option<ComponentRelationshipAccessor<Self>>
ComponentRelationshipAccessor] required for working with relationships in dynamic contexts. Read more§fn on_add() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_add() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
on_add [ComponentHook] for this [Component] if one is defined.§fn on_insert() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_insert() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
on_insert [ComponentHook] for this [Component] if one is defined.§fn on_replace() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_replace() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
on_replace [ComponentHook] for this [Component] if one is defined.§fn on_remove() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_remove() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
on_remove [ComponentHook] for this [Component] if one is defined.§fn on_despawn() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_despawn() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
on_despawn [ComponentHook] for this [Component] if one is defined.§fn map_entities<E>(_this: &mut Self, _mapper: &mut E)where
E: EntityMapper,
fn map_entities<E>(_this: &mut Self, _mapper: &mut E)where
E: EntityMapper,
EntityMapper]. This is used to remap entities in contexts like scenes and entity cloning.
When deriving [Component], this is populated by annotating fields containing entities with #[entities] Read moreSource§impl Deref for ItemFrameItem
impl Deref for ItemFrameItem
Source§impl DerefMut for ItemFrameItem
impl DerefMut for ItemFrameItem
Source§impl PartialEq for ItemFrameItem
impl PartialEq for ItemFrameItem
impl StructuralPartialEq for ItemFrameItem
Auto Trait Implementations§
impl Freeze for ItemFrameItem
impl RefUnwindSafe for ItemFrameItem
impl Send for ItemFrameItem
impl Sync for ItemFrameItem
impl Unpin for ItemFrameItem
impl UnsafeUnpin for ItemFrameItem
impl UnwindSafe for ItemFrameItem
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
§impl<C> Bundle for Cwhere
C: Component,
impl<C> Bundle for Cwhere
C: Component,
fn component_ids( components: &mut ComponentsRegistrator<'_>, ) -> impl Iterator<Item = ComponentId> + use<C>
§fn get_component_ids(
components: &Components,
) -> impl Iterator<Item = Option<ComponentId>>
fn get_component_ids( components: &Components, ) -> impl Iterator<Item = Option<ComponentId>>
Bundle]’s component ids. This will be None if the component has not been registered.§impl<C> BundleFromComponents for Cwhere
C: Component,
impl<C> BundleFromComponents for Cwhere
C: Component,
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.