You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
8.1KB

  1. --
  2. -- Minetest lurkcoin mod - Bank
  3. --
  4. -- © 2019 by luk3yx
  5. --
  6. -- Add a function to automatically change the bank
  7. function lurkcoin.change_bank(bank)
  8. -- Sanity checks
  9. assert(type(bank) == 'table')
  10. assert(bank.getbal and bank.setbal)
  11. -- Get the current mod name
  12. if not bank.mod then
  13. bank.mod = minetest.get_current_modname() or '???'
  14. end
  15. -- Make sure "getbal" has a consistent return result and add user_exists if
  16. -- it doesn't.
  17. if type(bank.getbal('\194\164 Fake user')) ~= 'number' then
  18. local getbal = bank.getbal
  19. if not bank.user_exists then
  20. function bank.user_exists(name)
  21. return getbal(name) and true or false
  22. end
  23. end
  24. function bank.getbal(name)
  25. return getbal(name) or 0
  26. end
  27. end
  28. assert(bank.user_exists)
  29. -- Make sure "setbal" has a consistent return value.
  30. do
  31. local setbal = bank.setbal
  32. function bank.setbal(name, amount, reason)
  33. if type(amount) ~= 'number' or amount ~= amount then
  34. return false
  35. end
  36. local success = setbal(name, amount, reason)
  37. if success == nil then
  38. return true
  39. end
  40. return success
  41. end
  42. end
  43. -- Make sure "changebal" exists
  44. if not bank.changebal then
  45. if bank.add and bank.subtract then
  46. function bank.changebal(name, amount, reason)
  47. if amount == 0 then
  48. return true
  49. elseif type(amount) ~= 'number' or amount ~= amount then
  50. return false
  51. end
  52. if amount > 0 then
  53. return bank.add(name, amount, reason)
  54. else
  55. return bank.subtract(name, amount, reason)
  56. end
  57. end
  58. else
  59. function bank.changebal(name, amount, reason)
  60. if amount == 0 then
  61. return true
  62. elseif type(amount) ~= 'number' or amount ~= amount then
  63. return false
  64. end
  65. local resulting_bal = bank.getbal(name) + amount
  66. if resulting_bal < 0 then
  67. return false
  68. end
  69. return bank.setbal(name, resulting_bal, reason)
  70. end
  71. end
  72. end
  73. -- Make sure "add" exists
  74. if not bank.add then
  75. function bank.add(name, amount, reason)
  76. if amount < 0 then
  77. return false
  78. end
  79. return bank.changebal(name, amount, reason)
  80. end
  81. end
  82. -- Make sure "subtract" exists
  83. if not bank.subtract then
  84. function bank.subtract(name, amount, reason)
  85. if amount < 0 then
  86. return false
  87. end
  88. return bank.changebal(name, 0 - amount, reason)
  89. end
  90. end
  91. -- Make sure "pay" exists, and if so, make sure it has consistent return
  92. -- values.
  93. if bank.pay then
  94. local pay = bank.pay
  95. function bank.pay(from, to, amount)
  96. if type(amount) ~= 'number' or amount ~= amount then
  97. return false, 'Invalid number!'
  98. end
  99. local success, msg = pay(from, to, amount)
  100. if success or success == nil then
  101. return true, msg or 'Transaction sent!'
  102. else
  103. return false, msg or 'Error processing transaction!'
  104. end
  105. end
  106. else
  107. function bank.pay(from, to, amount)
  108. if type(amount) == 'number' then
  109. amount = math.floor(amount * 100) / 100
  110. end
  111. if not bank.user_exists(from) or not
  112. bank.user_exists(to) then
  113. return false, 'The specified user does not exist!'
  114. elseif type(amount) ~= 'number' or amount ~= amount or
  115. amount <= 0 then
  116. return false, 'Invalid number!'
  117. elseif bank.getbal(from) - amount < 0 then
  118. return false, 'You cannot afford to do that!'
  119. end
  120. local success = false
  121. if bank.subtract(from, amount, 'Transaction to ' ..
  122. to) then
  123. success = bank.add(to, amount, 'Transaction from ' ..
  124. from)
  125. -- Revert failed transactions
  126. if not success and success ~= nil then
  127. bank.add(from, amount,
  128. 'Reverting failed transaction.')
  129. end
  130. end
  131. if success or success == nil then
  132. minetest.log('action', '[lurkcoin] User ' .. from .. ' paid ' ..
  133. to .. ' ' .. tostring(amount) .. 'cr.')
  134. return true, 'Transaction sent!'
  135. end
  136. return false, 'Error processing transaction!'
  137. end
  138. end
  139. -- Set lurkcoin.bank to the new bank.
  140. lurkcoin.bank = bank
  141. end
  142. -- Built-in mod integrations
  143. -- These should be in alphabetical order (except ones that use the "money"
  144. -- global).
  145. if minetest.get_modpath('atm') and rawget(_G, 'atm') and atm.balance then
  146. -- ATM mod from https://git.gpcf.eu/?p=atm.git;a=tree
  147. -- Add (really) basic wrapper functions that should be replaced in
  148. -- change_bank().
  149. lurkcoin.change_bank({
  150. mod = 'atm',
  151. getbal = function(name)
  152. return atm.balance[name]
  153. end,
  154. setbal = function(name, bal)
  155. atm.balance[name] = bal
  156. atm.saveaccounts()
  157. end
  158. })
  159. elseif minetest.get_modpath('bank_accounts') and rawget(_G, 'accounts') and
  160. accounts.balance and accounts.pin and accounts.credit then
  161. -- https://github.com/Tmanyo/bank_accounts
  162. lurkcoin.change_bank({
  163. mod = 'bank_accounts',
  164. getbal = function(name)
  165. return accounts.balance[name]
  166. end,
  167. setbal = function(name, bal)
  168. accounts.balance[name] = bal
  169. end
  170. })
  171. elseif minetest.get_modpath('economy') and rawget(_G, 'economy') and
  172. economy.balance and economy.accountlog then
  173. -- https://github.com/orwell96/economy
  174. -- economy.moneyof() automatically adds non-existent entries, therefore it
  175. -- is not used by default.
  176. lurkcoin.change_bank({
  177. mod = 'economy',
  178. getbal = function(name)
  179. return economy.balance[name]
  180. end,
  181. setbal = function(name, amount, reason)
  182. local difference = amount - economy.balance[name]
  183. economy.balance[name] = amount
  184. local symbol
  185. if difference >= 0 then
  186. symbol = '+'
  187. else
  188. symbol = '-'
  189. difference = 0 - difference
  190. end
  191. if not economy.accountlog[name] then
  192. economy.accountlog[name] = {}
  193. end
  194. if not reason then
  195. reason = 'Transaction on ' .. os.date('%Y-%m-%d %H:%M:%S')
  196. end
  197. table.insert(economy.accountlog[name], 1, {
  198. action = reason,
  199. amount = symbol .. ' ' .. tostring(difference)
  200. })
  201. end,
  202. })
  203. elseif rawget(_G, 'money') then
  204. -- Mods that (incorrectly) use the "money" global variable.
  205. if minetest.get_modpath('economy') and money.get_money then
  206. lurkcoin.change_bank({
  207. mod = 'economy',
  208. user_exists = money.exist,
  209. getbal = money.get_money,
  210. setbal = money.set_money,
  211. })
  212. elseif minetest.get_modpath('money2') and money.get then
  213. -- money.add and money.dec have a different return value system.
  214. lurkcoin.change_bank({
  215. mod = 'money2',
  216. user_exists = money.has_credit,
  217. getbal = money.get,
  218. setbal = function(name, ...)
  219. if money.has_credit(name) then
  220. money.set(name, ...)
  221. return true
  222. end
  223. return false
  224. end,
  225. pay = function(from, to, amount)
  226. local err = money.transfer(from, to, amount)
  227. return not err, err
  228. end
  229. })
  230. end
  231. end