RelBlockPos

Struct RelBlockPos 

Source
#[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: i32

The actual non-relative Y coordinate of the block.

§x: i16

The X coordinate of the block, relative to some origin.

§z: i16

The Y coordinate of the block, relative to some origin.

Implementations§

Source§

impl RelBlockPos

Source

pub fn get_origin(origin: BlockPos) -> Self

Source

pub const fn new(x: i16, y: i32, z: i16) -> Self

Source

pub fn apply(self, origin: BlockPos) -> BlockPos

Source

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

pub fn up(&self, y: i32) -> Self

Source

pub fn down(&self, y: i32) -> Self

Source

pub fn north(&self, z: i16) -> Self

Source

pub fn south(&self, z: i16) -> Self

Source

pub fn east(&self, x: i16) -> Self

Source

pub fn west(&self, x: i16) -> Self

Source

pub fn as_u64(self) -> u64

Trait Implementations§

Source§

impl Add for RelBlockPos

Source§

type Output = RelBlockPos

The resulting type after applying the + operator.
Source§

fn add(self, rhs: RelBlockPos) -> Self::Output

Performs the + operation. Read more
Source§

impl Clone for RelBlockPos

Source§

fn clone(&self) -> RelBlockPos

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

impl Debug for RelBlockPos

Source§

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

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

impl Hash for RelBlockPos

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Mul<i16> for RelBlockPos

Source§

type Output = RelBlockPos

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: i16) -> Self::Output

Performs the * operation. Read more
Source§

impl PartialEq for RelBlockPos

Source§

fn eq(&self, other: &RelBlockPos) -> 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.
Source§

impl Copy for RelBlockPos

Source§

impl Eq for RelBlockPos

Source§

impl StructuralPartialEq for RelBlockPos

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

impl<T> DynEq for T
where T: Any + Eq,

§

fn dyn_eq(&self, other: &(dyn DynEq + 'static)) -> bool

This method tests for self and other values to be equal. Read more
§

impl<T> DynHash for T
where T: DynEq + Hash,

§

fn dyn_hash(&self, state: &mut dyn Hasher)

Feeds this value into the given Hasher.
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

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> 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,