init.lua 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. --[[
  2. Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
  3. "frame" is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of
  6. the license, or (at your option) any later version.
  7. --]]
  8. frame = {}
  9. -- handle node removal from frame
  10. local function frame_on_punch(pos, node, puncher, pointed_thing)
  11. if puncher and not minetest.check_player_privs(puncher, "protection_bypass") then
  12. local name = puncher:get_player_name()
  13. if minetest.is_protected(pos, name) then
  14. minetest.record_protection_violation(pos, name)
  15. return false
  16. end
  17. end
  18. local def = minetest.registered_nodes[node.name]
  19. local item = ItemStack(def.frame_contents)
  20. -- preserve itemstack metadata and wear
  21. local meta = minetest.get_meta(pos)
  22. local wear = meta:get_int("wear")
  23. if wear then
  24. item:set_wear(wear)
  25. end
  26. local metadata = meta:get_string("metadata")
  27. if metadata ~= "" then
  28. item:set_metadata(metadata)
  29. end
  30. --minetest.handle_node_drops(pos, {item}, puncher)
  31. local inv = puncher:get_inventory()
  32. if inv:room_for_item("main", item) then
  33. inv:add_item("main", item)
  34. minetest.sound_play(def.sounds.dug, {pos = pos})
  35. minetest.swap_node(pos, {name = "frame:empty", param2 = node.param2})
  36. end
  37. end
  38. -- handle node insertion into frame
  39. local function frame_on_rightclick(pos, node, clicker, itemstack, pointed_thing)
  40. if clicker and not minetest.check_player_privs(clicker, "protection_bypass") then
  41. local name = clicker:get_player_name()
  42. if minetest.is_protected(pos, name) then
  43. minetest.record_protection_violation(pos, name)
  44. return itemstack
  45. end
  46. end
  47. local nodename = itemstack:get_name()
  48. if not nodename then
  49. return itemstack
  50. end
  51. local wear = itemstack:get_wear()
  52. if wear then
  53. local meta = minetest.get_meta(pos)
  54. meta:set_int("wear", wear)
  55. end
  56. local metadata = itemstack:get_metadata()
  57. if metadata ~= "" then
  58. local meta = minetest.get_meta(pos)
  59. meta:set_string("metadata", metadata)
  60. end
  61. local name = "frame:" .. nodename:gsub(":", "_")
  62. local def = minetest.registered_nodes[name]
  63. if not def then
  64. def = minetest.registered_items[name]
  65. if not def then
  66. return itemstack
  67. end
  68. end
  69. minetest.sound_play(def.sounds.place, {pos = pos})
  70. minetest.swap_node(pos, {name = name, param2 = node.param2})
  71. if not minetest.settings:get_bool("creative_mode") then
  72. itemstack:take_item()
  73. end
  74. return itemstack
  75. end
  76. function frame.register(name)
  77. assert(name, "no content passed")
  78. assert(string.sub(name, 1, 1) ~= ":", "name must not start with ':'")
  79. local tiles
  80. local def = minetest.registered_nodes[name]
  81. if not def then
  82. -- item?
  83. def = minetest.registered_items[name]
  84. if not def then
  85. -- nonexistant item.
  86. minetest.log("warning", "Frame registered for \"" .. name .. "\" but it isn't registered")
  87. return
  88. end
  89. assert(def.inventory_image, "no inventory image for " .. name)
  90. tiles = {
  91. {name = "frame_frame.png"},
  92. {name = def.inventory_image},
  93. {name = "doors_blank.png"},
  94. {name = "doors_blank.png"},
  95. {name = "doors_blank.png"},
  96. }
  97. else
  98. -- node
  99. if def.inventory_image ~= "" then
  100. -- custom inventory override image first.
  101. tiles = {
  102. {name = "frame_frame.png"},
  103. {name = def.inventory_image or "doors_blank.png"},
  104. {name = "doors_blank.png"},
  105. {name = "doors_blank.png"},
  106. {name = "doors_blank.png"},
  107. }
  108. elseif def.drawtype ~= "normal" then
  109. -- use tiles[1] only, but on frame
  110. tiles = {
  111. {name = "frame_frame.png"},
  112. {name = def.tiles[1] and def.tiles[1].name or def.tiles[1] or "doors_blank.png"},
  113. {name = "doors_blank.png"},
  114. {name = "doors_blank.png"},
  115. {name = "doors_blank.png"},
  116. }
  117. else -- type(def.tiles[1]) == "table" then
  118. -- multiple tiles
  119. tiles = {
  120. {name = "frame_frame.png"},
  121. {name = "doors_blank.png"},
  122. {name = def.tiles[1] and def.tiles[1].name or def.tiles[1]
  123. or "doors_blank.png"},
  124. {name = def.tiles[2] and def.tiles[2].name or def.tiles[2]
  125. or def.tiles[1] and def.tiles[1].name or def.tiles[1]
  126. or "doors_blank.png"},
  127. {name = def.tiles[6] and def.tiles[6].name or def.tiles[6]
  128. or def.tiles[3] and def.tiles[3].name or def.tiles[3]
  129. or def.tiles[2] and def.tiles[2].name or def.tiles[2]
  130. or def.tiles[1] and def.tiles[1].name or def.tiles[1]
  131. or "doors_blank.png"},
  132. }
  133. end
  134. end
  135. assert(def, name .. " is not a known node or item")
  136. minetest.register_node(":frame:" .. name:gsub(":", "_"), {
  137. description = "Item Frame with " .. def.description,
  138. drawtype = "mesh",
  139. mesh = "frame.obj",
  140. tiles = tiles,
  141. paramtype = "light",
  142. paramtype2 = "wallmounted",
  143. sunlight_propagates = true,
  144. walkable = false,
  145. selection_box = {
  146. type = "wallmounted",
  147. wall_side = {-1/2, -1/2, -1/2, -3/8, 1/2, 1/2},
  148. },
  149. sounds = default.node_sound_defaults(),
  150. groups = {attached_node = 1, oddly_breakable_by_hand = 1, snappy = 3, not_in_creative_inventory = 1},
  151. frame_contents = name,
  152. drop = "frame:empty", -- FIXME item should be in there but this would allow free repair
  153. on_punch = frame_on_punch,
  154. })
  155. end
  156. -- empty frame
  157. minetest.register_node("frame:empty", {
  158. description = "Item Frame",
  159. drawtype = "mesh",
  160. mesh = "frame.obj",
  161. inventory_image = "frame_frame.png",
  162. wield_image = "frame_frame.png",
  163. tiles = {
  164. {name = "frame_frame.png"},
  165. {name = "doors_blank.png"},
  166. {name = "doors_blank.png"},
  167. {name = "doors_blank.png"},
  168. {name = "doors_blank.png"},
  169. },
  170. paramtype = "light",
  171. paramtype2 = "wallmounted",
  172. sunlight_propagates = true,
  173. walkable = false,
  174. selection_box = {
  175. type = "wallmounted",
  176. wall_side = {-1/2, -1/2, -1/2, -3/8, 1/2, 1/2},
  177. },
  178. sounds = default.node_sound_defaults(),
  179. groups = {attached_node = 1, oddly_breakable_by_hand = 3, cracky = 1},
  180. on_rightclick = frame_on_rightclick,
  181. })
  182. -- craft
  183. minetest.register_craft({
  184. output = "frame:empty",
  185. recipe = {
  186. {"default:stick", "default:stick", "default:stick"},
  187. {"default:stick", "default:paper", "default:stick"},
  188. {"default:stick", "default:stick", "default:stick"},
  189. }
  190. })
  191. local items_to_frame = {}
  192. for _, node in pairs(minetest.registered_items) do
  193. if (minetest.get_item_group(node.name, "not_in_creative_inventory") == 0 and
  194. node.drawtype ~= "airlike" and
  195. node.drawtype ~= "nodebox" and
  196. node.drawtype ~= "mesh") or
  197. ((node.drawtype == "nodebox" or
  198. node.drawtype == "mesh") and
  199. node.inventory_image ~= "") then
  200. table.insert(items_to_frame, node.name)
  201. end
  202. end
  203. for _, node in pairs(items_to_frame) do
  204. frame.register(node)
  205. end