init.lua 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. voidchest = voidchest or {}
  2. voidchest.modpath = minetest.get_modpath("voidchest")
  3. local function get_chest_formspec()
  4. -- Obtain hooks into the trash mod's trash slot inventory.
  5. local ltrash, mtrash = trash.get_listname()
  6. local itrash = trash.get_iconname()
  7. local formspec = "size[14,9]" ..
  8. default.gui_bg ..
  9. default.gui_bg_img ..
  10. default.gui_slots ..
  11. "list[current_player;voidchest:voidchest;0,0.3;14,4;]" ..
  12. "list[current_player;main;2,4.85;8,1;]" ..
  13. "list[current_player;main;2,6.08;8,3;8]" ..
  14. "listring[current_player;voidchest:voidchest]" ..
  15. "listring[current_player;main]" ..
  16. default.get_hotbar_bg(2, 4.85)
  17. -- Trash icon.
  18. .. "list[" .. ltrash .. ";" .. mtrash .. ";11,4.85;1,1;]" ..
  19. "image[11,4.85;1,1;" .. itrash .. "]"
  20. return formspec
  21. end
  22. local open_chests = {}
  23. local function chest_lid_obstructed(pos)
  24. local above = {x=pos.x, y=pos.y+1, z=pos.z}
  25. local def = minetest.reg_ns_nodes[minetest.get_node(above).name]
  26. -- Unknown node obstructs.
  27. if not def then
  28. return true
  29. end
  30. -- Allow ladders, signs, wallmounted things and torches to not obstruct.
  31. if def.drawtype == "airlike" or
  32. def.drawtype == "signlike" or
  33. def.drawtype == "torchlike" or
  34. (def.drawtype == "nodebox" and def.paramtype2 == "wallmounted") then
  35. return false
  36. end
  37. return true
  38. end
  39. local function open_chest(pname, pos, node)
  40. ambiance.sound_play("default_chest_open", pos, 0.5, 10)
  41. if not chest_lid_obstructed(pos) then
  42. minetest.swap_node(pos, {
  43. name = "voidchest:voidchest_opened",
  44. param2 = node.param2,
  45. })
  46. end
  47. minetest.after(0.2, minetest.show_formspec,
  48. pname, "voidchest:chest", get_chest_formspec())
  49. open_chests[pname] = {pos=pos}
  50. end
  51. local function close_chest(pname, pos, node)
  52. open_chests[pname] = nil
  53. minetest.after(0.2, minetest.swap_node, pos, {
  54. name = "voidchest:voidchest_closed",
  55. param2 = node.param2
  56. })
  57. ambiance.sound_play("default_chest_close", pos, 0.5, 10)
  58. end
  59. -- Guard against players leaving the game while a chest is open.
  60. minetest.register_on_leaveplayer(function(player, timeout)
  61. if not player or not player:is_player() then return end
  62. local pn = player:get_player_name()
  63. if open_chests[pn] then
  64. local pos = open_chests[pn].pos
  65. local node = minetest.get_node(pos)
  66. local sound = open_chests[pn].sound
  67. local swap = open_chests[pn].swap
  68. close_chest(pn, pos, node, swap, sound)
  69. end
  70. end)
  71. minetest.register_on_player_receive_fields(function(player, formname, fields)
  72. if formname ~= "voidchest:chest" then return end -- Wrong formspec.
  73. local pname = player:get_player_name()
  74. if not open_chests[pname] then return true end -- No opened chest.
  75. local pos = open_chests[pname].pos
  76. local node = minetest.get_node(pos)
  77. local nn = node.name
  78. if nn ~= "voidchest:voidchest_opened" then return true end -- Wrong node!
  79. if fields.quit then
  80. close_chest(pname, pos, node)
  81. end
  82. return true
  83. end)
  84. local function perform_inventory_check(player)
  85. local inv = player:get_inventory()
  86. inv:set_size("voidchest:voidchest", 14*4)
  87. end
  88. -- Definitions common to both open and closed variants on the starfissure chest.
  89. local VOIDCHEST_DEF = {
  90. drawtype = "mesh",
  91. visual = "mesh",
  92. paramtype = "light",
  93. paramtype2 = "facedir",
  94. legacy_facedir_simple = true,
  95. is_ground_content = false,
  96. description = "Star-Fissure Chest\n\nHas a shared inventory with other Star-Fissure Chests.\nIs volatile when dug!",
  97. tiles = {"voidchest_voidchest.png"},
  98. drop = "starpearl:pearl 8",
  99. groups = utility.dig_groups("chest", {
  100. immovable = 1, -- No pistons, no nothing.
  101. chest = 1,
  102. }),
  103. sounds = default.node_sound_stone_defaults(),
  104. -- After digging chest, sometimes, a nasty surprise.
  105. after_dig_node = function(pos, oldnode, oldmetadata, digger)
  106. minetest.sound_play("tnt_gunpowder_burning", {pos=pos, gain=2})
  107. if math.random(1, 10) == 1 then
  108. minetest.after(math.random(1, 5), function()
  109. tnt.boom(pos, {
  110. radius = 2,
  111. ignore_protection = false,
  112. ignore_on_blast = false,
  113. damage_radius = 3,
  114. disable_drops = true,
  115. })
  116. end)
  117. elseif math.random(1, 10) == 1 then
  118. minetest.add_node(pos, {name="fire:nether_flame"})
  119. end
  120. end,
  121. -- Setup initial metadata.
  122. after_place_node = function(pos, placer)
  123. local meta = minetest.get_meta(pos)
  124. local pname = placer:get_player_name()
  125. local dname = rename.gpn(pname)
  126. meta:set_string("owner", pname)
  127. meta:set_string("rename", dname)
  128. meta:set_string("infotext", "Star-Fissure Box (Owned by <" .. dname .. ">!)")
  129. end,
  130. -- Open chest formspec.
  131. on_rightclick = function(pos, node, clicker)
  132. local meta = minetest.get_meta(pos)
  133. local owner = meta:get_string("owner") or ""
  134. local pname = clicker:get_player_name()
  135. -- Only the owner may view the inventory.
  136. if owner == pname then
  137. -- Update infotext.
  138. local dname = rename.gpn(pname)
  139. meta:set_string("infotext", "Star-Fissure Box (Owned by <" .. dname .. ">!)")
  140. open_chest(pname, pos, node)
  141. end
  142. end,
  143. -- Handle explosions. The chest generates a secondary explosion.
  144. on_blast = function(pos)
  145. minetest.remove_node(pos)
  146. minetest.after(0.5, function()
  147. tnt.boom(pos, {
  148. radius = 2,
  149. ignore_protection = false,
  150. ignore_on_blast = false,
  151. damage_radius = 3,
  152. disable_drops = true,
  153. })
  154. end)
  155. end,
  156. -- Called by rename LBM.
  157. _on_rename_check = function(pos)
  158. local meta = minetest.get_meta(pos)
  159. local owner = meta:get_string("owner")
  160. -- Nobody placed this block.
  161. if owner == "" then
  162. return
  163. end
  164. local dname = rename.gpn(owner)
  165. meta:set_string("rename", dname)
  166. meta:set_string("infotext", "Star-Fissure Box (Owned by <" .. dname .. ">!)")
  167. end,
  168. -- Don't permit placement in certain realms.
  169. on_place = function(itemstack, placer, pt)
  170. if not placer or not placer:is_player() then
  171. return
  172. end
  173. if pt.type == "node" then
  174. local rnu = rc.current_realm_at_pos(pt.under)
  175. local rna = rc.current_realm_at_pos(pt.above)
  176. if rnu == "abyss" or rna == "abyss" or rnu == "" or rna == "" then
  177. utility.shell_boom(pt.above)
  178. itemstack:take_item()
  179. return itemstack
  180. end
  181. perform_inventory_check(placer)
  182. return minetest.item_place(itemstack, placer, pt)
  183. end
  184. end,
  185. }
  186. -- Split definitions.
  187. local VOIDCHEST_CLOSED = table.copy(VOIDCHEST_DEF)
  188. local VOIDCHEST_OPENED = table.copy(VOIDCHEST_DEF)
  189. VOIDCHEST_OPENED.mesh = "chest_open.obj"
  190. VOIDCHEST_CLOSED.mesh = "chest_close.obj"
  191. -- Chest can't be dug while opened.
  192. VOIDCHEST_OPENED.can_dig = function()
  193. return false
  194. end
  195. VOIDCHEST_OPENED.groups.not_in_creative_inventory = 1
  196. VOIDCHEST_OPENED.selection_box = {
  197. type = "fixed",
  198. fixed = { -1/2, -1/2, -1/2, 1/2, 3/16, 1/2 },
  199. }
  200. minetest.register_node("voidchest:voidchest_closed", VOIDCHEST_CLOSED)
  201. minetest.register_node("voidchest:voidchest_opened", VOIDCHEST_OPENED)
  202. -- Compatibility.
  203. minetest.register_alias("voidchest:voidchest", "voidchest:voidchest_closed")
  204. -- This is strictly an upgrade from the usual xdecor void-chest.
  205. minetest.register_craft({
  206. output = "voidchest:voidchest_closed",
  207. recipe = {
  208. {"starpearl:pearl", "starpearl:pearl", "starpearl:pearl"},
  209. {"starpearl:pearl", "xdecor:xchest", "starpearl:pearl"},
  210. {"starpearl:pearl", "starpearl:pearl", "starpearl:pearl"},
  211. },
  212. })