Skip to main content

ItemStack

Enum ItemStack 

pub enum ItemStack {
    Empty,
    Present(ItemStackData),
}
Expand description

Either an item in an inventory or nothing.

Variants§

§

Empty

§

Present(ItemStackData)

Implementations§

§

impl ItemStack

pub fn new(item: ItemKind, count: i32) -> ItemStack

Create a new ItemStack with the given number of ItemKinds.

If item is air or the count isn’t positive, then it’ll be set to an empty ItemStack.

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.

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

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

Remove count items from this slot, returning the removed items.

pub fn kind(&self) -> ItemKind

Get the kind of the item in this slot, or ItemKind::Air

Examples found in repository?
azalea/examples/nearest_entity.rs (line 71)
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)

Update whether this slot is empty, based on the count.

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 get_component<'a, T>(&'a self) -> Option<Cow<'a, T>>

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?
azalea/examples/testbot/commands/debug.rs (line 248)
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("pathfinderstate").executes(|ctx: &Ctx| {
172        let source = ctx.source.lock();
173        let pathfinder = source.bot.get_component::<Pathfinder>();
174        let Some(pathfinder) = pathfinder else {
175            source.reply("I don't have the Pathfinder component");
176            return 1;
177        };
178        source.reply(format!(
179            "pathfinder.is_calculating: {}",
180            pathfinder.is_calculating
181        ));
182
183        let executing_path = source.bot.get_component::<ExecutingPath>();
184        let Some(executing_path) = executing_path else {
185            source.reply("I'm not executing a path");
186            return 1;
187        };
188        source.reply(format!(
189            "is_path_partial: {}, path.len: {}, queued_path.len: {}",
190            executing_path.is_path_partial,
191            executing_path.path.len(),
192            if let Some(queued) = &executing_path.queued_path {
193                queued.len().to_string()
194            } else {
195                "n/a".to_owned()
196            },
197        ));
198        1
199    }));
200    commands.register(literal("pathfindermoves").executes(|ctx: &Ctx| {
201        let source = ctx.source.lock();
202
203        let Some(entity) = source.entity() else {
204            source.reply("You aren't in render distance!");
205            return 0;
206        };
207        let position = entity.position();
208        let position = BlockPos::from(position);
209
210        let mut edges = Vec::new();
211        let cached_world = CachedWorld::new(source.bot.world(), position);
212        let mining_cache = MiningCache::new(Some(Menu::Player(inventory::Player::default())));
213        let custom_state = CustomPathfinderStateRef::default();
214
215        azalea::pathfinder::moves::default_move(
216            &mut MovesCtx {
217                edges: &mut edges,
218                world: &cached_world,
219                mining_cache: &mining_cache,
220                custom_state: &custom_state,
221            },
222            RelBlockPos::from_origin(position, position),
223        );
224
225        if edges.is_empty() {
226            source.reply("No possible moves.");
227        } else {
228            source.reply("Moves:");
229            for (i, edge) in edges.iter().enumerate() {
230                source.reply(format!("{}) {edge:?}", i + 1));
231            }
232        }
233
234        1
235    }));
236
237    commands.register(literal("startuseitem").executes(|ctx: &Ctx| {
238        let source = ctx.source.lock();
239        source.bot.start_use_item();
240        source.reply("Ok!");
241        1
242    }));
243    commands.register(literal("maxstacksize").executes(|ctx: &Ctx| {
244        let source = ctx.source.lock();
245        let max_stack_size = source
246            .bot
247            .get_held_item()
248            .get_component::<MaxStackSize>()
249            .map_or(-1, |s| s.count);
250        source.reply(format!("{max_stack_size}"));
251        1
252    }));
253
254    commands.register(literal("dimensions").executes(|ctx: &Ctx| {
255        let source = ctx.source.lock();
256        let bot_dimensions = source.bot.dimensions();
257        source.reply(format!("{bot_dimensions:?}"));
258        1
259    }));
260
261    commands.register(literal("players").executes(|ctx: &Ctx| {
262        let source = ctx.source.lock();
263        let player_entities = source
264            .bot
265            .nearest_entities_by::<(), With<metadata::Player>>(|_: ()| true);
266        let tab_list = source.bot.tab_list();
267        for player_entity in player_entities {
268            let uuid = player_entity.uuid();
269            source.reply(format!(
270                "{} - {} ({:?})",
271                player_entity.id(),
272                tab_list.get(&uuid).map_or("?", |p| p.profile.name.as_str()),
273                uuid
274            ));
275        }
276        1
277    }));
278
279    commands.register(literal("enchants").executes(|ctx: &Ctx| {
280        let source = ctx.source.lock();
281        source.bot.with_registry_holder(|r| {
282            let enchants = &r.enchantment;
283            println!("enchants: {enchants:?}");
284        });
285        1
286    }));
287
288    commands.register(literal("attributes").executes(|ctx: &Ctx| {
289        let source = ctx.source.lock();
290        let attributes = source.bot.attributes();
291        println!("attributes: {attributes:?}");
292        1
293    }));
294
295    commands.register(literal("debugecsleak").executes(|ctx: &Ctx| {
296        let source = ctx.source.lock();
297
298        source.reply("Ok!");
299
300
301
302        source.bot.disconnect();
303
304        let ecs = source.bot.ecs.clone();
305        thread::spawn(move || {
306            thread::sleep(Duration::from_secs(1));
307            // dump the ecs
308
309            let mut ecs = ecs.write();
310
311            let report_path = env::temp_dir().join("azalea-ecs-leak-report.txt");
312            let mut report = File::create(&report_path).unwrap();
313
314            let mut query = ecs.query::<EntityRef>();
315            for entity in query.iter(& ecs) {
316                writeln!(report, "Entity: {}", entity.id()).unwrap();
317                let archetype = entity.archetype();
318                let component_count = archetype.component_count();
319
320                let component_names = archetype
321                    .components()
322                    .iter()
323                    .map(|c| ecs.components().get_info(*c).unwrap().name().to_string())
324                    .collect::<Vec<_>>();
325                writeln!(
326                    report,
327                    "- {component_count} components: {}",
328                    component_names.join(", ")
329                )
330                .unwrap();
331            }
332
333            writeln!(report).unwrap();
334
335
336            for (info, _) in ecs.iter_resources() {
337                let name = info.name().to_string();
338                writeln!(report, "Resource: {name}").unwrap();
339                // writeln!(report, "- Size: {} bytes",
340                // info.layout().size()).unwrap();
341
342                match name.as_ref() {
343                    "azalea_world::container::Worlds" => {
344                        let worlds = ecs.resource::<Worlds>();
345
346                        for (world_name, world) in &worlds.map {
347                            writeln!(report, "- Name: {world_name}").unwrap();
348                            writeln!(report, "- Reference count: {}", world.strong_count())
349                                .unwrap();
350                            if let Some(world) = world.upgrade() {
351                                let world = world.read();
352                                let chunks = &world.chunks;
353                                let chunks = (chunks as &dyn Any).downcast_ref::<WeakChunkStorage>();
354                                if let Some(chunks) = chunks {
355                                    let strong_chunks = chunks
356                                        .map
357                                        .iter()
358                                        .filter(|(_, v)| v.strong_count() > 0)
359                                        .count();
360                                    writeln!(
361                                        report,
362                                        "- Chunks: {} strongly referenced, {} in map",
363                                        strong_chunks,
364                                        chunks.map.len()
365                                    )
366                                    .unwrap();
367                                }
368                                writeln!(
369                                    report,
370                                    "- Entities: {}",
371                                    world.entities_by_chunk.len()
372                                )
373                                .unwrap();
374                            }
375                        }
376                    }
377                    "bevy_ecs::message::Messages<azalea_client::packet::game::ReceivePacketEvent>" => {
378                        let events = ecs.resource::<Messages<game::ReceiveGamePacketEvent>>();
379                        writeln!(report, "- Event count: {}", events.len()).unwrap();
380                    }
381                    "bevy_ecs::message::Messages<azalea_client::chunks::ReceiveChunkEvent>" => {
382                        let events = ecs.resource::<Messages<ReceiveChunkEvent>>();
383                        writeln!(report, "- Event count: {}", events.len()).unwrap();
384                    }
385
386                    _ => {}
387                }
388            }
389
390            println!("\x1b[1mWrote report to {}\x1b[m", report_path.display());
391        });
392
393        1
394    }));
395
396    commands.register(literal("exit").executes(|ctx: &Ctx| {
397        let source = ctx.source.lock();
398        source.reply("bye!");
399
400        source.bot.disconnect();
401
402        let source = ctx.source.clone();
403        thread::spawn(move || {
404            thread::sleep(Duration::from_secs(1));
405
406            source
407                .lock()
408                .bot
409                .ecs
410                .write()
411                .write_message(AppExit::Success);
412        });
413
414        1
415    }));
416}

