bank_accounts/computer.lua
2025-08-22 02:10:35 +02:00

135 lines
12 KiB
Lua

-- computer.lua (Zurückgesetzt auf stabile Basis + Nur "System is busy" Logik hinzugefügt)
minetest.register_privilege("bank_teller", {
description = S("Qualified Bank Teller"),
})
pos_data = {}
local function show_teller_form(player, pos, customer_name)
local list_name = "nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z
local data = {balance = 0, credit = 0}
if customer_name and customer_name ~= "" and bank_accounts.player_has_account(customer_name) then
data = bank_accounts.get_account_data(customer_name)
end
local formspec = "size[8,9.5]" ..
"label[0,-.25;"..S("Deposit:").."]" ..
"list["..list_name..";ones;0,.25;1,1]" .. "list["..list_name..";fives;1.25,.25;1,1]" .. "list["..list_name..";tens;2.5,.25;1,1]" ..
"label[0.25,1.2;1 MG]" .. "label[1.5,1.2;5 MG]" .. "label[2.75,1.2;10 MG]" ..
"field[4,.5;4,1;playername;"..S("Player:")..";"..minetest.formspec_escape(customer_name or "").."]" ..
"field[.3,2.25;4,1;withdrawal;"..S("Withdraw:")..";]" .. "field[.3,3.25;4,1;credit_debt;"..S("Credit Payment:")..";]" ..
"label[.5,4.5;"..S("Balance: @1", string.format("%.2f", data.balance).." MG").."]" ..
"label[.5,4.75;"..S("Credit Debt: @1", string.format("%.2f", data.credit).." MG").."]" ..
"button_exit[5.5,1;2,1;stats;"..S("Show Account").."]" ..
"button_exit[5.5,2;2,1;statement;"..S("Account Statement").."]" ..
"button_exit[5.5,3;2,1;wipe;"..S("Wipe Account").."]" .. "button_exit[5.5,4;2,1;reset_pin;"..S("Reset PIN").."]" ..
"button_exit[3,5.5;2,1;exit;"..S("Cancel").."]" .. "button_exit[5.5,5.5;2,1;enter;"..S("Enter").."]" ..
"list[current_player;main;0,7;8,2.5;]"
minetest.show_formspec(player:get_player_name(), "bank_accounts:teller", formspec)
end
local function show_statement_form(player, pos, customer_name, account_type)
local data = bank_accounts.get_account_data(customer_name)
local history = data.history; local lines = {}; local current_total_label = ""
table.insert(lines, minetest.formspec_escape(string.format("%-11s | %-13s | %-13s | %-20s | %-20s | %s", S("Date"), S("Amount"), S("New Balance"), S("Method"), S("Purpose"), S("Partner"))))
table.insert(lines, minetest.formspec_escape("-----------------------------------------------------------------------------------------"))
if history then for _, t in ipairs(history) do if t.account == account_type then
local parts = {}; table.insert(parts, string.format("%-11s", os.date("%Y-%m-%d", t.timestamp))); table.insert(parts, string.format("%12s", string.format("%+.2f", t.amount) .. " MG")); table.insert(parts, string.format("%12s", string.format("%.2f", t.new_total).." MG")); table.insert(parts, string.format("%-20s", S(t.type)))
local purpose = t.purpose or ""; local partner = t.other or ""; if purpose ~= "" or partner ~= "" then table.insert(parts, string.format("%-20s", purpose)); if partner ~= "" then table.insert(parts, partner) end end
table.insert(lines, minetest.formspec_escape(table.concat(parts, " | ")))
end end end
if account_type == "balance" then current_total_label = S("Current Balance: @1", string.format("%.2f", data.balance).." MG") else current_total_label = S("Current Credit Debt: @1", string.format("%.2f", data.credit).." MG") end
local form_name = "bank_accounts:statement@" .. customer_name
local formspec = "size[13,9]".."label[0,0;"..S("Account Statement for @1",customer_name).."]".."button_exit[0,0.5;2,1;view_balance;"..S("Balance").."]".."button_exit[2,0.5;2,1;view_credit;"..S("Credit").."]".."textlist[0,1.2;13,7;statement_list;"..table.concat(lines,",").."]".."label[0,8.4;"..current_total_label.."]".."button_exit[11,8.4;2,1;back;"..S("Back").."]"
minetest.show_formspec(player:get_player_name(), form_name, formspec)
end
minetest.register_node("bank_accounts:teller_computer", {
description = S("Bank Teller's Computer"),
drawtype = "mesh", mesh = "computer.obj", paramtype = "light", paramtype2 = "facedir", light_source = 5,
tiles = {{name="computer.png"},{name="computer_screen.png"}}, groups = {cracky=3, crumbly=3, oddly_breakable_by_hand=2},
selection_box = {type="fixed",fixed={-0.5,-0.5,-0.5,0.5,0.4,0.2}}, collision_box = {type="fixed",fixed={-0.5,-0.5,-0.5,0.5,0.4,0.2}},
on_construct = function(pos) local meta = minetest.get_meta(pos); local inv = meta:get_inventory(); inv:set_size("ones", 1); inv:set_size("fives", 1); inv:set_size("tens", 1) end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
pos_info = pos
local player_name = player:get_player_name()
if player:get_player_control().aux1 and minetest.check_player_privs(player_name, {server=true}) then minetest.show_formspec(player_name, "bank_accounts:admin_teller", "size[8,4]" .. "field[.5,.5;4,1;search;"..S("Search:")..";]" .. "button_exit[4.5,.22;2,1;search_button;"..S("Search").."]" .. "label[.5,1.25;"..S("Player:").."]".. "label[3.5,1.25;"..S("Seized:").."]")
elseif minetest.check_player_privs(player_name, {bank_teller=true}) then show_teller_form(player, pos, "")
else minetest.chat_send_player(player_name, S("[Bank] Insufficient privileges.")) end
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player) if listname=="ones" and stack:get_name()~="currency:minegeld" then return 0 end; if listname=="fives" and stack:get_name()~="currency:minegeld_5" then return 0 end; if listname=="tens" and stack:get_name()~="currency:minegeld_10" then return 0 end; return stack:get_count() end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) local inv=minetest.get_meta(pos):get_inventory(); local stack=inv:get_stack(from_list, from_index); if to_list=="ones" and stack:get_name()~="currency:minegeld" then return 0 end; if to_list=="fives" and stack:get_name()~="currency:minegeld_5" then return 0 end; if to_list=="tens" and stack:get_name()~="currency:minegeld_10" then return 0 end; return count end,
})
minetest.register_on_player_receive_fields(function(player, formname, fields)
if not formname:find("bank_accounts:teller") and not formname:find("bank_accounts:admin_teller") and not formname:find("bank_accounts:statement") then return end
local player_name = player:get_player_name(); local pos = pos_info; if not pos then return end
local function on_fail()
minetest.chat_send_player(player_name, S("[Bank] System is busy, please try again in a moment."))
end
if formname == "bank_accounts:admin_teller" then
if fields.search_button and fields.search and fields.search ~= "" then
local search_name=fields.search; local status; if not bank_accounts.player_has_account(search_name) then status=S("No Account") elseif minetest.check_player_privs(search_name,{seized=true}) then status=S("Yes") else status=S("No") end; minetest.show_formspec(player_name,formname,"size[8,4]".."field[.5,.5;4,1;search;"..S("Search:")..";"..minetest.formspec_escape(search_name).."]".."button_exit[4.5,.22;2,1;search_button;"..S("Search").."]".."label[.5,1.25;"..S("Player:").."]".."label[3.5,1.25;"..S("Seized:").."]".."label[.5,1.75;"..minetest.formspec_escape(search_name).."]".."label[3.5,1.75;"..status.."]")
end; return
end
if formname == "bank_accounts:teller" then
local customer_name = fields.playername
-- Die "seltsame", aber für dich funktionierende Validierungslogik. Unverändert.
if (not customer_name or customer_name=="") and not fields.exit then minetest.chat_send_player(player_name, S("[Bank] Must enter a player name.")); return end
if (customer_name and customer_name~="" and not bank_accounts.player_has_account(customer_name)) and not fields.exit then minetest.chat_send_player(player_name, S("[Bank] Invalid player name entered.")); return end
-- Funktions-Wrapper beibehalten, da er in der funktionierenden Basis war.
local function show_updated_form(p, a_pos, c_name)
show_teller_form(p, a_pos, c_name)
end
if fields.stats then
show_updated_form(player, pos, customer_name)
elseif fields.statement then
show_statement_form(player, pos, customer_name, "balance")
elseif fields.wipe then
if not bank_accounts.set_balance(customer_name, 0, "Teller Wipe", S("Teller: @1", player_name), player_name) then on_fail() end
show_updated_form(player, pos, customer_name)
elseif fields.reset_pin then
if not bank_accounts.set_pin(customer_name, "0000") then on_fail() end
show_updated_form(player, pos, customer_name)
elseif fields.enter then
local meta=minetest.get_meta(pos); local inv=meta:get_inventory();
local total_deposit=inv:get_stack("ones",1):get_count()+inv:get_stack("fives",1):get_count()*5+inv:get_stack("tens",1):get_count()*10
if total_deposit>0 then
if not bank_accounts.add_balance(customer_name,total_deposit,"Teller Deposit",S("Teller: @1",player_name),player_name) then on_fail() end
end
local withdrawal = tonumber(fields.withdrawal); if withdrawal and withdrawal>0 then
if withdrawal%1~=0 then minetest.chat_send_player(player_name,S("[Bank] Withdrawal amount must be a whole number."))
elseif bank_accounts.get_balance(customer_name)>=withdrawal then
if not bank_accounts.add_balance(customer_name,-withdrawal,"Teller Withdrawal",S("Teller: @1",player_name),player_name) then on_fail()
else local tens=math.floor(withdrawal/10);local rem=withdrawal%10;local fives=math.floor(rem/5);local ones=rem%5;player:get_inventory():add_item("main",{name="currency:minegeld_10",count=tens});player:get_inventory():add_item("main",{name="currency:minegeld_5",count=fives});player:get_inventory():add_item("main",{name="currency:minegeld",count=ones}) end
else minetest.chat_send_player(player_name,S("[Bank] Player has insufficient funds for withdrawal.")) end
end
local credit_payment = normalize_and_tonumber(fields.credit_debt); if credit_payment and credit_payment>0 then
if bank_accounts.get_balance(customer_name)>=credit_payment then
if bank_accounts.get_credit(customer_name)>=credit_payment then
local s1 = bank_accounts.add_balance(customer_name,-credit_payment,"Teller Credit Payment",S("Teller: @1",player_name),player_name)
local s2 = bank_accounts.add_credit(customer_name,-credit_payment,"Teller Credit Payment",S("Teller: @1",player_name),player_name)
if not s1 or not s2 then on_fail() end
else minetest.chat_send_player(player_name,S("[Bank] Player does not have that much credit debt.")) end
else minetest.chat_send_player(player_name,S("[Bank] Player has insufficient funds for credit payment.")) end
end
inv:set_stack("ones",1,nil);inv:set_stack("fives",1,nil);inv:set_stack("tens",1,nil);
show_updated_form(player,pos,customer_name)
end
end
if formname:find("bank_accounts:statement@") then
local customer_name=formname:match("bank_accounts:statement@(.*)"); if not customer_name then return end
if fields.view_balance then show_statement_form(player, pos, customer_name, "balance")
elseif fields.view_credit then show_statement_form(player, pos, customer_name, "credit")
elseif fields.back then show_teller_form(player, pos, customer_name) end
end
end)