signs.lua 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. local itemsign= {}
  2. local function remove_item(pos, node)
  3. local objs = minetest.get_objects_inside_radius(pos, 0.5)
  4. if not objs then return end
  5. for _, obj in pairs(objs) do
  6. if obj and obj:get_luaentity() and
  7. obj:get_luaentity().name == 'epic:sign_item' then
  8. obj:remove()
  9. end
  10. end
  11. end
  12. local facedir = {
  13. [0] = {x=0, y=0, z=1}, {x=1, y=0, z=0}, {x=0, y=0, z=-1}, {x=-1, y=0, z=0}
  14. }
  15. -- Works good for the most items, but not for all
  16. local function get_drawtype(itemstring)
  17. local def = minetest.registered_items[itemstring]
  18. --minetest.debug(string.format('Item: %s dt: %s, wield: %s', itemstring, dump(drawtype),dump(wield_image)))
  19. if not def then
  20. return 'twosided'
  21. elseif def.wield_image ~= '' or def.inventory_image ~= '' then
  22. return 'twosided'
  23. elseif def.drawtype == 'normal' or
  24. def.drawtype == 'mesh' or
  25. def.drawtype == 'nodebox' then
  26. return 'centered'
  27. else
  28. return 'twosided'
  29. end
  30. end
  31. local PI = math.pi
  32. local function update_item(pos, node)
  33. remove_item(pos, node)
  34. local meta = minetest.get_meta(pos)
  35. local inv = meta:get_inventory()
  36. local itemstring = inv:get_stack('item', 1):get_name()
  37. local posad = facedir[node.param2]
  38. if not posad or itemstring == '' then return end
  39. local yaw = PI*2 - node.param2 * PI/2
  40. if get_drawtype(itemstring) == 'centered' then
  41. local pos = pos
  42. local obj = minetest.add_entity(pos, 'epic:sign_item')
  43. obj:setyaw(yaw)
  44. obj:get_luaentity():init(itemstring)
  45. elseif get_drawtype(itemstring)=='twosided' then
  46. -- Front
  47. local pos1 = vector.add(pos, vector.multiply(posad, -1/16) )
  48. local obj1 = minetest.add_entity(pos1, 'epic:sign_item')
  49. obj1:setyaw(yaw)
  50. obj1:get_luaentity():init(itemstring)
  51. -- Back
  52. local pos2 = vector.add(pos, vector.multiply(posad, 1/16) )
  53. local obj2 = minetest.add_entity(pos2, 'epic:sign_item')
  54. obj2:setyaw(yaw+PI) --rotate this about 180 Degrees
  55. obj2:get_luaentity():init(itemstring)
  56. else
  57. minetest.log('error', 'Error: Invalid drawtype of '..itemstring)
  58. end
  59. pos = vector.add(pos, vector.multiply(posad, -1/16) )
  60. end
  61. local formspec = [[
  62. size[8,6]
  63. list[context;item;0,0;1,1;]
  64. label[0,-0.35;Item to show:]
  65. field[2,0.3;4.1,1;text;Text:;${text}]
  66. button_exit[6,0;2,1;submit;OK]
  67. list[current_player;main;0,1.85;8,1;]
  68. list[current_player;main;0,3.08;8,3;8]
  69. listring[context;item]
  70. listring[current_player;main]
  71. ]]
  72. function itemsign.construct(pos)
  73. local meta = minetest.get_meta(pos)
  74. meta:set_string('formspec', formspec)
  75. local inv = meta:get_inventory()
  76. inv:set_size('item', 1)
  77. end
  78. function itemsign.can_dig(pos, player)
  79. local meta = minetest.get_meta(pos);
  80. local inv = meta:get_inventory()
  81. return inv:is_empty('item')
  82. end
  83. function itemsign.after_place(pos, placer, itemstack)
  84. local meta = minetest.get_meta(pos)
  85. local name = placer:get_player_name()
  86. meta:set_string('owner', name)
  87. meta:set_string('infotext', 'Item Sign')
  88. end
  89. function itemsign.on_receive_fields(pos, formname, fields, sender)
  90. local player_name = sender:get_player_name() or ''
  91. local meta = minetest.get_meta(pos)
  92. if meta:get_string('owner') == player_name then
  93. if fields.text then
  94. local meta = minetest.get_meta(pos)
  95. minetest.log('action', string.format('%s wrote %q to itemsign at %s', player_name, fields.text, minetest.pos_to_string(pos)))
  96. meta:set_string('text', fields.text)
  97. meta:set_string('infotext', fields.text)
  98. end
  99. end
  100. end
  101. function itemsign.inventory_modified(pos, listname, index, stack, player)
  102. local node = minetest.get_node(pos)
  103. update_item(pos, node)
  104. end
  105. function itemsign.allow_inventory(pos, listname, index, stack, player)
  106. local meta = minetest.get_meta(pos)
  107. local player_name = player:get_player_name()
  108. if meta:get_string('owner') ~= player_name then
  109. return 0
  110. else
  111. return 1
  112. end
  113. end
  114. minetest.register_node('epic:sign', {
  115. drawtype = 'mesh',
  116. mesh = 'epic_hanging_sign.obj',
  117. description = 'Trading sign',
  118. groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
  119. sounds = default.node_sound_wood_defaults(),
  120. sunlight_propagates = true,
  121. paramtype = 'light',
  122. paramtype2 = 'facedir',
  123. tiles = {'epic_hanging_sign.png'},
  124. inventory_image = 'epic_hanging_sign_inv.png',
  125. wield_image = 'epic_hanging_sign_inv.png',
  126. selection_box = {
  127. type = 'fixed',
  128. fixed = {-.45, -.45, -.1, .45, .4, .1},
  129. },
  130. collision_box = {
  131. type = 'fixed',
  132. fixed = {-.45, -.45, -.1, .45, .4, .1},
  133. },
  134. after_place_node = itemsign.after_place,
  135. on_construct = itemsign.construct,
  136. allow_metadata_inventory_put = itemsign.allow_inventory,
  137. allow_metadata_inventory_take = itemsign.allow_inventory,
  138. on_metadata_inventory_put = itemsign.inventory_modified,
  139. on_metadata_inventory_take = itemsign.inventory_modified,
  140. on_receive_fields = itemsign.on_receive_fields,
  141. on_punch = update_item,
  142. can_dig = itemsign.can_dig,
  143. after_destruct = remove_item
  144. })
  145. minetest.register_entity('epic:sign_item', {
  146. visual = 'wielditem',
  147. visual_size = {x=0.33, y=0.33},
  148. collisionbox = {0},
  149. physical = false,
  150. textures = {'air'},
  151. -- Init the item with the texture
  152. init = function(self, item)
  153. self.data.item = item
  154. self.object:set_properties({textures={self.data.item}})
  155. end,
  156. -- Everytime the item gets loaded
  157. on_activate = function(self, staticdata)
  158. local pos = self.object:get_pos()
  159. if minetest.get_node(pos).name ~= 'epic:sign' then
  160. self.object:remove()
  161. end
  162. self.data = minetest.deserialize(staticdata) or {}
  163. if self.data.item then
  164. self.object:set_properties({textures={self.data.item}})
  165. end
  166. end,
  167. -- Data, that shouldnt get loosed
  168. get_staticdata = function(self)
  169. return minetest.serialize(self.data)
  170. end
  171. })
  172. minetest.register_node('epic:sign_post', {
  173. drawtype = 'mesh',
  174. mesh = 'epic_sign_post.obj',
  175. description = 'Sign post',
  176. groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
  177. sounds = default.node_sound_wood_defaults(),
  178. sunlight_propagates = true,
  179. paramtype = 'light',
  180. paramtype2 = 'facedir',
  181. tiles = {'epic_sign_post.png'},
  182. selection_box = {
  183. type = 'fixed',
  184. fixed = {-.1, -.45, -.5, .1, .35, .5},
  185. },
  186. collision_box = {
  187. type = 'fixed',
  188. fixed = {-.45, -.45, -.1, .45, .4, .1},
  189. },
  190. })
  191. minetest.register_node('epic:sign_post_metal', {
  192. drawtype = 'mesh',
  193. mesh = 'epic_sign_post.obj',
  194. description = 'Metal Sign Post',
  195. groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
  196. sounds = default.node_sound_metal_defaults(),
  197. sunlight_propagates = true,
  198. paramtype = 'light',
  199. paramtype2 = 'facedir',
  200. tiles = {'epic_sign_post_metal.png'},
  201. selection_box = {
  202. type = 'fixed',
  203. fixed = {-.1, -.45, -.5, .1, .35, .5},
  204. },
  205. collision_box = {
  206. type = 'fixed',
  207. fixed = {-.45, -.45, -.1, .45, .4, .1},
  208. },
  209. })
  210. minetest.register_node('epic:directional_sign', {
  211. drawtype = 'mesh',
  212. mesh = 'epic_directional_sign.obj',
  213. description = 'Directional sign post',
  214. groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3},
  215. sounds = default.node_sound_wood_defaults(),
  216. sunlight_propagates = true,
  217. paramtype = 'light',
  218. paramtype2 = 'facedir',
  219. tiles = {'epic_directional_sign.png'},
  220. selection_box = {
  221. type = 'fixed',
  222. fixed = {-.4, -.1, -.1, .45, .4, .1},
  223. },
  224. collision_box = {
  225. type = 'fixed',
  226. fixed = {-.4, -.3, -.1, .45, .4, .1},
  227. },
  228. on_construct = function(pos)
  229. local meta = minetest.get_meta(pos)
  230. meta:set_string('formspec', 'field[text;;${text}]')
  231. meta:set_string('infotext', '')
  232. end,
  233. after_place_node = function(pos, placer)
  234. local meta = minetest.get_meta(pos)
  235. meta:set_string('owner',placer:get_player_name())
  236. end,
  237. on_receive_fields = function(pos, formname, fields, sender)
  238. local meta = minetest.get_meta(pos)
  239. if sender:get_player_name() == meta:get_string('owner') then
  240. if not fields.text then return end
  241. meta:set_string('text', fields.text)
  242. meta:set_string('infotext', fields.text)
  243. end
  244. end,
  245. })