init.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. local S = minetest.get_translator("itemframes")
  2. local tmp = {}
  3. local sd_disallow = minetest.get_modpath("screwdriver") and screwdriver.disallow or nil
  4. minetest.register_entity("itemframes:item",{
  5. hp_max = 1,
  6. visual="wielditem",
  7. visual_size={x = 0.33, y = 0.33},
  8. collisionbox = {0, 0, 0, 0, 0, 0},
  9. physical = false,
  10. textures = {"air"},
  11. on_activate = function(self, staticdata)
  12. if tmp.nodename ~= nil and tmp.texture ~= nil then
  13. self.nodename = tmp.nodename
  14. tmp.nodename = nil
  15. self.texture = tmp.texture
  16. tmp.texture = nil
  17. else
  18. if staticdata ~= nil and staticdata ~= "" then
  19. local data = staticdata:split(';')
  20. if data and data[1] and data[2] then
  21. self.nodename = data[1]
  22. self.texture = data[2]
  23. end
  24. end
  25. end
  26. if self.texture ~= nil then
  27. self.object:set_properties({textures = {self.texture}})
  28. end
  29. if self.nodename == "itemframes:pedestal" then
  30. self.object:set_properties({automatic_rotate = 1})
  31. end
  32. if self.texture ~= nil and self.nodename ~= nil then
  33. local entity_pos = vector.round(self.object:get_pos())
  34. local objs = minetest.get_objects_inside_radius(entity_pos, 0.5)
  35. for _, obj in ipairs(objs) do
  36. if obj ~= self.object and
  37. obj:get_luaentity() and
  38. obj:get_luaentity().name == "itemframes:item" and
  39. obj:get_luaentity().nodename == self.nodename and
  40. obj:get_properties() and
  41. obj:get_properties().textures and
  42. obj:get_properties().textures[1] == self.texture then
  43. minetest.log("action","[itemframes] Removing extra " ..
  44. self.texture .. " found in " .. self.nodename .. " at " ..
  45. minetest.pos_to_string(entity_pos))
  46. self.object:remove()
  47. break
  48. end
  49. end
  50. end
  51. end,
  52. get_staticdata = function(self)
  53. if self.nodename ~= nil and self.texture ~= nil then
  54. return self.nodename .. ';' .. self.texture
  55. end
  56. return ""
  57. end,
  58. })
  59. local facedir = {}
  60. facedir[0] = {x = 0, y = 0, z = 1}
  61. facedir[1] = {x = 1, y = 0, z = 0}
  62. facedir[2] = {x = 0, y = 0, z = -1}
  63. facedir[3] = {x = -1, y = 0, z = 0}
  64. local remove_item = function(pos, node)
  65. local objs = nil
  66. if node.name == "itemframes:frame" then
  67. objs = minetest.get_objects_inside_radius(pos, .5)
  68. elseif node.name == "itemframes:pedestal" then
  69. objs = minetest.get_objects_inside_radius({x=pos.x,y=pos.y+1,z=pos.z}, .5)
  70. end
  71. if objs then
  72. for _, obj in ipairs(objs) do
  73. if obj and obj:get_luaentity() and obj:get_luaentity().name == "itemframes:item" then
  74. obj:remove()
  75. end
  76. end
  77. end
  78. end
  79. local update_item = function(pos, node)
  80. remove_item(pos, node)
  81. local meta = minetest.get_meta(pos)
  82. if meta:get_string("item") ~= "" then
  83. if node.name == "itemframes:frame" then
  84. local posad = facedir[node.param2]
  85. if not posad then return end
  86. pos.x = pos.x + posad.x * 6.5 / 16
  87. pos.y = pos.y + posad.y * 6.5 / 16
  88. pos.z = pos.z + posad.z * 6.5 / 16
  89. elseif node.name == "itemframes:pedestal" then
  90. pos.y = pos.y + 12 / 16 + 0.33
  91. end
  92. tmp.nodename = node.name
  93. tmp.texture = ItemStack(meta:get_string("item")):get_name()
  94. local e = minetest.add_entity(pos,"itemframes:item")
  95. if node.name == "itemframes:frame" then
  96. local yaw = math.pi * 2 - node.param2 * math.pi / 2
  97. e:setyaw(yaw)
  98. end
  99. end
  100. end
  101. local drop_item = function(pos, node)
  102. local meta = minetest.get_meta(pos)
  103. if meta:get_string("item") ~= "" then
  104. if node.name == "itemframes:frame" then
  105. minetest.add_item(pos, meta:get_string("item"))
  106. elseif node.name == "itemframes:pedestal" then
  107. minetest.add_item({x=pos.x,y=pos.y+1,z=pos.z}, meta:get_string("item"))
  108. end
  109. meta:set_string("item","")
  110. end
  111. remove_item(pos, node)
  112. end
  113. minetest.register_node("itemframes:frame",{
  114. description = S("Item frame"),
  115. drawtype = "nodebox",
  116. node_box = {
  117. type = "fixed",
  118. fixed = {-0.5, -0.5, 7/16, 0.5, 0.5, 0.5}
  119. },
  120. selection_box = {
  121. type = "fixed",
  122. fixed = {-0.5, -0.5, 7/16, 0.5, 0.5, 0.5}
  123. },
  124. tiles = {"itemframes_frame.png"},
  125. inventory_image = "itemframes_frame.png",
  126. wield_image = "itemframes_frame.png",
  127. paramtype = "light",
  128. paramtype2 = "facedir",
  129. sunlight_propagates = true,
  130. groups = {choppy = 2, dig_immediate = 2},
  131. legacy_wallmounted = true,
  132. sounds = default.node_sound_wood_defaults(),
  133. on_rotate = sd_disallow or nil,
  134. after_place_node = function(pos, placer, itemstack)
  135. local meta = minetest.get_meta(pos)
  136. meta:set_string("owner",placer:get_player_name())
  137. meta:set_string("infotext", S("Item frame (owned by @1)", placer:get_player_name()))
  138. end,
  139. on_rightclick = function(pos, node, clicker, itemstack)
  140. if not itemstack then return end
  141. local meta = minetest.get_meta(pos)
  142. local name = clicker and clicker:get_player_name()
  143. if name == meta:get_string("owner") or
  144. minetest.check_player_privs(name, "protection_bypass") then
  145. drop_item(pos,node)
  146. local s = itemstack:take_item()
  147. meta:set_string("item",s:to_string())
  148. local item_meta = s:get_meta()
  149. local description = item_meta:get_string("description")
  150. if description == "" then
  151. local item_name = s:get_name()
  152. if minetest.registered_items[item_name]
  153. and minetest.registered_items[item_name].description
  154. then
  155. description = minetest.registered_items[item_name].description
  156. else
  157. description = item_name
  158. end
  159. end
  160. meta:set_string("infotext", S("Item frame (owned by @1)", name) .. "\n" .. description)
  161. update_item(pos,node)
  162. end
  163. return itemstack
  164. end,
  165. on_punch = function(pos,node,puncher)
  166. local meta = minetest.get_meta(pos)
  167. local name = puncher and puncher:get_player_name()
  168. if name == meta:get_string("owner") or
  169. minetest.check_player_privs(name, "protection_bypass") then
  170. drop_item(pos, node)
  171. meta:set_string("infotext", S("Item frame (owned by @1)", name))
  172. end
  173. end,
  174. can_dig = function(pos,player)
  175. if not player then return end
  176. local name = player and player:get_player_name()
  177. local meta = minetest.get_meta(pos)
  178. return name == meta:get_string("owner") or
  179. minetest.check_player_privs(name, "protection_bypass")
  180. end,
  181. on_destruct = function(pos)
  182. local meta = minetest.get_meta(pos)
  183. local node = minetest.get_node(pos)
  184. if meta:get_string("item") ~= "" then
  185. drop_item(pos, node)
  186. end
  187. end,
  188. })
  189. minetest.register_node("itemframes:pedestal",{
  190. description = S("Pedestal"),
  191. drawtype = "nodebox",
  192. node_box = {
  193. type = "fixed", fixed = {
  194. {-7/16, -8/16, -7/16, 7/16, -7/16, 7/16}, -- bottom plate
  195. {-6/16, -7/16, -6/16, 6/16, -6/16, 6/16}, -- bottom plate (upper)
  196. {-0.25, -6/16, -0.25, 0.25, 11/16, 0.25}, -- pillar
  197. {-7/16, 11/16, -7/16, 7/16, 12/16, 7/16}, -- top plate
  198. }
  199. },
  200. --selection_box = {
  201. -- type = "fixed",
  202. -- fixed = {-7/16, -0.5, -7/16, 7/16, 12/16, 7/16}
  203. --},
  204. tiles = {"itemframes_pedestal.png"},
  205. paramtype = "light",
  206. groups = {cracky = 3},
  207. sounds = default.node_sound_stone_defaults(),
  208. on_rotate = sd_disallow or nil,
  209. after_place_node = function(pos, placer, itemstack)
  210. local meta = minetest.get_meta(pos)
  211. meta:set_string("owner",placer:get_player_name())
  212. meta:set_string("infotext", S("Pedestal (owned by @1)", placer:get_player_name()))
  213. end,
  214. on_rightclick = function(pos, node, clicker, itemstack)
  215. if not itemstack then return end
  216. local meta = minetest.get_meta(pos)
  217. local name = clicker and clicker:get_player_name()
  218. if name == meta:get_string("owner") or
  219. minetest.check_player_privs(name, "protection_bypass") then
  220. drop_item(pos,node)
  221. local s = itemstack:take_item()
  222. meta:set_string("item",s:to_string())
  223. local item_meta = s:get_meta()
  224. local description = item_meta:get_string("description")
  225. if description == "" then
  226. local item_name = s:get_name()
  227. if minetest.registered_items[item_name]
  228. and minetest.registered_items[item_name].description
  229. then
  230. description = minetest.registered_items[item_name].description
  231. else
  232. description = item_name
  233. end
  234. end
  235. meta:set_string("infotext", S("Pedestal (owned by @1)", name) .. "\n" .. description)
  236. update_item(pos,node)
  237. end
  238. return itemstack
  239. end,
  240. on_punch = function(pos,node,puncher)
  241. local meta = minetest.get_meta(pos)
  242. local name = puncher and puncher:get_player_name()
  243. if name == meta:get_string("owner") or
  244. minetest.check_player_privs(name, "protection_bypass") then
  245. drop_item(pos,node)
  246. meta:set_string("infotext", S("Pedestal (owned by @1)", name))
  247. end
  248. end,
  249. can_dig = function(pos,player)
  250. if not player then return end
  251. local name = player and player:get_player_name()
  252. local meta = minetest.get_meta(pos)
  253. return name == meta:get_string("owner") or
  254. minetest.check_player_privs(name, "protection_bypass")
  255. end,
  256. on_destruct = function(pos)
  257. local meta = minetest.get_meta(pos)
  258. local node = minetest.get_node(pos)
  259. if meta:get_string("item") ~= "" then
  260. drop_item(pos, node)
  261. end
  262. end,
  263. })
  264. -- automatically restore entities lost from frames/pedestals
  265. -- due to /clearobjects or similar
  266. minetest.register_lbm({
  267. label = "Maintain itemframe and pedestal entities",
  268. name = "itemframes:maintain_entities",
  269. nodenames = {"itemframes:frame", "itemframes:pedestal"},
  270. run_at_every_load = true,
  271. action = function(pos1, node1)
  272. minetest.after(0,
  273. function(pos, node)
  274. local meta = minetest.get_meta(pos)
  275. local itemstring = meta:get_string("item")
  276. if itemstring ~= "" then
  277. local entity_pos = pos
  278. if node.name == "itemframes:pedestal" then
  279. entity_pos = {x=pos.x,y=pos.y+1,z=pos.z}
  280. end
  281. local objs = minetest.get_objects_inside_radius(entity_pos, 0.5)
  282. if #objs == 0 then
  283. minetest.log("action","[itemframes] Replacing missing " ..
  284. itemstring .. " in " .. node.name .. " at " ..
  285. minetest.pos_to_string(pos))
  286. update_item(pos, node)
  287. end
  288. end
  289. end,
  290. pos1, node1)
  291. end
  292. })
  293. -- crafts
  294. minetest.register_craft({
  295. output = 'itemframes:frame',
  296. recipe = {
  297. {'group:stick', 'group:stick', 'group:stick'},
  298. {'group:stick', 'default:paper', 'default:stick'},
  299. {'group:stick', 'group:stick', 'group:stick'},
  300. }
  301. })
  302. minetest.register_craft({
  303. output = 'itemframes:pedestal',
  304. recipe = {
  305. {'default:stone', 'default:stone', 'default:stone'},
  306. {'', 'default:stone', ''},
  307. {'default:stone', 'default:stone', 'default:stone'},
  308. }
  309. })
  310. -- stop mesecon pistons from pushing itemframes and pedestals
  311. if minetest.get_modpath("mesecons_mvps") then
  312. mesecon.register_mvps_stopper("itemframes:frame")
  313. mesecon.register_mvps_stopper("itemframes:pedestal")
  314. end