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