init.lua 4.2 KB

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