feat(client): add inventory manipulation wrappers
This commit is contained in:
88
src/lua/client/container.rs
Normal file
88
src/lua/client/container.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
use super::{Client, Container, ContainerRef, ItemStack, Vec3};
|
||||
use azalea::{
|
||||
BlockPos, inventory::Inventory, prelude::ContainerClientExt,
|
||||
protocol::packets::game::ServerboundSetCarriedItem,
|
||||
};
|
||||
use log::error;
|
||||
use mlua::{Lua, Result, UserDataRef};
|
||||
|
||||
pub fn held_item(_lua: &Lua, client: &Client) -> Result<ItemStack> {
|
||||
Ok(ItemStack {
|
||||
inner: client
|
||||
.inner
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.component::<Inventory>()
|
||||
.held_item(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn held_slot(_lua: &Lua, client: &Client) -> Result<u8> {
|
||||
Ok(client
|
||||
.inner
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.component::<Inventory>()
|
||||
.selected_hotbar_slot)
|
||||
}
|
||||
|
||||
pub fn open_container(_lua: &Lua, client: &Client) -> Result<Option<ContainerRef>> {
|
||||
Ok(client
|
||||
.inner
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_open_container()
|
||||
.map(|c| ContainerRef { inner: c }))
|
||||
}
|
||||
|
||||
pub async fn open_container_at(
|
||||
_lua: Lua,
|
||||
client: UserDataRef<Client>,
|
||||
position: Vec3,
|
||||
) -> Result<Option<Container>> {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
Ok(client
|
||||
.inner
|
||||
.clone()
|
||||
.unwrap()
|
||||
.open_container_at(BlockPos::new(
|
||||
position.x as i32,
|
||||
position.y as i32,
|
||||
position.z as i32,
|
||||
))
|
||||
.await
|
||||
.map(|c| Container { inner: c }))
|
||||
}
|
||||
|
||||
pub fn open_inventory(_lua: &Lua, client: &mut Client, _: ()) -> Result<Option<Container>> {
|
||||
Ok(client
|
||||
.inner
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.open_inventory()
|
||||
.map(|c| Container { inner: c }))
|
||||
}
|
||||
|
||||
pub fn set_held_slot(_lua: &Lua, client: &Client, slot: u8) -> Result<()> {
|
||||
if slot > 8 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let client = client.inner.as_ref().unwrap();
|
||||
{
|
||||
let mut ecs = client.ecs.lock();
|
||||
let mut inventory = client.query::<&mut Inventory>(&mut ecs);
|
||||
if inventory.selected_hotbar_slot == slot {
|
||||
return Ok(());
|
||||
}
|
||||
inventory.selected_hotbar_slot = slot;
|
||||
};
|
||||
|
||||
if let Err(error) = client.write_packet(ServerboundSetCarriedItem {
|
||||
slot: u16::from(slot),
|
||||
}) {
|
||||
error!("failed to send SetCarriedItem packet: {error:?}");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
@@ -1,10 +1,17 @@
|
||||
mod container;
|
||||
mod interaction;
|
||||
mod movement;
|
||||
mod state;
|
||||
mod world;
|
||||
|
||||
use super::{
|
||||
block::Block, direction::Direction, entity::Entity, fluid_state::FluidState, hunger::Hunger,
|
||||
block::Block,
|
||||
container::item_stack::ItemStack,
|
||||
container::{Container, ContainerRef},
|
||||
direction::Direction,
|
||||
entity::Entity,
|
||||
fluid_state::FluidState,
|
||||
hunger::Hunger,
|
||||
vec3::Vec3,
|
||||
};
|
||||
use azalea::Client as AzaleaClient;
|
||||
@@ -20,8 +27,11 @@ impl UserData for Client {
|
||||
f.add_field_method_get("direction", movement::direction);
|
||||
f.add_field_method_get("eye_position", movement::eye_position);
|
||||
f.add_field_method_get("health", state::health);
|
||||
f.add_field_method_get("held_item", container::held_item);
|
||||
f.add_field_method_get("held_slot", container::held_slot);
|
||||
f.add_field_method_get("hunger", state::hunger);
|
||||
f.add_field_method_get("looking_at", movement::looking_at);
|
||||
f.add_field_method_get("open_container", container::open_container);
|
||||
f.add_field_method_get("pathfinder", movement::pathfinder);
|
||||
f.add_field_method_get("position", movement::position);
|
||||
f.add_field_method_get("score", state::score);
|
||||
@@ -31,13 +41,17 @@ impl UserData for Client {
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(m: &mut M) {
|
||||
m.add_async_method("mine", interaction::mine);
|
||||
m.add_async_method("open_container_at", container::open_container_at);
|
||||
m.add_async_method("set_client_information", state::set_client_information);
|
||||
m.add_method("best_tool_for_block", world::best_tool_for_block);
|
||||
m.add_method("block_names_to_states", world::block_names_to_states);
|
||||
m.add_method("chat", chat);
|
||||
m.add_method("find_blocks", world::find_blocks);
|
||||
m.add_method("find_entities", world::find_entities);
|
||||
m.add_method("get_block_from_state", world::get_block_from_state);
|
||||
m.add_method("get_block_state", world::get_block_state);
|
||||
m.add_method("get_fluid_state", world::get_fluid_state);
|
||||
m.add_method("set_held_slot", container::set_held_slot);
|
||||
m.add_method("set_mining", interaction::set_mining);
|
||||
m.add_method("stop_pathfinding", movement::stop_pathfinding);
|
||||
m.add_method_mut("attack", interaction::attack);
|
||||
@@ -45,6 +59,7 @@ impl UserData for Client {
|
||||
m.add_method_mut("goto", movement::goto);
|
||||
m.add_method_mut("jump", movement::jump);
|
||||
m.add_method_mut("look_at", movement::look_at);
|
||||
m.add_method_mut("open_inventory", container::open_inventory);
|
||||
m.add_method_mut("set_direction", movement::set_direction);
|
||||
m.add_method_mut("set_jumping", movement::set_jumping);
|
||||
m.add_method_mut("sprint", movement::sprint);
|
||||
|
@@ -1,17 +1,47 @@
|
||||
use super::{Block, Client, Entity, FluidState, Vec3};
|
||||
use azalea::{
|
||||
BlockPos,
|
||||
auto_tool::AutoToolClientExt,
|
||||
blocks::{Block as AzaleaBlock, BlockState, BlockStates},
|
||||
ecs::query::Without,
|
||||
entity::{Dead, EntityKind, EntityUuid, Position as AzaleaPosition, metadata::CustomName},
|
||||
world::MinecraftEntityId,
|
||||
};
|
||||
use mlua::{Function, Lua, Result};
|
||||
use mlua::{Function, Lua, Result, Table};
|
||||
|
||||
pub fn best_tool_for_block(lua: &Lua, client: &Client, block_state: u16) -> Result<Table> {
|
||||
let tr = client
|
||||
.inner
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.best_tool_in_hotbar_for_block(BlockState { id: block_state });
|
||||
|
||||
let tool_result = lua.create_table()?;
|
||||
tool_result.set("index", tr.index)?;
|
||||
tool_result.set("percentage_per_tick", tr.percentage_per_tick)?;
|
||||
Ok(tool_result)
|
||||
}
|
||||
|
||||
pub fn block_names_to_states(
|
||||
_lua: &Lua,
|
||||
_client: &Client,
|
||||
block_names: Vec<String>,
|
||||
) -> Result<Vec<u16>> {
|
||||
Ok(block_names
|
||||
.iter()
|
||||
.flat_map(|n| {
|
||||
(u32::MIN..u32::MAX)
|
||||
.map_while(|i| BlockState::try_from(i).ok())
|
||||
.filter(move |&b| n == Into::<Box<dyn AzaleaBlock>>::into(b).id())
|
||||
.map(|b| b.id)
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn find_blocks(
|
||||
_lua: &Lua,
|
||||
client: &Client,
|
||||
(nearest_to, block_names): (Vec3, Vec<String>),
|
||||
(nearest_to, block_states): (Vec3, Vec<u16>),
|
||||
) -> Result<Vec<Vec3>> {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
Ok(client
|
||||
@@ -27,14 +57,7 @@ pub fn find_blocks(
|
||||
nearest_to.z as i32,
|
||||
),
|
||||
&BlockStates {
|
||||
set: block_names
|
||||
.iter()
|
||||
.flat_map(|n| {
|
||||
(u32::MIN..u32::MAX)
|
||||
.map_while(|i| BlockState::try_from(i).ok())
|
||||
.filter(move |&b| n == Into::<Box<dyn AzaleaBlock>>::into(b).id())
|
||||
})
|
||||
.collect(),
|
||||
set: block_states.iter().map(|&id| BlockState { id }).collect(),
|
||||
},
|
||||
)
|
||||
.map(|p| Vec3 {
|
||||
|
Reference in New Issue
Block a user