147 lines
5.9 KiB
Lua
147 lines
5.9 KiB
Lua
-- functions.lua (Corrected for Deadlock issue during interest calculation)
|
|
|
|
local world_path = minetest.get_worldpath()
|
|
local file_path = world_path .. "/accounts"
|
|
|
|
function normalize_and_tonumber(str)
|
|
if not str then return nil end
|
|
str = str:gsub(",", ".")
|
|
return tonumber(str)
|
|
end
|
|
|
|
local function read_accounts_file()
|
|
local f = io.open(file_path, "r")
|
|
if not f then return { balance = {}, pin = {}, credit = {}, history = {} } end
|
|
local data = f:read("*a")
|
|
f:close()
|
|
if data == "" or data == nil then return { balance = {}, pin = {}, credit = {}, history = {} } end
|
|
return minetest.deserialize(data) or { balance = {}, pin = {}, credit = {}, history = {} }
|
|
end
|
|
|
|
-- CORRECTED: The save function now accepts an optional parameter to bypass the lock.
|
|
local function save_accounts_file(data, bypass_lock)
|
|
-- If the interest script is running AND the lock bypass is NOT active, block the save.
|
|
if not bypass_lock and bank_accounts and bank_accounts.is_calculating_interest then
|
|
minetest.log("warning", "[bank_accounts] Save operation blocked: Daily interest calculation is in progress.")
|
|
return false -- Signal failure
|
|
end
|
|
|
|
local f, err = io.open(file_path, "w")
|
|
if not f then
|
|
minetest.log("error", "[bank_accounts] Could not open accounts file for writing: " .. tostring(err))
|
|
return false
|
|
end
|
|
f:write(minetest.serialize(data))
|
|
f:close()
|
|
return true
|
|
end
|
|
|
|
local function log_transaction(data, player_name, account_type, amount, new_total, trans_type, purpose, other_party)
|
|
if not data.history then data.history = {} end
|
|
if not data.history[player_name] then data.history[player_name] = {} end
|
|
local transaction = { timestamp = os.time(), type = trans_type or "unknown", account = account_type, amount = amount, new_total = new_total, purpose = purpose or "", other = other_party or "" }
|
|
table.insert(data.history[player_name], 1, transaction)
|
|
while #data.history[player_name] > 200 do
|
|
table.remove(data.history[player_name])
|
|
end
|
|
end
|
|
|
|
-- On first run, bypass lock to create file safely.
|
|
do
|
|
local f = io.open(file_path, "r")
|
|
if not f then
|
|
save_accounts_file({ balance = {}, pin = {}, credit = {}, history = {} }, true)
|
|
else
|
|
f:close()
|
|
end
|
|
end
|
|
|
|
--- API ---
|
|
|
|
function bank_accounts.get_account_data(player_name)
|
|
if not player_name then
|
|
return read_accounts_file()
|
|
end
|
|
local data = read_accounts_file()
|
|
if not data.history then data.history = {} end
|
|
return {
|
|
balance = data.balance[player_name] or 0,
|
|
pin = data.pin[player_name] or "0000",
|
|
credit = data.credit[player_name] or 0,
|
|
history = data.history[player_name] or {},
|
|
}
|
|
end
|
|
|
|
function bank_accounts.get_all_data()
|
|
return read_accounts_file()
|
|
end
|
|
|
|
-- CORRECTED: save_all now calls the internal save function with the bypass parameter.
|
|
function bank_accounts.save_all(data)
|
|
return save_accounts_file(data, true)
|
|
end
|
|
|
|
function bank_accounts.get_balance(player_name) local data = read_accounts_file(); return data.balance[player_name] or 0 end
|
|
function bank_accounts.get_credit(player_name) local data = read_accounts_file(); return data.credit[player_name] or 0 end
|
|
function bank_accounts.get_pin(player_name) local data = read_accounts_file(); return data.pin[player_name] or "0000" end
|
|
|
|
function bank_accounts.add_balance(player_name, amount, trans_type, purpose, other_party)
|
|
local data = read_accounts_file()
|
|
local current_balance = data.balance[player_name] or 0
|
|
local new_balance = current_balance + tonumber(amount)
|
|
data.balance[player_name] = new_balance
|
|
log_transaction(data, player_name, "balance", amount, new_balance, trans_type, purpose, other_party)
|
|
return save_accounts_file(data)
|
|
end
|
|
|
|
function bank_accounts.set_balance(player_name, amount, trans_type, purpose, other_party)
|
|
local data = read_accounts_file()
|
|
local current_balance = data.balance[player_name] or 0
|
|
local new_balance = tonumber(amount)
|
|
local diff = new_balance - current_balance
|
|
data.balance[player_name] = new_balance
|
|
log_transaction(data, player_name, "balance", diff, new_balance, trans_type or "admin_set", purpose, other_party)
|
|
return save_accounts_file(data)
|
|
end
|
|
|
|
function bank_accounts.add_credit(player_name, amount, trans_type, purpose, other_party)
|
|
local data = read_accounts_file()
|
|
local current_credit = data.credit[player_name] or 0
|
|
local new_credit = current_credit + tonumber(amount)
|
|
data.credit[player_name] = new_credit
|
|
log_transaction(data, player_name, "credit", amount, new_credit, trans_type, purpose, other_party)
|
|
return save_accounts_file(data)
|
|
end
|
|
|
|
function bank_accounts.set_credit(player_name, amount, trans_type, purpose, other_party)
|
|
local data = read_accounts_file()
|
|
local current_credit = data.credit[player_name] or 0
|
|
local new_credit = tonumber(amount)
|
|
local diff = new_credit - current_credit
|
|
data.credit[player_name] = new_credit
|
|
log_transaction(data, player_name, "credit", diff, new_credit, trans_type or "admin_set_credit", purpose, other_party)
|
|
return save_accounts_file(data)
|
|
end
|
|
|
|
function bank_accounts.set_pin(player_name, pin)
|
|
local data = read_accounts_file()
|
|
data.pin[player_name] = tostring(pin)
|
|
return save_accounts_file(data)
|
|
end
|
|
|
|
function bank_accounts.player_has_account(player_name)
|
|
local data = read_accounts_file()
|
|
return data.balance[player_name] ~= nil
|
|
end
|
|
|
|
function bank_accounts.create_account(player_name)
|
|
if bank_accounts.player_has_account(player_name) then return false end
|
|
local data = read_accounts_file()
|
|
data.balance[player_name] = 0
|
|
data.pin[player_name] = "0000"
|
|
data.credit[player_name] = 0
|
|
if not data.history then data.history = {} end
|
|
data.history[player_name] = {}
|
|
log_transaction(data, player_name, "system", 0, 0, "Account Created", "Initial account setup")
|
|
return save_accounts_file(data)
|
|
end
|