local positions, index, global_goal local function roundvec(v, d) return vector.divide(vector.round(vector.multiply(v, d)), d) end local function findpath(pos) global_goal = pos index = 2 positions = minetest.find_path( minetest.localplayer:get_pos(), pos, tonumber(minetest.settings:get("goto_max_distance") or 25), tonumber(minetest.settings:get("goto_max_jump") or 1), tonumber(minetest.settings:get("goto_max_drop") or minetest.settings:get_bool("prevent_natural_damage") and 1000 or 5) ) end minetest.register_chatcommand("goto", { description = "Go to a position (use pathfinding).", param = "", func = function(param) if positions then return false, "Goto is still active. Use .gotoabort to abort it." end local success, pos = minetest.parse_pos(param) if not success then return false, pos end findpath(pos) end, }) minetest.register_chatcommand("gotoabort", { description = "Abort goto.", param = "", func = function(param) if not positions then return false, "Goto is currently not running (and also not walking haha)" end minetest.set_keypress("forward", false) minetest.set_keypress("sneak", false) positions, index, global_goal = nil return true, "Aborted." end, }) minetest.register_globalstep(function(dtime) if positions then minetest.set_keypress("forward", true) minetest.set_keypress("sneak", false) local player = minetest.localplayer local pos = player:get_pos() local goal, next_goal = positions[index], positions[index+1] if not goal then positions, index, global_goal = nil minetest.set_keypress("forward", false) minetest.display_chat_message("Reached goal.") return end if next_goal then local d, dn = vector.subtract(pos, goal), vector.subtract(next_goal, goal) for k, v in pairs(dn) do if v ~= 0 and k ~= "y" then local cv = d[k] if v > 0 and cv > 0 or v < 0 and cv < 0 then index = index + 1 goal = next_goal end break end end end local npos = vector.add(goal, {x = 0, y = 1, z = 0}) local node = minetest.get_node_or_nil(npos) if node and node.name ~= air then minetest.dig_node(npos) end local velocity = player:get_velocity() velocity.y = 0 if vector.length(velocity) < 0.1 then findpath(global_goal) return end local distance = vector.distance(pos, goal) if not next_goal and distance < 1 then index = index + 1 end local direction = vector.direction(pos, vector.new(goal.x, 0, goal.z)) local yaw = player:get_yaw() % 360 local goal_yaw = math.deg(math.atan2(-direction.x, direction.z)) % 360 local diff = math.abs(goal_yaw - yaw) if diff > 175 and diff < 185 and distance < 1 then index = index + 1 elseif diff > 10 and diff < 350 then if yaw < goal_yaw and diff < 180 or yaw > goal_yaw and diff > 180 then yaw = yaw + 10 elseif yaw < goal_yaw and diff > 180 or yaw > goal_yaw and diff < 180 then yaw = yaw - 10 end if diff >= 90 and diff <= 270 then minetest.set_keypress("sneak", true) end player:set_yaw(yaw) else player:set_yaw(goal_yaw) end end end)