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.

bank.lua 8.5KB

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