init.lua 7.4 KB

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