init.lua 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. defenestrate = defenestrate or {}
  2. defenestrate.modpath = minetest.get_modpath("defenestrate")
  3. defenestrate.timeout = 3
  4. --[===[
  5. -- Returns nil, or item, number.
  6. function defenestrate.get_random_item_in_play()
  7. local vendor = depositor.get_random_vending_or_depositing_machine()
  8. if not vendor or not vendor.active then
  9. -- Ignore inactive shops.
  10. return
  11. end
  12. -- Item must actually exist.
  13. if not minetest.registered_items[vendor.item] then
  14. return
  15. end
  16. -- Ignore certain items.
  17. if vendor.item == "air" or vendor.item:find("ignore") then
  18. return
  19. end
  20. -- Must be a valid number of items being sold.
  21. -- Can't be less than 1, and avoid larger than 64 because we're only doing small transactions.
  22. if vendor.number < 1 or vendor.number > 64 then
  23. return
  24. end
  25. return vendor
  26. end
  27. function defenestrate.do_stuff()
  28. -- Get the name and number of a random item being sold on the market.
  29. local random_shop = defenestrate.get_random_item_in_play()
  30. if not random_shop then
  31. minetest.log("autotrade: Did not find a random item being sold on the market.")
  32. return
  33. end
  34. local item, number = random_shop.item, random_shop.number
  35. -- Get the data for a random depositor buying NOT MORE THAN this amount of the item. Highest bid first.
  36. local deposit = depositor.get_random_depositor_buying_item(item, number)
  37. -- Get the data for a random vendor selling NOT LESS THAN this amount of the item. Lowest price first.
  38. local vendor = depositor.get_random_vendor_selling_item(item, number)
  39. if not deposit then
  40. minetest.log("autotrade: Did not find a depositor to sell " .. number .. " " .. item .. ".")
  41. return
  42. end
  43. if not vendor then
  44. minetest.log("autotrade: Did not find a vendor from which to buy " .. number .. " " .. item .. ".")
  45. return
  46. end
  47. if vector.distance(vendor.pos, deposit.pos) > ads.viewrange then
  48. minetest.log("autotrade: Randomly selected vending and depositing machines exceed maximum trading range.")
  49. return
  50. end
  51. local sell_cost = currency.get_stack_value(deposit.currency, deposit.cost)
  52. local buy_cost = currency.get_stack_value(vendor.currency, vendor.cost)
  53. -- Get location of the market booth belonging to the owner of this vending machine.
  54. local deposit_drop_pos = depositor.get_drop_location(deposit.owner)
  55. local vendor_drop_pos = depositor.get_drop_location(vendor.owner)
  56. if not deposit_drop_pos then
  57. -- Ignore vending machines that aren't set up to support remote trading.
  58. minetest.log("autotrade: Randomly chosen depositor (to sell " .. number .. " " .. item .. ") doesn't have a registered market booth.")
  59. return
  60. end
  61. if not vendor_drop_pos then
  62. -- Ignore vending machines that aren't set up to support remote trading.
  63. minetest.log("autotrade: Randomly chosen vendor (from which to buy " .. number .. " " .. item .. ") doesn't have a registered market booth.")
  64. return
  65. end
  66. -- Ensure depositor's drop location is valid.
  67. utility.ensure_map_loaded(vector.add(deposit_drop_pos, {x=-7, y=-7, z=-7}), vector.add(deposit_drop_pos, {x=7, y=7, z=7}))
  68. utility.ensure_map_loaded(vector.add(vendor_drop_pos, {x=-7, y=-7, z=-7}), vector.add(vendor_drop_pos, {x=7, y=7, z=7}))
  69. if minetest.get_node(deposit_drop_pos).name ~= "market:booth" then
  70. minetest.log("autotrade: Could not validate depositor's market booth.")
  71. return
  72. end
  73. if minetest.get_node(vendor_drop_pos).name ~= "market:booth" then
  74. minetest.log("autotrade: Could not validate vendor's market booth.")
  75. return
  76. end
  77. -- Ignore vending machine if the data doesn't match what's recorded.
  78. local deposit_machine_pos = table.copy(deposit.pos)
  79. local deposit_machine_meta = minetest.get_meta(deposit_machine_pos)
  80. if deposit_machine_meta:get_string("owner") ~= deposit.owner or
  81. deposit_machine_meta:get_string("itemname") ~= deposit.item or
  82. deposit_machine_meta:get_string("machine_currency") ~= deposit.currency or
  83. deposit_machine_meta:get_int("number") ~= deposit.number or
  84. deposit_machine_meta:get_int("cost") ~= deposit.cost
  85. then
  86. minetest.log("autotrade: Actual depositor machine data is not in sync with registered depositor info.")
  87. return
  88. end
  89. local vendor_machine_pos = table.copy(vendor.pos)
  90. local vendor_machine_meta = minetest.get_meta(vendor_machine_pos)
  91. if vendor_machine_meta:get_string("owner") ~= vendor.owner or
  92. vendor_machine_meta:get_string("itemname") ~= vendor.item or
  93. vendor_machine_meta:get_string("machine_currency") ~= vendor.currency or
  94. vendor_machine_meta:get_int("number") ~= vendor.number or
  95. vendor_machine_meta:get_int("cost") ~= vendor.cost
  96. then
  97. minetest.log("autotrade: Actual vendor machine data is not in sync with registered vendor info.")
  98. return
  99. end
  100. -- Create an itemstack. This is the item we're gonna try to sell someone.
  101. local itemstack = ItemStack(item .. " " .. number)
  102. -- Create a fake player object.
  103. local fakeplayer = {}
  104. function fakeplayer.is_player(self)
  105. return true
  106. end
  107. function fakeplayer.get_player_name(self)
  108. return "server"
  109. end
  110. local deposit_drop_meta = minetest.get_meta(deposit_drop_pos)
  111. local deposit_drop_inv = deposit_drop_meta:get_inventory()
  112. if not deposit_drop_inv then
  113. minetest.log("autotrade: Could not obtain inventory for depositor's market booth.")
  114. return
  115. end
  116. local vendor_drop_meta = minetest.get_meta(vendor_drop_pos)
  117. local vendor_drop_inv = vendor_drop_meta:get_inventory()
  118. if not vendor_drop_inv then
  119. minetest.log("autotrade: Could not obtain inventory for vendor's market booth.")
  120. return
  121. end
  122. -- Construct an inventory containing the item we're going to sell someone.
  123. local user_inv = minetest.create_detached_inventory("defenestrate:inv", {}, "server")
  124. user_inv:set_size("storage", 5)
  125. user_inv:set_stack("storage", 1, itemstack)
  126. minetest.log("autotrade: Attempting to sell " .. itemstack:get_count() .. " " ..
  127. itemstack:get_name() .. " to depositor at " .. minetest.pos_to_string(deposit_machine_pos) ..
  128. " for " .. sell_cost .. " minegeld.")
  129. minetest.log("autotrade: Attempting to buy " .. itemstack:get_count() .. " " ..
  130. itemstack:get_name() .. " from vendor at " .. minetest.pos_to_string(vendor_machine_pos) ..
  131. " for " .. buy_cost .. " minegeld.")
  132. -- The trade function requires map access!
  133. -- Sell item, get money.
  134. utility.ensure_map_loaded(vector.add(deposit_machine_pos, {x=-7, y=-7, z=-7}), vector.add(deposit_machine_pos, {x=7, y=7, z=7}))
  135. easyvend.execute_trade(deposit_machine_pos, fakeplayer, user_inv, "storage", deposit_drop_inv, "storage", ads.tax)
  136. -- The detached inventory should now contain less (or none) of the item to be sold, and it should contain some minegeld.
  137. -- Now we can go look for someone who sells something for less or equal to this amount, and buy it.
  138. -- The trade function requires map access!
  139. -- Use money obtained in previous transaction to buy item.
  140. utility.ensure_map_loaded(vector.add(vendor_machine_pos, {x=-7, y=-7, z=-7}), vector.add(vendor_machine_pos, {x=7, y=7, z=7}))
  141. easyvend.execute_trade(vendor_machine_pos, fakeplayer, user_inv, "storage", vendor_drop_inv, "storage", ads.tax)
  142. -- Finally, cleanup.
  143. minetest.remove_detached_inventory("defenestrate:inv")
  144. end
  145. function defenestrate.execute()
  146. defenestrate.do_stuff()
  147. -- Repeat.
  148. minetest.after(defenestrate.timeout, function()
  149. defenestrate.execute()
  150. end)
  151. end
  152. --]===]
  153. if not defenestrate.registered then
  154. local c = "autotrade:core"
  155. local f = defenestrate.modpath .. "/init.lua"
  156. reload.register_file(c, f, false)
  157. --minetest.after(defenestrate.timeout, function()
  158. -- defenestrate.execute()
  159. --end)
  160. defenestrate.registered = true
  161. end