Instance

Struct Instance 

Source
pub struct Instance {
    pub chunks: ChunkStorage,
    pub entities_by_chunk: HashMap<ChunkPos, HashSet<Entity>>,
    pub entity_by_id: IntMap<MinecraftEntityId, Entity>,
    pub registries: RegistryHolder,
}
Expand description

A world where the chunks are stored as weak pointers. This is used for shared worlds.

Also see PartialInstance.

This is sometimes interchangeably called a “world”. However, this type is called Instance to avoid colliding with the World type from Bevy ECS.

Fields§

§chunks: ChunkStorage§entities_by_chunk: HashMap<ChunkPos, HashSet<Entity>>

An index of all the entities we know are in the chunks of the world

§entity_by_id: IntMap<MinecraftEntityId, Entity>

An index of Minecraft entity IDs to Azalea ECS entities.

You should avoid using this (particularly if you’re using swarms) and instead use azalea_entity::EntityIdIndex, since some servers may give different entity IDs for the same entities to different players.

§registries: RegistryHolder

Implementations§

Source§

impl Instance

Source

pub fn find_block( &self, nearest_to: impl Into<BlockPos>, block_states: &BlockStates, ) -> Option<BlockPos>

Find the coordinates of a block in the world.

Note that this is sorted by x+y+z and not x^2+y^2+z^2 for performance purposes.

client
    .world()
    .read()
    .find_block(client.position(), &BlockKind::Chest.into());
Source

pub fn find_blocks<'a>( &'a self, nearest_to: impl Into<BlockPos>, block_states: &'a BlockStates, ) -> FindBlocks<'a>

Find all the coordinates of a block in the world.

This returns an iterator that yields the [BlockPos]s of blocks that are in the given block states.

Note that this is sorted by x+y+z and not x^2+y^2+z^2 for performance purposes.

Examples found in repository?
azalea/examples/steal.rs (line 58)
42async fn steal(bot: Client, state: State) -> anyhow::Result<()> {
43    {
44        let mut is_stealing = state.is_stealing.lock();
45        if *is_stealing {
46            bot.chat("Already stealing");
47            return Ok(());
48        }
49        *is_stealing = true;
50    }
51
52    state.checked_chests.lock().clear();
53
54    loop {
55        let chest_block = bot
56            .world()
57            .read()
58            .find_blocks(bot.position(), &BlockKind::Chest.into())
59            .find(
60                // find the closest chest that hasn't been checked
61                |block_pos| !state.checked_chests.lock().contains(block_pos),
62            );
63        let Some(chest_block) = chest_block else {
64            break;
65        };
66
67        state.checked_chests.lock().push(chest_block);
68
69        bot.goto(RadiusGoal::new(chest_block.center(), 3.)).await;
70
71        let Some(chest) = bot.open_container_at(chest_block).await else {
72            println!("Couldn't open chest at {chest_block:?}");
73            continue;
74        };
75
76        println!("Getting contents of chest at {chest_block:?}");
77        for (index, slot) in chest.contents().unwrap_or_default().iter().enumerate() {
78            println!("Checking slot {index}: {slot:?}");
79            let ItemStack::Present(item) = slot else {
80                continue;
81            };
82            if item.kind == ItemKind::Diamond {
83                println!("clicking slot ^");
84                chest.click(QuickMoveClick::Left { slot: index as u16 });
85            }
86        }
87    }
88
89    bot.chat("Done");
90
91    *state.is_stealing.lock() = false;
92
93    Ok(())
94}
Source§

impl Instance

Source

pub fn get_block_state(&self, pos: BlockPos) -> Option<BlockState>

Get the block at the given position, or None if it’s outside of the world that we have loaded.

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

pub fn get_fluid_state(&self, pos: BlockPos) -> Option<FluidState>

Similar to Self::get_block_state, but returns data about the fluid at the position, including for waterlogged blocks.

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

pub fn get_biome(&self, pos: BlockPos) -> Option<Biome>

Get the biome at the given position.

You can then use Client::with_resolved_registry to get the name and data from the biome.

Note that biomes are internally stored as 4x4x4 blocks, so if you’re writing code that searches for a specific biome it’ll probably be more efficient to avoid scanning every single block.

Source

pub fn set_block_state( &self, pos: BlockPos, state: BlockState, ) -> Option<BlockState>

Trait Implementations§

Source§

impl Debug for Instance

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for Instance

Source§

fn default() -> Instance

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

impl From<ChunkStorage> for Instance

Source§

fn from(chunks: ChunkStorage) -> Self

Make an empty world from this ChunkStorage. This is meant to be a convenience function for tests.

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
§

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
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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> 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,