mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
rename open_container to open_container_at and add get_open_container
This commit is contained in:
parent
13e6421cf5
commit
1347f35492
6 changed files with 101 additions and 33 deletions
|
@ -90,6 +90,9 @@ pub struct InventoryComponent {
|
|||
/// The current container menu that the player has open. If no container is
|
||||
/// open, this will be `None`.
|
||||
pub container_menu: Option<azalea_inventory::Menu>,
|
||||
/// The custom name of the menu that's currently open. This is Some when
|
||||
/// `container_menu` is Some.
|
||||
pub container_menu_title: Option<FormattedText>,
|
||||
/// The item that is currently held by the cursor. `Slot::Empty` if nothing
|
||||
/// is currently being held.
|
||||
///
|
||||
|
@ -566,6 +569,7 @@ impl Default for InventoryComponent {
|
|||
inventory_menu: Menu::Player(azalea_inventory::Player::default()),
|
||||
id: 0,
|
||||
container_menu: None,
|
||||
container_menu_title: None,
|
||||
carried: ItemSlot::Empty,
|
||||
state_id: 0,
|
||||
quick_craft_status: QuickCraftStatusKind::Start,
|
||||
|
@ -593,6 +597,7 @@ fn handle_menu_opened_event(
|
|||
let mut inventory = query.get_mut(event.entity).unwrap();
|
||||
inventory.id = event.window_id as u8;
|
||||
inventory.container_menu = Some(Menu::from_kind(event.menu_type));
|
||||
inventory.container_menu_title = Some(event.title.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -651,6 +656,7 @@ pub fn handle_client_side_close_container_event(
|
|||
let mut inventory = query.get_mut(event.entity).unwrap();
|
||||
inventory.container_menu = None;
|
||||
inventory.id = 0;
|
||||
inventory.container_menu_title = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufWritable};
|
||||
use std::io::{Cursor, Write};
|
||||
use tracing::warn;
|
||||
use tracing::debug;
|
||||
|
||||
/// A Minecraft gamemode, like survival or creative.
|
||||
#[derive(Hash, Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
|
@ -96,11 +96,11 @@ impl McBufReadable for GameMode {
|
|||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let id = u32::var_read_from(buf)?;
|
||||
let id = id.try_into().unwrap_or_else(|_| {
|
||||
warn!("Unknown game mode id {id}, defaulting to survival");
|
||||
debug!("Unknown game mode id {id}, defaulting to survival");
|
||||
0
|
||||
});
|
||||
Ok(GameMode::from_id(id).unwrap_or_else(|| {
|
||||
warn!("Unknown game mode id {id}, defaulting to survival");
|
||||
debug!("Unknown game mode id {id}, defaulting to survival");
|
||||
GameMode::Survival
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<(
|
|||
return Ok(());
|
||||
};
|
||||
// bot.goto(BlockPosGoal(chest_block));
|
||||
let Some(chest) = bot.open_container(chest_block).await else {
|
||||
let Some(chest) = bot.open_container_at(chest_block).await else {
|
||||
println!("Couldn't open chest");
|
||||
return Ok(());
|
||||
};
|
||||
|
|
|
@ -216,7 +216,7 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
|
|||
return Ok(());
|
||||
};
|
||||
bot.look_at(target_pos.center());
|
||||
let container = bot.open_container(target_pos).await;
|
||||
let container = bot.open_container_at(target_pos).await;
|
||||
println!("container: {container:?}");
|
||||
if let Some(container) = container {
|
||||
if let Some(contents) = container.contents() {
|
||||
|
|
|
@ -38,7 +38,7 @@ async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
|||
bot.goto(pathfinder::Goals::NearXZ(5, azalea::BlockXZ(0, 0)))
|
||||
.await;
|
||||
let chest = bot
|
||||
.open_container(&bot.world().find_block(azalea::Block::Chest))
|
||||
.open_container_at(&bot.world().find_block(azalea::Block::Chest))
|
||||
.await
|
||||
.unwrap();
|
||||
bot.take_amount_from_container(&chest, 5, |i| i.id == "#minecraft:planks")
|
||||
|
|
|
@ -23,11 +23,12 @@ impl Plugin for ContainerPlugin {
|
|||
}
|
||||
|
||||
pub trait ContainerClientExt {
|
||||
fn open_container(
|
||||
fn open_container_at(
|
||||
&mut self,
|
||||
pos: BlockPos,
|
||||
) -> impl Future<Output = Option<ContainerHandle>> + Send;
|
||||
fn open_inventory(&mut self) -> Option<ContainerHandle>;
|
||||
fn get_open_container(&self) -> Option<ContainerHandleRef>;
|
||||
}
|
||||
|
||||
impl ContainerClientExt for Client {
|
||||
|
@ -45,10 +46,10 @@ impl ContainerClientExt for Client {
|
|||
/// bot.chat("no chest found");
|
||||
/// return;
|
||||
/// };
|
||||
/// let container = bot.open_container(target_pos).await;
|
||||
/// let container = bot.open_container_at(target_pos).await;
|
||||
/// # }
|
||||
/// ```
|
||||
async fn open_container(&mut self, pos: BlockPos) -> Option<ContainerHandle> {
|
||||
async fn open_container_at(&mut self, pos: BlockPos) -> Option<ContainerHandle> {
|
||||
self.ecs
|
||||
.lock()
|
||||
.entity_mut(self.entity)
|
||||
|
@ -70,10 +71,7 @@ impl ContainerClientExt for Client {
|
|||
if inventory.id == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ContainerHandle {
|
||||
id: inventory.id,
|
||||
client: self.clone(),
|
||||
})
|
||||
Some(ContainerHandle::new(inventory.id, self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,40 +92,55 @@ impl ContainerClientExt for Client {
|
|||
.expect("no inventory");
|
||||
|
||||
if inventory.id == 0 {
|
||||
Some(ContainerHandle {
|
||||
id: 0,
|
||||
client: self.clone(),
|
||||
})
|
||||
Some(ContainerHandle::new(0, self.clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// 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::<InventoryComponent>(self.entity)
|
||||
.expect("no inventory");
|
||||
|
||||
if inventory.id == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ContainerHandleRef {
|
||||
id: inventory.id,
|
||||
client: self.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to the open container. The container will be closed once this is
|
||||
/// dropped.
|
||||
pub struct ContainerHandle {
|
||||
/// The id of the container. If this is 0, that means it's the player's
|
||||
/// inventory.
|
||||
/// A handle to a container that may be open. This does not close the container
|
||||
/// when it's dropped. See [`ContainerHandle`] if that behavior is desired.
|
||||
pub struct ContainerHandleRef {
|
||||
id: u8,
|
||||
client: Client,
|
||||
}
|
||||
impl Drop for ContainerHandle {
|
||||
fn drop(&mut self) {
|
||||
impl Debug for ContainerHandleRef {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("ContainerHandle")
|
||||
.field("id", &self.id())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
impl ContainerHandleRef {
|
||||
pub fn close(&self) {
|
||||
self.client.ecs.lock().send_event(CloseContainerEvent {
|
||||
entity: self.client.entity,
|
||||
id: self.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
impl Debug for ContainerHandle {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("ContainerHandle")
|
||||
.field("id", &self.id)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
impl ContainerHandle {
|
||||
|
||||
/// 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.
|
||||
|
@ -175,6 +188,55 @@ impl ContainerHandle {
|
|||
}
|
||||
}
|
||||
|
||||
/// A handle to the open container. The container will be closed once this is
|
||||
/// dropped.
|
||||
pub struct ContainerHandle(ContainerHandleRef);
|
||||
|
||||
impl Drop for ContainerHandle {
|
||||
fn drop(&mut self) {
|
||||
self.0.close();
|
||||
}
|
||||
}
|
||||
impl Debug for ContainerHandle {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("ContainerHandle")
|
||||
.field("id", &self.id())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
impl ContainerHandle {
|
||||
fn new(id: u8, client: Client) -> Self {
|
||||
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) -> u8 {
|
||||
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<ItemSlot>> {
|
||||
self.0.contents()
|
||||
}
|
||||
|
||||
pub fn click(&self, operation: impl Into<ClickOperation>) {
|
||||
self.0.click(operation);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct WaitingForInventoryOpen;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue