1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
local S = minetest.get_translator("testpathfinder")
-- Config parameters
-- Maximum direct distance between start and end
local MAX_DIRECT_DISTANCE = 64
-- Maximum search distance
local MAX_SEARCH_DISTANCE = 32
-- Maximum permitted jump height
local MAX_JUMP = 1
-- Maximum permitted drop height
local MAX_DROP = 5
-- If true, mod won't refuse to run pathfinder even at long distances
local IGNORE_MAX_DISTANCE_SAFEGUARD = false
-- End of config parameters
local timer = 0
local algorithms = {
"A*_noprefetch",
"A*",
"Dijkstra",
}
local function find_path_for_player(player, itemstack)
local meta = itemstack:get_meta()
if not meta then
return
end
local x = meta:get_int("pos_x")
local y = meta:get_int("pos_y")
local z = meta:get_int("pos_z")
local algo = meta:get_int("algorithm")
if x and y and z then
local pos2 = {x=x, y=y, z=z}
algo = algorithms[algo+1]
local pos1 = vector.round(player:get_pos())
-- Don't bother calling pathfinder for high distance to avoid freezing
if (not IGNORE_MAX_DISTANCE_SAFEGUARD) and (vector.distance(pos1, pos2) > MAX_DIRECT_DISTANCE) then
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))
return
end
local str = S("Path from @1 to @2:",
minetest.pos_to_string(pos1),
minetest.pos_to_string(pos2))
minetest.chat_send_player(player:get_player_name(), str)
local time_start = minetest.get_us_time()
local path = minetest.find_path(pos1, pos2, MAX_SEARCH_DISTANCE, MAX_JUMP, MAX_DROP, algo)
local time_end = minetest.get_us_time()
local time_diff = time_end - time_start
str = ""
if not path then
minetest.chat_send_player(player:get_player_name(), S("No path!"))
minetest.chat_send_player(player:get_player_name(), S("Time: @1 ms", time_diff/1000))
return
end
for s=1, #path do
str = str .. minetest.pos_to_string(path[s]) .. "\n"
local t
if s == #path then
t = "testpathfinder_waypoint_end.png"
elseif s == 1 then
t = "testpathfinder_waypoint_start.png"
else
local c = math.floor(((#path-s)/#path)*255)
t = string.format("testpathfinder_waypoint.png^[multiply:#%02x%02x00", 0xFF-c, c)
end
minetest.add_particle({
pos = path[s],
expirationtime = 5 + 0.2 * s,
playername = player:get_player_name(),
glow = minetest.LIGHT_MAX,
texture = t,
size = 3,
})
end
minetest.chat_send_player(player:get_player_name(), str)
minetest.chat_send_player(player:get_player_name(), S("Path length: @1", #path))
minetest.chat_send_player(player:get_player_name(), S("Time: @1 ms", time_diff/1000))
end
end
local function set_destination(itemstack, user, pointed_thing)
if not (user and user:is_player()) then
return
end
local name = user:get_player_name()
local obj
local meta = itemstack:get_meta()
if pointed_thing.type == "node" then
local pos = pointed_thing.above
meta:set_int("pos_x", pos.x)
meta:set_int("pos_y", pos.y)
meta:set_int("pos_z", pos.z)
minetest.chat_send_player(user:get_player_name(), S("Destination set to @1", minetest.pos_to_string(pos)))
return itemstack
end
end
local function find_path_or_set_algorithm(itemstack, user, pointed_thing)
if not (user and user:is_player()) then
return
end
local ctrl = user:get_player_control()
-- No sneak: Find path
if not ctrl.sneak then
find_path_for_player(user, itemstack)
else
-- Sneak: Set algorithm
local meta = itemstack:get_meta()
local algo = meta:get_int("algorithm")
algo = (algo + 1) % #algorithms
meta:set_int("algorithm", algo)
minetest.chat_send_player(user:get_player_name(), S("Algorithm: @1", algorithms[algo+1]))
return itemstack
end
end
-- Punch: Find path
-- Sneak+punch: Select pathfinding algorithm
-- Place: Select destination node
minetest.register_tool("testpathfinder:testpathfinder", {
description = S("Pathfinder Tester"),
inventory_image = "testpathfinder_testpathfinder.png",
groups = { testtool = 1, disable_repair = 1 },
on_use = find_path_or_set_algorithm,
on_secondary_use = set_destination,
on_place = set_destination,
})
|