easyvend.lua 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. easyvend = easyvend or {}
  2. easyvend.modpath = minetest.get_modpath("easyvend")
  3. local traversable_node_types = easyvend.traversable_node_types
  4. local registered_chests = easyvend.registered_chests
  5. local currency_types = {}
  6. local initial_currency = 1
  7. for k, v in ipairs(currency.note_names) do
  8. table.insert(currency_types, v)
  9. end
  10. -- Maximum price that can be configured on a vendor or depositor.
  11. local maxcost = 1000000
  12. local slots_max = 30
  13. -- Allow for other mods to register custom chests
  14. easyvend.register_chest = function(node_name, inv_list, meta_owner)
  15. easyvend.registered_chests[node_name] = { inv_list = inv_list, meta_owner = meta_owner }
  16. easyvend.traversable_node_types[node_name] = true
  17. end
  18. -- Partly a wrapper around contains_item, but does special treatment if the item
  19. -- is a tool. Basically checks whether the items exist in the supplied inventory
  20. -- list. If check_wear is true, only counts items without wear.
  21. easyvend.check_and_get_items = function(inventory, listname, itemtable, check_wear)
  22. local itemstring = itemtable.name
  23. local minimum = itemtable.count
  24. if check_wear == nil then check_wear = false end
  25. local get_items = {}
  26. -- Tool workaround
  27. if minetest.registered_tools[itemstring] ~= nil then
  28. local count = 0
  29. for i=1,inventory:get_size(listname) do
  30. local stack = inventory:get_stack(listname, i)
  31. if stack:get_name() == itemstring then
  32. if not check_wear or stack:get_wear() == 0 then
  33. count = count + 1
  34. table.insert(get_items, {id=i, item=stack})
  35. if count >= minimum then
  36. return true, get_items
  37. end
  38. end
  39. end
  40. end
  41. return false
  42. else
  43. -- Normal Minetest check
  44. return inventory:contains_item(listname, ItemStack(itemtable))
  45. end
  46. end
  47. easyvend.free_slots = function(inv, listname)
  48. local size = inv:get_size(listname)
  49. local free = 0
  50. for i=1,size do
  51. local stack = inv:get_stack(listname, i)
  52. if stack:is_empty() then
  53. free = free + 1
  54. end
  55. end
  56. return free
  57. end
  58. easyvend.buysell = function(nodename)
  59. local buysell = nil
  60. if ( nodename == "easyvend:depositor" or nodename == "easyvend:depositor_on" ) then
  61. buysell = "buy"
  62. elseif ( nodename == "easyvend:vendor" or nodename == "easyvend:vendor_on" ) then
  63. buysell = "sell"
  64. end
  65. return buysell
  66. end
  67. easyvend.is_active = function(nodename)
  68. if ( nodename == "easyvend:depositor_on" or nodename == "easyvend:vendor_on" ) then
  69. return true
  70. elseif ( nodename == "easyvend:depositor" or nodename == "easyvend:vendor" ) then
  71. return false
  72. else
  73. return nil
  74. end
  75. end
  76. easyvend.set_formspec = function(pos)
  77. local meta = minetest.get_meta(pos)
  78. local node = minetest.get_node(pos)
  79. local description = utility.get_short_desc(minetest.reg_ns_nodes[node.name].description);
  80. local number = meta:get_int("number")
  81. local cost = meta:get_int("cost")
  82. local itemname = meta:get_string("itemname")
  83. local bg = ""
  84. local configmode = meta:get_int("configmode") == 1
  85. if minetest.get_modpath("default") then
  86. bg = default.formspec.get_form_colors() .. default.formspec.get_form_image() .. default.formspec.get_slot_colors()
  87. end
  88. local numbertext, costtext, buysellbuttontext
  89. local itemcounttooltip = "Item count"
  90. local buysell = easyvend.buysell(node.name)
  91. if buysell == "sell" then
  92. numbertext = "Offered Item"
  93. costtext = "Price"
  94. buysellbuttontext = "Buy"
  95. elseif buysell == "buy" then
  96. numbertext = "Requested Item"
  97. costtext = "Payment"
  98. buysellbuttontext = "Sell"
  99. else
  100. return
  101. end
  102. local status = meta:get_string("status")
  103. if status == "" then status = "Unknown." end
  104. local message = meta:get_string("message")
  105. if message == "" then message = "No message." end
  106. local status_image
  107. if node.name == "easyvend:vendor_on" or node.name == "easyvend:depositor_on" then
  108. status_image = "easyvend_status_on.png"
  109. else
  110. status_image = "easyvend_status_off.png"
  111. end
  112. -- TODO: Expose number of items in stock
  113. local formspec = "size[8,7.3;]"
  114. .. bg
  115. .."label[3,-0.2;" .. minetest.formspec_escape(description) .. "]"
  116. .."image[7.5,0.2;0.5,1;" .. status_image .. "]"
  117. .."textarea[2.8,0.2;5.1,2;;Status: " .. minetest.formspec_escape(status) .. ";]"
  118. .."textarea[2.8,1.3;5.6,2;;Message: " .. minetest.formspec_escape(message) .. ";]"
  119. .."label[0,-0.15;"..numbertext.."]"
  120. .."label[0,1.2;"..costtext.."]"
  121. .."list[current_player;main;0,3.5;8,4;]"
  122. local machine_currency = meta:get_string("machine_currency")
  123. if configmode then
  124. local wear = "false"
  125. if meta:get_int("wear") == 1 then wear = "true" end
  126. formspec = formspec
  127. .."item_image_button[0,1.65;1,1;" .. machine_currency .. ";easyvend_currency_image;]"
  128. .."list[context;item;0,0.35;1,1;]"
  129. .."listring[current_player;main]"
  130. .."listring[context;item]"
  131. .."field[1.3,0.65;1.5,1;number;;" .. number .. "]"
  132. .."tooltip[number;"..itemcounttooltip.."]"
  133. .."field[1.3,1.95;1.5,1;cost;;" .. cost .. "]"
  134. .."tooltip[cost;"..itemcounttooltip.."]"
  135. .."button[6,2.8;2,0.5;save;Confirm]"
  136. .."tooltip[save;Confirm configuration and activate machine (only for owner)]"
  137. local weartext, weartooltip
  138. if buysell == "buy" then
  139. weartext = "Buy worn tools"
  140. weartooltip = "If disabled, only tools in perfect condition will be bought from sellers (only settable by owner)"
  141. else
  142. weartext = "Sell worn tools"
  143. weartooltip = "If disabled, only tools in perfect condition will be sold (only settable by owner)"
  144. end
  145. if minetest.registered_tools[itemname] ~= nil then
  146. formspec = formspec .."checkbox[2,2.4;wear;"..minetest.formspec_escape(weartext)..";"..wear.."]"
  147. .."tooltip[wear;"..minetest.formspec_escape(weartooltip).."]"
  148. end
  149. else
  150. formspec = formspec
  151. .."item_image_button[0,1.65;1,1;" .. machine_currency .. ";easyvend_currency_image;]"
  152. .."item_image_button[0,0.35;1,1;"..itemname..";item_image;]"
  153. .."label[1,1.85;×" .. cost .. "]"
  154. .."label[1,0.55;×" .. number .. "]"
  155. .."button[6,2.8;2,0.5;config;Configure]"
  156. if buysell == "sell" then
  157. formspec = formspec .. "tooltip[config;Configure offered items and price (only for owner)]"
  158. else
  159. formspec = formspec .. "tooltip[config;Configure requested items and payment (only for owner)]"
  160. end
  161. formspec = formspec .."button[0,2.8;2,0.5;buysell;"..buysellbuttontext.."]"
  162. if minetest.registered_tools[itemname] ~= nil then
  163. local weartext
  164. if meta:get_int("wear") == 0 then
  165. if buysell == "buy" then
  166. weartext = "Only intact tools are bought."
  167. else
  168. weartext = "Only intact tools are sold."
  169. end
  170. else
  171. if buysell == "sell" then
  172. weartext = "Warning: Might sell worn tools."
  173. else
  174. weartext = "Worn tools are bought, too."
  175. end
  176. end
  177. if weartext ~= nil then
  178. formspec = formspec .."textarea[2.3,2.6;3,1;;"..minetest.formspec_escape(weartext)..";]"
  179. end
  180. end
  181. end
  182. meta:set_string("formspec", formspec)
  183. end
  184. easyvend.machine_disable = function(pos, node, playername)
  185. if node.name == "easyvend:vendor_on" then
  186. easyvend.sound_disable(pos)
  187. minetest.swap_node(pos, {name="easyvend:vendor", param2 = node.param2})
  188. return true
  189. elseif node.name == "easyvend:depositor_on" then
  190. easyvend.sound_disable(pos)
  191. minetest.swap_node(pos, {name="easyvend:depositor", param2 = node.param2})
  192. return true
  193. else
  194. if playername ~= nil then
  195. easyvend.sound_error(playername)
  196. end
  197. return false
  198. end
  199. end
  200. easyvend.machine_enable = function(pos, node)
  201. if node.name == "easyvend:vendor" then
  202. easyvend.sound_setup(pos)
  203. minetest.swap_node(pos, {name="easyvend:vendor_on", param2 = node.param2})
  204. return true
  205. elseif node.name == "easyvend:depositor" then
  206. easyvend.sound_setup(pos)
  207. minetest.swap_node(pos, {name="easyvend:depositor_on", param2 = node.param2})
  208. return true
  209. else
  210. return false
  211. end
  212. end
  213. easyvend.upgrade_currency = function(pos, meta, old_currency, old_cost)
  214. if old_currency == "default:gold_ingot" then
  215. -- Upgrade gold to currency at 1 to 25. This is a fixed exchange rate.
  216. meta:set_string("machine_currency", "currency:minegeld_5")
  217. meta:set_int("cost", math.floor((old_cost * 25) / 5))
  218. return ("currency:minegeld_5"), math.floor((old_cost * 25) / 5)
  219. end
  220. return old_currency, old_cost
  221. end
  222. easyvend.machine_check = function(pos, node)
  223. local active = true
  224. local status = "Ready."
  225. local meta = minetest.get_meta(pos)
  226. local machine_owner = meta:get_string("owner")
  227. local itemname = meta:get_string("itemname")
  228. local number = meta:get_int("number")
  229. local check_wear = meta:get_int("wear") == 0
  230. local inv = meta:get_inventory()
  231. local itemstack = inv:get_stack("item", 1)
  232. local buysell = easyvend.buysell(node.name)
  233. local machine_currency = meta:get_string("machine_currency")
  234. local cost = meta:get_int("cost")
  235. -- If the machine uses a depreciated currency, this will upgrade it using a fixed exchange rate.
  236. machine_currency, cost = easyvend.upgrade_currency(pos, meta, machine_currency, cost)
  237. local chest_pos_remove, chest_error_remove, chest_pos_add, chest_error_add
  238. if buysell == "sell" then
  239. -- Vending machine.
  240. chest_pos_remove, chest_error_remove = easyvend.find_connected_chest(machine_owner, pos, itemname, check_wear, number, true)
  241. chest_pos_add, chest_error_add = easyvend.find_connected_chest(machine_owner, pos, machine_currency, check_wear, cost, false)
  242. else
  243. -- Depositing machine.
  244. chest_pos_remove, chest_error_remove = easyvend.find_connected_chest(machine_owner, pos, machine_currency, check_wear, cost, true)
  245. chest_pos_add, chest_error_add = easyvend.find_connected_chest(machine_owner, pos, itemname, check_wear, number, false)
  246. end
  247. if chest_pos_remove and chest_pos_add then
  248. local rchest, rchestdef, rchest_meta, rchest_inv
  249. rchest = minetest.get_node(chest_pos_remove)
  250. rchestdef = registered_chests[rchest.name]
  251. rchest_meta = minetest.get_meta(chest_pos_remove)
  252. rchest_inv = rchest_meta:get_inventory()
  253. local checkstack, checkitem
  254. if buysell == "buy" then
  255. checkitem = machine_currency
  256. else
  257. checkitem = itemname
  258. end
  259. local stock = 0
  260. -- Count stock
  261. -- FIXME: Ignore tools with bad wear level
  262. for i=1,rchest_inv:get_size(rchestdef.inv_list) do
  263. checkstack = rchest_inv:get_stack(rchestdef.inv_list, i)
  264. if checkstack:get_name() == checkitem then
  265. stock = stock + checkstack:get_count()
  266. end
  267. end
  268. meta:set_int("stock", stock)
  269. if not itemstack:is_empty() then
  270. local number_stack_max = itemstack:get_stack_max()
  271. local maxnumber = number_stack_max * slots_max
  272. if not(number >= 1 and number <= maxnumber and cost >= 1 and cost <= maxcost) then
  273. active = false
  274. if buysell == "sell" then
  275. status = "Invalid item count or price."
  276. else
  277. status = "Invalid item count or payment."
  278. end
  279. end
  280. else
  281. active = false
  282. status = "Awaiting configuration by owner."
  283. end
  284. else
  285. active = false
  286. meta:set_int("stock", 0)
  287. if chest_error_remove == "no_chest" and chest_error_add == "no_chest" then
  288. status = "No storage; machine needs to be connected with a locked chest."
  289. elseif chest_error_remove == "not_owned" or chest_error_add == "not_owned" then
  290. status = "Storage can’t be accessed because it is owned by a different person!"
  291. elseif chest_error_remove == "no_stock" then
  292. if buysell == "sell" then
  293. status = "The vending machine has insufficient materials!"
  294. else
  295. status = "The depositing machine is out of money!"
  296. end
  297. elseif chest_error_add == "no_space" then
  298. status = "No room in the machine’s storage!"
  299. else
  300. status = "Unknown error!"
  301. end
  302. end
  303. if meta:get_int("configmode") == 1 then
  304. active = false
  305. status = "Awaiting configuration by owner."
  306. end
  307. if currency.is_currency(itemname) then
  308. status = "Cannot treat currency as a directly saleable item!"
  309. active = false
  310. end
  311. -- If the currency type is depreciated, then this warning overrides all others.
  312. if not currency.is_currency(machine_currency) then
  313. status = "Machine uses a depreciated currency standard!"
  314. active = false
  315. end
  316. meta:set_string("status", status)
  317. itemname=itemstack:get_name()
  318. meta:set_string("itemname", itemname)
  319. -- Inform remote market system of any changes.
  320. depositor.update_info(pos, machine_owner, itemname, number, cost, machine_currency, buysell, active)
  321. local change
  322. if node.name == "easyvend:vendor" or node.name == "easyvend:depositor" then
  323. if active then change = easyvend.machine_enable(pos, node) end
  324. elseif node.name == "easyvend:vendor_on" or node.name == "easyvend:depositor_on" then
  325. if not active then change = easyvend.machine_disable(pos, node) end
  326. end
  327. local current_node = minetest.get_node(pos)
  328. meta:set_string("infotext", easyvend.make_infotext(pos, current_node.name, machine_owner, cost, number, itemname))
  329. easyvend.set_formspec(pos)
  330. return change
  331. end
  332. easyvend.on_receive_fields_config = function(pos, formname, fields, sender)
  333. local node = minetest.get_node(pos)
  334. local meta = minetest.get_meta(pos)
  335. local inv_self = meta:get_inventory()
  336. local itemstack = inv_self:get_stack("item",1)
  337. local buysell = easyvend.buysell(node.name)
  338. if fields.config then
  339. meta:set_int("configmode", 1)
  340. local was_active = easyvend.is_active(node.name)
  341. if was_active then
  342. meta:set_string("message", "Configuration mode activated; machine disabled.")
  343. else
  344. meta:set_string("message", "Configuration mode activated.")
  345. end
  346. easyvend.machine_check(pos, node)
  347. return
  348. end
  349. if not fields.save then
  350. return
  351. end
  352. local number = fields.number
  353. local cost = fields.cost
  354. number = tonumber(number)
  355. cost = tonumber(cost)
  356. local itemname=""
  357. local number_stack_max = 0
  358. if itemstack and not itemstack:is_empty() then
  359. itemname = itemstack:get_name()
  360. number_stack_max = itemstack:get_stack_max()
  361. end
  362. local oldnumber = meta:get_int("number")
  363. local oldcost = meta:get_int("cost")
  364. local maxnumber = number_stack_max * slots_max
  365. if ( itemstack == nil or itemstack:is_empty() ) then
  366. meta:set_string("status", "Awaiting configuration by owner.")
  367. meta:set_string("message", "No item specified.")
  368. easyvend.sound_error(sender:get_player_name())
  369. easyvend.set_formspec(pos)
  370. return
  371. elseif ( number == nil or number < 1 or number > maxnumber ) then
  372. if maxnumber > 1 then
  373. meta:set_string("message", string.format("Invalid item count; must be between 1 and %d!", maxnumber))
  374. else
  375. meta:set_string("message", "Invalid item count; must be exactly 1!")
  376. end
  377. meta:set_int("number", oldnumber)
  378. easyvend.sound_error(sender:get_player_name())
  379. easyvend.set_formspec(pos)
  380. return
  381. elseif ( cost == nil or cost < 1 or cost > maxcost ) then
  382. if maxcost > 1 then
  383. meta:set_string("message", string.format("Invalid cost; must be between 1 and %d!", maxcost))
  384. else
  385. meta:set_string("message", "Invalid cost; must be exactly 1!")
  386. end
  387. meta:set_int("cost", oldcost)
  388. easyvend.sound_error(sender:get_player_name())
  389. easyvend.set_formspec(pos)
  390. return
  391. end
  392. meta:set_int("number", number)
  393. meta:set_int("cost", cost)
  394. meta:set_string("itemname", itemname)
  395. meta:set_int("configmode", 0)
  396. meta:set_string("message", "Configuration successful.")
  397. local change = easyvend.machine_check(pos, node)
  398. if not change then
  399. if (node.name == "easyvend:vendor_on" or node.name == "easyvend:depositor_on") then
  400. easyvend.sound_setup(pos)
  401. else
  402. easyvend.sound_disable(pos)
  403. end
  404. end
  405. end
  406. easyvend.make_infotext = function(pos, nodename, owner, cost, number, itemstring)
  407. local dname = rename.gpn(owner)
  408. local d = ""
  409. if itemstring == nil or itemstring == "" or number == 0 or cost == 0 then
  410. if easyvend.buysell(nodename) == "sell" then
  411. d = string.format("Inactive Vending Machine (Owned by <%s>!)", dname)
  412. else
  413. d = string.format("Inactive Depositing Machine (Owned by <%s>!)", dname)
  414. end
  415. return d
  416. end
  417. local iname = minetest.registered_items[itemstring].description
  418. if iname == nil then iname = itemstring end
  419. iname = utility.get_short_desc(iname)
  420. local printitem, printcost
  421. if number == 1 then
  422. printitem = iname
  423. else
  424. printitem = string.format("%d×%s", number, iname)
  425. end
  426. local meta = minetest.get_meta(pos)
  427. local machine_currency = meta:get_string("machine_currency")
  428. if currency.is_currency(machine_currency) then
  429. printcost = currency.get_stack_value(machine_currency, cost) .. " Minegeld"
  430. else
  431. printcost = "Depreciated Currency!"
  432. end
  433. if nodename == "easyvend:vendor_on" then
  434. d = string.format("Vending Machine (Owned by <%s>!)\nSelling: %s\nPrice: %s", dname, printitem, printcost)
  435. elseif nodename == "easyvend:vendor" then
  436. d = string.format("Inactive Vending Machine (Owned by <%s>!)\nSelling: %s\nPrice: %s", dname, printitem, printcost)
  437. elseif nodename == "easyvend:depositor_on" then
  438. d = string.format("Depositing Machine (Owned by <%s>!)\nBuying: %s\nPayment: %s", dname, printitem, printcost)
  439. elseif nodename == "easyvend:depositor" then
  440. d = string.format("Inactive Depositing Machine (Owned by <%s>!)\nBuying: %s\nPayment: %s", dname, printitem, printcost)
  441. end
  442. return d
  443. end
  444. easyvend.execute_trade = function(pos, sender, player_inv, pin, vendor_inv, iin, remote_tax)
  445. local sendername = sender:get_player_name()
  446. local meta = minetest.get_meta(pos)
  447. local node = minetest.get_node(pos)
  448. local number = meta:get_int("number")
  449. local cost = meta:get_int("cost")
  450. local itemname=meta:get_string("itemname")
  451. local item=meta:get_inventory():get_stack("item", 1)
  452. local check_wear = meta:get_int("wear") == 0 and minetest.registered_tools[itemname] ~= nil
  453. local buysell = easyvend.buysell(node.name)
  454. local number_stack_max = item:get_stack_max()
  455. local maxnumber = number_stack_max * slots_max
  456. if ( number == nil or number < 1 or number > maxnumber ) or
  457. ( cost == nil or cost < 1 or cost > maxcost ) or
  458. ( itemname == nil or itemname=="") then
  459. meta:set_string("status", "Invalid item count or price!")
  460. easyvend.machine_disable(pos, node, sendername)
  461. easyvend.set_formspec(pos)
  462. return
  463. end
  464. local machine_currency = meta:get_string("machine_currency")
  465. local machine_owner = meta:get_string("owner")
  466. -- Check currency.
  467. if not currency.is_currency(machine_currency) then
  468. easyvend.sound_error(sendername)
  469. minetest.chat_send_player(sendername, "# Server: Shop at " .. rc.pos_to_namestr(pos) .. " uses a depreciated currency, attempting to upgrade!")
  470. minetest.chat_send_player(sendername, "# Server: If this happens, try to use the shop again and it may work if nothing else is wrong.")
  471. easyvend.machine_check(pos, node)
  472. --meta:set_string("status", "Machine uses a depreciated currency standard!")
  473. --easyvend.machine_disable(pos, node, sendername)
  474. --easyvend.set_formspec(pos)
  475. return
  476. end
  477. -- Cannot sell or buy currency directly.
  478. if currency.is_currency(itemname) then
  479. meta:set_string("status", "Cannot treat currency as a directly saleable item!")
  480. easyvend.machine_disable(pos, node, sendername)
  481. easyvend.set_formspec(pos)
  482. return
  483. end
  484. local chest_pos_remove, chest_error_remove, chest_pos_add, chest_error_add
  485. if buysell == "sell" then
  486. -- Vending.
  487. chest_pos_remove, chest_error_remove = easyvend.find_connected_chest(machine_owner, pos, itemname, check_wear, number, true)
  488. chest_pos_add, chest_error_add = easyvend.find_connected_chest(machine_owner, pos, machine_currency, check_wear, cost, false)
  489. else
  490. -- Depositing.
  491. chest_pos_remove, chest_error_remove = easyvend.find_connected_chest(machine_owner, pos, machine_currency, check_wear, cost, true)
  492. chest_pos_add, chest_error_add = easyvend.find_connected_chest(machine_owner, pos, itemname, check_wear, number, false)
  493. end
  494. if chest_pos_remove ~= nil and chest_pos_add ~= nil and sender and sender:is_player() then
  495. local rchest = minetest.get_node(chest_pos_remove)
  496. local rchestdef = registered_chests[rchest.name]
  497. local rchest_meta = minetest.get_meta(chest_pos_remove)
  498. local rchest_inv = rchest_meta:get_inventory()
  499. local achest = minetest.get_node(chest_pos_add)
  500. local achestdef = registered_chests[achest.name]
  501. local achest_meta = minetest.get_meta(chest_pos_add)
  502. local achest_inv = achest_meta:get_inventory()
  503. -- If passing a target inventory, redirect operations to it.
  504. -- This also indicates whether this is a remote trade executed via market.
  505. local vchest_inv = achest_inv
  506. local vchest_name = achestdef.inv_list
  507. if vendor_inv and iin then
  508. vchest_inv = vendor_inv
  509. vchest_name = iin
  510. end
  511. local stack = {name=itemname, count=number, wear=0, metadata=""}
  512. local price = currency.get_stack_value(machine_currency, cost)
  513. local chest_has, player_has, chest_free, player_free, chest_out, player_out
  514. local msg = ""
  515. if buysell == "sell" then
  516. -- Vending.
  517. local pricewithtax = price
  518. if vendor_inv then
  519. pricewithtax = currency.calculate_tax(price, 1, remote_tax)
  520. end
  521. chest_has, chest_out = easyvend.check_and_get_items(rchest_inv, rchestdef.inv_list, stack, check_wear)
  522. player_has = currency.has_cash_amount(player_inv, pin, pricewithtax)
  523. chest_free = currency.room_for_cash(vchest_inv, vchest_name, price)
  524. player_free = player_inv:room_for_item(pin, stack)
  525. if chest_has and player_has and chest_free and player_free then
  526. if number <= number_stack_max then
  527. easyvend.machine_enable(pos, node)
  528. -- Transfer items before transfering cash (this is because cash transfers can use up an unexpected number of free slots).
  529. if check_wear then
  530. rchest_inv:set_stack(rchestdef.inv_list, chest_out[1].id, "")
  531. player_inv:add_item(pin, chest_out[1].item)
  532. else
  533. stack = rchest_inv:remove_item(rchestdef.inv_list, stack)
  534. player_inv:add_item(pin, stack)
  535. end
  536. -- Transfer cash.
  537. currency.remove_cash(player_inv, pin, pricewithtax)
  538. currency.add_cash(vchest_inv, vchest_name, price)
  539. -- Deliver tax to the colonial government.
  540. currency.record_tax_income(pricewithtax - price)
  541. meta:set_string("message", "Item bought.")
  542. easyvend.sound_vend(pos)
  543. easyvend.machine_check(pos, node)
  544. local remote_str = ""
  545. if vendor_inv then
  546. remote_str = " remotely"
  547. end
  548. minetest.log("action", sendername .. remote_str .. " bought " .. number .. " " ..
  549. itemname .. " for " .. price .. " minegeld from vending machine owned by " ..
  550. machine_owner .. " at " .. minetest.pos_to_string(pos) .. ", tax was " .. (pricewithtax - price))
  551. else
  552. -- Large item counts (multiple stacks)
  553. local numberstacks = math.modf(number / number_stack_max)
  554. local numberremainder = math.fmod(number, number_stack_max)
  555. local numberfree = numberstacks
  556. if numberremainder > 0 then numberfree = numberfree + 1 end
  557. if not player_free and easyvend.free_slots(player_inv, pin) < numberfree then
  558. if numberfree > 1 then
  559. msg = string.format("No room in your inventory (%d empty slots required)!", numberfree)
  560. else
  561. msg = "No room in your inventory!"
  562. end
  563. meta:set_string("message", msg)
  564. elseif not chest_free and not currency.room_for_cash(vchest_inv, vchest_name, price) then
  565. meta:set_string("status", "No room in the machine’s storage!")
  566. easyvend.machine_disable(pos, node, sendername)
  567. else
  568. -- Remember items for transfer
  569. local cheststacks = {}
  570. easyvend.machine_enable(pos, node)
  571. -- Transfer items before transfering cash (this is because cash transfers can use up an unexpected number of free slots).
  572. if check_wear then
  573. for o=1, #chest_out do
  574. rchest_inv:set_stack(rchestdef.inv_list, chest_out[o].id, "")
  575. end
  576. else
  577. for i=1, numberstacks do
  578. stack.count = number_stack_max
  579. table.insert(cheststacks, rchest_inv:remove_item(rchestdef.inv_list, stack))
  580. end
  581. end
  582. if numberremainder > 0 then
  583. stack.count = numberremainder
  584. table.insert(cheststacks, rchest_inv:remove_item(rchestdef.inv_list, stack))
  585. end
  586. if check_wear then
  587. for o=1, #chest_out do
  588. player_inv:add_item(pin, chest_out[o].item)
  589. end
  590. else
  591. for i=1, #cheststacks do
  592. player_inv:add_item(pin, cheststacks[i])
  593. end
  594. end
  595. -- Transfer money.
  596. currency.remove_cash(player_inv, pin, pricewithtax)
  597. currency.add_cash(vchest_inv, vchest_name, price)
  598. -- Deliver tax to the colonial government.
  599. currency.record_tax_income(pricewithtax - price)
  600. meta:set_string("message", "Item bought.")
  601. easyvend.sound_vend(pos)
  602. easyvend.machine_check(pos, node)
  603. local remote_str = ""
  604. if vendor_inv then
  605. remote_str = " remotely"
  606. end
  607. minetest.log("action", sendername .. remote_str .. " bought " .. number .. " " ..
  608. itemname .. " for " .. price .. " minegeld from vending machine owned by " ..
  609. machine_owner .. " at " .. minetest.pos_to_string(pos) .. ", tax was " .. (pricewithtax - price))
  610. end
  611. end
  612. elseif chest_has and player_has then
  613. if not player_free then
  614. msg = "No room in your inventory!"
  615. meta:set_string("message", msg)
  616. easyvend.sound_error(sendername)
  617. elseif not chest_free then
  618. msg = "No room in the machine’s storage!"
  619. meta:set_string("status", msg)
  620. easyvend.machine_disable(pos, node, sendername)
  621. end
  622. else
  623. if not chest_has then
  624. msg = "The vending machine has insufficient materials!"
  625. meta:set_string("status", msg)
  626. easyvend.machine_disable(pos, node, sendername)
  627. elseif not player_has then
  628. msg = "You can’t afford this item!"
  629. meta:set_string("message", msg)
  630. easyvend.sound_error(sendername)
  631. end
  632. end
  633. else
  634. -- Depositing.
  635. local pricewithtax = price
  636. if vendor_inv then
  637. pricewithtax = currency.calculate_tax(price, 2, remote_tax)
  638. end
  639. chest_has = currency.has_cash_amount(rchest_inv, rchestdef.inv_list, price)
  640. player_has, player_out = easyvend.check_and_get_items(player_inv, pin, stack, check_wear)
  641. chest_free = vchest_inv:room_for_item(vchest_name, stack)
  642. player_free = currency.room_for_cash(player_inv, pin, pricewithtax)
  643. if chest_has and player_has and chest_free and player_free then
  644. if number <= number_stack_max then
  645. easyvend.machine_enable(pos, node)
  646. -- Transfer items before transfering cash (this is because cash transfers can use up an unexpected number of free slots).
  647. if check_wear then
  648. player_inv:set_stack(pin, player_out[1].id, "")
  649. vchest_inv:add_item(vchest_name, player_out[1].item)
  650. else
  651. stack = player_inv:remove_item(pin, stack)
  652. vchest_inv:add_item(vchest_name, stack)
  653. end
  654. -- Transfer money.
  655. currency.remove_cash(rchest_inv, rchestdef.inv_list, price)
  656. currency.add_cash(player_inv, pin, pricewithtax)
  657. -- Deliver tax to the colonial government.
  658. currency.record_tax_income(price - pricewithtax)
  659. meta:set_string("status", "Ready.")
  660. meta:set_string("message", "Item sold.")
  661. easyvend.sound_deposit(pos)
  662. easyvend.machine_check(pos, node)
  663. local remote_str = ""
  664. if vendor_inv then
  665. remote_str = " remotely"
  666. end
  667. minetest.log("action", sendername .. remote_str .. " sold " .. number .. " " ..
  668. itemname .. " for " .. price .. " minegeld to depositing machine owned by " ..
  669. machine_owner .. " at " .. minetest.pos_to_string(pos) .. ", tax was " .. (price - pricewithtax))
  670. else
  671. -- Large item counts (multiple stacks)
  672. local numberstacks = math.modf(number / number_stack_max)
  673. local numberremainder = math.fmod(number, number_stack_max)
  674. local numberfree = numberstacks
  675. if numberremainder > 0 then numberfree = numberfree + 1 end
  676. if not player_free and not currency.room_for_cash(player_inv, pin, pricewithtax) then
  677. msg = "Not enough room in your inventory for payment!"
  678. meta:set_string("message", msg)
  679. easyvend.sound_error(sendername)
  680. elseif not chest_free and easyvend.free_slots(vchest_inv, vchest_name) < numberfree then
  681. meta:set_string("status", "No room in the machine’s storage!")
  682. easyvend.machine_disable(pos, node, sendername)
  683. else
  684. easyvend.machine_enable(pos, node)
  685. -- Remember removed items for transfer
  686. local playerstacks = {}
  687. -- Transfer items before transfering cash (this is because cash transfers can use up an unexpected number of free slots).
  688. if check_wear then
  689. for o=1, #player_out do
  690. player_inv:set_stack(pin, player_out[o].id, "")
  691. end
  692. else
  693. for i=1, numberstacks do
  694. stack.count = number_stack_max
  695. table.insert(playerstacks, player_inv:remove_item(pin, stack))
  696. end
  697. end
  698. if numberremainder > 0 then
  699. stack.count = numberremainder
  700. table.insert(playerstacks, player_inv:remove_item(pin, stack))
  701. end
  702. if check_wear then
  703. for o=1, #player_out do
  704. vchest_inv:add_item(vchest_name, player_out[o].item)
  705. end
  706. else
  707. for i=1, #playerstacks do
  708. vchest_inv:add_item(vchest_name, playerstacks[i])
  709. end
  710. end
  711. -- Transfer money.
  712. currency.remove_cash(rchest_inv, rchestdef.inv_list, price)
  713. currency.add_cash(player_inv, pin, pricewithtax)
  714. -- Deliver tax to the colonial government.
  715. currency.record_tax_income(price - pricewithtax)
  716. meta:set_string("message", "Item sold.")
  717. easyvend.sound_deposit(pos)
  718. easyvend.machine_check(pos, node)
  719. local remote_str = ""
  720. if vendor_inv then
  721. remote_str = " remotely"
  722. end
  723. minetest.log("action", sendername .. remote_str .. " sold " .. number .. " " ..
  724. itemname .. " for " .. price .. " minegeld to depositing machine owned by " ..
  725. machine_owner .. " at " .. minetest.pos_to_string(pos) .. ", tax was " .. (price - pricewithtax))
  726. end
  727. end
  728. elseif chest_has and player_has then
  729. if not player_free then
  730. msg = "No room in your inventory!"
  731. meta:set_string("message", msg)
  732. easyvend.sound_error(sendername)
  733. elseif not chest_free then
  734. msg = "No room in the machine’s storage!"
  735. meta:set_string("status", msg)
  736. easyvend.machine_disable(pos, node, sendername)
  737. end
  738. else
  739. if not player_has then
  740. msg = "You have insufficient materials!"
  741. meta:set_string("message", msg)
  742. easyvend.sound_error(sendername)
  743. elseif not chest_has then
  744. msg = "The depositing machine is out of money!"
  745. meta:set_string("status", msg)
  746. easyvend.machine_disable(pos, node, sendername)
  747. end
  748. end
  749. end
  750. else
  751. local status
  752. meta:set_int("stock", 0)
  753. if chest_error_remove == "no_chest" and chest_error_add == "no_chest" then
  754. status = "No storage; machine needs to be connected with a locked chest."
  755. elseif chest_error_remove == "not_owned" or chest_error_add == "not_owned" then
  756. status = "Storage can’t be accessed because it is owned by a different person!"
  757. elseif chest_error_remove == "no_stock" then
  758. if buysell == "sell" then
  759. status = "The vending machine has insufficient materials!"
  760. else
  761. status = "The depositing machine is out of money!"
  762. end
  763. elseif chest_error_add == "no_space" then
  764. status = "No room in the machine’s storage!"
  765. else
  766. status = "Unknown error!"
  767. end
  768. meta:set_string("status", status)
  769. easyvend.sound_error(sendername)
  770. end
  771. easyvend.set_formspec(pos)
  772. end
  773. -- Executed when player uses formspec on actual vending machine.
  774. easyvend.on_receive_fields_buysell = function(pos, formname, fields, sender)
  775. if not fields.buysell then
  776. return
  777. end
  778. return easyvend.execute_trade(pos, sender, sender:get_inventory(), "main", nil, nil, nil)
  779. end
  780. easyvend.after_place_node = function(pos, placer)
  781. local node = minetest.get_node(pos)
  782. local meta = minetest.get_meta(pos)
  783. local inv = meta:get_inventory()
  784. local player_name = placer:get_player_name()
  785. local dname = rename.gpn(player_name)
  786. inv:set_size("item", 1)
  787. inv:set_size("gold", 1)
  788. local machine_currency = currency_types[initial_currency]
  789. meta:set_string("machine_currency", machine_currency)
  790. meta:set_int("machine_currency_idx", initial_currency)
  791. inv:set_stack( "gold", 1, machine_currency )
  792. local d = ""
  793. if node.name == "easyvend:vendor" then
  794. d = string.format("Inactive Vending Machine (Owned by <%s>!)", dname)
  795. meta:set_int("wear", 1)
  796. elseif node.name == "easyvend:depositor" then
  797. d = string.format("Inactive Depositing Machine (Owned by <%s>!)", dname)
  798. meta:set_int("wear", 0)
  799. end
  800. meta:set_string("infotext", d)
  801. meta:set_string("status", "Awaiting configuration by owner.")
  802. meta:set_string("message", "Welcome! Please prepare the machine.")
  803. meta:set_int("number", 1)
  804. meta:set_int("cost", 1)
  805. meta:set_int("stock", -1)
  806. meta:set_int("configmode", 1)
  807. meta:set_string("itemname", "")
  808. meta:set_string("owner", player_name or "")
  809. meta:set_string("rename", dname)
  810. easyvend.set_formspec(pos)
  811. end
  812. easyvend.can_dig = function(pos, player)
  813. local meta = minetest.get_meta(pos)
  814. local name = player:get_player_name()
  815. local owner = meta:get_string("owner")
  816. -- Owner can always dig shop
  817. if owner == name then
  818. return true
  819. end
  820. local chest_pos = easyvend.find_connected_chest(owner, pos)
  821. local chest, meta_chest
  822. if chest_pos then
  823. chest = minetest.get_node(chest_pos)
  824. meta_chest = minetest.get_meta(chest_pos)
  825. else
  826. return true --if no chest, enyone can dig this shop
  827. end
  828. if registered_chests[chest.name] then
  829. if player and player:is_player() then
  830. local owner_chest = meta_chest:get_string(registered_chests[chest.name].meta_owner)
  831. if name == owner_chest then
  832. return true --chest owner can also dig shop
  833. end
  834. end
  835. return false
  836. else
  837. return true --if no chest, enyone can dig this shop
  838. end
  839. end
  840. easyvend.on_receive_fields = function(pos, formname, fields, sender)
  841. local meta = minetest.get_meta(pos)
  842. local node = minetest.get_node(pos)
  843. local owner = meta:get_string("owner")
  844. local sendername = sender:get_player_name(sender)
  845. if fields.easyvend_currency_image then
  846. if meta:get_int("configmode") == 1 and sendername == owner then
  847. -- Toggle through possible banknote denominations.
  848. local idx = meta:get_int("machine_currency_idx") or initial_currency
  849. idx = idx + 1
  850. if idx > #currency_types then idx = 1 end
  851. meta:set_string("machine_currency", currency_types[idx])
  852. meta:set_int("machine_currency_idx", idx)
  853. easyvend.set_formspec(pos)
  854. end
  855. end
  856. if fields.config or fields.save or fields.usermode then
  857. if sender:get_player_name() == owner then
  858. easyvend.on_receive_fields_config(pos, formname, fields, sender)
  859. else
  860. meta:set_string("message", "Only the owner may change the configuration.")
  861. easyvend.sound_error(sendername)
  862. easyvend.set_formspec(pos)
  863. return
  864. end
  865. elseif fields.wear ~= nil then
  866. if sender:get_player_name() == owner then
  867. if fields.wear == "true" then
  868. if easyvend.buysell(node.name) == "buy" then
  869. meta:set_string("message", "Used tools are now accepted.")
  870. else
  871. meta:set_string("message", "Used tools are now for sale.")
  872. end
  873. meta:set_int("wear", 1)
  874. elseif fields.wear == "false" then
  875. if easyvend.buysell(node.name) == "buy" then
  876. meta:set_string("message", "Used tools are now rejected.")
  877. else
  878. meta:set_string("message", "Used tools won’t be sold anymore.")
  879. end
  880. meta:set_int("wear", 0)
  881. end
  882. easyvend.set_formspec(pos)
  883. return
  884. else
  885. meta:set_string("message", "Only the owner may change the configuration.")
  886. easyvend.sound_error(sendername)
  887. easyvend.set_formspec(pos)
  888. return
  889. end
  890. elseif fields.buysell then
  891. easyvend.on_receive_fields_buysell(pos, formname, fields, sender)
  892. end
  893. end
  894. easyvend.sound_error = function(playername)
  895. minetest.sound_play("easyvend_error", {to_player = playername, gain = 0.25})
  896. end
  897. easyvend.sound_setup = function(pos)
  898. minetest.sound_play("easyvend_activate", {pos = pos, gain = 0.5, max_hear_distance = 12,})
  899. end
  900. easyvend.sound_disable = function(pos)
  901. minetest.sound_play("easyvend_disable", {pos = pos, gain = 0.9, max_hear_distance = 12,})
  902. end
  903. easyvend.sound_vend = function(pos)
  904. minetest.sound_play("easyvend_vend", {pos = pos, gain = 0.4, max_hear_distance = 5,})
  905. end
  906. easyvend.sound_deposit = function(pos)
  907. minetest.sound_play("easyvend_deposit", {pos = pos, gain = 0.4, max_hear_distance = 5,})
  908. end
  909. --[[ Tower building ]]
  910. easyvend.is_traversable = function(pos)
  911. local node = minetest.get_node_or_nil(pos)
  912. if (node == nil) then
  913. return false
  914. end
  915. return traversable_node_types[node.name] == true
  916. end
  917. easyvend.neighboring_nodes = function(pos)
  918. local check = {
  919. {x=pos.x, y=pos.y-1, z=pos.z},
  920. {x=pos.x, y=pos.y+1, z=pos.z},
  921. }
  922. local trav = {}
  923. for i=1,#check do
  924. if easyvend.is_traversable(check[i]) then
  925. table.insert(trav, check[i])
  926. end
  927. end
  928. return trav
  929. end
  930. easyvend.find_connected_chest = function(owner, pos, nodename, check_wear, amount, removing)
  931. local nodes = easyvend.neighboring_nodes(pos)
  932. if (#nodes < 1 or #nodes > 2) then
  933. return nil, "no_chest"
  934. end
  935. -- Find the stack direction
  936. local first = nil
  937. local second = nil
  938. for i=1,#nodes do
  939. if ( first == nil ) then
  940. first = nodes[i]
  941. else
  942. second = nodes[i]
  943. end
  944. end
  945. local chest_pos, chest_internal
  946. if (first ~= nil and second ~= nil) then
  947. local dy = (first.y - second.y)/2
  948. chest_pos, chest_internal = easyvend.find_chest(owner, pos, dy, nodename, check_wear, amount, removing)
  949. if ( chest_pos == nil ) then
  950. chest_pos, chest_internal = easyvend.find_chest(owner, pos, -dy, nodename, check_wear, amount, removing, chest_internal)
  951. end
  952. else
  953. local dy = first.y - pos.y
  954. chest_pos, chest_internal = easyvend.find_chest(owner, pos, dy, nodename, check_wear, amount, removing)
  955. end
  956. if chest_internal.chests == 0 then
  957. return nil, "no_chest"
  958. elseif chest_internal.chests == chest_internal.other_chests then
  959. return nil, "not_owned"
  960. elseif removing and chest_internal.stock < 1 then
  961. return nil, "no_stock"
  962. elseif not removing and chest_internal.space < 1 then
  963. return nil, "no_space"
  964. elseif chest_pos ~= nil then
  965. return chest_pos
  966. else
  967. return nil, "unknown"
  968. end
  969. end
  970. easyvend.find_chest = function(owner, pos, dy, itemname, check_wear, amount, removing, internal)
  971. pos = {x=pos.x, y=pos.y + dy, z=pos.z}
  972. if internal == nil then
  973. internal = {}
  974. internal.chests = 0
  975. internal.other_chests = 0
  976. internal.stock = 0
  977. internal.space = 0
  978. end
  979. local node = minetest.get_node_or_nil(pos)
  980. if ( node == nil ) then
  981. return nil, internal
  982. end
  983. local chestdef = registered_chests[node.name]
  984. if (chestdef ~= nil) then
  985. internal.chests = internal.chests + 1
  986. local meta = minetest.get_meta(pos)
  987. if (owner ~= meta:get_string(chestdef.meta_owner)) then
  988. internal.other_chests = internal.other_chests + 1
  989. return nil, internal
  990. end
  991. local inv = meta:get_inventory()
  992. if (inv ~= nil) then
  993. if (itemname ~= nil and amount ~= nil and removing ~= nil and check_wear ~= nil) then
  994. local chest_has, chest_free
  995. -- We're going to query the chest to answer two questions:
  996. -- Does the chest contain the item in the amount requested?
  997. -- Does the chest contain free slots suitable to store the amount requested?
  998. if currency.is_currency(itemname) then
  999. -- Item is a fungible currency, use currency-related functions.
  1000. local value = currency.get_stack_value(itemname, amount)
  1001. chest_free = currency.room_for_cash(inv, chestdef.inv_list, value)
  1002. chest_has = currency.has_cash_amount(inv, chestdef.inv_list, value)
  1003. -- If the chest doesn't have enough space to ADD currency,
  1004. -- we can't safely remove currency, either (due to denomination splitting).
  1005. if not chest_free then
  1006. chest_has = false
  1007. end
  1008. else
  1009. -- Do regular itemstack-style check. Note: as of the current Minetest version,
  1010. -- the raw inv:room_for_item() check works with stacks over the stackmax limit.
  1011. -- The old version of this check also checked for number of free slots,
  1012. -- but that shouldn't be necessary.
  1013. local stack = {name=itemname, count=amount, wear=0, metadata=""}
  1014. chest_has = easyvend.check_and_get_items(inv, chestdef.inv_list, stack, check_wear)
  1015. chest_free = inv:room_for_item(chestdef.inv_list, stack)
  1016. end
  1017. if chest_has then
  1018. internal.stock = internal.stock + 1
  1019. end
  1020. if chest_free then
  1021. internal.space = internal.space + 1
  1022. end
  1023. if (removing and internal.stock == 0) or (not removing and internal.space == 0) then
  1024. return easyvend.find_chest(owner, pos, dy, itemname, check_wear, amount, removing, internal)
  1025. else
  1026. return pos, internal
  1027. end
  1028. end
  1029. end
  1030. elseif (node.name ~= "easyvend:vendor" and node.name~="easyvend:depositor" and node.name~="easyvend:vendor_on" and node.name~="easyvend:depositor_on") then
  1031. return nil, internal
  1032. end
  1033. return easyvend.find_chest(owner, pos, dy, itemname, check_wear, amount, removing, internal)
  1034. end
  1035. -- Pseudo-inventory handling
  1036. easyvend.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
  1037. if listname=="item" then
  1038. local meta = minetest.get_meta(pos);
  1039. local owner = meta:get_string("owner")
  1040. local name = player:get_player_name()
  1041. if name == owner then
  1042. local inv = meta:get_inventory()
  1043. if stack==nil then
  1044. inv:set_stack( "item", 1, nil )
  1045. else
  1046. local sn = stack:get_name()
  1047. -- Do not permit currency denominations to be placed in this slot.
  1048. if currency.is_currency(sn) then
  1049. return 0
  1050. end
  1051. inv:set_stack("item", 1, sn)
  1052. meta:set_string("itemname", sn)
  1053. easyvend.set_formspec(pos)
  1054. end
  1055. end
  1056. end
  1057. return 0
  1058. end
  1059. easyvend.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
  1060. return 0
  1061. end
  1062. easyvend.allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
  1063. return 0
  1064. end