mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
replace Client::get_open_container and view_container_or_inventory with get_inventory
This commit is contained in:
parent
40bcb62a77
commit
086f979a28
3 changed files with 66 additions and 113 deletions
|
@ -3,7 +3,6 @@ use azalea_core::{
|
|||
position::{ChunkPos, Vec3},
|
||||
resource_location::ResourceLocation,
|
||||
};
|
||||
use azalea_entity::metadata::Cow;
|
||||
use azalea_protocol::{
|
||||
common::movements::{PositionMoveRotation, RelativeMovements},
|
||||
packets::{
|
||||
|
@ -13,7 +12,6 @@ use azalea_protocol::{
|
|||
};
|
||||
use azalea_registry::{DataRegistry, DimensionType, EntityKind};
|
||||
use azalea_world::MinecraftEntityId;
|
||||
use bevy_ecs::query::With;
|
||||
|
||||
#[test]
|
||||
fn test_move_and_despawn_entity() {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/// Representations of various inventory data structures in Minecraft.
|
||||
//! Representations of various inventory data structures in Minecraft.
|
||||
|
||||
pub mod components;
|
||||
pub mod item;
|
||||
pub mod operations;
|
||||
|
|
|
@ -14,6 +14,7 @@ use azalea_physics::collision::BlockWithShape;
|
|||
use azalea_protocol::packets::game::ClientboundGamePacket;
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::{component::Component, prelude::EventReader, system::Commands};
|
||||
use derive_more::Deref;
|
||||
use futures_lite::Future;
|
||||
|
||||
use crate::bot::BotClientExt;
|
||||
|
@ -26,17 +27,6 @@ impl Plugin for ContainerPlugin {
|
|||
}
|
||||
|
||||
pub trait ContainerClientExt {
|
||||
fn open_container_at(
|
||||
&self,
|
||||
pos: BlockPos,
|
||||
) -> impl Future<Output = Option<ContainerHandle>> + Send;
|
||||
fn open_inventory(&self) -> Option<ContainerHandle>;
|
||||
fn get_held_item(&self) -> ItemStack;
|
||||
fn get_open_container(&self) -> Option<ContainerHandleRef>;
|
||||
fn view_container_or_inventory(&self) -> Menu;
|
||||
}
|
||||
|
||||
impl ContainerClientExt for Client {
|
||||
/// Open a container in the world, like a chest. Use
|
||||
/// [`Client::open_inventory`] to open your own inventory.
|
||||
///
|
||||
|
@ -54,6 +44,39 @@ impl ContainerClientExt for Client {
|
|||
/// let container = bot.open_container_at(target_pos).await;
|
||||
/// # }
|
||||
/// ```
|
||||
fn open_container_at(
|
||||
&self,
|
||||
pos: BlockPos,
|
||||
) -> impl Future<Output = Option<ContainerHandle>> + Send;
|
||||
/// Open the player's inventory. This will return None if another
|
||||
/// container is open.
|
||||
///
|
||||
/// Note that this will send a packet to the server once it's dropped. Also,
|
||||
/// due to how it's implemented, you could call this function multiple times
|
||||
/// while another inventory handle already exists (but you shouldn't).
|
||||
///
|
||||
/// If you just want to get the items in the player's inventory without
|
||||
/// sending any packets, use [`Client::menu`], [`Menu::player_slots_range`],
|
||||
/// and [`Menu::slots`].
|
||||
fn open_inventory(&self) -> Option<ContainerHandle>;
|
||||
/// Returns a [`ContainerHandleRef`] to the client's currently open
|
||||
/// container, or their inventory.
|
||||
///
|
||||
/// This will not send a packet to close the container when it's dropped,
|
||||
/// which may cause anticheat compatibility issues if you modify your
|
||||
/// inventory without closing it afterwards.
|
||||
///
|
||||
/// To simulate opening your own inventory (like pressing 'e') in a way that
|
||||
/// won't trigger anticheats, use [`Client::open_inventory`].
|
||||
///
|
||||
/// To open a container in the world, use [`Client::open_container_at`].
|
||||
fn get_inventory(&self) -> ContainerHandleRef;
|
||||
/// Get the item in the bot's hotbar that is currently being held in its
|
||||
/// main hand.
|
||||
fn get_held_item(&self) -> ItemStack;
|
||||
}
|
||||
|
||||
impl ContainerClientExt for Client {
|
||||
async fn open_container_at(&self, pos: BlockPos) -> Option<ContainerHandle> {
|
||||
let mut ticks = self.get_tick_broadcaster();
|
||||
// wait until it's not air (up to 10 ticks)
|
||||
|
@ -92,20 +115,9 @@ impl ContainerClientExt for Client {
|
|||
}
|
||||
}
|
||||
|
||||
/// Open the player's inventory. This will return None if another
|
||||
/// container is open.
|
||||
///
|
||||
/// Note that this will send a packet to the server once it's dropped. Also,
|
||||
/// due to how it's implemented, you could call this function multiple times
|
||||
/// while another inventory handle already exists (but you shouldn't).
|
||||
///
|
||||
/// If you just want to get the items in the player's inventory without
|
||||
/// sending any packets, use [`Client::menu`], [`Menu::player_slots_range`],
|
||||
/// and [`Menu::slots`].
|
||||
fn open_inventory(&self) -> Option<ContainerHandle> {
|
||||
let ecs = self.ecs.lock();
|
||||
let inventory = ecs.get::<Inventory>(self.entity).expect("no inventory");
|
||||
|
||||
if inventory.id == 0 {
|
||||
Some(ContainerHandle::new(0, self.clone()))
|
||||
} else {
|
||||
|
@ -113,46 +125,16 @@ impl ContainerClientExt for Client {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the item in the bot's hotbar that is currently being held in its
|
||||
/// main hand.
|
||||
fn get_inventory(&self) -> ContainerHandleRef {
|
||||
let ecs = self.ecs.lock();
|
||||
let inventory = ecs.get::<Inventory>(self.entity).expect("no inventory");
|
||||
ContainerHandleRef::new(inventory.id, self.clone())
|
||||
}
|
||||
|
||||
fn get_held_item(&self) -> ItemStack {
|
||||
self.map_get_component::<Inventory, _>(|inventory| inventory.held_item())
|
||||
.expect("no inventory")
|
||||
}
|
||||
|
||||
/// Get a handle to the open container. This will return None if no
|
||||
/// container is open. This will not close the container when it's dropped.
|
||||
///
|
||||
/// See [`Client::open_inventory`] or [`Client::menu`] if you want to open
|
||||
/// your own inventory.
|
||||
fn get_open_container(&self) -> Option<ContainerHandleRef> {
|
||||
let ecs = self.ecs.lock();
|
||||
let inventory = ecs.get::<Inventory>(self.entity).expect("no inventory");
|
||||
|
||||
if inventory.id == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ContainerHandleRef {
|
||||
id: inventory.id,
|
||||
client: self.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the player's currently open container menu, or their inventory
|
||||
/// if no container is open.
|
||||
///
|
||||
/// This tries to access the client's [`Inventory::container_menu`] and
|
||||
/// falls back to [`Inventory::inventory_menu`].
|
||||
fn view_container_or_inventory(&self) -> Menu {
|
||||
self.map_get_component::<Inventory, _>(|inventory| {
|
||||
inventory
|
||||
.container_menu
|
||||
.clone()
|
||||
.unwrap_or(inventory.inventory_menu.clone())
|
||||
})
|
||||
.expect("no inventory")
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to a container that may be open. This does not close the container
|
||||
|
@ -169,6 +151,10 @@ impl Debug for ContainerHandleRef {
|
|||
}
|
||||
}
|
||||
impl ContainerHandleRef {
|
||||
pub fn new(id: i32, client: Client) -> Self {
|
||||
Self { id, client }
|
||||
}
|
||||
|
||||
pub fn close(&self) {
|
||||
self.client.ecs.lock().send_event(CloseContainerEvent {
|
||||
entity: self.client.entity,
|
||||
|
@ -219,6 +205,25 @@ impl ContainerHandleRef {
|
|||
self.menu().map(|menu| menu.slots())
|
||||
}
|
||||
|
||||
/// A shortcut for [`Self::click`] with `PickupClick::Left`.
|
||||
pub fn left_click(&self, slot: impl Into<usize>) {
|
||||
self.click(PickupClick::Left {
|
||||
slot: Some(slot.into() as u16),
|
||||
});
|
||||
}
|
||||
/// A shortcut for [`Self::click`] with `QuickMoveClick::Left`.
|
||||
pub fn shift_click(&self, slot: impl Into<usize>) {
|
||||
self.click(QuickMoveClick::Left {
|
||||
slot: slot.into() as u16,
|
||||
});
|
||||
}
|
||||
/// A shortcut for [`Self::click`] with `PickupClick::Right`.
|
||||
pub fn right_click(&self, slot: impl Into<usize>) {
|
||||
self.click(PickupClick::Right {
|
||||
slot: Some(slot.into() as u16),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn click(&self, operation: impl Into<ClickOperation>) {
|
||||
let operation = operation.into();
|
||||
self.client.ecs.lock().send_event(ContainerClickEvent {
|
||||
|
@ -231,6 +236,7 @@ impl ContainerHandleRef {
|
|||
|
||||
/// A handle to the open container. The container will be closed once this is
|
||||
/// dropped.
|
||||
#[derive(Deref)]
|
||||
pub struct ContainerHandle(ContainerHandleRef);
|
||||
|
||||
impl Drop for ContainerHandle {
|
||||
|
@ -250,62 +256,10 @@ impl ContainerHandle {
|
|||
Self(ContainerHandleRef { id, client })
|
||||
}
|
||||
|
||||
/// Get the id of the container. If this is 0, that means it's the player's
|
||||
/// inventory. Otherwise, the number isn't really meaningful since only one
|
||||
/// container can be open at a time.
|
||||
pub fn id(&self) -> i32 {
|
||||
self.0.id()
|
||||
}
|
||||
|
||||
/// Returns the menu of the container. If the container is closed, this
|
||||
/// will return `None`.
|
||||
///
|
||||
/// Note that any modifications you make to the `Menu` you're given will not
|
||||
/// actually cause any packets to be sent. If you're trying to modify your
|
||||
/// inventory, use [`ContainerHandle::click`] instead
|
||||
pub fn menu(&self) -> Option<Menu> {
|
||||
self.0.menu()
|
||||
}
|
||||
|
||||
/// Returns the item slots in the container, not including the player's
|
||||
/// inventory. If the container is closed, this will return `None`.
|
||||
pub fn contents(&self) -> Option<Vec<ItemStack>> {
|
||||
self.0.contents()
|
||||
}
|
||||
|
||||
/// Return the contents of the menu, including the player's inventory. If
|
||||
/// the container is closed, this will return `None`.
|
||||
pub fn slots(&self) -> Option<Vec<ItemStack>> {
|
||||
self.0.slots()
|
||||
}
|
||||
|
||||
/// Closes the inventory by dropping the handle.
|
||||
pub fn close(self) {
|
||||
// implicitly calls drop
|
||||
}
|
||||
|
||||
pub fn click(&self, operation: impl Into<ClickOperation>) {
|
||||
self.0.click(operation);
|
||||
}
|
||||
|
||||
/// A shortcut for [`Self::click`] with `PickupClick::Left`.
|
||||
pub fn left_click(&self, slot: impl Into<usize>) {
|
||||
self.click(PickupClick::Left {
|
||||
slot: Some(slot.into() as u16),
|
||||
});
|
||||
}
|
||||
/// A shortcut for [`Self::click`] with `QuickMoveClick::Left`.
|
||||
pub fn shift_click(&self, slot: impl Into<usize>) {
|
||||
self.click(QuickMoveClick::Left {
|
||||
slot: slot.into() as u16,
|
||||
});
|
||||
}
|
||||
/// A shortcut for [`Self::click`] with `PickupClick::Right`.
|
||||
pub fn right_click(&self, slot: impl Into<usize>) {
|
||||
self.click(PickupClick::Right {
|
||||
slot: Some(slot.into() as u16),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
|
|
Loading…
Add table
Reference in a new issue