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: RegistryHolderImplementations§
Source§impl Instance
impl Instance
Sourcepub fn find_block(
&self,
nearest_to: impl Into<BlockPos>,
block_states: &BlockStates,
) -> Option<BlockPos>
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());Sourcepub fn find_blocks<'a>(
&'a self,
nearest_to: impl Into<BlockPos>,
block_states: &'a BlockStates,
) -> FindBlocks<'a> ⓘ
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?
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
impl Instance
Sourcepub fn get_block_state(&self, pos: BlockPos) -> Option<BlockState>
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?
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}Sourcepub fn get_fluid_state(&self, pos: BlockPos) -> Option<FluidState>
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?
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}Sourcepub fn get_biome(&self, pos: BlockPos) -> Option<Biome>
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.
pub fn set_block_state( &self, pos: BlockPos, state: BlockState, ) -> Option<BlockState>
Trait Implementations§
Source§impl From<ChunkStorage> for Instance
impl From<ChunkStorage> for Instance
Source§fn from(chunks: ChunkStorage) -> Self
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§
impl Freeze for Instance
impl !RefUnwindSafe for Instance
impl Send for Instance
impl Sync for Instance
impl Unpin for Instance
impl !UnwindSafe for Instance
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<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self using default().