init.lua 24 KB

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