1 local S = minetest.get_translator("testpathfinder")
5 -- Maximum direct distance between start and end
6 local MAX_DIRECT_DISTANCE = 64
7 -- Maximum search distance
8 local MAX_SEARCH_DISTANCE = 32
9 -- Maximum permitted jump height
11 -- Maximum permitted drop height
13 -- If true, mod won't refuse to run pathfinder even at long distances
14 local IGNORE_MAX_DISTANCE_SAFEGUARD = false
16 -- End of config parameters
25 local function find_path_for_player(player, itemstack)
26 local meta = itemstack:get_meta()
30 local x = meta:get_int("pos_x")
31 local y = meta:get_int("pos_y")
32 local z = meta:get_int("pos_z")
33 local algo = meta:get_int("algorithm")
35 local pos2 = {x=x, y=y, z=z}
36 algo = algorithms[algo+1]
37 local pos1 = vector.round(player:get_pos())
38 -- Don't bother calling pathfinder for high distance to avoid freezing
39 if (not IGNORE_MAX_DISTANCE_SAFEGUARD) and (vector.distance(pos1, pos2) > MAX_DIRECT_DISTANCE) then
40 minetest.chat_send_player(player:get_player_name(), S("Destination too far away! Set a destination (via placing) within a distance of @1 and try again!", MAX_DIRECT_DISTANCE))
43 local str = S("Path from @1 to @2:",
44 minetest.pos_to_string(pos1),
45 minetest.pos_to_string(pos2))
47 minetest.chat_send_player(player:get_player_name(), str)
48 local time_start = minetest.get_us_time()
49 local path = minetest.find_path(pos1, pos2, MAX_SEARCH_DISTANCE, MAX_JUMP, MAX_DROP, algo)
50 local time_end = minetest.get_us_time()
51 local time_diff = time_end - time_start
54 minetest.chat_send_player(player:get_player_name(), S("No path!"))
55 minetest.chat_send_player(player:get_player_name(), S("Time: @1 ms", time_diff/1000))
59 str = str .. minetest.pos_to_string(path[s]) .. "\n"
62 t = "testpathfinder_waypoint_end.png"
64 t = "testpathfinder_waypoint_start.png"
66 local c = math.floor(((#path-s)/#path)*255)
67 t = string.format("testpathfinder_waypoint.png^[multiply:#%02x%02x00", 0xFF-c, c)
69 minetest.add_particle({
71 expirationtime = 5 + 0.2 * s,
72 playername = player:get_player_name(),
73 glow = minetest.LIGHT_MAX,
78 minetest.chat_send_player(player:get_player_name(), str)
79 minetest.chat_send_player(player:get_player_name(), S("Path length: @1", #path))
80 minetest.chat_send_player(player:get_player_name(), S("Time: @1 ms", time_diff/1000))
84 local function set_destination(itemstack, user, pointed_thing)
85 if not (user and user:is_player()) then
88 local name = user:get_player_name()
90 local meta = itemstack:get_meta()
91 if pointed_thing.type == "node" then
92 local pos = pointed_thing.above
93 meta:set_int("pos_x", pos.x)
94 meta:set_int("pos_y", pos.y)
95 meta:set_int("pos_z", pos.z)
96 minetest.chat_send_player(user:get_player_name(), S("Destination set to @1", minetest.pos_to_string(pos)))
101 local function find_path_or_set_algorithm(itemstack, user, pointed_thing)
102 if not (user and user:is_player()) then
105 local ctrl = user:get_player_control()
106 -- No sneak: Find path
107 if not ctrl.sneak then
108 find_path_for_player(user, itemstack)
110 -- Sneak: Set algorithm
111 local meta = itemstack:get_meta()
112 local algo = meta:get_int("algorithm")
113 algo = (algo + 1) % #algorithms
114 meta:set_int("algorithm", algo)
115 minetest.chat_send_player(user:get_player_name(), S("Algorithm: @1", algorithms[algo+1]))
121 -- Sneak+punch: Select pathfinding algorithm
122 -- Place: Select destination node
123 minetest.register_tool("testpathfinder:testpathfinder", {
124 description = S("Pathfinder Tester") .."\n"..
125 S("Finds path between 2 points") .."\n"..
126 S("Place on node: Select destination") .."\n"..
127 S("Punch: Find path from here") .."\n"..
128 S("Sneak+Punch: Change algorithm"),
129 inventory_image = "testpathfinder_testpathfinder.png",
130 groups = { testtool = 1, disable_repair = 1 },
131 on_use = find_path_or_set_algorithm,
132 on_secondary_use = set_destination,
133 on_place = set_destination,