init.lua 7.4 KB

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