init.lua 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. screwdriver = screwdriver or {}
  2. local tmp = {}
  3. local max_objs = tonumber(minetest.setting_get("max_objects_per_block")) or 49
  4. -- item entity
  5. minetest.register_entity("itemframes:item",{
  6. hp_max = 1,
  7. visual = "wielditem",
  8. visual_size = {x = 0.33, y = 0.33},
  9. collisionbox = {0, 0, 0, 0, 0, 0},
  10. physical = false,
  11. textures = {"air"},
  12. on_activate = function(self, staticdata)
  13. if not self then
  14. self.object:remove()
  15. return
  16. end
  17. if tmp.nodename ~= nil
  18. and tmp.texture ~= nil then
  19. self.nodename = tmp.nodename
  20. tmp.nodename = nil
  21. self.texture = tmp.texture
  22. tmp.texture = nil
  23. self.glow = tmp.glow
  24. tmp.glow = nil
  25. else
  26. if staticdata ~= nil
  27. and staticdata ~= "" then
  28. local data = staticdata:split(";")
  29. if data and data[1] and data[2] then
  30. self.nodename = data[1]
  31. self.texture = data[2]
  32. self.glow = data[3]
  33. end
  34. end
  35. end
  36. if self.texture ~= nil then
  37. self.object:set_properties({textures = {self.texture}})
  38. end
  39. if self.nodename == "itemframes:pedestal" then
  40. self.object:set_properties({automatic_rotate = 1})
  41. end
  42. if self.glow ~= nil then
  43. self.object:set_properties({glow = self.glow})
  44. end
  45. end,
  46. get_staticdata = function(self)
  47. if self.nodename ~= nil
  48. and self.texture ~= nil then
  49. return self.nodename .. ";" .. self.texture .. ";" .. (self.glow or "")
  50. end
  51. return ""
  52. end,
  53. })
  54. -- helper table
  55. local facedir = {
  56. [0] = {x = 0, y = 0, z = 1},
  57. [1] = {x = 1, y = 0, z = 0},
  58. [2] = {x = 0, y = 0, z = -1},
  59. [3] = {x = -1, y = 0, z = 0}
  60. }
  61. -- remove entities
  62. local remove_item = function(pos, nodename)
  63. local ypos = 0
  64. if nodename == "itemframes:pedestal" then
  65. ypos = 1
  66. end
  67. local objs = minetest.get_objects_inside_radius({
  68. x = pos.x, y = pos.y + ypos, z = pos.z}, 0.5)
  69. if objs then
  70. for _, obj in pairs(objs) do
  71. if obj and obj:get_luaentity()
  72. and obj:get_luaentity().name == "itemframes:item" then
  73. obj:remove()
  74. end
  75. end
  76. end
  77. end
  78. -- update entity
  79. local update_item = function(pos, node)
  80. remove_item(pos, node.name)
  81. local meta = minetest.get_meta(pos)
  82. if not meta then return end
  83. local item = meta:get_string("item")
  84. if item ~= "" then
  85. if node.name == "itemframes:frame" then
  86. local posad = facedir[node.param2]
  87. if not posad then return end
  88. pos.x = pos.x + posad.x * 6.5 / 16
  89. pos.y = pos.y + posad.y * 6.5 / 16
  90. pos.z = pos.z + posad.z * 6.5 / 16
  91. elseif node.name == "itemframes:pedestal" then
  92. pos.y = pos.y + 12 / 16 + 0.33
  93. end
  94. tmp.nodename = node.name
  95. tmp.texture = ItemStack(item):get_name()
  96. local def = core.registered_nodes[item]
  97. tmp.glow = def and def.light_source
  98. local e = minetest.add_entity(pos,"itemframes:item")
  99. if node.name == "itemframes:frame" then
  100. --local yaw = math.pi * 2 - node.param2 * math.pi / 2
  101. local yaw = 6.28 - node.param2 * 1.57
  102. e:set_yaw(yaw)
  103. end
  104. end
  105. end
  106. -- remove entity and drop as item
  107. local drop_item = function(pos, nodename, metadata)
  108. local meta = metadata or minetest.get_meta(pos)
  109. if not meta then return end
  110. local item = meta:get_string("item")
  111. meta:set_string("item", "")
  112. if item ~= "" then
  113. remove_item(pos, nodename)
  114. if nodename == "itemframes:pedestal" then
  115. pos.y = pos.y + 1
  116. end
  117. minetest.add_item(pos, item)
  118. end
  119. end
  120. -- pedestal node and recipe
  121. minetest.register_node("itemframes:pedestal",{
  122. description = "Pedestal",
  123. drawtype = "nodebox",
  124. node_box = {
  125. type = "fixed", fixed = {
  126. {-7/16, -8/16, -7/16, 7/16, -7/16, 7/16}, -- bottom plate
  127. {-6/16, -7/16, -6/16, 6/16, -6/16, 6/16}, -- bottom plate (upper)
  128. {-0.25, -6/16, -0.25, 0.25, 11/16, 0.25}, -- pillar
  129. {-7/16, 11/16, -7/16, 7/16, 12/16, 7/16}, -- top plate
  130. }
  131. },
  132. selection_box = {
  133. type = "fixed",
  134. fixed = {-7/16, -0.5, -7/16, 7/16, 12/16, 7/16}
  135. },
  136. tiles = {"itemframes_pedestal.png"},
  137. paramtype = "light",
  138. groups = {cracky = 3},
  139. sounds = default.node_sound_defaults(),
  140. on_rotate = screwdriver.disallow,
  141. after_place_node = function(pos, placer, itemstack)
  142. local meta = minetest.get_meta(pos)
  143. meta:set_string("infotext","Pedestal (right-click to add or remove item)")
  144. end,
  145. on_rightclick = function(pos, node, clicker, itemstack)
  146. if not itemstack
  147. or minetest.is_protected(pos, clicker:get_player_name()) then
  148. return
  149. end
  150. local meta = minetest.get_meta(pos)
  151. if not meta then return end
  152. if meta:get_string("item") ~= "" then
  153. drop_item(pos, node.name, meta)
  154. else
  155. local s = itemstack:take_item()
  156. meta:set_string("item", s:to_string())
  157. update_item(pos, node)
  158. return itemstack
  159. end
  160. end,
  161. on_destruct = function(pos)
  162. drop_item(pos, "itemframes:pedestal")
  163. end,
  164. on_punch = function(pos, node, puncher)
  165. update_item(pos, node)
  166. end,
  167. on_blast = function(pos, intensity)
  168. drop_item(pos, "itemframes:pedestal")
  169. minetest.add_item(pos, {name = "itemframes:pedestal"})
  170. minetest.remove_node(pos)
  171. end
  172. })
  173. minetest.register_craft({
  174. output = "itemframes:pedestal",
  175. recipe = {
  176. {"default:stone", "default:stone", "default:stone"},
  177. {"", "default:stone", ""},
  178. {"default:stone", "default:stone", "default:stone"},
  179. }
  180. })
  181. -- automatically restore entities lost from frames/pedestals
  182. -- due to /clearobjects or similar
  183. minetest.register_abm({
  184. nodenames = {"itemframes:frame", "itemframes:pedestal"},
  185. interval = 25,
  186. chance = 1,
  187. catch_up = false,
  188. action = function(pos, node, active_object_count, active_object_count_wider)
  189. if active_object_count >= max_objs then
  190. return
  191. end
  192. local num
  193. if node.name == "itemframes:frame" then
  194. num = #minetest.get_objects_inside_radius(pos, 0.5)
  195. elseif node.name == "itemframes:pedestal" then
  196. pos.y = pos.y + 1
  197. num = #minetest.get_objects_inside_radius(pos, 0.5)
  198. pos.y = pos.y - 1
  199. end
  200. if num > 0 then
  201. return
  202. end
  203. update_item(pos, node)
  204. end
  205. })