105 lines
4.3 KiB
Lua
105 lines
4.3 KiB
Lua
-- interest.lua (Deadlock problem fixed)
|
|
|
|
local BALANCE_INTEREST_RATE = tonumber(minetest.settings:get("bank_accounts.interest_rate_balance")) or 0.005
|
|
local CREDIT_INTEREST_RATE = tonumber(minetest.settings:get("bank_accounts.interest_rate_credit")) or 0.03
|
|
local INTEREST_CHECK_INTERVAL = tonumber(minetest.settings:get("bank_accounts.interest_check_interval")) or 600
|
|
local ONE_DAY_IN_SECONDS = 86400
|
|
|
|
local timestamp_file_path = minetest.get_worldpath() .. "/bank_interest_timestamp.txt"
|
|
|
|
local function read_timestamp()
|
|
local f = io.open(timestamp_file_path, "r")
|
|
if not f then return 0 end
|
|
local time = tonumber(f:read("*a"))
|
|
f:close()
|
|
return time or 0
|
|
end
|
|
|
|
local function write_timestamp(time)
|
|
local f = io.open(timestamp_file_path, "w")
|
|
if not f then return end
|
|
f:write(tostring(time))
|
|
f:close()
|
|
end
|
|
|
|
local time_since_last_check = 0
|
|
bank_accounts.is_calculating_interest = false
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
if not minetest.settings:get_bool("bank_accounts.interest_enabled", true) then
|
|
return
|
|
end
|
|
|
|
time_since_last_check = time_since_last_check + dtime
|
|
if time_since_last_check < INTEREST_CHECK_INTERVAL then
|
|
return
|
|
end
|
|
time_since_last_check = 0
|
|
|
|
local last_timestamp = read_timestamp()
|
|
|
|
if os.time() - last_timestamp >= ONE_DAY_IN_SECONDS then
|
|
if bank_accounts.is_calculating_interest then
|
|
return
|
|
end
|
|
|
|
minetest.log("action", "[bank_accounts] Starting daily interest calculation...")
|
|
bank_accounts.is_calculating_interest = true
|
|
|
|
local data = bank_accounts.get_all_data()
|
|
local changes_made = false
|
|
|
|
-- Calculate interest on positive balances
|
|
if BALANCE_INTEREST_RATE > 0 then
|
|
for player_name, balance in pairs(data.balance) do
|
|
if balance > 0 then
|
|
local interest = balance * BALANCE_INTEREST_RATE
|
|
data.balance[player_name] = balance + interest
|
|
if not data.history then data.history = {} end
|
|
if not data.history[player_name] then data.history[player_name] = {} end
|
|
table.insert(data.history[player_name], 1, {
|
|
timestamp = os.time(), type = "Interest Paid", account = "balance",
|
|
amount = interest, new_total = data.balance[player_name],
|
|
purpose = S("Daily interest (@1%)", BALANCE_INTEREST_RATE * 100), other = "Bank"
|
|
})
|
|
changes_made = true
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Calculate interest on credit debt
|
|
if CREDIT_INTEREST_RATE > 0 then
|
|
for player_name, credit in pairs(data.credit) do
|
|
if credit > 0 then
|
|
local interest = credit * CREDIT_INTEREST_RATE
|
|
data.credit[player_name] = credit + interest
|
|
if not data.history then data.history = {} end
|
|
if not data.history[player_name] then data.history[player_name] = {} end
|
|
table.insert(data.history[player_name], 1, {
|
|
timestamp = os.time(), type = "Interest Charged", account = "credit",
|
|
amount = interest, new_total = data.credit[player_name],
|
|
purpose = S("Daily interest (@1%)", CREDIT_INTEREST_RATE * 100), other = "Bank"
|
|
})
|
|
changes_made = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if changes_made then
|
|
-- CORRECTED: Now calls the API function that bypasses the lock
|
|
local success = bank_accounts.save_all(data)
|
|
if success then
|
|
minetest.log("action", "[bank_accounts] Daily interest calculation complete and saved.")
|
|
-- CORRECTED: Timestamp is only updated after a successful save.
|
|
write_timestamp(os.time())
|
|
else
|
|
minetest.log("error", "[bank_accounts] Saving interest data FAILED. Will retry later.")
|
|
end
|
|
else
|
|
-- If no changes were made, still update the timestamp to prevent re-running immediately.
|
|
write_timestamp(os.time())
|
|
end
|
|
|
|
bank_accounts.is_calculating_interest = false
|
|
end
|
|
end)
|