api.lua 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. -- Removes a node without calling on on_destruct()
  2. -- We use this to mess with bed nodes without causing unwanted recursion.
  3. local function remove_no_destruct(pos)
  4. minetest.swap_node(pos, {name = "air"})
  5. minetest.remove_node(pos) -- Now clear the meta
  6. minetest.check_for_falling(pos)
  7. end
  8. local function destruct_bed(pos, n)
  9. local node = minetest.get_node(pos)
  10. local other
  11. if n == 2 then
  12. local dir = minetest.facedir_to_dir(node.param2)
  13. other = vector.subtract(pos, dir)
  14. elseif n == 1 then
  15. local dir = minetest.facedir_to_dir(node.param2)
  16. other = vector.add(pos, dir)
  17. end
  18. local oname = minetest.get_node(other).name
  19. if minetest.get_item_group(oname, "bed") ~= 0 then
  20. remove_no_destruct(other)
  21. beds.remove_spawns_at(pos)
  22. beds.remove_spawns_at(other)
  23. end
  24. end
  25. function beds.register_bed(name, def)
  26. minetest.register_node(name .. "_bottom", {
  27. description = def.description,
  28. inventory_image = def.inventory_image,
  29. wield_image = def.wield_image,
  30. drawtype = "nodebox",
  31. tiles = def.tiles.bottom,
  32. use_texture_alpha = "clip",
  33. paramtype = "light",
  34. paramtype2 = "facedir",
  35. is_ground_content = false,
  36. stack_max = 1,
  37. groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1},
  38. sounds = def.sounds or default.node_sound_wood_defaults(),
  39. node_box = {
  40. type = "fixed",
  41. fixed = def.nodebox.bottom,
  42. },
  43. selection_box = {
  44. type = "fixed",
  45. fixed = def.selectionbox,
  46. },
  47. on_place = function(itemstack, placer, pointed_thing)
  48. local under = pointed_thing.under
  49. local node = minetest.get_node(under)
  50. local udef = minetest.registered_nodes[node.name]
  51. if udef and udef.on_rightclick and
  52. not (placer and placer:is_player() and
  53. placer:get_player_control().sneak) then
  54. return udef.on_rightclick(under, node, placer, itemstack,
  55. pointed_thing) or itemstack
  56. end
  57. local pos
  58. if udef and udef.buildable_to then
  59. pos = under
  60. else
  61. pos = pointed_thing.above
  62. end
  63. local player_name = placer and placer:get_player_name() or ""
  64. if minetest.is_protected(pos, player_name) and
  65. not minetest.check_player_privs(player_name, "protection_bypass") then
  66. minetest.record_protection_violation(pos, player_name)
  67. return itemstack
  68. end
  69. local node_def = minetest.registered_nodes[minetest.get_node(pos).name]
  70. if not node_def or not node_def.buildable_to then
  71. return itemstack
  72. end
  73. local dir = placer and placer:get_look_dir() and
  74. minetest.dir_to_facedir(placer:get_look_dir()) or 0
  75. local botpos = vector.add(pos, minetest.facedir_to_dir(dir))
  76. if minetest.is_protected(botpos, player_name) and
  77. not minetest.check_player_privs(player_name, "protection_bypass") then
  78. minetest.record_protection_violation(botpos, player_name)
  79. return itemstack
  80. end
  81. local botdef = minetest.registered_nodes[minetest.get_node(botpos).name]
  82. if not botdef or not botdef.buildable_to then
  83. return itemstack
  84. end
  85. minetest.set_node(pos, {name = name .. "_bottom", param2 = dir})
  86. minetest.set_node(botpos, {name = name .. "_top", param2 = dir})
  87. if not minetest.is_creative_enabled(player_name) then
  88. itemstack:take_item()
  89. end
  90. return itemstack
  91. end,
  92. on_destruct = function(pos)
  93. destruct_bed(pos, 1)
  94. end,
  95. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  96. beds.on_rightclick(pos, clicker)
  97. return itemstack
  98. end,
  99. on_rotate = function(pos, node, user, _, new_param2)
  100. local dir = minetest.facedir_to_dir(node.param2)
  101. -- old position of the top node
  102. local p = vector.add(pos, dir)
  103. local node2 = minetest.get_node_or_nil(p)
  104. if not node2 or minetest.get_item_group(node2.name, "bed") ~= 2 or
  105. node.param2 ~= node2.param2 then
  106. return false
  107. end
  108. if minetest.is_protected(p, user:get_player_name()) then
  109. minetest.record_protection_violation(p, user:get_player_name())
  110. return false
  111. end
  112. if new_param2 % 32 > 3 then
  113. return false
  114. end
  115. -- new position of the top node
  116. local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
  117. local node3 = minetest.get_node_or_nil(newp)
  118. local node_def = node3 and minetest.registered_nodes[node3.name]
  119. if not node_def or not node_def.buildable_to then
  120. return false
  121. end
  122. if minetest.is_protected(newp, user:get_player_name()) then
  123. minetest.record_protection_violation(newp, user:get_player_name())
  124. return false
  125. end
  126. node.param2 = new_param2
  127. remove_no_destruct(p)
  128. minetest.set_node(pos, node)
  129. minetest.set_node(newp, {name = name .. "_top", param2 = new_param2})
  130. return true
  131. end,
  132. can_dig = function(pos, player)
  133. return beds.can_dig(pos)
  134. end,
  135. })
  136. minetest.register_node(name .. "_top", {
  137. drawtype = "nodebox",
  138. tiles = def.tiles.top,
  139. use_texture_alpha = "clip",
  140. paramtype = "light",
  141. paramtype2 = "facedir",
  142. is_ground_content = false,
  143. pointable = false,
  144. groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2,
  145. not_in_creative_inventory = 1},
  146. sounds = def.sounds or default.node_sound_wood_defaults(),
  147. drop = name .. "_bottom",
  148. node_box = {
  149. type = "fixed",
  150. fixed = def.nodebox.top,
  151. },
  152. on_destruct = function(pos)
  153. destruct_bed(pos, 2)
  154. end,
  155. can_dig = function(pos, player)
  156. local node = minetest.get_node(pos)
  157. local dir = minetest.facedir_to_dir(node.param2)
  158. local p = vector.add(pos, dir)
  159. return beds.can_dig(p)
  160. end,
  161. })
  162. minetest.register_alias(name, name .. "_bottom")
  163. minetest.register_craft({
  164. output = name,
  165. recipe = def.recipe
  166. })
  167. end