barter.lua 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. currency.barter = {}
  2. barter = currency.barter -- Kept as a global variable for compatibility
  3. local S = minetest.get_translator("currency")
  4. barter.chest = {}
  5. barter.chest.expire_after = tonumber(minetest.settings:get('barter.chest.expireafter')) or 15 * 60
  6. barter.chest.formspec = {
  7. main = "size[8,9]"..
  8. "list[current_name;pl1;0,0;3,4;]"..
  9. "list[current_name;pl2;5,0;3,4;]"..
  10. "list[current_player;main;0,5;8,4;]",
  11. pl1 = {
  12. start = "button[0,4;3,1;pl1_start;" .. S("Start") .. "]",
  13. player = function(name) return "label[0,4;"..name.."]" end,
  14. accept1 = "button[2.9,1;1.2,1;pl1_accept1;" .. S("Confirm") .. "]"..
  15. "button[2.9,2;1.2,1;pl1_cancel;" .. S("Cancel") .. "]",
  16. accept2 = "button[2.9,1;1.2,1;pl1_accept2;" .. S("Exchange") .. "]"..
  17. "button[2.9,2;1.2,1;pl1_cancel;" .. S("Cancel") .. "]",
  18. },
  19. pl2 = {
  20. start = "button[5,4;3,1;pl2_start;" .. S("Start") .. "]",
  21. player = function(name) return "label[5,4;"..name.."]" end,
  22. accept1 = "button[3.9,1;1.2,1;pl2_accept1;" .. S("Confirm") .. "]"..
  23. "button[3.9,2;1.2,1;pl2_cancel;" .. S("Cancel") .. "]",
  24. accept2 = "button[3.9,1;1.2,1;pl2_accept2;" .. S("Exchange") .. "]"..
  25. "button[3.9,2;1.2,1;pl2_cancel;" .. S("Cancel") .. "]",
  26. },
  27. }
  28. barter.chest.check_privilege = function(listname,playername,meta)
  29. if listname == "pl1" then
  30. if playername ~= meta:get_string("pl1") then
  31. return false
  32. elseif meta:get_int("pl1step") ~= 1 then
  33. return false
  34. end
  35. end
  36. if listname == "pl2" then
  37. if playername ~= meta:get_string("pl2") then
  38. return false
  39. elseif meta:get_int("pl2step") ~= 1 then
  40. return false
  41. end
  42. end
  43. return true
  44. end
  45. barter.chest.update_formspec = function(meta)
  46. formspec = barter.chest.formspec.main
  47. pl_formspec = function (n)
  48. if meta:get_int(n.."step")==0 then
  49. formspec = formspec .. barter.chest.formspec[n].start
  50. else
  51. formspec = formspec .. barter.chest.formspec[n].player(meta:get_string(n))
  52. if meta:get_int(n.."step") == 1 then
  53. formspec = formspec .. barter.chest.formspec[n].accept1
  54. elseif meta:get_int(n.."step") == 2 then
  55. formspec = formspec .. barter.chest.formspec[n].accept2
  56. end
  57. end
  58. end
  59. pl_formspec("pl1") pl_formspec("pl2")
  60. meta:set_string("formspec",formspec)
  61. end
  62. barter.chest.give_inventory = function(inv,list,playername)
  63. player = minetest.get_player_by_name(playername)
  64. if player then
  65. for k,v in ipairs(inv:get_list(list)) do
  66. if player:get_inventory():room_for_item("main",v) then
  67. player:get_inventory():add_item("main",v)
  68. else
  69. minetest.add_item(player:get_pos(),v)
  70. end
  71. inv:remove_item(list,v)
  72. end
  73. end
  74. end
  75. barter.chest.cancel = function(meta)
  76. barter.chest.give_inventory(meta:get_inventory(),"pl1",meta:get_string("pl1"))
  77. barter.chest.give_inventory(meta:get_inventory(),"pl2",meta:get_string("pl2"))
  78. meta:set_string("pl1","")
  79. meta:set_string("pl2","")
  80. meta:set_int("pl1step",0)
  81. meta:set_int("pl2step",0)
  82. meta:set_int("clean",1)
  83. meta:set_int("timer",0)
  84. end
  85. barter.chest.exchange = function(meta)
  86. barter.chest.give_inventory(meta:get_inventory(),"pl1",meta:get_string("pl2"))
  87. barter.chest.give_inventory(meta:get_inventory(),"pl2",meta:get_string("pl1"))
  88. meta:set_string("pl1","")
  89. meta:set_string("pl2","")
  90. meta:set_int("pl1step",0)
  91. meta:set_int("pl2step",0)
  92. meta:set_int("clean",1)
  93. meta:set_int("timer",0)
  94. end
  95. barter.chest.start_timer = function(pos, meta)
  96. meta:set_int("clean",0)
  97. meta:set_int("timer",0)
  98. local node_timer = minetest.get_node_timer(pos)
  99. if node_timer:is_started() then return end
  100. node_timer:start(22)
  101. end
  102. minetest.register_node("currency:barter", {
  103. drawtype = "nodebox",
  104. description = S("Barter Table"),
  105. paramtype = "light",
  106. paramtype2 = "facedir",
  107. tiles = {"barter_top.png",
  108. "barter_base.png",
  109. "barter_side.png"},
  110. inventory_image = "barter_top.png",
  111. node_box = {
  112. type = "fixed",
  113. fixed = {
  114. {-0.500000,0.312500,-0.500000,0.500000,0.500000,0.500000},
  115. {-0.437500,-0.500000,-0.437500,-0.250000,0.500000,-0.250000},
  116. {-0.437500,-0.500000,0.250000,-0.250000,0.500000,0.437500},
  117. {0.250000,-0.500000,-0.437500,0.437500,0.500000,-0.250000},
  118. {0.250000,-0.500000,0.250000,0.437500,0.500000,0.447500},
  119. },
  120. },
  121. groups = {choppy=2,oddly_breakable_by_hand=2},
  122. sounds = currency.node_sound_wood_defaults(),
  123. on_construct = function(pos)
  124. local meta = minetest.get_meta(pos)
  125. meta:set_string("infotext", S("Barter Table"))
  126. meta:set_string("pl1","")
  127. meta:set_string("pl2","")
  128. meta:set_int("clean",1)
  129. meta:set_int("timer",0)
  130. barter.chest.update_formspec(meta)
  131. local inv = meta:get_inventory()
  132. inv:set_size("pl1", 12) -- 3*4
  133. inv:set_size("pl2", 12) -- 3*4
  134. end,
  135. on_receive_fields = function(pos, formname, fields, sender)
  136. local meta = minetest.get_meta(pos)
  137. barter.chest.start_timer(pos, meta)
  138. pl_receive_fields = function(n)
  139. if fields[n.."_start"] and meta:get_string(n) == "" then
  140. meta:set_string(n,sender:get_player_name())
  141. end
  142. if meta:get_string(n) == "" then
  143. meta:set_int(n.."step",0)
  144. elseif meta:get_int(n.."step")==0 then
  145. meta:set_int(n.."step",1)
  146. end
  147. if sender:get_player_name() == meta:get_string(n) then
  148. if meta:get_int(n.."step")==1 and fields[n.."_accept1"] then
  149. meta:set_int(n.."step",2)
  150. end
  151. if meta:get_int(n.."step")==2 and fields[n.."_accept2"] then
  152. meta:set_int(n.."step",3)
  153. if n == "pl1" and meta:get_int("pl2step") == 3 then barter.chest.exchange(meta) end
  154. if n == "pl2" and meta:get_int("pl1step") == 3 then barter.chest.exchange(meta) end
  155. end
  156. if fields[n.."_cancel"] then barter.chest.cancel(meta) end
  157. end
  158. end
  159. pl_receive_fields("pl1") pl_receive_fields("pl2")
  160. -- End
  161. barter.chest.update_formspec(meta)
  162. end,
  163. allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
  164. local meta = minetest.get_meta(pos)
  165. barter.chest.start_timer(pos, meta)
  166. if not barter.chest.check_privilege(from_list,player:get_player_name(),meta) then return 0 end
  167. if not barter.chest.check_privilege(to_list,player:get_player_name(),meta) then return 0 end
  168. return count
  169. end,
  170. allow_metadata_inventory_put = function(pos, listname, index, stack, player)
  171. local meta = minetest.get_meta(pos)
  172. barter.chest.start_timer(pos, meta)
  173. if not barter.chest.check_privilege(listname,player:get_player_name(),meta) then return 0 end
  174. return stack:get_count()
  175. end,
  176. allow_metadata_inventory_take = function(pos, listname, index, stack, player)
  177. local meta = minetest.get_meta(pos)
  178. barter.chest.start_timer(pos, meta)
  179. if not barter.chest.check_privilege(listname,player:get_player_name(),meta) then return 0 end
  180. return stack:get_count()
  181. end,
  182. on_timer = function(pos, dtime)
  183. local meta = minetest.get_meta(pos)
  184. if 1 == meta:get_int("clean") then return false end
  185. local timer = meta:get_int("timer")
  186. timer = timer + dtime
  187. if timer > barter.chest.expire_after then
  188. -- attempt to return items to owners
  189. barter.chest.cancel(meta)
  190. -- also clear out items of offline users
  191. local inv = meta:get_inventory()
  192. inv:set_list("pl1", {})
  193. inv:set_list("pl2", {})
  194. return false
  195. end
  196. meta:set_int("timer",timer)
  197. return true
  198. end
  199. })