init.lua 24 KB

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