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},
|
position::{ChunkPos, Vec3},
|
||||||
resource_location::ResourceLocation,
|
resource_location::ResourceLocation,
|
||||||
};
|
};
|
||||||
use azalea_entity::metadata::Cow;
|
|
||||||
use azalea_protocol::{
|
use azalea_protocol::{
|
||||||
common::movements::{PositionMoveRotation, RelativeMovements},
|
common::movements::{PositionMoveRotation, RelativeMovements},
|
||||||
packets::{
|
packets::{
|
||||||
|
@ -13,7 +12,6 @@ use azalea_protocol::{
|
||||||
};
|
};
|
||||||
use azalea_registry::{DataRegistry, DimensionType, EntityKind};
|
use azalea_registry::{DataRegistry, DimensionType, EntityKind};
|
||||||
use azalea_world::MinecraftEntityId;
|
use azalea_world::MinecraftEntityId;
|
||||||
use bevy_ecs::query::With;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_move_and_despawn_entity() {
|
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 components;
|
||||||
pub mod item;
|
pub mod item;
|
||||||
pub mod operations;
|
pub mod operations;
|
||||||
|
|
|
@ -14,6 +14,7 @@ use azalea_physics::collision::BlockWithShape;
|
||||||
use azalea_protocol::packets::game::ClientboundGamePacket;
|
use azalea_protocol::packets::game::ClientboundGamePacket;
|
||||||
use bevy_app::{App, Plugin, Update};
|
use bevy_app::{App, Plugin, Update};
|
||||||
use bevy_ecs::{component::Component, prelude::EventReader, system::Commands};
|
use bevy_ecs::{component::Component, prelude::EventReader, system::Commands};
|
||||||
|
use derive_more::Deref;
|
||||||
use futures_lite::Future;
|
use futures_lite::Future;
|
||||||
|
|
||||||
use crate::bot::BotClientExt;
|
use crate::bot::BotClientExt;
|
||||||
|
@ -26,17 +27,6 @@ impl Plugin for ContainerPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ContainerClientExt {
|
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
|
/// Open a container in the world, like a chest. Use
|
||||||
/// [`Client::open_inventory`] to open your own inventory.
|
/// [`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;
|
/// 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> {
|
async fn open_container_at(&self, pos: BlockPos) -> Option<ContainerHandle> {
|
||||||
let mut ticks = self.get_tick_broadcaster();
|
let mut ticks = self.get_tick_broadcaster();
|
||||||
// wait until it's not air (up to 10 ticks)
|
// 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> {
|
fn open_inventory(&self) -> Option<ContainerHandle> {
|
||||||
let ecs = self.ecs.lock();
|
let ecs = self.ecs.lock();
|
||||||
let inventory = ecs.get::<Inventory>(self.entity).expect("no inventory");
|
let inventory = ecs.get::<Inventory>(self.entity).expect("no inventory");
|
||||||
|
|
||||||
if inventory.id == 0 {
|
if inventory.id == 0 {
|
||||||
Some(ContainerHandle::new(0, self.clone()))
|
Some(ContainerHandle::new(0, self.clone()))
|
||||||
} else {
|
} else {
|
||||||
|
@ -113,46 +125,16 @@ impl ContainerClientExt for Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the item in the bot's hotbar that is currently being held in its
|
fn get_inventory(&self) -> ContainerHandleRef {
|
||||||
/// main hand.
|
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 {
|
fn get_held_item(&self) -> ItemStack {
|
||||||
self.map_get_component::<Inventory, _>(|inventory| inventory.held_item())
|
self.map_get_component::<Inventory, _>(|inventory| inventory.held_item())
|
||||||
.expect("no inventory")
|
.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
|
/// 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 {
|
impl ContainerHandleRef {
|
||||||
|
pub fn new(id: i32, client: Client) -> Self {
|
||||||
|
Self { id, client }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn close(&self) {
|
pub fn close(&self) {
|
||||||
self.client.ecs.lock().send_event(CloseContainerEvent {
|
self.client.ecs.lock().send_event(CloseContainerEvent {
|
||||||
entity: self.client.entity,
|
entity: self.client.entity,
|
||||||
|
@ -219,6 +205,25 @@ impl ContainerHandleRef {
|
||||||
self.menu().map(|menu| menu.slots())
|
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>) {
|
pub fn click(&self, operation: impl Into<ClickOperation>) {
|
||||||
let operation = operation.into();
|
let operation = operation.into();
|
||||||
self.client.ecs.lock().send_event(ContainerClickEvent {
|
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
|
/// A handle to the open container. The container will be closed once this is
|
||||||
/// dropped.
|
/// dropped.
|
||||||
|
#[derive(Deref)]
|
||||||
pub struct ContainerHandle(ContainerHandleRef);
|
pub struct ContainerHandle(ContainerHandleRef);
|
||||||
|
|
||||||
impl Drop for ContainerHandle {
|
impl Drop for ContainerHandle {
|
||||||
|
@ -250,62 +256,10 @@ impl ContainerHandle {
|
||||||
Self(ContainerHandleRef { id, client })
|
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.
|
/// Closes the inventory by dropping the handle.
|
||||||
pub fn close(self) {
|
pub fn close(self) {
|
||||||
// implicitly calls drop
|
// 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)]
|
#[derive(Component, Debug)]
|
||||||
|
|
Loading…
Add table
Reference in a new issue