refactor: random fixes and usage improvements
This commit is contained in:
parent
8f2fbf11da
commit
dde489a8ed
@ -12,17 +12,16 @@ opt-level = 3
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
panic = "abort"
|
||||
strip = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
azalea = { git = "https://github.com/azalea-rs/azalea.git" }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
futures = "0"
|
||||
http-body-util = "0"
|
||||
hyper = { version = "1", features = ["server"] }
|
||||
hyper-util = "0"
|
||||
log = { version = "0" }
|
||||
mlua = { version = "0", features = ["async", "luau", "send"] }
|
||||
tokio = { version = "1", features = ["macros"] }
|
||||
futures = "0"
|
||||
|
@ -6,6 +6,8 @@ for _, module in
|
||||
{
|
||||
"enum",
|
||||
"events",
|
||||
"inventory",
|
||||
"movement",
|
||||
"utils",
|
||||
}
|
||||
do
|
||||
|
@ -1,5 +1,5 @@
|
||||
local center = { x = 0, z = 0 }
|
||||
local radius = 50
|
||||
local radius = 100
|
||||
|
||||
function on_tick()
|
||||
local entities = client:find_entities(function(e)
|
||||
@ -15,6 +15,10 @@ function on_tick()
|
||||
end
|
||||
|
||||
function on_init()
|
||||
info("client initialized, setting client information")
|
||||
info("client initialized, setting information...")
|
||||
client:set_client_information({ view_distance = 16 })
|
||||
end
|
||||
|
||||
function on_login()
|
||||
info("player successfully logged in!")
|
||||
end
|
||||
|
38
lib/inventory.lua
Normal file
38
lib/inventory.lua
Normal file
@ -0,0 +1,38 @@
|
||||
function steal(item_name)
|
||||
for _, chest_pos in client:find_blocks(client.position, get_block_states({ "chest" })) do
|
||||
client:chat(dump(chest_pos))
|
||||
|
||||
client:goto({ position = chest_pos, radius = 3 }, { type = RADIUS_GOAL })
|
||||
while client.pathfinder.is_calculating or client.pathfinder.is_executing do
|
||||
sleep(50)
|
||||
end
|
||||
client:look_at(chest_pos)
|
||||
|
||||
local container = client:open_container_at(chest_pos)
|
||||
for index, item in container.contents do
|
||||
if item.kind == item_name then
|
||||
container:click({slot = index - 1}, THROW_ALL)
|
||||
sleep(50)
|
||||
end
|
||||
end
|
||||
|
||||
container = nil
|
||||
while client.open_container do
|
||||
sleep(50)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function drop_all_hotbar()
|
||||
local inventory = client:open_inventory()
|
||||
for i = 0, 9 do
|
||||
inventory:click({slot = 36 + i}, THROW_ALL)
|
||||
end
|
||||
end
|
||||
|
||||
function drop_all_inventory()
|
||||
local inventory = client:open_inventory()
|
||||
for i = 0, 45 do
|
||||
inventory:click({slot = i}, THROW_ALL)
|
||||
end
|
||||
end
|
18
lib/movement.lua
Normal file
18
lib/movement.lua
Normal file
@ -0,0 +1,18 @@
|
||||
function look_at_player(name)
|
||||
local player = get_player(name)
|
||||
if player then
|
||||
player.position.y = player.position.y + 1
|
||||
client:look_at(player.position)
|
||||
else
|
||||
client:chat("player not found!")
|
||||
end
|
||||
end
|
||||
|
||||
function goto_player(name)
|
||||
local player = get_player(name)
|
||||
if player then
|
||||
client:goto(player.position)
|
||||
else
|
||||
client:chat("player not found!")
|
||||
end
|
||||
end
|
@ -1,3 +1,17 @@
|
||||
function get_player(name)
|
||||
local target_uuid = nil
|
||||
for uuid, player in client.tab_list do
|
||||
if player.name == name then
|
||||
target_uuid = uuid
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return client:find_entities(function(e)
|
||||
return e.kind == "minecraft:player" and e.uuid == target_uuid
|
||||
end)[1]
|
||||
end
|
||||
|
||||
function dump(object)
|
||||
if type(object) == "table" then
|
||||
local string = "{ "
|
||||
|
@ -7,6 +7,7 @@ use mlua::{Function, IntoLuaMulti, Table};
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||
state.lua.gc_stop();
|
||||
let globals = state.lua.globals();
|
||||
|
||||
match event {
|
||||
|
@ -24,8 +24,8 @@ pub async fn serve(
|
||||
let bytes = request.into_body().collect().await?.to_bytes();
|
||||
match std::str::from_utf8(&bytes) {
|
||||
Ok(code) => Response::new(full(match path.as_str() {
|
||||
"/eval" => format!("{:?}", eval(&state.lua, code).await),
|
||||
"/exec" => format!("{:?}", exec(&state.lua, code).await),
|
||||
"/eval" => format!("{:#?}", eval(&state.lua, code).await),
|
||||
"/exec" => format!("{:#?}", exec(&state.lua, code).await),
|
||||
_ => unreachable!(),
|
||||
})),
|
||||
Err(error) => status_code_response(
|
||||
|
@ -1,4 +1,8 @@
|
||||
use mlua::{FromLua, IntoLua, Lua, Result, Value};
|
||||
use azalea::blocks::{
|
||||
Block as AzaleaBlock, BlockState,
|
||||
properties::{ChestType, Facing, LightLevel},
|
||||
};
|
||||
use mlua::{FromLua, Function, IntoLua, Lua, Result, Table, Value};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Block {
|
||||
@ -46,3 +50,57 @@ impl FromLua for Block {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_functions(lua: &Lua, globals: &Table) -> Result<()> {
|
||||
globals.set(
|
||||
"get_block_from_state",
|
||||
lua.create_function(get_block_from_state)?,
|
||||
)?;
|
||||
globals.set("get_block_states", lua.create_function(get_block_states)?)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_block_from_state(_lua: &Lua, state: u32) -> Result<Option<Block>> {
|
||||
let Ok(state) = BlockState::try_from(state) else {
|
||||
return Ok(None);
|
||||
};
|
||||
let block: Box<dyn AzaleaBlock> = state.into();
|
||||
let behavior = block.behavior();
|
||||
|
||||
Ok(Some(Block {
|
||||
id: block.id().to_string(),
|
||||
friction: behavior.friction,
|
||||
jump_factor: behavior.jump_factor,
|
||||
destroy_time: behavior.destroy_time,
|
||||
explosion_resistance: behavior.explosion_resistance,
|
||||
requires_correct_tool_for_drops: behavior.requires_correct_tool_for_drops,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn get_block_states(
|
||||
lua: &Lua,
|
||||
(block_names, filter_fn): (Vec<String>, Option<Function>),
|
||||
) -> Result<Vec<u16>> {
|
||||
let mut matched = Vec::new();
|
||||
for block_name in block_names {
|
||||
for b in
|
||||
(u32::MIN..u32::MAX).map_while(|possible_id| BlockState::try_from(possible_id).ok())
|
||||
{
|
||||
if block_name == Into::<Box<dyn AzaleaBlock>>::into(b).id()
|
||||
&& (if let Some(filter_fn) = &filter_fn {
|
||||
let p = lua.create_table()?;
|
||||
p.set("chest_type", b.property::<ChestType>().map(|v| v as u8))?;
|
||||
p.set("facing", b.property::<Facing>().map(|v| v as u8))?;
|
||||
p.set("light_level", b.property::<LightLevel>().map(|v| v as u8))?;
|
||||
filter_fn.call::<bool>(p.clone())?
|
||||
} else {
|
||||
true
|
||||
})
|
||||
{
|
||||
matched.push(b.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(matched)
|
||||
}
|
||||
|
@ -6,6 +6,15 @@ use azalea::{
|
||||
use log::error;
|
||||
use mlua::{Lua, Result, UserDataRef};
|
||||
|
||||
pub fn container(_lua: &Lua, client: &Client) -> Result<Option<ContainerRef>> {
|
||||
Ok(client
|
||||
.inner
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_open_container()
|
||||
.map(|c| ContainerRef { inner: c }))
|
||||
}
|
||||
|
||||
pub fn held_item(_lua: &Lua, client: &Client) -> Result<ItemStack> {
|
||||
Ok(ItemStack {
|
||||
inner: client
|
||||
@ -26,15 +35,6 @@ pub fn held_slot(_lua: &Lua, client: &Client) -> Result<u8> {
|
||||
.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>,
|
||||
|
@ -5,7 +5,6 @@ mod state;
|
||||
mod world;
|
||||
|
||||
use super::{
|
||||
block::Block,
|
||||
container::item_stack::ItemStack,
|
||||
container::{Container, ContainerRef},
|
||||
direction::Direction,
|
||||
@ -24,6 +23,7 @@ pub struct Client {
|
||||
impl UserData for Client {
|
||||
fn add_fields<F: UserDataFields<Self>>(f: &mut F) {
|
||||
f.add_field_method_get("air_supply", state::air_supply);
|
||||
f.add_field_method_get("container", container::container);
|
||||
f.add_field_method_get("direction", movement::direction);
|
||||
f.add_field_method_get("eye_position", movement::eye_position);
|
||||
f.add_field_method_get("has_attack_cooldown", interaction::has_attack_cooldown);
|
||||
@ -32,7 +32,6 @@ impl UserData for Client {
|
||||
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);
|
||||
@ -41,16 +40,15 @@ impl UserData for Client {
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(m: &mut M) {
|
||||
m.add_async_method("goto", movement::goto);
|
||||
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("disconnect", disconnect);
|
||||
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);
|
||||
@ -58,7 +56,6 @@ impl UserData for Client {
|
||||
m.add_method("stop_pathfinding", movement::stop_pathfinding);
|
||||
m.add_method_mut("attack", interaction::attack);
|
||||
m.add_method_mut("block_interact", interaction::block_interact);
|
||||
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);
|
||||
|
@ -3,11 +3,11 @@ use azalea::{
|
||||
BlockPos, BotClientExt, Client as AzaleaClient, SprintDirection, WalkDirection,
|
||||
interact::HitResultComponent,
|
||||
pathfinder::{
|
||||
ExecutingPath, Pathfinder, PathfinderClientExt,
|
||||
ExecutingPath, GotoEvent, Pathfinder, PathfinderClientExt,
|
||||
goals::{BlockPosGoal, Goal, RadiusGoal, ReachBlockPosGoal, XZGoal, YGoal},
|
||||
},
|
||||
};
|
||||
use mlua::{FromLua, Lua, Result, Table, Value};
|
||||
use mlua::{FromLua, Lua, Result, Table, UserDataRef, Value};
|
||||
|
||||
pub fn direction(_lua: &Lua, client: &Client) -> Result<Direction> {
|
||||
let d = client.inner.as_ref().unwrap().direction();
|
||||
@ -23,9 +23,9 @@ pub fn eye_position(_lua: &Lua, client: &Client) -> Result<Vec3> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn goto(
|
||||
lua: &Lua,
|
||||
client: &mut Client,
|
||||
pub async fn goto(
|
||||
lua: Lua,
|
||||
client: UserDataRef<Client>,
|
||||
(data, metadata): (Value, Option<Table>),
|
||||
) -> Result<()> {
|
||||
fn g(client: &AzaleaClient, without_mining: bool, goal: impl Goal + Send + Sync + 'static) {
|
||||
@ -55,7 +55,7 @@ pub fn goto(
|
||||
match goal_type {
|
||||
1 => {
|
||||
let t = data.as_table().ok_or(error)?;
|
||||
let p = Vec3::from_lua(t.get("position")?, lua)?;
|
||||
let p = Vec3::from_lua(t.get("position")?, &lua)?;
|
||||
g(
|
||||
client,
|
||||
without_mining,
|
||||
@ -66,7 +66,7 @@ pub fn goto(
|
||||
);
|
||||
}
|
||||
2 => {
|
||||
let p = Vec3::from_lua(data, lua)?;
|
||||
let p = Vec3::from_lua(data, &lua)?;
|
||||
g(
|
||||
client,
|
||||
without_mining,
|
||||
@ -95,7 +95,7 @@ pub fn goto(
|
||||
},
|
||||
),
|
||||
_ => {
|
||||
let p = Vec3::from_lua(data, lua)?;
|
||||
let p = Vec3::from_lua(data, &lua)?;
|
||||
g(
|
||||
client,
|
||||
without_mining,
|
||||
@ -104,6 +104,12 @@ pub fn goto(
|
||||
}
|
||||
}
|
||||
|
||||
while client.get_tick_broadcaster().recv().await.is_ok() {
|
||||
if client.ecs.lock().get::<GotoEvent>(client.entity).is_none() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::{Block, Client, Entity, FluidState, Vec3};
|
||||
use super::{Client, Entity, FluidState, Vec3};
|
||||
use azalea::{
|
||||
BlockPos,
|
||||
auto_tool::AutoToolClientExt,
|
||||
blocks::{Block as AzaleaBlock, BlockState, BlockStates},
|
||||
blocks::{BlockState, BlockStates},
|
||||
ecs::query::Without,
|
||||
entity::{Dead, EntityKind, EntityUuid, Position as AzaleaPosition, metadata::CustomName},
|
||||
world::MinecraftEntityId,
|
||||
@ -22,22 +22,6 @@ pub fn best_tool_for_block(lua: &Lua, client: &Client, block_state: u16) -> Resu
|
||||
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,
|
||||
@ -93,7 +77,7 @@ pub fn find_entities(_lua: &Lua, client: &Client, filter_fn: Function) -> Result
|
||||
custom_name: custom_name.as_ref().map(ToString::to_string),
|
||||
};
|
||||
|
||||
if filter_fn.call::<bool>(entity.clone()).unwrap() {
|
||||
if filter_fn.call::<bool>(entity.clone())? {
|
||||
matched.push(entity);
|
||||
}
|
||||
}
|
||||
@ -101,23 +85,6 @@ pub fn find_entities(_lua: &Lua, client: &Client, filter_fn: Function) -> Result
|
||||
Ok(matched)
|
||||
}
|
||||
|
||||
pub fn get_block_from_state(_lua: &Lua, _client: &Client, state: u32) -> Result<Option<Block>> {
|
||||
let Ok(state) = BlockState::try_from(state) else {
|
||||
return Ok(None);
|
||||
};
|
||||
let block: Box<dyn AzaleaBlock> = state.into();
|
||||
let behavior = block.behavior();
|
||||
|
||||
Ok(Some(Block {
|
||||
id: block.id().to_string(),
|
||||
friction: behavior.friction,
|
||||
jump_factor: behavior.jump_factor,
|
||||
destroy_time: behavior.destroy_time,
|
||||
explosion_resistance: behavior.explosion_resistance,
|
||||
requires_correct_tool_for_drops: behavior.requires_correct_tool_for_drops,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn get_block_state(_lua: &Lua, client: &Client, position: Vec3) -> Result<Option<u16>> {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
Ok(client
|
||||
|
@ -32,10 +32,14 @@ impl UserData for Container {
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(m: &mut M) {
|
||||
m.add_method("click", |_, this, operation: Table| {
|
||||
this.inner.click(click_operation_from_table(operation)?);
|
||||
Ok(())
|
||||
});
|
||||
m.add_method(
|
||||
"click",
|
||||
|_, this, (operation, operation_type): (Table, Option<u8>)| {
|
||||
this.inner
|
||||
.click(click_operation_from_table(operation, operation_type)?);
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,59 +70,63 @@ impl UserData for ContainerRef {
|
||||
Ok(())
|
||||
});
|
||||
|
||||
m.add_method("click", |_, this, operation: Table| {
|
||||
this.inner.click(click_operation_from_table(operation)?);
|
||||
Ok(())
|
||||
});
|
||||
m.add_method(
|
||||
"click",
|
||||
|_, this, (operation, operation_type): (Table, Option<u8>)| {
|
||||
this.inner
|
||||
.click(click_operation_from_table(operation, operation_type)?);
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn click_operation_from_table(o: Table) -> Result<ClickOperation> {
|
||||
Ok(match o.get("type")? {
|
||||
fn click_operation_from_table(op: Table, op_type: Option<u8>) -> Result<ClickOperation> {
|
||||
Ok(match op_type.unwrap_or_default() {
|
||||
0 => ClickOperation::Pickup(PickupClick::Left {
|
||||
slot: o.get("slot")?,
|
||||
slot: op.get("slot")?,
|
||||
}),
|
||||
1 => ClickOperation::Pickup(PickupClick::Right {
|
||||
slot: o.get("slot")?,
|
||||
slot: op.get("slot")?,
|
||||
}),
|
||||
2 => ClickOperation::Pickup(PickupClick::LeftOutside),
|
||||
3 => ClickOperation::Pickup(PickupClick::RightOutside),
|
||||
5 => ClickOperation::QuickMove(QuickMoveClick::Right {
|
||||
slot: o.get("slot")?,
|
||||
slot: op.get("slot")?,
|
||||
}),
|
||||
6 => ClickOperation::Swap(SwapClick {
|
||||
source_slot: o.get("source_slot")?,
|
||||
target_slot: o.get("target_slot")?,
|
||||
source_slot: op.get("source_slot")?,
|
||||
target_slot: op.get("target_slot")?,
|
||||
}),
|
||||
7 => ClickOperation::Clone(CloneClick {
|
||||
slot: o.get("slot")?,
|
||||
slot: op.get("slot")?,
|
||||
}),
|
||||
8 => ClickOperation::Throw(ThrowClick::Single {
|
||||
slot: o.get("slot")?,
|
||||
slot: op.get("slot")?,
|
||||
}),
|
||||
9 => ClickOperation::Throw(ThrowClick::All {
|
||||
slot: o.get("slot")?,
|
||||
slot: op.get("slot")?,
|
||||
}),
|
||||
10 => ClickOperation::QuickCraft(QuickCraftClick {
|
||||
kind: match o.get("kind").unwrap_or_default() {
|
||||
kind: match op.get("kind").unwrap_or_default() {
|
||||
1 => QuickCraftKind::Right,
|
||||
2 => QuickCraftKind::Middle,
|
||||
_ => QuickCraftKind::Left,
|
||||
},
|
||||
status: match o.get("status").unwrap_or_default() {
|
||||
status: match op.get("status").unwrap_or_default() {
|
||||
1 => QuickCraftStatus::Add {
|
||||
slot: o.get("slot")?,
|
||||
slot: op.get("slot")?,
|
||||
},
|
||||
2 => QuickCraftStatus::End,
|
||||
_ => QuickCraftStatus::Start,
|
||||
},
|
||||
}),
|
||||
11 => ClickOperation::PickupAll(PickupAllClick {
|
||||
slot: o.get("slot")?,
|
||||
reversed: o.get("reversed").unwrap_or_default(),
|
||||
slot: op.get("slot")?,
|
||||
reversed: op.get("reversed").unwrap_or_default(),
|
||||
}),
|
||||
_ => ClickOperation::QuickMove(QuickMoveClick::Left {
|
||||
slot: o.get("slot")?,
|
||||
slot: op.get("slot")?,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ pub fn register_functions(lua: &Lua, globals: &Table) -> mlua::Result<()> {
|
||||
})?,
|
||||
)?;
|
||||
|
||||
logging::register_functions(lua, globals)
|
||||
logging::register_functions(lua, globals)?;
|
||||
block::register_functions(lua, globals)
|
||||
}
|
||||
|
||||
pub fn reload(lua: &Lua) -> Result<(), Error> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user