Compare commits
9 Commits
1ebe7dd0b9
...
a0fda6f285
Author | SHA1 | Date | |
---|---|---|---|
a0fda6f285 | |||
9ce39ebb67 | |||
225edd5529 | |||
8ae882a56a | |||
0ea2c81d2a | |||
73e7e17da4 | |||
14e3781e05 | |||
944f595841 | |||
492fecc32c |
@ -3,9 +3,11 @@ Username = "ErrorNoWatcher"
|
|||||||
Owners = { "ErrorNoInternet" }
|
Owners = { "ErrorNoInternet" }
|
||||||
|
|
||||||
for _, module in ipairs({
|
for _, module in ipairs({
|
||||||
|
"automation",
|
||||||
"enum",
|
"enum",
|
||||||
"events",
|
"events",
|
||||||
"inventory",
|
"inventory",
|
||||||
|
"lib",
|
||||||
"movement",
|
"movement",
|
||||||
"utils",
|
"utils",
|
||||||
}) do
|
}) do
|
||||||
@ -13,3 +15,5 @@ for _, module in ipairs({
|
|||||||
package.loaded[module] = nil
|
package.loaded[module] = nil
|
||||||
require(module)
|
require(module)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
update_listeners()
|
||||||
|
132
lib/automation.lua
Normal file
132
lib/automation.lua
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
FishingBobber = nil
|
||||||
|
FishingTicks = 0
|
||||||
|
FishLastCaught = 0
|
||||||
|
LastEaten = 0
|
||||||
|
|
||||||
|
function auto_fish()
|
||||||
|
stop_auto_fish()
|
||||||
|
FishingTicks = 0
|
||||||
|
|
||||||
|
function hold_fishing_rod()
|
||||||
|
if client.held_item.kind == "minecraft:fishing_rod" or hold_items({ "minecraft:fishing_rod" }) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
warn("no fishing rod found!")
|
||||||
|
end
|
||||||
|
|
||||||
|
if not hold_fishing_rod() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
add_listener("add_entity", function(entity)
|
||||||
|
if entity.kind == "minecraft:fishing_bobber" and entity.data == client.id then
|
||||||
|
FishingBobber = entity
|
||||||
|
end
|
||||||
|
end, "auto-fish_watch-bobber")
|
||||||
|
|
||||||
|
add_listener("remove_entities", function(entity_ids)
|
||||||
|
if table.contains(entity_ids, FishingBobber.id) then
|
||||||
|
if os.time() - LastEaten < 3 then
|
||||||
|
sleep(3000)
|
||||||
|
end
|
||||||
|
hold_fishing_rod()
|
||||||
|
client:use_item()
|
||||||
|
end
|
||||||
|
end, "auto-fish_watch-bobber")
|
||||||
|
|
||||||
|
add_listener("level_particles", function(particle)
|
||||||
|
if particle.kind == 30 and particle.count == 6 then
|
||||||
|
local current_bobber = client:find_entities(function(e)
|
||||||
|
return e.id == FishingBobber.id
|
||||||
|
end)[1]
|
||||||
|
if distance(current_bobber.position, particle.position) <= 0.75 then
|
||||||
|
FishLastCaught = os.time()
|
||||||
|
client:use_item()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, "auto-fish")
|
||||||
|
|
||||||
|
add_listener("tick", function()
|
||||||
|
FishingTicks = FishingTicks + 1
|
||||||
|
if FishingTicks % 600 ~= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if os.time() - FishLastCaught >= 60 then
|
||||||
|
hold_fishing_rod()
|
||||||
|
client:use_item()
|
||||||
|
end
|
||||||
|
end, "auto-fish_watchdog")
|
||||||
|
|
||||||
|
client:use_item()
|
||||||
|
end
|
||||||
|
|
||||||
|
function stop_auto_fish()
|
||||||
|
remove_listeners("add_entity", "auto-fish_watch-bobber")
|
||||||
|
remove_listeners("remove_entities", "auto-fish_watch-bobber")
|
||||||
|
remove_listeners("level_particles", "auto-fish")
|
||||||
|
remove_listeners("tick", "auto-fish_watchdog")
|
||||||
|
|
||||||
|
if FishingBobber and client:find_entities(function(e)
|
||||||
|
return e.id == FishingBobber.id
|
||||||
|
end)[1] then
|
||||||
|
FishingBobber = nil
|
||||||
|
client:use_item()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function attack_entities(target_kind, minimum)
|
||||||
|
if not minimum then
|
||||||
|
minimum = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function hold_sword()
|
||||||
|
if client.held_item.kind == "minecraft:iron_sword" or hold_items({ "minecraft:iron_sword" }) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
warn("no sword found!")
|
||||||
|
end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local self_pos = client.position
|
||||||
|
local entities = client:find_entities(function(e)
|
||||||
|
return e.kind == target_kind and distance(e.position, self_pos) < 5
|
||||||
|
end)
|
||||||
|
|
||||||
|
if #entities > minimum then
|
||||||
|
local e = entities[1]
|
||||||
|
local pos = e.position
|
||||||
|
pos.y = pos.y + 1.5
|
||||||
|
|
||||||
|
hold_sword()
|
||||||
|
client:look_at(pos)
|
||||||
|
client:attack(e.id)
|
||||||
|
while client.has_attack_cooldown do
|
||||||
|
sleep(100)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
sleep(1000)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function check_food(hunger)
|
||||||
|
if hunger.food >= 20 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local current_time = os.time()
|
||||||
|
if current_time - LastEaten >= 3 then
|
||||||
|
LastEaten = current_time
|
||||||
|
|
||||||
|
while not hold_items({
|
||||||
|
"minecraft:golden_carrot",
|
||||||
|
"minecraft:cooked_beef",
|
||||||
|
"minecraft:bread",
|
||||||
|
}) do
|
||||||
|
sleep(1000)
|
||||||
|
LastEaten = current_time
|
||||||
|
end
|
||||||
|
client:use_item()
|
||||||
|
end
|
||||||
|
end
|
11
lib/enum.lua
11
lib/enum.lua
@ -32,3 +32,14 @@ QUICK_CRAFT_START = 0
|
|||||||
QUICK_CRAFT_ADD = 1
|
QUICK_CRAFT_ADD = 1
|
||||||
QUICK_CRAFT_END = 2
|
QUICK_CRAFT_END = 2
|
||||||
PICKUP_ALL = 11
|
PICKUP_ALL = 11
|
||||||
|
|
||||||
|
POSE_NAMES = {
|
||||||
|
"standing",
|
||||||
|
"flying",
|
||||||
|
"sleeping",
|
||||||
|
"swimming",
|
||||||
|
"attacking",
|
||||||
|
"sneaking",
|
||||||
|
"jumping",
|
||||||
|
"dying",
|
||||||
|
}
|
||||||
|
108
lib/events.lua
108
lib/events.lua
@ -1,30 +1,90 @@
|
|||||||
local center = { x = 0, z = 0 }
|
Center = { x = 0, y = 64, z = 0 }
|
||||||
local radius = 100
|
Radius = 100
|
||||||
|
Whitelist = Owners
|
||||||
|
Ticks = -1
|
||||||
|
|
||||||
function log_player_positions()
|
function check_radius()
|
||||||
local entities = client:find_entities(function(e)
|
Ticks = Ticks + 1
|
||||||
return e.kind == "minecraft:player"
|
if Ticks % 20 ~= 0 then
|
||||||
and e.position.x > center.x - radius + 1
|
return
|
||||||
and e.position.x < center.x + radius
|
end
|
||||||
and e.position.z > center.z - radius
|
|
||||||
and e.position.z < center.z + radius
|
local self_id = client.id
|
||||||
|
local players = client:find_players(function(p)
|
||||||
|
return self_id ~= p.id
|
||||||
|
and p.position.x > Center.x - Radius + 1
|
||||||
|
and p.position.x < Center.x + Radius
|
||||||
|
and p.position.z > Center.z - Radius
|
||||||
|
and p.position.z < Center.z + Radius
|
||||||
end)
|
end)
|
||||||
for _, e in ipairs(entities) do
|
|
||||||
client:chat(string.format("%s (%s) at %.1f %.1f %.1f", e.kind, e.id, e.position.x, e.position.y, e.position.z))
|
local tab_list = client.tab_list
|
||||||
|
for _, player in ipairs(players) do
|
||||||
|
local target
|
||||||
|
for _, tab_player in ipairs(tab_list) do
|
||||||
|
if tab_player.uuid == player.uuid and not table.contains(Whitelist, tab_player.name) then
|
||||||
|
target = tab_player
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not target then
|
||||||
|
goto continue
|
||||||
|
end
|
||||||
|
|
||||||
|
client:chat(
|
||||||
|
string.format(
|
||||||
|
"%s is %s %d blocks away at %.2f %.2f %.2f facing %.2f %.2f",
|
||||||
|
target.name,
|
||||||
|
POSE_NAMES[player.pose + 1],
|
||||||
|
distance(Center, player.position),
|
||||||
|
player.position.x,
|
||||||
|
player.position.y,
|
||||||
|
player.position.z,
|
||||||
|
player.direction.x,
|
||||||
|
player.direction.y
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
::continue::
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
add_listener("init", function()
|
function update_listeners()
|
||||||
info("client initialized, setting information...")
|
for type, listeners in pairs(get_listeners()) do
|
||||||
client:set_client_information({ view_distance = 16 })
|
for id, _ in pairs(listeners) do
|
||||||
end)
|
remove_listeners(type, id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
add_listener("login", function()
|
for type, listeners in pairs({
|
||||||
info("player successfully logged in!")
|
login = {
|
||||||
end)
|
message = function()
|
||||||
|
info("bot successfully logged in!")
|
||||||
add_listener("death", function()
|
end,
|
||||||
warn(string.format("player died at %.1f %.1f %.1f!", client.position.x, client.position.y, client.position.z))
|
eat = function()
|
||||||
end, "warn_player_died")
|
sleep(5000)
|
||||||
|
check_food(client.hunger)
|
||||||
add_listener("tick", log_player_positions)
|
end,
|
||||||
|
},
|
||||||
|
death = {
|
||||||
|
warn_bot_died = function()
|
||||||
|
warn(
|
||||||
|
string.format(
|
||||||
|
"bot died at %.2f %.2f %.2f facing %.2f %.2f!",
|
||||||
|
client.position.x,
|
||||||
|
client.position.y,
|
||||||
|
client.position.z,
|
||||||
|
client.direction.x,
|
||||||
|
client.direction.y
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
set_health = { auto_eat = check_food },
|
||||||
|
tick = { log_player_positions = check_radius },
|
||||||
|
}) do
|
||||||
|
for id, callback in pairs(listeners) do
|
||||||
|
add_listener(type, callback, id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@ -1,10 +1,42 @@
|
|||||||
|
function hold_items_in_hotbar(target_kinds, inventory)
|
||||||
|
if not inventory then
|
||||||
|
inventory = client:open_inventory()
|
||||||
|
end
|
||||||
|
for index, item in ipairs(inventory.contents) do
|
||||||
|
if index >= 37 and index <= 45 and table.contains(target_kinds, item.kind) then
|
||||||
|
inventory = nil
|
||||||
|
sleep(500)
|
||||||
|
client:set_held_slot(index - 37)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function hold_items(target_kinds)
|
||||||
|
local inventory = client:open_inventory()
|
||||||
|
if hold_items_in_hotbar(target_kinds, inventory) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
for index, item in ipairs(inventory.contents) do
|
||||||
|
if table.contains(target_kinds, item.kind) then
|
||||||
|
inventory:click({ source_slot = index - 1, target_slot = client.held_slot }, SWAP)
|
||||||
|
sleep(100)
|
||||||
|
inventory = nil
|
||||||
|
sleep(500)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
inventory = nil
|
||||||
|
sleep(500)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
function steal(item_name)
|
function steal(item_name)
|
||||||
for _, chest_pos in ipairs(client:find_blocks(client.position, get_block_states({ "chest" }))) do
|
for _, chest_pos in ipairs(client:find_blocks(client.position, get_block_states({ "chest" }))) do
|
||||||
client:chat(dump(chest_pos))
|
|
||||||
|
|
||||||
client:go_to({ position = chest_pos, radius = 3 }, { type = RADIUS_GOAL })
|
client:go_to({ position = chest_pos, radius = 3 }, { type = RADIUS_GOAL })
|
||||||
while client.pathfinder.is_calculating or client.pathfinder.is_executing do
|
while client.pathfinder.is_calculating or client.pathfinder.is_executing do
|
||||||
sleep(50)
|
sleep(500)
|
||||||
end
|
end
|
||||||
client:look_at(chest_pos)
|
client:look_at(chest_pos)
|
||||||
|
|
||||||
@ -23,6 +55,23 @@ function steal(item_name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function dump_inventory(hide_empty)
|
||||||
|
local inventory = client:open_inventory()
|
||||||
|
for index, item in ipairs(inventory.contents) do
|
||||||
|
if hide_empty and item.count == 0 then
|
||||||
|
goto continue
|
||||||
|
end
|
||||||
|
|
||||||
|
local item_damage = ""
|
||||||
|
if item.damage then
|
||||||
|
item_damage = item.damage
|
||||||
|
end
|
||||||
|
info(string.format("%-2d = %2dx %-32s %s", index - 1, item.count, item.kind, item_damage))
|
||||||
|
|
||||||
|
::continue::
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function drop_all_hotbar()
|
function drop_all_hotbar()
|
||||||
local inventory = client:open_inventory()
|
local inventory = client:open_inventory()
|
||||||
for i = 0, 9 do
|
for i = 0, 9 do
|
||||||
|
72
lib/lib.lua
Normal file
72
lib/lib.lua
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
function clock_gettime(clock)
|
||||||
|
local status, module = pcall(require, "posix")
|
||||||
|
posix = status and module or nil
|
||||||
|
|
||||||
|
if posix then
|
||||||
|
local s, ns = posix.clock_gettime(clock)
|
||||||
|
return s + ns / (10 ^ (math.floor(math.log10(ns)) + 1))
|
||||||
|
else
|
||||||
|
warn("failed to load posix module! falling back to os.time()")
|
||||||
|
return os.time()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function distance(p1, p2)
|
||||||
|
return math.sqrt((p2.x - p1.x) ^ 2 + (p2.y - p1.y) ^ 2 + (p2.z - p1.z) ^ 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.shallow_copy(t)
|
||||||
|
local t2 = {}
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
t2[k] = v
|
||||||
|
end
|
||||||
|
return t2
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.map(t, f)
|
||||||
|
local t2 = {}
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
t2[k] = f(v)
|
||||||
|
end
|
||||||
|
return t2
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.contains(t, target)
|
||||||
|
for _, v in pairs(t) do
|
||||||
|
if v == target then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function dump(object)
|
||||||
|
if type(object) == "table" then
|
||||||
|
local string = "{ "
|
||||||
|
local parts = {}
|
||||||
|
for key, value in pairs(object) do
|
||||||
|
table.insert(parts, key .. " = " .. dump(value))
|
||||||
|
end
|
||||||
|
string = string .. table.concat(parts, ", ")
|
||||||
|
return string .. " " .. "}"
|
||||||
|
else
|
||||||
|
return tostring(object)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function dumpp(object, level)
|
||||||
|
if not level then
|
||||||
|
level = 0
|
||||||
|
end
|
||||||
|
if type(object) == "table" then
|
||||||
|
local string = "{\n" .. string.rep(" ", level + 1)
|
||||||
|
local parts = {}
|
||||||
|
for key, value in pairs(object) do
|
||||||
|
table.insert(parts, key .. " = " .. dumpp(value, level + 1))
|
||||||
|
end
|
||||||
|
string = string .. table.concat(parts, ",\n" .. string.rep(" ", level + 1))
|
||||||
|
return string .. "\n" .. string.rep(" ", level) .. "}"
|
||||||
|
else
|
||||||
|
return tostring(object)
|
||||||
|
end
|
||||||
|
end
|
@ -3,16 +3,9 @@ function look_at_player(name)
|
|||||||
if player then
|
if player then
|
||||||
player.position.y = player.position.y + 1
|
player.position.y = player.position.y + 1
|
||||||
client:look_at(player.position)
|
client:look_at(player.position)
|
||||||
else
|
|
||||||
client:chat(string.format("/w %s player not found!", sender))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function go_to_player(name, opts)
|
function go_to_player(name, go_to_opts)
|
||||||
local player = get_player(name)
|
client:go_to(get_player(name).position, go_to_opts)
|
||||||
if player then
|
|
||||||
client:go_to(player.position, opts)
|
|
||||||
else
|
|
||||||
client:chat(string.format("/w %s player not found!", sender))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
174
lib/utils.lua
174
lib/utils.lua
@ -1,3 +1,177 @@
|
|||||||
|
SpeedTracking = {}
|
||||||
|
TpsTracking = {}
|
||||||
|
|
||||||
|
function entity_speed(uuid, seconds)
|
||||||
|
if not seconds then
|
||||||
|
seconds = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local callback = function()
|
||||||
|
local old_entity = SpeedTracking[uuid]
|
||||||
|
local new_entity = client:find_entities(function(e)
|
||||||
|
return e.uuid == uuid
|
||||||
|
end)[1]
|
||||||
|
|
||||||
|
if not new_entity then
|
||||||
|
remove_listeners("tick", "speed-tracking_" .. uuid)
|
||||||
|
SpeedTracking[uuid] = -1
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if old_entity then
|
||||||
|
old_entity._distance = old_entity._distance + distance(old_entity.position, new_entity.position)
|
||||||
|
old_entity.position = new_entity.position
|
||||||
|
|
||||||
|
if old_entity._ticks < seconds * 20 then
|
||||||
|
old_entity._ticks = old_entity._ticks + 1
|
||||||
|
else
|
||||||
|
remove_listeners("tick", "speed-tracking_" .. uuid)
|
||||||
|
SpeedTracking[uuid] = old_entity._distance / seconds
|
||||||
|
end
|
||||||
|
else
|
||||||
|
new_entity._ticks = 1
|
||||||
|
new_entity._distance = 0
|
||||||
|
SpeedTracking[uuid] = new_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
add_listener("tick", callback, "speed-tracking_" .. uuid)
|
||||||
|
|
||||||
|
repeat
|
||||||
|
sleep(seconds * 1000 / 10)
|
||||||
|
until type(SpeedTracking[uuid]) == "number"
|
||||||
|
|
||||||
|
local speed = SpeedTracking[uuid]
|
||||||
|
SpeedTracking[uuid] = nil
|
||||||
|
return speed
|
||||||
|
end
|
||||||
|
|
||||||
|
function tps(seconds)
|
||||||
|
if not seconds then
|
||||||
|
seconds = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
add_listener("tick", function()
|
||||||
|
if not TpsTracking.ticks then
|
||||||
|
TpsTracking.ticks = 0
|
||||||
|
TpsTracking.start = clock_gettime(0)
|
||||||
|
else
|
||||||
|
TpsTracking.ticks = TpsTracking.ticks + 1
|
||||||
|
if TpsTracking.ticks >= seconds * 20 then
|
||||||
|
TpsTracking.stop = clock_gettime(0)
|
||||||
|
remove_listeners("tick", "tps_tracking")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end, "tps_tracking")
|
||||||
|
|
||||||
|
sleep(seconds * 1000)
|
||||||
|
repeat
|
||||||
|
sleep(20)
|
||||||
|
until TpsTracking.stop
|
||||||
|
|
||||||
|
local tps = seconds * 20 / (TpsTracking.stop - TpsTracking.start)
|
||||||
|
TpsTracking = {}
|
||||||
|
return tps
|
||||||
|
end
|
||||||
|
|
||||||
|
function nether_travel(pos, go_to_opts)
|
||||||
|
info(string.format("going to %.2f %.2f %.2f through nether", pos.x, pos.y, pos.z))
|
||||||
|
|
||||||
|
local portal_block_states = get_block_states({ "nether_portal" })
|
||||||
|
local nether_pos = table.shallow_copy(pos)
|
||||||
|
nether_pos.x = nether_pos.x / 8
|
||||||
|
nether_pos.z = nether_pos.z / 8
|
||||||
|
|
||||||
|
if client.dimension == "minecraft:overworld" then
|
||||||
|
info("currently in overworld, finding nearest portal")
|
||||||
|
local portals = client:find_blocks(client.position, portal_block_states)
|
||||||
|
|
||||||
|
info(string.format("going to %.2f %.2f %.2f through nether", portals[1].x, portals[1].y, portals[1].z))
|
||||||
|
client:go_to(portals[1], go_to_opts)
|
||||||
|
while client.dimension ~= "minecraft:the_nether" do
|
||||||
|
sleep(1000)
|
||||||
|
end
|
||||||
|
sleep(3000)
|
||||||
|
end
|
||||||
|
|
||||||
|
info(string.format("currently in nether, going to %.2f %.2f", nether_pos.x, nether_pos.z))
|
||||||
|
client:go_to(nether_pos, { type = XZ_GOAL })
|
||||||
|
while client.pathfinder.is_calculating or client.pathfinder.is_executing do
|
||||||
|
sleep(1000)
|
||||||
|
end
|
||||||
|
|
||||||
|
info("arrived, looking for nearest portal")
|
||||||
|
local portals_nether = client:find_blocks(client.position, portal_block_states)
|
||||||
|
if not next(portals_nether) then
|
||||||
|
warn("failed to find portals in the nether")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local found_portal = false
|
||||||
|
for _, portal in ipairs(portals_nether) do
|
||||||
|
if (client.position.y > 127) == (portal.y > 127) then
|
||||||
|
found_portal = true
|
||||||
|
|
||||||
|
info(string.format("found valid portal, going to %.2f %.2f %.2f", portal.x, portal.y, portal.z))
|
||||||
|
client:go_to(portal)
|
||||||
|
while client.dimension ~= "minecraft:overworld" do
|
||||||
|
sleep(1000)
|
||||||
|
end
|
||||||
|
sleep(3000)
|
||||||
|
end
|
||||||
|
|
||||||
|
if found_portal then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not found_portal then
|
||||||
|
warn("failed to find valid portals in the nether")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
info(string.format("back in overworld, going to %.2f %.2f %.2f", pos.x, pos.y, pos.z))
|
||||||
|
client:go_to(pos, go_to_opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
function interact_bed()
|
||||||
|
local bed = client:find_blocks(
|
||||||
|
client.position,
|
||||||
|
get_block_states({
|
||||||
|
"brown_bed",
|
||||||
|
"white_bed",
|
||||||
|
"yellow_bed",
|
||||||
|
})
|
||||||
|
)[1]
|
||||||
|
if not bed then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
client:go_to(bed, { type = REACH_BLOCK_POS_GOAL, options = { without_mining = true } })
|
||||||
|
while client.pathfinder.is_calculating or client.pathfinder.is_executing do
|
||||||
|
sleep(500)
|
||||||
|
end
|
||||||
|
|
||||||
|
client:look_at(bed)
|
||||||
|
client:block_interact(bed)
|
||||||
|
end
|
||||||
|
|
||||||
|
function closest_entity(target_kind)
|
||||||
|
local self_pos = client.position
|
||||||
|
local entities = client:find_entities(function(e)
|
||||||
|
return e.kind == target_kind
|
||||||
|
end)
|
||||||
|
|
||||||
|
local closest_entity = entities[1]
|
||||||
|
local closest_distance = distance(closest_entity.position, self_pos)
|
||||||
|
for _, entity in ipairs(entities) do
|
||||||
|
local dist = distance(entity.position, self_pos)
|
||||||
|
if dist <= closest_distance then
|
||||||
|
closest_entity = entity
|
||||||
|
closest_distance = dist
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return closest_entity
|
||||||
|
end
|
||||||
|
|
||||||
function get_player(name)
|
function get_player(name)
|
||||||
local target_uuid = nil
|
local target_uuid = nil
|
||||||
for _, player in ipairs(client.tab_list) do
|
for _, player in ipairs(client.tab_list) do
|
||||||
|
@ -24,12 +24,11 @@ impl CommandSource {
|
|||||||
.chunks(if self.ncr_options.is_some() { 150 } else { 236 })
|
.chunks(if self.ncr_options.is_some() { 150 } else { 236 })
|
||||||
.map(|chars| chars.iter().collect::<String>())
|
.map(|chars| chars.iter().collect::<String>())
|
||||||
{
|
{
|
||||||
if let (Some(options), Ok(encrypt)) = (
|
if let Some(options) = &self.ncr_options
|
||||||
&self.ncr_options,
|
&& let Ok(encrypt) = self.state.lua.globals().get::<Function>("ncr_encrypt")
|
||||||
self.state.lua.globals().get::<Function>("ncr_encrypt"),
|
&& let Ok(ciphertext) = encrypt.call::<String>((options, prepend_header(&chunk)))
|
||||||
) && let Ok(encrypted) = encrypt.call::<String>((options, prepend_header(&chunk)))
|
|
||||||
{
|
{
|
||||||
chunk = encrypted;
|
chunk = ciphertext;
|
||||||
}
|
}
|
||||||
self.client.chat(
|
self.client.chat(
|
||||||
&(if self.message.is_whisper()
|
&(if self.message.is_whisper()
|
||||||
|
@ -23,26 +23,30 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow:
|
|||||||
Event::Chat(message) => {
|
Event::Chat(message) => {
|
||||||
let globals = state.lua.globals();
|
let globals = state.lua.globals();
|
||||||
let (sender, mut content) = message.split_sender_and_content();
|
let (sender, mut content) = message.split_sender_and_content();
|
||||||
let formatted_message = message.message();
|
let uuid = message.uuid().map(|uuid| uuid.to_string());
|
||||||
info!("{}", formatted_message.to_ansi());
|
let is_whisper = message.is_whisper();
|
||||||
|
let text = message.message();
|
||||||
|
let ansi_text = text.to_ansi();
|
||||||
|
info!("{ansi_text}");
|
||||||
|
|
||||||
if let Some(sender) = sender {
|
if let Some(ref sender) = sender {
|
||||||
let mut ncr_options = None;
|
let mut ncr_options = None;
|
||||||
if let (Ok(options), Ok(decrypt)) = (
|
if let Ok(options) = globals.get::<Table>("NcrOptions")
|
||||||
globals.get::<Table>("NcrOptions"),
|
&& let Ok(decrypt) = globals.get::<Function>("ncr_decrypt")
|
||||||
globals.get::<Function>("ncr_decrypt"),
|
&& let Some(plaintext) = decrypt
|
||||||
) && let Ok(decrypted) =
|
.call::<String>((options.clone(), content.clone()))
|
||||||
decrypt.call::<String>((options.clone(), content.clone()))
|
.ok()
|
||||||
&& let Ok(trimmed) = trim_header(&decrypted)
|
.as_deref()
|
||||||
|
.and_then(|s| trim_header(s).ok())
|
||||||
{
|
{
|
||||||
ncr_options = Some(options);
|
ncr_options = Some(options);
|
||||||
trimmed.clone_into(&mut content);
|
plaintext.clone_into(&mut content);
|
||||||
info!("decrypted message from {sender}: {content}");
|
info!("decrypted message from {sender}: {content}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if message.is_whisper() && globals.get::<Vec<String>>("Owners")?.contains(&sender) {
|
if is_whisper && globals.get::<Vec<String>>("Owners")?.contains(sender) {
|
||||||
if let Err(error) = state.commands.execute(
|
if let Err(error) = state.commands.execute(
|
||||||
content,
|
content.clone(),
|
||||||
CommandSource {
|
CommandSource {
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
message: message.clone(),
|
message: message.clone(),
|
||||||
@ -62,7 +66,14 @@ pub async fn handle_event(client: Client, event: Event, state: State) -> anyhow:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
call_listeners(&state, "chat", formatted_message.to_string()).await;
|
let table = state.lua.create_table()?;
|
||||||
|
table.set("text", text.to_string())?;
|
||||||
|
table.set("ansi_text", ansi_text)?;
|
||||||
|
table.set("sender", sender)?;
|
||||||
|
table.set("content", content)?;
|
||||||
|
table.set("uuid", uuid)?;
|
||||||
|
table.set("is_whisper", is_whisper)?;
|
||||||
|
call_listeners(&state, "chat", table).await;
|
||||||
}
|
}
|
||||||
Event::Death(packet) => {
|
Event::Death(packet) => {
|
||||||
if let Some(packet) = packet {
|
if let Some(packet) = packet {
|
||||||
|
@ -1,27 +1,14 @@
|
|||||||
use super::{Client, Vec3};
|
use super::{Client, Vec3};
|
||||||
use azalea::{
|
use azalea::{
|
||||||
BlockPos, BotClientExt,
|
BlockPos, BotClientExt,
|
||||||
attack::AttackEvent,
|
|
||||||
protocol::packets::game::{ServerboundUseItem, s_interact::InteractionHand},
|
protocol::packets::game::{ServerboundUseItem, s_interact::InteractionHand},
|
||||||
world::MinecraftEntityId,
|
world::MinecraftEntityId,
|
||||||
};
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
use mlua::{Lua, Result, UserDataRef};
|
use mlua::{Lua, Result, UserDataRef};
|
||||||
|
|
||||||
pub async fn attack(_lua: Lua, client: UserDataRef<Client>, entity_id: i32) -> Result<()> {
|
pub fn attack(_lua: &Lua, client: &mut Client, entity_id: i32) -> Result<()> {
|
||||||
client.clone().attack(MinecraftEntityId(entity_id));
|
client.attack(MinecraftEntityId(entity_id));
|
||||||
|
|
||||||
while client.get_tick_broadcaster().recv().await.is_ok() {
|
|
||||||
if client
|
|
||||||
.ecs
|
|
||||||
.lock()
|
|
||||||
.get::<AttackEvent>(client.entity)
|
|
||||||
.is_none()
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,15 +55,16 @@ impl UserData for Client {
|
|||||||
f.add_field_method_get("position", movement::position);
|
f.add_field_method_get("position", movement::position);
|
||||||
f.add_field_method_get("score", state::score);
|
f.add_field_method_get("score", state::score);
|
||||||
f.add_field_method_get("tab_list", tab_list);
|
f.add_field_method_get("tab_list", tab_list);
|
||||||
|
f.add_field_method_get("username", username);
|
||||||
f.add_field_method_get("uuid", uuid);
|
f.add_field_method_get("uuid", uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<M: UserDataMethods<Self>>(m: &mut M) {
|
fn add_methods<M: UserDataMethods<Self>>(m: &mut M) {
|
||||||
m.add_async_method("attack", interaction::attack);
|
m.add_async_method("find_all_entities", world::find_all_entities);
|
||||||
|
m.add_async_method("find_all_players", world::find_all_players);
|
||||||
m.add_async_method("find_entities", world::find_entities);
|
m.add_async_method("find_entities", world::find_entities);
|
||||||
m.add_async_method("find_players", world::find_players);
|
m.add_async_method("find_players", world::find_players);
|
||||||
m.add_async_method("go_to", movement::go_to);
|
m.add_async_method("go_to", movement::go_to);
|
||||||
m.add_async_method("look_at", movement::look_at);
|
|
||||||
m.add_async_method("mine", interaction::mine);
|
m.add_async_method("mine", interaction::mine);
|
||||||
m.add_async_method("open_container_at", container::open_container_at);
|
m.add_async_method("open_container_at", container::open_container_at);
|
||||||
m.add_async_method("set_client_information", state::set_client_information);
|
m.add_async_method("set_client_information", state::set_client_information);
|
||||||
@ -80,8 +81,10 @@ impl UserData for Client {
|
|||||||
m.add_method("stop_pathfinding", movement::stop_pathfinding);
|
m.add_method("stop_pathfinding", movement::stop_pathfinding);
|
||||||
m.add_method("stop_sleeping", movement::stop_sleeping);
|
m.add_method("stop_sleeping", movement::stop_sleeping);
|
||||||
m.add_method("use_item", interaction::use_item);
|
m.add_method("use_item", interaction::use_item);
|
||||||
|
m.add_method_mut("attack", interaction::attack);
|
||||||
m.add_method_mut("block_interact", interaction::block_interact);
|
m.add_method_mut("block_interact", interaction::block_interact);
|
||||||
m.add_method_mut("jump", movement::jump);
|
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("open_inventory", container::open_inventory);
|
||||||
m.add_method_mut("set_direction", movement::set_direction);
|
m.add_method_mut("set_direction", movement::set_direction);
|
||||||
m.add_method_mut("set_jumping", movement::set_jumping);
|
m.add_method_mut("set_jumping", movement::set_jumping);
|
||||||
@ -113,6 +116,10 @@ fn tab_list(_lua: &Lua, client: &Client) -> Result<Vec<Player>> {
|
|||||||
Ok(tab_list)
|
Ok(tab_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn username(_lua: &Lua, client: &Client) -> Result<String> {
|
||||||
|
Ok(client.username())
|
||||||
|
}
|
||||||
|
|
||||||
fn uuid(_lua: &Lua, client: &Client) -> Result<String> {
|
fn uuid(_lua: &Lua, client: &Client) -> Result<String> {
|
||||||
Ok(client.uuid().to_string())
|
Ok(client.uuid().to_string())
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{Client, Direction, Vec3};
|
use super::{Client, Direction, Vec3};
|
||||||
use azalea::{
|
use azalea::{
|
||||||
BlockPos, BotClientExt, LookAtEvent, SprintDirection, WalkDirection,
|
BlockPos, BotClientExt, SprintDirection, WalkDirection,
|
||||||
entity::Position,
|
entity::Position,
|
||||||
interact::HitResultComponent,
|
interact::HitResultComponent,
|
||||||
pathfinder::{
|
pathfinder::{
|
||||||
@ -25,7 +25,7 @@ pub fn eye_position(_lua: &Lua, client: &Client) -> Result<Vec3> {
|
|||||||
pub async fn go_to(
|
pub async fn go_to(
|
||||||
lua: Lua,
|
lua: Lua,
|
||||||
client: UserDataRef<Client>,
|
client: UserDataRef<Client>,
|
||||||
(data, metadata): (Value, Option<Table>),
|
(data, metadata): (Table, Option<Table>),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
fn goto_with_options<G: Goal + Send + Sync + 'static>(
|
fn goto_with_options<G: Goal + Send + Sync + 'static>(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
@ -39,78 +39,48 @@ pub async fn go_to(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn goto<G: Goal + Send + Sync + 'static>(client: &Client, options: Table, goal: G) {
|
let table = metadata.unwrap_or(lua.create_table()?);
|
||||||
if options.get("inverse").unwrap_or_default() {
|
let goal_type = table.get("type").unwrap_or_default();
|
||||||
goto_with_options(client, &options, InverseGoal(goal));
|
let options = table.get("options").unwrap_or(lua.create_table()?);
|
||||||
} else {
|
|
||||||
goto_with_options(client, &options, goal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let error = mlua::Error::FromLuaConversionError {
|
macro_rules! goto {
|
||||||
from: data.type_name(),
|
($goal:expr) => {
|
||||||
to: "Table".to_string(),
|
if options.get("inverse").unwrap_or_default() {
|
||||||
message: None,
|
goto_with_options(&client, &options, InverseGoal($goal));
|
||||||
};
|
} else {
|
||||||
let (goal_type, options) = if let Some(metadata) = metadata {
|
goto_with_options(&client, &options, $goal);
|
||||||
(
|
}
|
||||||
metadata.get("type").unwrap_or_default(),
|
};
|
||||||
metadata.get("options").unwrap_or(lua.create_table()?),
|
}
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(0, lua.create_table()?)
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
match goal_type {
|
match goal_type {
|
||||||
1 => {
|
1 => {
|
||||||
let t = data.as_table().ok_or(error)?;
|
let p = Vec3::from_lua(data.get("position")?, &lua)?;
|
||||||
let p = Vec3::from_lua(t.get("position")?, &lua)?;
|
goto!(RadiusGoal {
|
||||||
goto(
|
pos: azalea::Vec3::new(p.x, p.y, p.z),
|
||||||
&client,
|
radius: data.get("radius")?,
|
||||||
options,
|
});
|
||||||
RadiusGoal {
|
|
||||||
pos: azalea::Vec3::new(p.x, p.y, p.z),
|
|
||||||
radius: t.get("radius")?,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let p = Vec3::from_lua(data, &lua)?;
|
let p = Vec3::from_lua(Value::Table(data), &lua)?;
|
||||||
goto(
|
goto!(ReachBlockPosGoal {
|
||||||
&client,
|
pos: BlockPos::new(p.x as i32, p.y as i32, p.z as i32),
|
||||||
options,
|
chunk_storage: client.world().read().chunks.clone(),
|
||||||
ReachBlockPosGoal {
|
});
|
||||||
pos: BlockPos::new(p.x as i32, p.y as i32, p.z as i32),
|
|
||||||
chunk_storage: client.world().read().chunks.clone(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
let t = data.as_table().ok_or(error)?;
|
goto!(XZGoal {
|
||||||
goto(
|
x: data.get("x")?,
|
||||||
&client,
|
z: data.get("z")?,
|
||||||
options,
|
});
|
||||||
XZGoal {
|
|
||||||
x: t.get("x")?,
|
|
||||||
z: t.get("z")?,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
4 => goto(
|
4 => goto!(YGoal { y: data.get("y")? }),
|
||||||
&client,
|
|
||||||
options,
|
|
||||||
YGoal {
|
|
||||||
y: data.as_table().ok_or(error)?.get("y")?,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_ => {
|
_ => {
|
||||||
let p = Vec3::from_lua(data, &lua)?;
|
let p = Vec3::from_lua(Value::Table(data), &lua)?;
|
||||||
goto(
|
goto!(BlockPosGoal(BlockPos::new(
|
||||||
&client,
|
p.x as i32, p.y as i32, p.z as i32
|
||||||
options,
|
)));
|
||||||
BlockPosGoal(BlockPos::new(p.x as i32, p.y as i32, p.z as i32)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,22 +111,8 @@ pub fn looking_at(lua: &Lua, client: &Client) -> Result<Option<Table>> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn look_at(_lua: Lua, client: UserDataRef<Client>, position: Vec3) -> Result<()> {
|
pub fn look_at(_lua: &Lua, client: &mut Client, position: Vec3) -> Result<()> {
|
||||||
client
|
client.look_at(azalea::Vec3::new(position.x, position.y, position.z));
|
||||||
.clone()
|
|
||||||
.look_at(azalea::Vec3::new(position.x, position.y, position.z));
|
|
||||||
|
|
||||||
while client.get_tick_broadcaster().recv().await.is_ok() {
|
|
||||||
if client
|
|
||||||
.ecs
|
|
||||||
.lock()
|
|
||||||
.get::<LookAtEvent>(client.entity)
|
|
||||||
.is_none()
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,26 +31,26 @@ pub fn score(_lua: &Lua, client: &Client) -> Result<i32> {
|
|||||||
pub async fn set_client_information(
|
pub async fn set_client_information(
|
||||||
_lua: Lua,
|
_lua: Lua,
|
||||||
client: UserDataRef<Client>,
|
client: UserDataRef<Client>,
|
||||||
ci: Table,
|
info: Table,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let model_customization = if let Some(mc) = ci.get::<Option<Table>>("model_customization")? {
|
let get_bool = |table: &Table, name| table.get(name).unwrap_or(true);
|
||||||
ModelCustomization {
|
|
||||||
cape: mc.get("cape")?,
|
|
||||||
jacket: mc.get("jacket")?,
|
|
||||||
left_sleeve: mc.get("left_sleeve")?,
|
|
||||||
right_sleeve: mc.get("right_sleeve")?,
|
|
||||||
left_pants: mc.get("left_pants")?,
|
|
||||||
right_pants: mc.get("right_pants")?,
|
|
||||||
hat: mc.get("hat")?,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ModelCustomization::default()
|
|
||||||
};
|
|
||||||
if let Err(error) = client
|
if let Err(error) = client
|
||||||
.set_client_information(ClientInformation {
|
.set_client_information(ClientInformation {
|
||||||
allows_listing: ci.get("allows_listing")?,
|
allows_listing: info.get("allows_listing")?,
|
||||||
model_customization,
|
model_customization: info
|
||||||
view_distance: ci.get("view_distance").unwrap_or(8),
|
.get::<Table>("model_customization")
|
||||||
|
.map(|t| ModelCustomization {
|
||||||
|
cape: get_bool(&t, "cape"),
|
||||||
|
jacket: get_bool(&t, "jacket"),
|
||||||
|
left_sleeve: get_bool(&t, "left_sleeve"),
|
||||||
|
right_sleeve: get_bool(&t, "right_sleeve"),
|
||||||
|
left_pants: get_bool(&t, "left_pants"),
|
||||||
|
right_pants: get_bool(&t, "right_pants"),
|
||||||
|
hat: get_bool(&t, "hat"),
|
||||||
|
})
|
||||||
|
.unwrap_or_default(),
|
||||||
|
view_distance: info.get("view_distance").unwrap_or(8),
|
||||||
..ClientInformation::default()
|
..ClientInformation::default()
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
#[macro_use]
|
||||||
|
mod queries;
|
||||||
|
|
||||||
use super::{Client, Direction, Vec3};
|
use super::{Client, Direction, Vec3};
|
||||||
use azalea::{
|
use azalea::{
|
||||||
BlockPos,
|
BlockPos,
|
||||||
@ -48,100 +51,90 @@ pub fn find_blocks(
|
|||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn find_all_entities(lua: Lua, client: UserDataRef<Client>, (): ()) -> Result<Vec<Table>> {
|
||||||
|
let mut matched = Vec::new();
|
||||||
|
for (position, custom_name, kind, uuid, direction, id, owner_uuid, pose) in
|
||||||
|
get_entities!(client)
|
||||||
|
{
|
||||||
|
let table = lua.create_table()?;
|
||||||
|
table.set("position", position)?;
|
||||||
|
table.set("custom_name", custom_name)?;
|
||||||
|
table.set("kind", kind)?;
|
||||||
|
table.set("uuid", uuid)?;
|
||||||
|
table.set("direction", direction)?;
|
||||||
|
table.set("id", id)?;
|
||||||
|
table.set(
|
||||||
|
"owner_uuid",
|
||||||
|
owner_uuid.and_then(|v| *v).map(|v| v.to_string()),
|
||||||
|
)?;
|
||||||
|
table.set("pose", pose)?;
|
||||||
|
matched.push(table);
|
||||||
|
}
|
||||||
|
Ok(matched)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn find_entities(
|
pub async fn find_entities(
|
||||||
lua: Lua,
|
lua: Lua,
|
||||||
client: UserDataRef<Client>,
|
client: UserDataRef<Client>,
|
||||||
filter_fn: Function,
|
filter_fn: Function,
|
||||||
) -> Result<Vec<Table>> {
|
) -> Result<Vec<Table>> {
|
||||||
let entities = {
|
|
||||||
let mut ecs = client.ecs.lock();
|
|
||||||
ecs.query::<(
|
|
||||||
&AzaleaPosition,
|
|
||||||
&CustomName,
|
|
||||||
&EntityKind,
|
|
||||||
&EntityUuid,
|
|
||||||
&LookDirection,
|
|
||||||
&MinecraftEntityId,
|
|
||||||
Option<&Owneruuid>,
|
|
||||||
&Pose,
|
|
||||||
)>()
|
|
||||||
.iter(&ecs)
|
|
||||||
.map(
|
|
||||||
|(position, custom_name, kind, uuid, direction, id, owner_uuid, pose)| {
|
|
||||||
(
|
|
||||||
Vec3::from(position),
|
|
||||||
custom_name.as_ref().map(ToString::to_string),
|
|
||||||
kind.to_string(),
|
|
||||||
uuid.to_string(),
|
|
||||||
Direction::from(direction),
|
|
||||||
id.0,
|
|
||||||
owner_uuid.map(ToOwned::to_owned),
|
|
||||||
*pose as u8,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut matched = Vec::new();
|
let mut matched = Vec::new();
|
||||||
for (position, custom_name, kind, uuid, direction, id, owner_uuid, pose) in entities {
|
for (position, custom_name, kind, uuid, direction, id, owner_uuid, pose) in
|
||||||
let entity = lua.create_table()?;
|
get_entities!(client)
|
||||||
entity.set("position", position)?;
|
{
|
||||||
entity.set("custom_name", custom_name)?;
|
let table = lua.create_table()?;
|
||||||
entity.set("kind", kind)?;
|
table.set("position", position)?;
|
||||||
entity.set("uuid", uuid)?;
|
table.set("custom_name", custom_name)?;
|
||||||
entity.set("direction", direction)?;
|
table.set("kind", kind)?;
|
||||||
entity.set("id", id)?;
|
table.set("uuid", uuid)?;
|
||||||
if let Some(v) = owner_uuid
|
table.set("direction", direction)?;
|
||||||
&& let Some(uuid) = *v
|
table.set("id", id)?;
|
||||||
{
|
table.set(
|
||||||
entity.set("owner_uuid", uuid.to_string())?;
|
"owner_uuid",
|
||||||
}
|
owner_uuid.and_then(|v| *v).map(|v| v.to_string()),
|
||||||
entity.set("pose", pose)?;
|
)?;
|
||||||
if filter_fn.call_async::<bool>(&entity).await? {
|
table.set("pose", pose)?;
|
||||||
matched.push(entity);
|
if filter_fn.call_async::<bool>(&table).await? {
|
||||||
|
matched.push(table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(matched)
|
Ok(matched)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn find_players(lua: Lua, client: UserDataRef<Client>, (): ()) -> Result<Vec<Table>> {
|
pub async fn find_all_players(lua: Lua, client: UserDataRef<Client>, (): ()) -> Result<Vec<Table>> {
|
||||||
let entities = {
|
let mut matched = Vec::new();
|
||||||
let mut ecs = client.ecs.lock();
|
for (id, uuid, kind, position, direction, pose) in get_players!(client) {
|
||||||
ecs.query_filtered::<(
|
let table = lua.create_table()?;
|
||||||
&MinecraftEntityId,
|
table.set("id", id)?;
|
||||||
&EntityUuid,
|
table.set("uuid", uuid)?;
|
||||||
&EntityKind,
|
table.set("kind", kind)?;
|
||||||
&AzaleaPosition,
|
table.set("position", position)?;
|
||||||
&LookDirection,
|
table.set("direction", direction)?;
|
||||||
&Pose,
|
table.set("pose", pose)?;
|
||||||
), (With<Player>, Without<Dead>)>()
|
matched.push(table);
|
||||||
.iter(&ecs)
|
|
||||||
.map(|(id, uuid, kind, position, direction, pose)| {
|
|
||||||
(
|
|
||||||
id.0,
|
|
||||||
uuid.to_string(),
|
|
||||||
kind.to_string(),
|
|
||||||
Vec3::from(position),
|
|
||||||
Direction::from(direction),
|
|
||||||
*pose as u8,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut players = Vec::new();
|
|
||||||
for (id, uuid, kind, position, direction, pose) in entities {
|
|
||||||
let entity = lua.create_table()?;
|
|
||||||
entity.set("id", id)?;
|
|
||||||
entity.set("uuid", uuid)?;
|
|
||||||
entity.set("kind", kind)?;
|
|
||||||
entity.set("position", position)?;
|
|
||||||
entity.set("direction", direction)?;
|
|
||||||
entity.set("pose", pose)?;
|
|
||||||
players.push(entity);
|
|
||||||
}
|
}
|
||||||
Ok(players)
|
Ok(matched)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn find_players(
|
||||||
|
lua: Lua,
|
||||||
|
client: UserDataRef<Client>,
|
||||||
|
filter_fn: Function,
|
||||||
|
) -> Result<Vec<Table>> {
|
||||||
|
let mut matched = Vec::new();
|
||||||
|
for (id, uuid, kind, position, direction, pose) in get_players!(client) {
|
||||||
|
let table = lua.create_table()?;
|
||||||
|
table.set("id", id)?;
|
||||||
|
table.set("uuid", uuid)?;
|
||||||
|
table.set("kind", kind)?;
|
||||||
|
table.set("position", position)?;
|
||||||
|
table.set("direction", direction)?;
|
||||||
|
table.set("pose", pose)?;
|
||||||
|
if filter_fn.call_async::<bool>(&table).await? {
|
||||||
|
matched.push(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(matched)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_block_state(_lua: &Lua, client: &Client, position: Vec3) -> Result<Option<u16>> {
|
pub fn get_block_state(_lua: &Lua, client: &Client, position: Vec3) -> Result<Option<u16>> {
|
59
src/lua/client/world/queries.rs
Normal file
59
src/lua/client/world/queries.rs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#[macro_export]
|
||||||
|
macro_rules! get_entities {
|
||||||
|
($client:ident) => {{
|
||||||
|
let mut ecs = $client.ecs.lock();
|
||||||
|
ecs.query::<(
|
||||||
|
&AzaleaPosition,
|
||||||
|
&CustomName,
|
||||||
|
&EntityKind,
|
||||||
|
&EntityUuid,
|
||||||
|
&LookDirection,
|
||||||
|
&MinecraftEntityId,
|
||||||
|
Option<&Owneruuid>,
|
||||||
|
&Pose,
|
||||||
|
)>()
|
||||||
|
.iter(&ecs)
|
||||||
|
.map(
|
||||||
|
|(position, custom_name, kind, uuid, direction, id, owner_uuid, pose)| {
|
||||||
|
(
|
||||||
|
Vec3::from(position),
|
||||||
|
custom_name.as_ref().map(ToString::to_string),
|
||||||
|
kind.to_string(),
|
||||||
|
uuid.to_string(),
|
||||||
|
Direction::from(direction),
|
||||||
|
id.0,
|
||||||
|
owner_uuid.map(ToOwned::to_owned),
|
||||||
|
*pose as u8,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! get_players {
|
||||||
|
($client:ident) => {{
|
||||||
|
let mut ecs = $client.ecs.lock();
|
||||||
|
ecs.query_filtered::<(
|
||||||
|
&MinecraftEntityId,
|
||||||
|
&EntityUuid,
|
||||||
|
&EntityKind,
|
||||||
|
&AzaleaPosition,
|
||||||
|
&LookDirection,
|
||||||
|
&Pose,
|
||||||
|
), (With<Player>, Without<Dead>)>()
|
||||||
|
.iter(&ecs)
|
||||||
|
.map(|(id, uuid, kind, position, direction, pose)| {
|
||||||
|
(
|
||||||
|
id.0,
|
||||||
|
uuid.to_string(),
|
||||||
|
kind.to_string(),
|
||||||
|
Vec3::from(position),
|
||||||
|
Direction::from(direction),
|
||||||
|
*pose as u8,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}};
|
||||||
|
}
|
@ -110,7 +110,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
server.as_ref(),
|
server.as_ref(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
eprintln!("{error:?}");
|
eprintln!("{error}");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user