added new machines

This commit is contained in:
Rainer 2025-08-22 02:10:35 +02:00
parent ceb168de55
commit 8603834f56
35 changed files with 2223 additions and 1204 deletions

View file

@ -1,47 +1,31 @@
--[[
Core API and Data Handling
--------------------------
This file manages all low-level reading from and writing to the 'accounts' data file.
It provides a safe and centralized API for all other mod files to interact with player data.
--]]
-- functions.lua (Corrected for Deadlock issue during interest calculation)
local world_path = minetest.get_worldpath()
local file_path = world_path .. "/accounts"
-- Normalizes a string to use '.' as a decimal separator and converts to a number.
-- Handles both "1,23" and "1.23".
function normalize_and_tonumber(str)
if not str then
return nil
end
if not str then return nil end
str = str:gsub(",", ".")
return tonumber(str)
end
-- Internal function to read the entire accounts database file.
-- Returns a populated table or a clean default structure on any error.
local function read_accounts_file()
local f = io.open(file_path, "r")
if not f then
return { balance = {}, pin = {}, credit = {}, history = {} }
end
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
if data == "" or data == nil then return { balance = {}, pin = {}, credit = {}, history = {} } end
return minetest.deserialize(data) or { balance = {}, pin = {}, credit = {}, history = {} }
end
-- Internal function to write the entire accounts database file.
-- Includes a locking mechanism to prevent race conditions with the interest script.
local function save_accounts_file(data)
-- If the daily interest calculation is running, wait in short intervals until it's done.
while bank_accounts and bank_accounts.is_calculating_interest do
minetest.log("action", "[bank_accounts] Interest calculation in progress, delaying save operation...")
minetest.sleep(0.5)
-- 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))
@ -52,51 +36,34 @@ local function save_accounts_file(data)
return true
end
-- Internal function to log a single transaction to a player's history.
local function log_transaction(data, player_name, account_type, amount, new_total, trans_type, purpose, other_party)
-- Ensure history tables exist.
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, -- "balance" or "credit"
amount = amount,
new_total = new_total,
purpose = purpose or "", -- e.g., "Teller: Rage87" or user-defined text
other = other_party or "" -- e.g., recipient or sender name
}
-- Insert at the beginning of the list to show newest transactions first.
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)
-- Limit history to the last 200 entries to prevent the file from growing indefinitely.
while #data.history[player_name] > 200 do
table.remove(data.history[player_name])
end
end
-- On server start, create the accounts file if it doesn't exist.
-- 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 = {} })
save_accounts_file({ balance = {}, pin = {}, credit = {}, history = {} }, true)
else
f:close()
end
end
---------------------------------------------------
-- Public API accessible via `bank_accounts.*`
---------------------------------------------------
--- API ---
-- Gets all relevant data for a single player.
function bank_accounts.get_account_data(player_name)
local data = read_accounts_file()
-- Backwards compatibility check for old save files without a history table.
if not data.history then
data.history = {}
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",
@ -105,22 +72,19 @@ function bank_accounts.get_account_data(player_name)
}
end
-- Gets all data from the database (for background scripts like interest calculation).
function bank_accounts.get_all_data()
return read_accounts_file()
end
-- Saves the complete data object (for background scripts).
-- CORRECTED: save_all now calls the internal save function with the bypass parameter.
function bank_accounts.save_all(data)
return save_accounts_file(data)
return save_accounts_file(data, true)
end
-- Simple getter functions.
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
-- Adds a value to a player's balance and logs the transaction.
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
@ -130,7 +94,6 @@ function bank_accounts.add_balance(player_name, amount, trans_type, purpose, oth
return save_accounts_file(data)
end
-- Sets a player's balance to an absolute value and logs the transaction.
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
@ -141,7 +104,6 @@ function bank_accounts.set_balance(player_name, amount, trans_type, purpose, oth
return save_accounts_file(data)
end
-- Adds a value to a player's credit debt and logs the transaction.
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
@ -151,7 +113,6 @@ function bank_accounts.add_credit(player_name, amount, trans_type, purpose, othe
return save_accounts_file(data)
end
-- Sets a player's credit debt to an absolute value and logs the transaction.
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
@ -162,31 +123,24 @@ function bank_accounts.set_credit(player_name, amount, trans_type, purpose, othe
return save_accounts_file(data)
end
-- Sets a player's PIN.
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
-- Checks if a player has an entry in the database.
function bank_accounts.player_has_account(player_name)
local data = read_accounts_file()
return data.balance[player_name] ~= nil
end
-- Creates a new, empty account for a player.
function bank_accounts.create_account(player_name)
if bank_accounts.player_has_account(player_name) then
return false
end
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
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)