--[[ Card Swipe Node --------------- This file defines the Card Swipe node, which allows players to set up shops and sell items via card payments. --]] -- Uses the global 'pos_info' variable for consistency. -- Node definition for the Card Swipe. minetest.register_node("bank_accounts:card_swipe", { description = S("Card Swipe"), drawtype = "mesh", mesh = "card_swipe.obj", paramtype = "light", paramtype2 = "facedir", tiles = {"card_reader_col.png"}, groups = {cracky=3, crumbly=3, oddly_breakable_by_hand=2}, selection_box = { type = "fixed", fixed = {{-.3,-.5,-.3,.4,-.2,.3}} }, collision_box = { type = "fixed", fixed = {{-.3,-.5,-.3,.4,-.2,.3}} }, -- Creates the item inventory when the node is placed. on_construct = function(pos) minetest.get_meta(pos):get_inventory():set_size("items", 8) end, -- Sets the owner of the node after it has been placed. after_place_node = function(pos, placer) local meta = minetest.get_meta(pos) local owner = placer:get_player_name() meta:set_string("infotext", S("Card Swipe (owned by @1)", owner)) meta:set_string("owner", owner) end, -- Ensures only the owner can dig the node, and only if it's empty. can_dig = function(pos, player) local meta = minetest.get_meta(pos) if player:get_player_name() == meta:get_string("owner") then return meta:get_inventory():is_empty("items") end return false end, -- Called when a player right-clicks the node. on_rightclick = function(pos, node, player, itemstack, pointed_thing) pos_info = pos -- Set global position. local meta = minetest.get_meta(pos) local player_name = player:get_player_name() local owner = meta:get_string("owner") local list_name = "nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z -- Show seller interface if the player is the owner. if player_name == owner then minetest.show_formspec(player_name, "bank_accounts:card_swipe_seller", "size[8,9]" .. "field[1,0.5;4,1;price;"..S("Price in MG:")..";"..minetest.formspec_escape(meta:get_string("price") or "").."]" .. "label[0,1.75;"..S("Items for Sale:").."]".. "list["..list_name..";items;0,2.25;8,2]" .. "label[0,4.5;"..S("Your Inventory:").."]".. "list[current_player;main;0,5;8,3]" .. "button_exit[1,8.25;3,1;reset;"..S("Reset Price").."]" .. "button_exit[4.5,8.25;3,1;set_price;"..S("Set Price").."]") -- Show buyer interface for everyone else. else if meta:get_inventory():is_empty("items") then minetest.chat_send_player(player_name, S("[Card Swipe] This machine is empty.")) return end local price_str = meta:get_string("price") if not price_str or price_str == "" then minetest.chat_send_player(player_name, S("[Card Swipe] No price has been set.")) return end local wielded_item = itemstack:get_name() if wielded_item ~= "bank_accounts:debit_card" and wielded_item ~= "bank_accounts:credit_card" then minetest.chat_send_player(player_name, S("[Card Swipe] Must use a debit or credit card.")) return end if minetest.check_player_privs(player_name, {seized=true}) then minetest.chat_send_player(player_name, S("[Card Swipe] Your account has been seized! Transaction denied.")) return end local price = tonumber(price_str) if wielded_item == "bank_accounts:debit_card" and bank_accounts.get_balance(player_name) < price then minetest.chat_send_player(player_name, S("[Card Swipe] Card declined. Insufficient funds.")) return end minetest.show_formspec(player_name, "bank_accounts:card_swipe_buyer", "size[8,8]" .. "label[1,1;"..S("Price: @1", string.format("%.2f", price).." MG").."]" .. "label[1,1.5;"..S("Owner: @1", owner).."]".. "label[1,2;"..S("Items for Sale (Click 'Buy' to receive):").."]".. "list["..list_name..";items;0,2.5;8,2]" .. "list[current_player;main;0,5;8,2;]" .. "button_exit[2,7.4;2,1;cancel;"..S("Cancel").."]" .. "button_exit[4,7.4;2,1;buy;"..S("Buy").."]") end end, -- Only the owner can put items into the swipe machine. allow_metadata_inventory_put = function(pos, listname, index, stack, player) if player:get_player_name() == minetest.get_meta(pos):get_string("owner") then return stack:get_count() end return 0 end, -- THEFT-PREVENTION: Players cannot take items manually. -- The script transfers them automatically upon successful purchase. allow_metadata_inventory_take = function(pos, listname, index, stack, player) return 0 end, }) -- Crafting recipe for the Card Swipe machine. minetest.register_craft({ output = "bank_accounts:card_swipe", recipe = { {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"}, {"bank_accounts:credit_card", "default:mese", "bank_accounts:debit_card"}, {"default:steel_ingot", "default:copper_ingot", "default:steel_ingot"}, }, }) -- Handles formspec submissions for the Card Swipe. minetest.register_on_player_receive_fields(function(player, formname, fields) if not formname:find("bank_accounts:card_swipe") then return end local player_name = player:get_player_name() local pos = pos_info if not pos then return end local meta = minetest.get_meta(pos) if not meta then return end -- Logic for the seller's interface. if formname == "bank_accounts:card_swipe_seller" then if fields.set_price then local price = normalize_and_tonumber(fields.price) if price and price > 0 then meta:set_string("price", tostring(price)) minetest.chat_send_player(player_name, S("[Card Swipe] Price set to @1.", string.format("%.2f", price).." MG")) else minetest.chat_send_player(player_name, S("[Card Swipe] Invalid price. Must be a number greater than 0.")) end elseif fields.reset then meta:set_string("price", "") minetest.chat_send_player(player_name, S("[Card Swipe] Price has been reset.")) end end -- Logic for the buyer's interface. if formname == "bank_accounts:card_swipe_buyer" then if fields.buy then local owner = meta:get_string("owner") local price = tonumber(meta:get_string("price") or "0") local shop_inv = meta:get_inventory() local wielded_item = player:get_wielded_item():get_name() if price <= 0 or shop_inv:is_empty("items") then minetest.chat_send_player(player_name, S("[Card Swipe] This offer is no longer valid.")) return end local payment_successful = false local description_for_buyer = S("Items from @1", owner) local description_for_seller = S("Items to @1", player_name) -- Debit Card Transaction if wielded_item == "bank_accounts:debit_card" then if bank_accounts.get_balance(player_name) >= price then bank_accounts.add_balance(player_name, -price, "Purchase", "", description_for_buyer, owner) bank_accounts.add_balance(owner, price, "Sale", "", description_for_seller, player_name) payment_successful = true end -- Credit Card Transaction elseif wielded_item == "bank_accounts:credit_card" then bank_accounts.add_credit(player_name, price, "Credit Purchase", "", description_for_buyer, owner) bank_accounts.add_balance(owner, price, "Sale", "", description_for_seller, player_name) payment_successful = true end -- If payment was successful, transfer items. if payment_successful then local player_inv = player:get_inventory() for i=1, shop_inv:get_size("items") do local stack = shop_inv:get_stack("items", i) if not stack:is_empty() then player_inv:add_item("main", stack) end end shop_inv:set_list("items", {}) meta:set_string("price", "") minetest.chat_send_player(player_name, S("[Card Swipe] Purchase successful!")) minetest.chat_send_player(owner, S("[Card Swipe] Your items have been sold for @1.", string.format("%.2f", price).." MG")) player:get_inventory():add_item("main", "bank_accounts:receipt") else minetest.chat_send_player(player_name, S("[Card Swipe] Payment declined!")) end end end end)