init.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. doors = {}
  2. -- Registers a door
  3. -- name: The name of the door
  4. -- def: a table with the folowing fields:
  5. -- description
  6. -- inventory_image
  7. -- groups
  8. -- tiles_bottom: the tiles of the bottom part of the door {front, side}
  9. -- tiles_top: the tiles of the bottom part of the door {front, side}
  10. -- If the following fields are not defined the default values are used
  11. -- node_box_bottom
  12. -- node_box_top
  13. -- selection_box_bottom
  14. -- selection_box_top
  15. -- only_placer_can_open: if true only the player who placed the door can
  16. -- open it
  17. -- races: optional; only players from these races can open or dig the door
  18. function doors:register_door(name, def)
  19. def.groups.not_in_creative_inventory = 1
  20. local box = {{-0.5, -0.5, -0.5, 0.5, 0.5, -0.5+1.5/16}}
  21. if not def.node_box_bottom then
  22. def.node_box_bottom = box
  23. end
  24. if not def.node_box_top then
  25. def.node_box_top = box
  26. end
  27. if not def.selection_box_bottom then
  28. def.selection_box_bottom= box
  29. end
  30. if not def.selection_box_top then
  31. def.selection_box_top = box
  32. end
  33. minetest.register_craftitem(name, {
  34. description = def.description,
  35. inventory_image = def.inventory_image,
  36. on_place = function(itemstack, placer, pointed_thing)
  37. if not pointed_thing.type == "node" then
  38. return itemstack
  39. end
  40. local ptu = pointed_thing.under
  41. local nu = minetest.get_node(ptu)
  42. if minetest.registered_nodes[nu.name].on_rightclick then
  43. return minetest.registered_nodes[nu.name].on_rightclick(ptu, nu, placer, itemstack)
  44. end
  45. local pt = pointed_thing.above
  46. local pt2 = {x=pt.x, y=pt.y, z=pt.z}
  47. pt2.y = pt2.y+1
  48. if
  49. not minetest.registered_nodes[minetest.get_node(pt).name].buildable_to or
  50. not minetest.registered_nodes[minetest.get_node(pt2).name].buildable_to or
  51. not placer or
  52. not placer:is_player()
  53. then
  54. return itemstack
  55. end
  56. if minetest.is_protected(pt, placer:get_player_name()) or
  57. minetest.is_protected(pt2, placer:get_player_name()) then
  58. minetest.record_protection_violation(pt, placer:get_player_name())
  59. return itemstack
  60. end
  61. local p2 = minetest.dir_to_facedir(placer:get_look_dir())
  62. local pt3 = {x=pt.x, y=pt.y, z=pt.z}
  63. if p2 == 0 then
  64. pt3.x = pt3.x-1
  65. elseif p2 == 1 then
  66. pt3.z = pt3.z+1
  67. elseif p2 == 2 then
  68. pt3.x = pt3.x+1
  69. elseif p2 == 3 then
  70. pt3.z = pt3.z-1
  71. end
  72. if minetest.get_item_group(minetest.get_node(pt3).name, "door") == 0 then
  73. minetest.set_node(pt, {name=name.."_b_1", param2=p2})
  74. minetest.set_node(pt2, {name=name.."_t_1", param2=p2})
  75. else
  76. minetest.set_node(pt, {name=name.."_b_2", param2=p2})
  77. minetest.set_node(pt2, {name=name.."_t_2", param2=p2})
  78. end
  79. local meta = minetest.get_meta(pt)
  80. meta:set_string("state", "closed")
  81. meta = minetest.get_meta(pt2)
  82. meta:set_string("state", "closed")
  83. if def.only_placer_can_open then
  84. local pn = placer:get_player_name()
  85. meta = minetest.get_meta(pt)
  86. meta:set_string("doors_owner", pn)
  87. meta:set_string("infotext", "Owned by "..pn)
  88. meta = minetest.get_meta(pt2)
  89. meta:set_string("doors_owner", pn)
  90. meta:set_string("infotext", "Owned by "..pn)
  91. end
  92. if def.custom_on_place then
  93. def.custom_on_place(itemstack, placer, pointed_thing, def)
  94. end
  95. if not minetest.setting_getbool("creative_mode") then
  96. itemstack:take_item()
  97. end
  98. return itemstack
  99. end,
  100. })
  101. local tt = def.tiles_top
  102. local tb = def.tiles_bottom
  103. local function after_dig_node(pos, name)
  104. if minetest.get_node(pos).name == name then
  105. minetest.remove_node(pos)
  106. end
  107. end
  108. local function on_rightclick(pos, dir, check_name, replace, replace_dir, params)
  109. pos.y = pos.y+dir
  110. if not minetest.get_node(pos).name == check_name then
  111. return
  112. end
  113. local p2 = minetest.get_node(pos).param2
  114. p2 = params[p2+1]
  115. local meta = minetest.get_meta(pos)
  116. if meta:get_string("state") == "open" then
  117. minetest.sound_play(def.sound_close, {pos = pos, gain = 0.3, max_hear_distance = 10})
  118. meta:set_string("state", "closed")
  119. else
  120. minetest.sound_play(def.sound_open, {pos = pos, gain = 0.3, max_hear_distance = 10})
  121. meta:set_string("state", "open")
  122. end
  123. minetest.swap_node(pos, {name=replace_dir, param2=p2})
  124. pos.y = pos.y-dir
  125. minetest.swap_node(pos, {name=replace, param2=p2})
  126. end
  127. local function check_player_priv(pos, player)
  128. if not def.only_placer_can_open and not def.races then
  129. return true
  130. end
  131. local meta = minetest.get_meta(pos)
  132. local pn = player:get_player_name()
  133. return (def.only_placer_can_open and meta:get_string("doors_owner") == pn) or
  134. (def.races and lottclasses.player_race_in_table(player, def.races)) or
  135. minetest.check_player_privs(pn, {GAMEwizard = true})
  136. end
  137. local function check_can_dig(pos, player)
  138. if not def.only_placer_can_open then
  139. return true
  140. end
  141. local meta = minetest.get_meta(pos)
  142. local pn = player:get_player_name()
  143. return (def.only_placer_can_open and meta:get_string("doors_owner") == pn) or minetest.check_player_privs(pn, {GAMEwizard = true})
  144. end
  145. local tb_final_1 = nil
  146. if table.getn(tb) > 2 then
  147. tb_final_1 = {tb[1], tb[2], tb[3], tb[4], tb[5], tb[6].."^[transformfx"}
  148. else
  149. tb_final_1 = {tb[2], tb[2], tb[2], tb[2], tb[1], tb[1].."^[transformfx"}
  150. end
  151. minetest.register_node(name.."_b_1", {
  152. tiles = tb_final_1,
  153. paramtype = "light",
  154. paramtype2 = "facedir",
  155. drop = name,
  156. drawtype = "nodebox",
  157. node_box = {
  158. type = "fixed",
  159. fixed = def.node_box_bottom
  160. },
  161. selection_box = {
  162. type = "fixed",
  163. fixed = def.selection_box_bottom
  164. },
  165. groups = def.groups,
  166. after_dig_node = function(pos, oldnode, oldmetadata, digger)
  167. pos.y = pos.y+1
  168. after_dig_node(pos, name.."_t_1")
  169. end,
  170. on_rightclick = function(pos, node, clicker)
  171. if check_player_priv(pos, clicker) then
  172. on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0})
  173. end
  174. end,
  175. can_dig = check_can_dig,
  176. })
  177. local tt_final_1 = nil
  178. if table.getn(tt) > 2 then
  179. tt_final_1 = {tt[1], tt[2], tt[3], tt[4], tt[5], tt[6].."^[transformfx"}
  180. else
  181. tt_final_1 = {tt[2], tt[2], tt[2], tt[2], tt[1], tt[1].."^[transformfx"}
  182. end
  183. minetest.register_node(name.."_t_1", {
  184. tiles = tt_final_1,
  185. paramtype = "light",
  186. paramtype2 = "facedir",
  187. drop = name,
  188. drawtype = "nodebox",
  189. node_box = {
  190. type = "fixed",
  191. fixed = def.node_box_top
  192. },
  193. selection_box = {
  194. type = "fixed",
  195. fixed = def.selection_box_top
  196. },
  197. groups = def.groups,
  198. after_dig_node = function(pos, oldnode, oldmetadata, digger)
  199. pos.y = pos.y-1
  200. after_dig_node(pos, name.."_b_1")
  201. end,
  202. on_rightclick = function(pos, node, clicker)
  203. if check_player_priv(pos, clicker) then
  204. on_rightclick(pos, -1, name.."_b_1", name.."_t_2", name.."_b_2", {1,2,3,0})
  205. end
  206. end,
  207. can_dig = check_can_dig,
  208. })
  209. local tb_final_2 = nil
  210. if table.getn(tb) > 2 then
  211. tb_final_2 = {tb[1], tb[2], tb[3], tb[4], tb[5].."^[transformfx", tb[6]}
  212. else
  213. tb_final_2 = {tb[2], tb[2], tb[2], tb[2], tb[1].."^[transformfx", tb[1]}
  214. end
  215. minetest.register_node(name.."_b_2", {
  216. tiles = tb_final_2,
  217. paramtype = "light",
  218. paramtype2 = "facedir",
  219. drop = name,
  220. drawtype = "nodebox",
  221. node_box = {
  222. type = "fixed",
  223. fixed = def.node_box_bottom
  224. },
  225. selection_box = {
  226. type = "fixed",
  227. fixed = def.selection_box_bottom
  228. },
  229. groups = def.groups,
  230. after_dig_node = function(pos, oldnode, oldmetadata, digger)
  231. pos.y = pos.y+1
  232. after_dig_node(pos, name.."_t_2")
  233. end,
  234. on_rightclick = function(pos, node, clicker)
  235. if check_player_priv(pos, clicker) then
  236. on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2})
  237. end
  238. end,
  239. can_dig = check_can_dig,
  240. })
  241. local tt_final_2 = nil
  242. if table.getn(tt) > 2 then
  243. tt_final_2 = {tt[1], tt[2], tt[3], tt[4], tt[5].."^[transformfx", tt[6]}
  244. else
  245. tt_final_2 = {tt[2], tt[2], tt[2], tt[2], tt[1].."^[transformfx", tt[1]}
  246. end
  247. minetest.register_node(name.."_t_2", {
  248. tiles = tt_final_2,
  249. paramtype = "light",
  250. paramtype2 = "facedir",
  251. drop = name,
  252. drawtype = "nodebox",
  253. node_box = {
  254. type = "fixed",
  255. fixed = def.node_box_top
  256. },
  257. selection_box = {
  258. type = "fixed",
  259. fixed = def.selection_box_top
  260. },
  261. groups = def.groups,
  262. after_dig_node = function(pos, oldnode, oldmetadata, digger)
  263. pos.y = pos.y-1
  264. after_dig_node(pos, name.."_b_2")
  265. end,
  266. on_rightclick = function(pos, node, clicker)
  267. if check_player_priv(pos, clicker) then
  268. on_rightclick(pos, -1, name.."_b_2", name.."_t_1", name.."_b_1", {3,0,1,2})
  269. end
  270. end,
  271. can_dig = check_can_dig,
  272. })
  273. end
  274. doors:register_door("doors:door_wood", {
  275. description = "Wooden Door",
  276. inventory_image = "door_wood.png",
  277. groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=2,door=1},
  278. tiles_bottom = {"door_wood_b.png", "door_brown.png"},
  279. tiles_top = {"door_wood_a.png", "door_brown.png"},
  280. sounds = default.node_sound_wood_defaults(),
  281. sound_open = "doors_door_open",
  282. sound_close = "doors_door_close"
  283. })
  284. minetest.register_craft({
  285. output = "doors:door_wood",
  286. recipe = {
  287. {"default:wood", "default:wood"},
  288. {"default:wood", "default:wood"},
  289. {"default:wood", "default:wood"}
  290. }
  291. })
  292. doors:register_door("doors:door_steel", {
  293. description = "Steel Door",
  294. inventory_image = "door_steel.png",
  295. groups = {snappy=1,bendy=2,cracky=1,melty=2,level=2,door=1},
  296. tiles_bottom = {"door_steel_b.png", "door_grey.png"},
  297. tiles_top = {"door_steel_a.png", "door_grey.png"},
  298. only_placer_can_open = true,
  299. })
  300. minetest.register_craft({
  301. output = "doors:door_steel",
  302. recipe = {
  303. {"default:steel_ingot", "default:steel_ingot"},
  304. {"default:steel_ingot", "default:steel_ingot"},
  305. {"default:steel_ingot", "default:steel_ingot"}
  306. }
  307. })
  308. minetest.register_alias("doors:door_wood_a_c", "doors:door_wood_t_1")
  309. minetest.register_alias("doors:door_wood_a_o", "doors:door_wood_t_1")
  310. minetest.register_alias("doors:door_wood_b_c", "doors:door_wood_b_1")
  311. minetest.register_alias("doors:door_wood_b_o", "doors:door_wood_b_1")
  312. doors:register_door("doors:door_glass", {
  313. description = "Glass Door",
  314. inventory_image = "door_glass.png",
  315. groups = {snappy=1,cracky=1,oddly_breakable_by_hand=3,door=1},
  316. tiles_bottom = {"door_glass_b.png", "door_glass_side.png"},
  317. tiles_top = {"door_glass_a.png", "door_glass_side.png"},
  318. sounds = default.node_sound_glass_defaults(),
  319. sunlight = true,
  320. })
  321. minetest.register_craft({
  322. output = "doors:door_glass",
  323. recipe = {
  324. {"default:glass", "default:glass"},
  325. {"default:glass", "default:glass"},
  326. {"default:glass", "default:glass"}
  327. }
  328. })
  329. ----trapdoor----
  330. function doors.register_trapdoor(name, def)
  331. local name_closed = name
  332. local name_opened = name.."_open"
  333. def.on_rightclick = function (pos, node)
  334. local newname = node.name == name_closed and name_opened or name_closed
  335. if node.name == name_closed then sound = def.sound_open end
  336. if node.name == name_opened then sound = def.sound_close end
  337. if sound then
  338. minetest.sound_play(sound, {pos = pos, gain = 0.3, max_hear_distance = 10})
  339. end
  340. minetest.set_node(pos, {name = newname, param1 = node.param1, param2 = node.param2})
  341. end
  342. -- Common trapdoor configuration
  343. def.drawtype = "nodebox"
  344. def.paramtype = "light"
  345. def.paramtype2 = "facedir"
  346. local def_opened = table.copy(def)
  347. local def_closed = table.copy(def)
  348. def_closed.node_box = {
  349. type = "fixed",
  350. fixed = {-0.5, -0.5, -0.5, 0.5, -0.4, 0.5}
  351. }
  352. def_closed.selection_box = {
  353. type = "fixed",
  354. fixed = {-0.5, -0.5, -0.5, 0.5, -0.4, 0.5}
  355. }
  356. def_closed.tiles = { def.tile_closed, def.tile_closed, def.tile_side, def.tile_side,
  357. def.tile_side, def.tile_side }
  358. def_opened.node_box = {
  359. type = "fixed",
  360. fixed = {-0.5, -0.5, 0.4, 0.5, 0.5, 0.5}
  361. }
  362. def_opened.selection_box = {
  363. type = "fixed",
  364. fixed = {-0.5, -0.5, 0.4, 0.5, 0.5, 0.5}
  365. }
  366. def_opened.tiles = { def.tile_side, def.tile_side, def.tile_side, def.tile_side,
  367. def.tile_open, def.tile_open }
  368. def_opened.drop = name_closed
  369. def_opened.climbable = true
  370. def_opened.groups.not_in_creative_inventory = 1
  371. minetest.register_node(name_opened, def_opened)
  372. minetest.register_node(name_closed, def_closed)
  373. end
  374. doors.register_trapdoor("doors:trapdoor", {
  375. description = "Trapdoor",
  376. inventory_image = "door_trapdoor.png",
  377. wield_image = "door_trapdoor.png",
  378. tile_open = "door_trapdoor_open.png",
  379. tile_closed = "door_trapdoor.png",
  380. tile_side = "door_trapdoor_side.png",
  381. groups = {snappy=1, choppy=2, oddly_breakable_by_hand=2, flammable=2, door=1},
  382. sounds = default.node_sound_wood_defaults(),
  383. sound_open = "doors_door_open",
  384. sound_close = "doors_door_close"
  385. })
  386. minetest.register_craft({
  387. output = 'doors:trapdoor',
  388. recipe = {
  389. {'default:wood', 'default:wood'},
  390. {'default:wood', 'default:wood'},
  391. }
  392. })