api.lua 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. local reverse = true
  2. local function destruct_bed(pos, n)
  3. local node = minetest.get_node(pos)
  4. local other
  5. if n == 2 then
  6. local dir = minetest.facedir_to_dir(node.param2)
  7. other = vector.subtract(pos, dir)
  8. elseif n == 1 then
  9. local meta = minetest.get_meta(pos)
  10. local owner = meta:get_string("owner") or ""
  11. if owner ~= "" and owner ~= "server" then
  12. if beds.spawn[owner] then
  13. local p1 = vector.round(pos)
  14. local p2 = vector.round(beds.spawn[owner])
  15. if vector.equals(p1, p2) then
  16. beds.spawn[owner] = nil
  17. beds.save_spawns()
  18. beds.storage:set_int(owner .. ":count", 0)
  19. chat_core.alert_player_sound(owner)
  20. local RED = core.get_color_escape_sequence("#ff0000")
  21. minetest.chat_send_player(owner, RED .. "# Server: Your primary bed is destroyed. Your home position is LOST!")
  22. else
  23. minetest.chat_send_player(owner, "# Server: A secondary bed owned by you was destroyed.")
  24. end
  25. else
  26. minetest.chat_send_player(owner, "# Server: A bed owned by you was destroyed, but you had no home position set.")
  27. end
  28. end
  29. local dir = minetest.facedir_to_dir(node.param2)
  30. other = vector.add(pos, dir)
  31. end
  32. if reverse then
  33. reverse = not reverse
  34. minetest.remove_node(other)
  35. minetest.check_for_falling(other)
  36. else
  37. reverse = not reverse
  38. end
  39. end
  40. function beds.register_bed(name, def)
  41. minetest.register_node(name .. "_bottom", {
  42. description = def.description,
  43. inventory_image = def.inventory_image,
  44. wield_image = def.wield_image,
  45. drawtype = "nodebox",
  46. tiles = def.tiles.bottom,
  47. paramtype = "light",
  48. paramtype2 = "facedir",
  49. is_ground_content = false,
  50. stack_max = 1,
  51. groups = utility.dig_groups("furniture", {flammable = 3, bed = 1, immovable = 1}),
  52. sounds = def.sounds or default.node_sound_wood_defaults(),
  53. node_box = {
  54. type = "fixed",
  55. fixed = def.nodebox.bottom,
  56. },
  57. selection_box = {
  58. type = "fixed",
  59. fixed = def.selectionbox,
  60. },
  61. on_place = function(itemstack, placer, pointed_thing)
  62. if not placer or not placer:is_player() then
  63. return itemstack
  64. end
  65. local under = pointed_thing.under
  66. local node = minetest.get_node(under)
  67. local udef = minetest.reg_ns_nodes[node.name]
  68. if udef and udef.on_rightclick and
  69. not (placer and placer:get_player_control().sneak) then
  70. return udef.on_rightclick(under, node, placer, itemstack,
  71. pointed_thing) or itemstack
  72. end
  73. local pos
  74. if minetest.registered_items[minetest.get_node(under).name].buildable_to then
  75. pos = under
  76. else
  77. pos = pointed_thing.above
  78. end
  79. if minetest.is_protected(pos, placer:get_player_name()) then
  80. minetest.record_protection_violation(pos, placer:get_player_name())
  81. return itemstack
  82. end
  83. local node_def = minetest.reg_ns_nodes[
  84. minetest.get_node(pos).name]
  85. if not node_def or not node_def.buildable_to then
  86. return itemstack
  87. end
  88. local dir = minetest.dir_to_facedir(placer:get_look_dir())
  89. local botpos = vector.add(pos, minetest.facedir_to_dir(dir))
  90. if minetest.is_protected(botpos, placer:get_player_name()) then
  91. minetest.record_protection_violation(botpos, placer:get_player_name())
  92. return itemstack
  93. end
  94. local botdef = minetest.reg_ns_nodes[
  95. minetest.get_node(botpos).name]
  96. if not botdef or not botdef.buildable_to then
  97. return itemstack
  98. end
  99. minetest.add_node(pos, {name = name .. "_bottom", param2 = dir})
  100. minetest.add_node(botpos, {name = name .. "_top", param2 = dir})
  101. -- If player is holding 'E', then bed shall be public.
  102. do
  103. local control = placer:get_player_control()
  104. if control.aux1 then
  105. local meta = minetest.get_meta(pos)
  106. meta:set_string("owner", "server") -- "server" is a reserved name.
  107. meta:mark_as_private("owner")
  108. meta:set_string("infotext", "Public Bed")
  109. end
  110. end
  111. if not minetest.setting_getbool("creative_mode") then
  112. itemstack:take_item()
  113. end
  114. return itemstack
  115. end,
  116. on_destruct = function(pos)
  117. destruct_bed(pos, 1)
  118. end,
  119. -- TNT+beds=problems.
  120. on_blast = function(pos) end,
  121. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  122. beds.on_rightclick(pos, clicker)
  123. return itemstack
  124. end,
  125. on_rotate = function(pos, node, user, mode, new_param2)
  126. local dir = minetest.facedir_to_dir(node.param2)
  127. local p = vector.add(pos, dir)
  128. local node2 = minetest.get_node_or_nil(p)
  129. if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or
  130. not node.param2 == node2.param2 then
  131. return false
  132. end
  133. if minetest.is_protected(p, user:get_player_name()) then
  134. minetest.record_protection_violation(p, user:get_player_name())
  135. return false
  136. end
  137. if mode ~= screwdriver.ROTATE_FACE then
  138. return false
  139. end
  140. local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
  141. local node3 = minetest.get_node_or_nil(newp)
  142. local node_def = node3 and minetest.reg_ns_nodes[node3.name]
  143. if not node_def or not node_def.buildable_to then
  144. return false
  145. end
  146. if minetest.is_protected(newp, user:get_player_name()) then
  147. minetest.record_protection_violation(newp, user:get_player_name())
  148. return false
  149. end
  150. node.param2 = new_param2
  151. -- do not remove_node here - it will trigger destroy_bed()
  152. minetest.swap_node(p, {name = "air"})
  153. minetest.swap_node(pos, node) -- Do not remove meta.
  154. minetest.add_node(newp, {name = name .. "_top", param2 = new_param2})
  155. return true
  156. end,
  157. -- Called by rename LBM.
  158. _on_rename_check = function(pos)
  159. local meta = minetest.get_meta(pos)
  160. local owner = meta:get_string("owner")
  161. -- Nobody placed this block.
  162. if owner == "" or owner == "server" then
  163. return
  164. end
  165. local dname = rename.gpn(owner)
  166. meta:set_string("rename", dname)
  167. meta:mark_as_private("rename")
  168. meta:set_string("infotext", "Bed (Owned by <" .. dname .. ">!)")
  169. end,
  170. })
  171. minetest.register_node(name .. "_top", {
  172. drawtype = "nodebox",
  173. tiles = def.tiles.top,
  174. paramtype = "light",
  175. paramtype2 = "facedir",
  176. is_ground_content = false,
  177. pointable = false,
  178. groups = utility.dig_groups("furniture", {oddly_breakable_by_hand = 1, flammable = 3, bed = 2, immovable = 1}),
  179. sounds = def.sounds or default.node_sound_wood_defaults(),
  180. drop = name .. "_bottom",
  181. node_box = {
  182. type = "fixed",
  183. fixed = def.nodebox.top,
  184. },
  185. on_destruct = function(pos)
  186. destruct_bed(pos, 2)
  187. end,
  188. -- TNT+beds=problems.
  189. on_blast = function(pos) end,
  190. })
  191. minetest.register_alias(name, name .. "_bottom")
  192. minetest.register_craft({
  193. output = name,
  194. recipe = def.recipe
  195. })
  196. end