init.lua 25 KB

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