init.lua 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. commandtools = commandtools or {}
  2. commandtools.modpath = minetest.get_modpath("commandtools")
  3. -- Localize for performance.
  4. local vector_round = vector.round
  5. -- Pick.
  6. commandtools.pick_on_use = function(itemstack, user, pointed_thing)
  7. local pname = user:get_player_name()
  8. local havepriv = minetest.check_player_privs(pname, {commandtools_pick=true})
  9. assert(type(havepriv) == "boolean")
  10. if havepriv == false then
  11. -- Try and remove it from the bad player.
  12. itemstack:take_item()
  13. return itemstack
  14. end
  15. if pointed_thing.type == "node" then
  16. local pos = pointed_thing.under
  17. if not pos then return end
  18. if minetest.get_node(pos).name ~= "air" then
  19. minetest.log("action", pname .. " digs " .. minetest.get_node(pos).name .. " at " .. minetest.pos_to_string(pos) .. " using an Admin Pickaxe.")
  20. minetest.remove_node(pos) -- The node is removed directly, which means it even works on non-empty containers and group-less nodes.
  21. minetest.check_for_falling(pos) -- Run node update actions like falling nodes.
  22. end
  23. elseif pointed_thing.type == "object" then
  24. local ref = pointed_thing.ref
  25. if ref then
  26. local tool_capabilities = {
  27. full_punch_interval = 0.1,
  28. max_drop_level = 3,
  29. groupcaps= {
  30. unbreakable = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  31. fleshy = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  32. choppy = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  33. bendy = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  34. cracky = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  35. crumbly = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  36. snappy = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  37. },
  38. damage_groups = {fleshy = 1000},
  39. }
  40. ref:punch(user, 1, tool_capabilities, nil)
  41. end
  42. end
  43. end
  44. -- Inventory is for display purposes only, don't allow taking, putting, or moving items.
  45. local detached_inventory_callbacks = {
  46. allow_move = function() return 0 end,
  47. allow_put = function() return 0 end,
  48. allow_take = function() return 0 end,
  49. }
  50. -- Hoe.
  51. commandtools.hoe_on_use = function(itemstack, user, pointed_thing)
  52. if not user then return end
  53. if not user:is_player() then return end
  54. local havepriv = minetest.check_player_privs(user, {commandtools_hoe=true})
  55. assert(type(havepriv) == "boolean")
  56. if havepriv == false then
  57. -- Try and remove it from the bad player.
  58. itemstack:take_item()
  59. return itemstack
  60. end
  61. if pointed_thing.type == "object" then
  62. local ref = pointed_thing.ref
  63. if ref == nil then return end
  64. if ref:is_player() then
  65. local inv = minetest.create_detached_inventory("commandtools:hoe:inv", detached_inventory_callbacks)
  66. local pinv = ref:get_inventory()
  67. if inv == nil then return end
  68. if pinv == nil then return end
  69. inv:set_size("main", 8*4)
  70. inv:set_list("main", pinv:get_list("main"))
  71. inv:set_size("craft", 3*3)
  72. inv:set_list("craft", pinv:get_list("craft"))
  73. local formspec = "size[8,9]" ..
  74. default.gui_bg ..
  75. default.gui_bg_img ..
  76. default.gui_slots ..
  77. "label[0,0;Static inventory view for player <" .. minetest.formspec_escape(rename.gpn(ref:get_player_name())) .. ">]" ..
  78. "list[detached:commandtools:hoe:inv;craft;0,1;3,3]" ..
  79. "list[detached:commandtools:hoe:inv;main;0,5;8,4]"
  80. minetest.show_formspec(user:get_player_name(), "commandtools:hoe", formspec)
  81. else
  82. -- Pick up item drops, or punch mobs.
  83. local tool_capabilities = {
  84. full_punch_interval = 0.1,
  85. max_drop_level = 3,
  86. groupcaps= {
  87. unbreakable = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  88. fleshy = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  89. choppy = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  90. bendy = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  91. cracky = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  92. crumbly = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  93. snappy = {times={[1] = 0, [2] = 0, [3] = 0}, uses = 0, maxlevel = 3},
  94. },
  95. damage_groups = {fleshy = 1},
  96. }
  97. ref:punch(user, 1, tool_capabilities, nil)
  98. end
  99. elseif pointed_thing.type == "node" then
  100. local pos = pointed_thing.under
  101. if not pos then return end
  102. pos = vector_round(pos)
  103. --sfn.update_node(pos)
  104. --do return end
  105. local node = minetest.get_node(pos)
  106. if node.name == "protector:protect" or
  107. node.name == "protector:protect2" or
  108. node.name == "protector:protect3" or
  109. node.name == "protector:protect4" then
  110. local def = minetest.reg_ns_nodes[node.name]
  111. if def and def.on_punch then
  112. def.on_punch(pos, node, user)
  113. end
  114. else
  115. local owner = protector.get_node_owner(pos)
  116. if owner then
  117. minetest.chat_send_player(user:get_player_name(), "# Server: Block owned by <" .. rename.gpn(owner) .. ">. (Should be protected.)")
  118. else
  119. minetest.chat_send_player(user:get_player_name(), "# Server: Block not owned by anyone.")
  120. end
  121. if minetest.test_protection(pos, "") then
  122. minetest.chat_send_player(user:get_player_name(), "# Server: The location is indeed protected!")
  123. else
  124. minetest.chat_send_player(user:get_player_name(), "# Server: This location is not protected.")
  125. end
  126. end
  127. end
  128. end
  129. local function get_right_dir(fdir)
  130. if fdir.x == 1 then
  131. return {x=0, y=0, z=-1}
  132. elseif fdir.x == -1 then
  133. return {x=0, y=0, z=1}
  134. elseif fdir.z == 1 then
  135. return {x=1, y=0, z=0}
  136. elseif fdir.z == -1 then
  137. return {x=-1, y=0, z=0}
  138. end
  139. return {x=0, y=0, z=0}
  140. end
  141. local function find_floor(pos)
  142. pos = {x=pos.x, y=pos.y+20, z=pos.z}
  143. local name = minetest.get_node(pos).name
  144. while name == "air" or name == "default:snow" do
  145. pos.y = pos.y - 1
  146. name = minetest.get_node(pos).name
  147. end
  148. -- Returns "base" position of the road surface at this location.
  149. pos.y = pos.y + 1
  150. return pos
  151. end
  152. local function choose_dir(dir)
  153. if dir.z == 1 then
  154. return "north"
  155. elseif dir.z == -1 then
  156. return "south"
  157. elseif dir.x == 1 then
  158. return "east"
  159. elseif dir.x == -1 then
  160. return "west"
  161. end
  162. return ""
  163. end
  164. local function fix_param2(pos)
  165. -- Reset param2 on all stonebrick nodes.
  166. local minp = vector.subtract(pos, 7)
  167. local maxp = vector.add(pos, 7)
  168. local nodes = minetest.find_nodes_in_area(minp, maxp, "default:stonebrick")
  169. if nodes then
  170. local stonebrick = {name="default:stonebrick"}
  171. for i=1, #nodes do
  172. minetest.set_node(nodes[i], stonebrick)
  173. local under = vector.add(nodes[i], {x=0, y=-1, z=0})
  174. if minetest.get_node(under).name == "default:stone" then
  175. minetest.set_node(under, stonebrick)
  176. end
  177. end
  178. end
  179. end
  180. local schems = {
  181. north = {
  182. up = {schem = "roadsection_n_up.mts", offset = {x=0, y=0, z=0}, rotation="0", prot = {x=2, y=1, z=3}},
  183. up_steep = {schem = "roadsection_n_up_steep.mts", offset = {x=0, y=0, z=0}, rotation="0", prot = {x=2, y=3, z=3}},
  184. down = {schem = "roadsection_n_down.mts", offset = {x=0, y=-2, z=0}, rotation="0", prot = {x=2, y=-1, z=3}},
  185. down_steep = {schem = "roadsection_n_down_steep.mts", offset = {x=0, y=-5, z=0}, rotation="0", prot = {x=2, y=-2, z=3}},
  186. flat = {schem = "roadsection_ns.mts", offset = {x=0, y=-3, z=0}, rotation="0", prot = {x=2, y=0, z=3}},
  187. corner = {schem = "roadcorner_ne.mts", offset = {x=0, y=-3, z=0}, rotation="90", prot = {x=2, y=0, z=2}},
  188. },
  189. south = {
  190. up = {schem = "roadsection_n_down.mts", offset = {x=-4, y=0, z=-6}, rotation="0", prot = {x=-2, y=1, z=-3}},
  191. up_steep = {schem = "roadsection_n_down_steep.mts", offset = {x=-4, y=0, z=-6}, rotation="0", prot = {x=-2, y=3, z=-3}},
  192. down = {schem = "roadsection_n_up.mts", offset = {x=-4, y=-2, z=-6}, rotation="0", prot = {x=-2, y=-1, z=-3}},
  193. down_steep = {schem = "roadsection_n_up_steep.mts", offset = {x=-4, y=-5, z=-6}, rotation="0", prot = {x=-2, y=-2, z=-3}},
  194. flat = {schem = "roadsection_ns.mts", offset = {x=-4, y=-3, z=-6}, rotation="0", prot = {x=-2, y=0, z=-3}},
  195. corner = {schem = "roadcorner_ne.mts", offset = {x=-4, y=-3, z=-4}, rotation="270", prot = {x=-2, y=0, z=-2}},
  196. },
  197. east = {
  198. up = {schem = "roadsection_n_up.mts", offset = {x=0, y=0, z=-4}, rotation="90", prot = {x=3, y=1, z=-2}},
  199. up_steep = {schem = "roadsection_n_up_steep.mts", offset = {x=0, y=0, z=-4}, rotation="90", prot = {x=3, y=3, z=-2}},
  200. down = {schem = "roadsection_n_down.mts", offset = {x=0, y=-2, z=-4}, rotation="90", prot = {x=3, y=-1, z=-2}},
  201. down_steep = {schem = "roadsection_n_down_steep.mts", offset = {x=0, y=-5, z=-4}, rotation="90", prot = {x=3, y=-2, z=-2}},
  202. flat = {schem = "roadsection_ns.mts", offset = {x=0, y=-3, z=-4}, rotation="90", prot = {x=3, y=0, z=-2}},
  203. corner = {schem = "roadcorner_ne.mts", offset = {x=0, y=-3, z=-4}, rotation="180", prot = {x=2, y=0, z=-2}},
  204. },
  205. west = {
  206. up = {schem = "roadsection_n_down.mts", offset = {x=-6, y=0, z=0}, rotation="90", prot = {x=-3, y=1, z=2}},
  207. up_steep = {schem = "roadsection_n_down_steep.mts", offset = {x=-6, y=0, z=0}, rotation="90", prot = {x=-3, y=3, z=2}},
  208. down = {schem = "roadsection_n_up.mts", offset = {x=-6, y=-2, z=0}, rotation="90", prot = {x=-3, y=-1, z=2}},
  209. down_steep = {schem = "roadsection_n_up_steep.mts", offset = {x=-6, y=-5, z=0}, rotation="90", prot = {x=-3, y=-2, z=2}},
  210. flat = {schem = "roadsection_ns.mts", offset = {x=-6, y=-3, z=0}, rotation="90", prot = {x=-3, y=0, z=2}},
  211. corner = {schem = "roadcorner_ne.mts", offset = {x=-4, y=-3, z=0}, rotation="0", prot = {x=-2, y=0, z=2}},
  212. },
  213. }
  214. local function place_schem(pos, dir, slope, placer)
  215. local data = schems[dir][slope]
  216. local path = commandtools.modpath .. "/schems/" .. data.schem
  217. minetest.place_schematic(vector.add(pos, data.offset), path, data.rotation)
  218. if data.prot then
  219. local p = vector.add(pos, data.prot)
  220. local def = minetest.reg_ns_nodes["protector:protect3"]
  221. if def and def.after_place_node then
  222. minetest.set_node(p, {name="protector:protect3"})
  223. def.after_place_node(p, placer)
  224. end
  225. end
  226. -- Bridge/tunnel building.
  227. local control = placer:get_player_control()
  228. if control.jump then
  229. return
  230. end
  231. if slope ~= "corner" then
  232. local path2 = commandtools.modpath .. "/schems/roadbed_ns.mts"
  233. local bp = vector.add(vector.add(pos, data.offset), {x=0, y=-4, z=0})
  234. for i=1, 3, 1 do
  235. minetest.place_schematic(bp, path2, data.rotation)
  236. bp.y = bp.y - 4
  237. end
  238. local path3 = commandtools.modpath .. "/schems/roadair_ns.mts"
  239. local ap
  240. if slope ~= "up_steep" and slope ~= "down_steep" then
  241. ap = vector.add(vector.add(pos, data.offset), {x=0, y=5, z=0})
  242. else
  243. -- Must start air a little bit higher up.
  244. ap = vector.add(vector.add(pos, data.offset), {x=0, y=7, z=0})
  245. end
  246. for i=1, 3, 1 do
  247. minetest.place_schematic(ap, path3, data.rotation)
  248. ap.y = ap.y + 4
  249. end
  250. else
  251. local path2 = commandtools.modpath .. "/schems/cornerbed_ne.mts"
  252. local bp = vector.add(vector.add(pos, data.offset), {x=0, y=-4, z=0})
  253. for i=1, 3, 1 do
  254. minetest.place_schematic(bp, path2, data.rotation)
  255. bp.y = bp.y - 4
  256. end
  257. local path3 = commandtools.modpath .. "/schems/cornerair_ne.mts"
  258. local ap = vector.add(vector.add(pos, data.offset), {x=0, y=5, z=0})
  259. for i=1, 3, 1 do
  260. minetest.place_schematic(ap, path3, data.rotation)
  261. ap.y = ap.y + 4
  262. end
  263. end
  264. end
  265. local function place_smart(pos, vdir, placer)
  266. local rd = get_right_dir(vdir)
  267. local p1 = vector.add(pos, vector.multiply(vdir, 4))
  268. local p2 = vector.add(p1, vector.multiply(rd, 4))
  269. local p3 = vector.add(pos, vector.multiply(vdir, 8))
  270. local p4 = vector.add(p3, vector.multiply(rd, 4))
  271. local p5 = vector.add(pos, vector.multiply(vdir, 18))
  272. local p6 = vector.add(p5, vector.multiply(rd, 4))
  273. -- Find out whether we are going up, down, or flat.
  274. p1 = find_floor(p1)
  275. p2 = find_floor(p2)
  276. p3 = find_floor(p3)
  277. p4 = find_floor(p4)
  278. p5 = find_floor(p5)
  279. p6 = find_floor(p6)
  280. -- Get the average slope.
  281. local y1 = (p1.y + p2.y + p3.y + p4.y + p5.y + p6.y) / 6
  282. local ny = 0
  283. if y1 < (pos.y - 4) then
  284. place_schem(pos, choose_dir(vdir), "down_steep", placer)
  285. ny = -5
  286. elseif y1 > (pos.y + 4) then
  287. place_schem(pos, choose_dir(vdir), "up_steep", placer)
  288. ny = 5
  289. elseif y1 < (pos.y - 2) then
  290. place_schem(pos, choose_dir(vdir), "down", placer)
  291. ny = -2
  292. elseif y1 > (pos.y + 2) then
  293. place_schem(pos, choose_dir(vdir), "up", placer)
  294. ny = 2
  295. else
  296. place_schem(pos, choose_dir(vdir), "flat", placer)
  297. end
  298. fix_param2(pos)
  299. --minetest.chat_send_player("MustTest", y1 .. ", " .. ny)
  300. -- Returns the wanted position of the next road section.
  301. local rp = vector.add(pos, vector.multiply(vdir, 7))
  302. rp.y = rp.y + ny
  303. return rp
  304. end
  305. commandtools.gateinfo = {
  306. target_pos = {x=0, y=0, z=0},
  307. origin_pos = {x=0, y=0, z=0},
  308. target_dest = {x=0, y=0, z=0},
  309. origin_dest = {x=0, y=0, z=0},
  310. target_owner = "",
  311. origin_owner = "",
  312. direction = ""
  313. }
  314. function commandtools.gaterepair_origin(pname, pos)
  315. local result
  316. local points
  317. local counts
  318. local origin
  319. local northsouth
  320. local ns_key
  321. local playerorigin
  322. -- Find the gateway (threshold under player)!
  323. result, points, counts, origin = schematic_find.detect_schematic(pos, obsidian_gateway.gate_ns_data)
  324. northsouth = true
  325. ns_key = "ns"
  326. if not result then
  327. -- Couldn't find northsouth gateway, so try to find eastwest.
  328. result, points, counts, origin = schematic_find.detect_schematic(pos, obsidian_gateway.gate_ew_data)
  329. northsouth = false
  330. ns_key = "ew"
  331. end
  332. -- Debugging.
  333. if not result then
  334. minetest.chat_send_player(pname, "# Server: Bad gateway.")
  335. return
  336. else
  337. minetest.chat_send_player(pname, "# Server: Found gateway in the " .. rc.pos_to_name(origin) .. " @ " .. rc.pos_to_string(origin) .. ".")
  338. end
  339. if commandtools.gateinfo.direction ~= ns_key then
  340. minetest.chat_send_player(pname, "# Server: Gateway orientations do NOT match!")
  341. return
  342. end
  343. local target = table.copy(commandtools.gateinfo.target_pos)
  344. target = vector_round(target)
  345. if ns_key == "ns" then
  346. playerorigin = vector.add(target, {x=1, y=1, z=0})
  347. elseif ns_key == "ew" then
  348. playerorigin = vector.add(target, {x=0, y=1, z=1})
  349. else
  350. playerorigin = table.copy(target)
  351. end
  352. local meta = minetest.get_meta(origin)
  353. meta:set_string("obsidian_gateway_success_" .. ns_key, "yes")
  354. meta:set_string("obsidian_gateway_destination_" .. ns_key, minetest.pos_to_string(playerorigin))
  355. meta:set_string("obsidian_gateway_owner_" .. ns_key, commandtools.gateinfo.target_owner)
  356. meta:set_int("obsidian_gateway_return_gate_" .. ns_key, 0) -- Not used by origin gates.
  357. minetest.chat_send_player(pname, "# Server: Pasted gateway information (linked ORIGIN to TARGET)!")
  358. end
  359. function commandtools.gaterepair_target(pname, pos)
  360. local result
  361. local points
  362. local counts
  363. local origin
  364. local northsouth
  365. local ns_key
  366. local playerorigin
  367. -- Find the gateway (threshold under player)!
  368. result, points, counts, origin = schematic_find.detect_schematic(pos, obsidian_gateway.gate_ns_data)
  369. northsouth = true
  370. ns_key = "ns"
  371. if not result then
  372. -- Couldn't find northsouth gateway, so try to find eastwest.
  373. result, points, counts, origin = schematic_find.detect_schematic(pos, obsidian_gateway.gate_ew_data)
  374. northsouth = false
  375. ns_key = "ew"
  376. end
  377. -- Debugging.
  378. if not result then
  379. minetest.chat_send_player(pname, "# Server: Bad gateway.")
  380. return
  381. else
  382. minetest.chat_send_player(pname, "# Server: Found gateway in the " .. rc.pos_to_name(origin) .. " @ " .. rc.pos_to_string(origin) .. ".")
  383. end
  384. if commandtools.gateinfo.direction ~= ns_key then
  385. minetest.chat_send_player(pname, "# Server: Gateway orientations do NOT match!")
  386. return
  387. end
  388. local target = table.copy(commandtools.gateinfo.origin_pos)
  389. target = vector_round(target)
  390. if ns_key == "ns" then
  391. playerorigin = vector.add(target, {x=1, y=1, z=0})
  392. elseif ns_key == "ew" then
  393. playerorigin = vector.add(target, {x=0, y=1, z=1})
  394. else
  395. playerorigin = table.copy(target)
  396. end
  397. local meta = minetest.get_meta(origin)
  398. meta:set_string("obsidian_gateway_success_" .. ns_key, "") -- Not used by return gates.
  399. meta:set_string("obsidian_gateway_destination_" .. ns_key, minetest.pos_to_string(playerorigin))
  400. meta:set_string("obsidian_gateway_owner_" .. ns_key, commandtools.gateinfo.origin_owner)
  401. meta:set_int("obsidian_gateway_return_gate_" .. ns_key, 1)
  402. minetest.chat_send_player(pname, "# Server: Pasted gateway information (linked TARGET to ORIGIN)!")
  403. end
  404. function commandtools.gatecopy_origin(pname, pos)
  405. local result
  406. local points
  407. local counts
  408. local origin
  409. local northsouth
  410. local ns_key
  411. local playerorigin
  412. -- Find the gateway (threshold under player)!
  413. result, points, counts, origin = schematic_find.detect_schematic(pos, obsidian_gateway.gate_ns_data)
  414. northsouth = true
  415. ns_key = "ns"
  416. if not result then
  417. -- Couldn't find northsouth gateway, so try to find eastwest.
  418. result, points, counts, origin = schematic_find.detect_schematic(pos, obsidian_gateway.gate_ew_data)
  419. northsouth = false
  420. ns_key = "ew"
  421. end
  422. -- Debugging.
  423. if not result then
  424. minetest.chat_send_player(pname, "# Server: Bad gateway.")
  425. return
  426. else
  427. minetest.chat_send_player(pname, "# Server: Found gateway in the " .. rc.pos_to_name(origin) .. " @ " .. rc.pos_to_string(origin) .. ".")
  428. end
  429. local meta = minetest.get_meta(origin)
  430. local target = minetest.string_to_pos(meta:get_string("obsidian_gateway_destination_" .. ns_key))
  431. local owner = meta:get_string("obsidian_gateway_owner_" .. ns_key)
  432. if target and owner and owner ~= "" then
  433. minetest.chat_send_player(pname, "# Server: Copied ORIGIN gateway information!")
  434. commandtools.gateinfo.origin_pos = vector_round(origin)
  435. commandtools.gateinfo.origin_dest = vector_round(target)
  436. commandtools.gateinfo.origin_owner = owner
  437. commandtools.gateinfo.direction = ns_key
  438. else
  439. minetest.chat_send_player(pname, "# Server: Invalid gateway metadata. Cannot copy!")
  440. end
  441. end
  442. function commandtools.gatecopy_target(pname, pos)
  443. local result
  444. local points
  445. local counts
  446. local origin
  447. local northsouth
  448. local ns_key
  449. local playerorigin
  450. -- Find the gateway (threshold under player)!
  451. result, points, counts, origin = schematic_find.detect_schematic(pos, obsidian_gateway.gate_ns_data)
  452. northsouth = true
  453. ns_key = "ns"
  454. if not result then
  455. -- Couldn't find northsouth gateway, so try to find eastwest.
  456. result, points, counts, origin = schematic_find.detect_schematic(pos, obsidian_gateway.gate_ew_data)
  457. northsouth = false
  458. ns_key = "ew"
  459. end
  460. -- Debugging.
  461. if not result then
  462. minetest.chat_send_player(pname, "# Server: Bad gateway.")
  463. return
  464. else
  465. minetest.chat_send_player(pname, "# Server: Found gateway in the " .. rc.pos_to_name(origin) .. " @ " .. rc.pos_to_string(origin) .. ".")
  466. end
  467. local meta = minetest.get_meta(origin)
  468. local target = minetest.string_to_pos(meta:get_string("obsidian_gateway_destination_" .. ns_key))
  469. local owner = meta:get_string("obsidian_gateway_owner_" .. ns_key)
  470. if target and owner and owner ~= "" then
  471. minetest.chat_send_player(pname, "# Server: Copied TARGET gateway information!")
  472. commandtools.gateinfo.target_pos = vector_round(origin)
  473. commandtools.gateinfo.target_dest = vector_round(target)
  474. commandtools.gateinfo.target_owner = owner
  475. commandtools.gateinfo.direction = ns_key
  476. else
  477. minetest.chat_send_player(pname, "# Server: Invalid gateway metadata. Cannot copy!")
  478. end
  479. end
  480. function commandtools.shovel_on_use(itemstack, user, pt)
  481. if not user then return end
  482. if not user:is_player() then return end
  483. local pname = user:get_player_name()
  484. local havepriv = minetest.check_player_privs(user, {commandtools_shovel=true})
  485. if not havepriv then
  486. -- Try and remove it from the bad player.
  487. itemstack:take_item()
  488. return itemstack
  489. end
  490. if pt.type ~= "node" then
  491. return
  492. end
  493. --[[
  494. local SCHEMATIC_RELP = {x=-4, y=-1, z=-4}
  495. local path = basictrees.modpath .. "/schematics/acacia_tree_from_sapling.mts"
  496. minetest.place_schematic(vector.add(pt.above, SCHEMATIC_RELP), path, "random", nil, false)
  497. --]]
  498. ---[[
  499. if pt.type ~= "node" then
  500. return
  501. end
  502. local control = user:get_player_control()
  503. local ldir = user:get_look_dir()
  504. local fdir = minetest.dir_to_facedir(ldir)
  505. local vdir = minetest.facedir_to_dir(fdir)
  506. -- Start 1 meter ahead of the target node.
  507. local start = vector.add(pt.under, vdir)
  508. if control.left and control.right and control.aux1 then
  509. local pos = {x=start.x, y=start.y, z=start.z}
  510. for i=1, 7, 1 do
  511. pos = place_smart(pos, vdir, user)
  512. end
  513. return
  514. elseif control.left and control.right then
  515. place_smart(start, vdir, user)
  516. return
  517. end
  518. if control.aux1 and not control.sneak and control.up then
  519. place_schem(start, choose_dir(vdir), "up", user)
  520. elseif control.aux1 and control.sneak and control.down then
  521. place_schem(start, choose_dir(vdir), "down_steep", user)
  522. elseif control.aux1 and control.sneak and control.up then
  523. place_schem(start, choose_dir(vdir), "up_steep", user)
  524. elseif control.aux1 and not control.sneak and control.down then
  525. place_schem(start, choose_dir(vdir), "down", user)
  526. elseif control.left then
  527. place_schem(start, choose_dir(vdir), "corner", user)
  528. else
  529. place_schem(start, choose_dir(vdir), "flat", user)
  530. end
  531. fix_param2(start)
  532. --]]
  533. end
  534. function commandtools.gate_on_use(itemstack, user, pt)
  535. if not user then return end
  536. if not user:is_player() then return end
  537. local pname = user:get_player_name()
  538. local havepriv = minetest.check_player_privs(user, {commandtools_shovel=true})
  539. if not havepriv then
  540. -- Try and remove it from the bad player.
  541. itemstack:take_item()
  542. return itemstack
  543. end
  544. local control = user:get_player_control()
  545. local good
  546. local err
  547. if control.aux1 then
  548. if control.sneak then
  549. -- Use + sneak: copy origin gate info.
  550. good, err = pcall(function() commandtools.gatecopy_origin(pname, pt.under) end)
  551. else
  552. -- Use - sneak: copy target gate info.
  553. good, err = pcall(function() commandtools.gatecopy_target(pname, pt.under) end)
  554. end
  555. else
  556. if control.sneak then
  557. -- Sneak (no use): paste target information onto origin gate.
  558. good, err = pcall(function() commandtools.gaterepair_origin(pname, pt.under) end)
  559. else
  560. -- Regular tool use: paste origin information onto target gate.
  561. good, err = pcall(function() commandtools.gaterepair_target(pname, pt.under) end)
  562. end
  563. end
  564. if not good then
  565. minetest.chat_send_player(pname, "# Server: Error running code! " .. err)
  566. else
  567. minetest.chat_send_player(pname, "# Server: Success.")
  568. end
  569. end
  570. -- Run-once initialization code only.
  571. if not commandtools.run_once then
  572. minetest.register_privilege("commandtools_pick", {
  573. description = "Player is allowed to use the Admin Pick.",
  574. give_to_singleplayer = false,
  575. })
  576. -- Used for destroying nodes and killing players/mobs.
  577. minetest.register_tool("commandtools:pick", {
  578. description = "Admin Pick\n\nUse for breaking stuff and killing things!",
  579. range = 12,
  580. inventory_image = "commandtools_pickaxe.png",
  581. groups = {not_in_creative_inventory = 1},
  582. on_use = function(...) return commandtools.pick_on_use(...) end,
  583. })
  584. minetest.register_alias("maptools:pick_admin1", "commandtools:pick")
  585. minetest.register_privilege("commandtools_hoe", {
  586. description = "Player is allowed to use the Admin Hoe.",
  587. give_to_singleplayer = false,
  588. })
  589. -- Used for peaking at a player's inventory.
  590. minetest.register_tool("commandtools:hoe", {
  591. description = "Admin Hoe\n\nUse to look at player inventories & check node protection.",
  592. range = 12,
  593. inventory_image = "commandtools_hoe.png",
  594. groups = {not_in_creative_inventory = 1},
  595. on_use = function(...) return commandtools.hoe_on_use(...) end,
  596. })
  597. minetest.register_privilege("commandtools_shovel", {
  598. description = "Player is allowed to use the Admin Shovel.",
  599. give_to_singleplayer = false,
  600. })
  601. -- Tester tool.
  602. minetest.register_tool("commandtools:shovel", {
  603. description = "Admin Shovel\n\nTester tool.",
  604. range = 12,
  605. inventory_image = "commandtools_shovel.png",
  606. groups = {not_in_creative_inventory = 1},
  607. on_use = function(...) return commandtools.shovel_on_use(...) end,
  608. })
  609. minetest.register_tool("commandtools:gate", {
  610. description = "Admin Gate Repair Tool\n\n" ..
  611. "Hold 'E' to copy gate data, otherwise will paste gate data.\n" ..
  612. "Hold 'sneak' to copy origin gate info, or paste target info onto origin gate.\n" ..
  613. "Otherwise will copy target gate info, or will paste origin info onto target gate.",
  614. range = 12,
  615. inventory_image = "commandtools_shovel.png",
  616. groups = {not_in_creative_inventory = 1},
  617. on_use = function(...) return commandtools.gate_on_use(...) end,
  618. })
  619. -- Reloadable.
  620. local file = commandtools.modpath .. "/init.lua"
  621. local name = "commandtools:core"
  622. reload.register_file(name, file, false)
  623. commandtools.run_once = true
  624. end