Skip to content

Commit

Permalink
rename open_container to open_container_at and add get_open_container
Browse files Browse the repository at this point in the history
  • Loading branch information
mat-1 committed Jan 4, 2024
1 parent 13e6421 commit 1347f35
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 33 deletions.
6 changes: 6 additions & 0 deletions azalea-client/src/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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());
}
}

Expand Down Expand Up @@ -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;
}
}

Expand Down
6 changes: 3 additions & 3 deletions azalea-core/src/game_type.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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
}))
}
Expand Down
2 changes: 1 addition & 1 deletion azalea/examples/steal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(());
};
Expand Down
2 changes: 1 addition & 1 deletion azalea/examples/testbot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion azalea/examples/todo/craft_dig_straight_down.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
116 changes: 89 additions & 27 deletions azalea/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
Expand All @@ -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()))
}
}

Expand All @@ -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) {
self.client.ecs.lock().send_event(CloseContainerEvent {
entity: self.client.entity,
id: self.id,
});
}
}
impl Debug for ContainerHandle {
impl Debug for ContainerHandleRef {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContainerHandle")
.field("id", &self.id)
.field("id", &self.id())
.finish()
}
}
impl ContainerHandle {
impl ContainerHandleRef {
pub fn close(&self) {
self.client.ecs.lock().send_event(CloseContainerEvent {
entity: self.client.entity,
id: self.id,
});
}

/// 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.
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 1347f35

Please sign in to comment.