pub fn with_component<T>(self, component: impl Into<Option<T>>) -> ItemStack

Trait Implementations§

§

impl AzBuf for ItemStack

§

fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<ItemStack, BufReadError>

§

fn azalea_write(&self, buf: &mut impl Write) -> Result<(), Error>

§

impl Clone for ItemStack

§

fn clone(&self) -> ItemStack

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
§

impl Debug for ItemStack

§

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

Formats the value using the given formatter. Read more
§

impl Default for ItemStack

§

fn default() -> ItemStack

Returns the “default value” for a type. Read more
§

impl From<(ItemKind, i32)> for ItemStack

§

fn from(item: (ItemKind, i32)) -> ItemStack

Converts to this type from the input type.
§

impl From<ItemKind> for ItemStack

§

fn from(item: ItemKind) -> ItemStack

Converts to this type from the input type.
§

impl From<ItemStackData> for ItemStack

§

fn from(item: ItemStackData) -> ItemStack

Converts to this type from the input type.
§

impl PartialEq for ItemStack

§

fn eq(&self, other: &ItemStack) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl Serialize for ItemStack

§

fn serialize<S>( &self, serializer: S, ) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more
§

impl StructuralPartialEq for ItemStack

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> FromWorld for T
where T: Default,

§

fn from_world(_world: &mut World) -> T

Creates Self using default().

§

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> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

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,