2024-10-28 15:57:54 +01:00
local S = core.get_translator ( " testpathfinder " )
2020-05-24 15:46:26 +02:00
-- 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
2024-10-28 15:57:54 +01:00
core.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 ) )
2020-05-24 15:46:26 +02:00
return
end
local str = S ( " Path from @1 to @2: " ,
2024-10-28 15:57:54 +01:00
core.pos_to_string ( pos1 ) ,
core.pos_to_string ( pos2 ) )
2020-05-24 15:46:26 +02:00
2024-10-28 15:57:54 +01:00
core.chat_send_player ( player : get_player_name ( ) , str )
local time_start = core.get_us_time ( )
local path = core.find_path ( pos1 , pos2 , MAX_SEARCH_DISTANCE , MAX_JUMP , MAX_DROP , algo )
local time_end = core.get_us_time ( )
2020-05-24 15:46:26 +02:00
local time_diff = time_end - time_start
str = " "
if not path then
2024-10-28 15:57:54 +01:00
core.chat_send_player ( player : get_player_name ( ) , S ( " No path! " ) )
core.chat_send_player ( player : get_player_name ( ) , S ( " Time: @1 ms " , time_diff / 1000 ) )
2020-05-24 15:46:26 +02:00
return
end
for s = 1 , # path do
2024-10-28 15:57:54 +01:00
str = str .. core.pos_to_string ( path [ s ] ) .. " \n "
2020-05-24 15:46:26 +02:00
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
2024-10-28 15:57:54 +01:00
core.add_particle ( {
2020-05-24 15:46:26 +02:00
pos = path [ s ] ,
expirationtime = 5 + 0.2 * s ,
playername = player : get_player_name ( ) ,
2024-10-28 15:57:54 +01:00
glow = core.LIGHT_MAX ,
2020-05-24 15:46:26 +02:00
texture = t ,
size = 3 ,
} )
end
2024-10-28 15:57:54 +01:00
core.chat_send_player ( player : get_player_name ( ) , str )
core.chat_send_player ( player : get_player_name ( ) , S ( " Path length: @1 " , # path ) )
core.chat_send_player ( player : get_player_name ( ) , S ( " Time: @1 ms " , time_diff / 1000 ) )
2020-05-24 15:46:26 +02:00
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 )
2024-10-28 15:57:54 +01:00
core.chat_send_player ( user : get_player_name ( ) , S ( " Destination set to @1 " , core.pos_to_string ( pos ) ) )
2020-05-24 15:46:26 +02:00
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 )
2024-10-28 15:57:54 +01:00
core.chat_send_player ( user : get_player_name ( ) , S ( " Algorithm: @1 " , algorithms [ algo + 1 ] ) )
2020-05-24 15:46:26 +02:00
return itemstack
end
end
-- Punch: Find path
-- Sneak+punch: Select pathfinding algorithm
-- Place: Select destination node
2024-10-28 15:57:54 +01:00
core.register_tool ( " testpathfinder:testpathfinder " , {
2020-09-04 20:50:03 +02:00
description = S ( " Pathfinder Tester " ) .. " \n " ..
S ( " Finds path between 2 points " ) .. " \n " ..
S ( " Place on node: Select destination " ) .. " \n " ..
S ( " Punch: Find path from here " ) .. " \n " ..
S ( " Sneak+Punch: Change algorithm " ) ,
2020-05-24 15:46:26 +02:00
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 ,
} )