feat(lib): update examples
This commit is contained in:
		| @@ -3,9 +3,11 @@ Username = "ErrorNoWatcher" | ||||
| Owners = { "ErrorNoInternet" } | ||||
|  | ||||
| for _, module in ipairs({ | ||||
| 	"automation", | ||||
| 	"enum", | ||||
| 	"events", | ||||
| 	"inventory", | ||||
| 	"lib", | ||||
| 	"movement", | ||||
| 	"utils", | ||||
| }) do | ||||
| @@ -13,3 +15,5 @@ for _, module in ipairs({ | ||||
| 	package.loaded[module] = nil | ||||
| 	require(module) | ||||
| 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_END = 2 | ||||
| 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 } | ||||
| local radius = 100 | ||||
| Center = { x = 0, y = 64, z = 0 } | ||||
| Radius = 100 | ||||
| Whitelist = Owners | ||||
| Ticks = -1 | ||||
|  | ||||
| function log_player_positions() | ||||
| 	local entities = client:find_entities(function(e) | ||||
| 		return e.kind == "minecraft:player" | ||||
| 			and e.position.x > center.x - radius + 1 | ||||
| 			and e.position.x < center.x + radius | ||||
| 			and e.position.z > center.z - radius | ||||
| 			and e.position.z < center.z + radius | ||||
| function check_radius() | ||||
| 	Ticks = Ticks + 1 | ||||
| 	if Ticks % 20 ~= 0 then | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| 	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) | ||||
| 	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 | ||||
|  | ||||
| add_listener("init", function() | ||||
| 	info("client initialized, setting information...") | ||||
| 	client:set_client_information({ view_distance = 16 }) | ||||
| end) | ||||
| function update_listeners() | ||||
| 	for type, listeners in pairs(get_listeners()) do | ||||
| 		for id, _ in pairs(listeners) do | ||||
| 			remove_listeners(type, id) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| add_listener("login", function() | ||||
| 	info("player successfully logged in!") | ||||
| end) | ||||
|  | ||||
| add_listener("death", function() | ||||
| 	warn(string.format("player died at %.1f %.1f %.1f!", client.position.x, client.position.y, client.position.z)) | ||||
| end, "warn_player_died") | ||||
|  | ||||
| add_listener("tick", log_player_positions) | ||||
| 	for type, listeners in pairs({ | ||||
| 		login = { | ||||
| 			message = function() | ||||
| 				info("bot successfully logged in!") | ||||
| 			end, | ||||
| 			eat = function() | ||||
| 				sleep(5000) | ||||
| 				check_food(client.hunger) | ||||
| 			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) | ||||
| 	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 }) | ||||
| 		while client.pathfinder.is_calculating or client.pathfinder.is_executing do | ||||
| 			sleep(50) | ||||
| 			sleep(500) | ||||
| 		end | ||||
| 		client:look_at(chest_pos) | ||||
|  | ||||
| @@ -23,6 +55,23 @@ function steal(item_name) | ||||
| 	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() | ||||
| 	local inventory = client:open_inventory() | ||||
| 	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 | ||||
| 		player.position.y = player.position.y + 1 | ||||
| 		client:look_at(player.position) | ||||
| 	else | ||||
| 		client:chat(string.format("/w %s player not found!", sender)) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function go_to_player(name, opts) | ||||
| 	local player = get_player(name) | ||||
| 	if player then | ||||
| 		client:go_to(player.position, opts) | ||||
| 	else | ||||
| 		client:chat(string.format("/w %s player not found!", sender)) | ||||
| 	end | ||||
| function go_to_player(name, go_to_opts) | ||||
| 	client:go_to(get_player(name).position, go_to_opts) | ||||
| 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) | ||||
| 	local target_uuid = nil | ||||
| 	for _, player in ipairs(client.tab_list) do | ||||
|   | ||||
		Reference in New Issue
	
	Block a user