init.lua 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. schematic_find = schematic_find or {}
  2. schematic_find.modpath = minetest.get_modpath("schematic_find")
  3. -- Test data.
  4. local o = "default:obsidian"
  5. local a = "air"
  6. local ts = {
  7. data = {
  8. {p={x=0, y=0, z=0}, n=o},
  9. {p={x=1, y=0, z=0}, n=o},
  10. {p={x=2, y=0, z=0}, n=o},
  11. {p={x=3, y=0, z=0}, n=o},
  12. {p={x=0, y=1, z=0}, n=o},
  13. {p={x=0, y=2, z=0}, n=o},
  14. {p={x=0, y=3, z=0}, n=o},
  15. {p={x=0, y=4, z=0}, n=o},
  16. {p={x=1, y=4, z=0}, n=o},
  17. {p={x=2, y=4, z=0}, n=o},
  18. {p={x=3, y=4, z=0}, n=o},
  19. {p={x=3, y=1, z=0}, n=o},
  20. {p={x=3, y=2, z=0}, n=o},
  21. {p={x=3, y=3, z=0}, n=o},
  22. {p={x=1, y=1, z=0}, n=a},
  23. {p={x=2, y=1, z=0}, n=a},
  24. {p={x=1, y=2, z=0}, n=a},
  25. {p={x=2, y=2, z=0}, n=a},
  26. {p={x=1, y=3, z=0}, n=a},
  27. {p={x=2, y=3, z=0}, n=a},
  28. },
  29. minp = {x=0, y=0, z=0},
  30. maxp = {x=3, y=4, z=0},
  31. }
  32. local os = {x=-2, y=-4, z=100}
  33. for k, v in ipairs(ts.data) do
  34. v.p = vector.add(v.p, os)
  35. end
  36. ts.minp = vector.add(ts.minp, os)
  37. ts.maxp = vector.add(ts.maxp, os)
  38. -- API function.
  39. -- Returns boolean success, table of schematic positions,
  40. -- table of node counts, and schematic origin.
  41. function schematic_find.detect_schematic(pos, schematic)
  42. local data = schematic.data
  43. local minp = schematic.minp
  44. local maxp = schematic.maxp
  45. local w = {x=0, y=0, z=0}
  46. local getn = minetest.get_node
  47. -- The extents of the schematic, min and max positions.
  48. for x = minp.x, maxp.x do
  49. for y = minp.y, maxp.y do
  50. for z = minp.z, maxp.z do
  51. local total = 0
  52. local positions = {}
  53. local counts = {}
  54. -- For each point defined in the schematic.
  55. for i = 1, #data do
  56. -- Point in model space.
  57. local p = data[i].p
  58. -- Adjust point relative to current position in schematic.
  59. w.x = p.x - x
  60. w.y = p.y - y
  61. w.z = p.z - z
  62. -- Convert to world-space coordinates.
  63. w.x = w.x + pos.x
  64. w.y = w.y + pos.y
  65. w.z = w.z + pos.z
  66. local n = data[i].n
  67. local nn = getn(w).name
  68. local yes = false
  69. if type(n) == "string" and nn == n then
  70. yes = true
  71. elseif type(n) == "table" then
  72. for j = 1, #n do
  73. if n[j] == nn then
  74. yes = true
  75. break
  76. end
  77. end
  78. elseif type(n) == "function" then
  79. if n(nn) then
  80. yes = true
  81. end
  82. end
  83. if yes then
  84. total = total + 1
  85. positions[#positions+1] = {x=w.x, y=w.y, z=w.z}
  86. local c = counts[nn] or 0
  87. c = c + 1
  88. counts[nn] = c
  89. goto nextpoint
  90. end
  91. goto nextextent
  92. ::nextpoint::
  93. end
  94. if total == #data then
  95. -- We have found the structure.
  96. local origin = {x=pos.x-x+minp.x, y=pos.y-y+minp.y, z=pos.z-z+minp.z}
  97. return true, positions, counts, origin
  98. end
  99. ::nextextent::
  100. end
  101. end
  102. end
  103. end
  104. function schematic_find.test_tool_on_use(itemstack, user, pointed_thing)
  105. if not user or not user:is_player() then
  106. return
  107. end
  108. if pointed_thing.type ~= "node" then
  109. return
  110. end
  111. local pname = user:get_player_name()
  112. local under = pointed_thing.under
  113. minetest.chat_send_player(pname, "# Server: Searching!")
  114. local result, points, counts, origin = schematic_find.detect_schematic(under, ts)
  115. if result then
  116. minetest.chat_send_player(pname, "# Server: Found test schematic!")
  117. local getn = minetest.get_node
  118. local setn = minetest.set_node
  119. local dk = {name="cavestuff:dark_obsidian"}
  120. --for i = 1, #points do
  121. -- if getn(points[i]).name == "default:obsidian" then
  122. -- setn(points[i], dk)
  123. -- end
  124. --end
  125. for k, v in pairs(counts) do
  126. minetest.chat_send_player(pname, "# Server: Found " .. v .. " '" .. k .. "'!")
  127. end
  128. minetest.chat_send_player(pname, "# Server: Origin @ " .. rc.pos_to_namestr(origin) .. "!")
  129. end
  130. end
  131. if not schematic_find.run_once then
  132. minetest.register_tool("schematic_find:test_tool", {
  133. description = "Schematic Search Test Tool",
  134. inventory_image = "default_tool_steelaxe.png",
  135. on_use = function(...)
  136. return schematic_find.test_tool_on_use(...)
  137. end,
  138. })
  139. local c = "schematic_find:core"
  140. local f = schematic_find.modpath .. "/init.lua"
  141. reload.register_file(c, f, false)
  142. schematic_find.run_once = true
  143. end