shopping-cd2025/player_to_player_shop.lua
2024-10-02 23:00:23 -05:00

244 lines
6.3 KiB
Lua

shopping.items_per_page = 48
local function give_item_to_player(player_name, item_stack)
local player = minetest.get_player_by_name(player_name)
if not player then
-- Player not found, handle error
return false
end
local inv = player:get_inventory()
if not inv:room_for_item("main", item_stack) then
-- Player does not have enough room for the item stack
minetest.chat_send_player(player_name, "Not enough room in your inventory.")
return false
end
inv:add_item("main", item_stack)
return true
end
local function remove_entry(list, index)
-- Shift elements to the left starting from the removed index
for i = index, #list - 1 do
list[i] = list[i + 1]
end
-- Remove the last element (which is now a duplicate)
list[#list] = nil
end
local function add_item_to_shop(itemstack, price, name)
local mod_storage = shopping.storage
local shop = minetest.deserialize(mod_storage:get_string("shop")) or {}
shop[#shop + 1] = {itemstack:to_string(), price, name}
mod_storage:set_string("shop", minetest.serialize(shop))
return true, "Item listed!"
end
local function get_item_from_shop(name, index)
local mod_storage = shopping.storage
local shop = minetest.deserialize(mod_storage:get_string("shop")) or {}
if (index == 0) or (index > #shop) then
return false, "Invalid index!"
end
privs = minetest.get_player_privs(name)
if privs["shopping_admin"] then
if give_item_to_player(name, shop[index][1]) then
remove_entry(shop, index)
else
return false, "Failed!"
end
mod_storage:set_string("shop", minetest.serialize(shop))
return true, "Item bought as admin!"
end
if shop[index][2] < 0 then return false, "Bad price!" end
if (jeans_economy.get_account(name) < shop[index][2]) and (not (name == shop[index][3])) then
return false, "You don't have enough money!"
else
if not (name == shop[index][3]) then
jeans_economy.book(name, shop[index][3], shop[index][2], name .. " bought item for " .. shop[index][2])
end
if give_item_to_player(name, shop[index][1]) then
remove_entry(shop, index)
else
return false, "Failed!"
end
mod_storage:set_string("shop", minetest.serialize(shop))
return true, "Item bought!"
end
end
-- Buy
function shopping.buy(name, index)
return get_item_from_shop(name, index)
end
-- Shop
function shopping.shop(name, page)
local mod_storage = shopping.storage
local shop = minetest.deserialize(mod_storage:get_string("shop")) or {}
local formspec = "size[9,8.5]" -- Increased width to accommodate the scrollbar
formspec = formspec .. "label[4.2,0;Shop]" -- Title of the formspec
formspec = formspec .. "button_exit[0.2,0.2;2,1;close;Close]" -- Add a Close button
-- Pagination logic
local total_pages = math.ceil(#shop / shopping.items_per_page)
page = page or 1 -- Ensure page is initialized
local start_index = (page - 1) * shopping.items_per_page + 1
local end_index = math.min(page * shopping.items_per_page, #shop)
-- Display items in the shop for the current page
local row = 1
local col = 0
for i = start_index, end_index do
if col == 8 then
col = 0
row = row + 1
end
local item_stack = shop[i][1]
local price = shop[i][2]
local seller_name = shop[i][3]
local meta = ItemStack(item_stack):get_meta()
local metadata_str = ""
-- Collect all metadata fields
for key, value in pairs(meta:to_table().fields) do
metadata_str = metadata_str .. key .. ": " .. value .. "\n"
end
formspec = formspec .. "item_image_button[" .. col .. "," .. row .. ";1.2,1.2;" .. ItemStack(item_stack):get_name() .. ";buy_" .. i .. ";]" ..
"tooltip[buy_" .. i .. ";" .. minetest.registered_items[ItemStack(item_stack):get_name()].description .. "\n" .. "$" .. price .. "\n" .. "Seller: " .. seller_name .. "\n" .. minetest.formspec_escape(metadata_str) .. "]" ..
"label[" .. (col + 0.7) .. "," .. (row + 0.7) .. ";" .. ItemStack(item_stack):get_count() .. "]"
col = col + 1
end
-- Previous page button
if page > 1 then
formspec = formspec .. "button[0,8;2,1;prev;<< Prev]"
end
-- Next page button
if page < total_pages then
formspec = formspec .. "button[7,8;2,1;next;Next >>]"
end
formspec = formspec .. "field[3.5,8;2,1;page;;" .. page .. "]" -- Add a hidden field to hold the current page
minetest.show_formspec(name, "shopping:shop_formspec", formspec)
end
-- Register a callback to handle button clicks in the shop formspec
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == "shopping:shop_formspec" then
local player_name = player:get_player_name()
local page = tonumber(fields.page) or 1
local mod_storage = shopping.storage
if page < 1 then
page = 1
end
if fields.next then
page = page + 1
shopping.shop(player_name, page)
return
elseif fields.prev then
if page < 1 then
page = 2
end
page = page - 1
shopping.shop(player_name, page)
return
elseif fields.close then
return
end
for field, _ in pairs(fields) do
if field:sub(1, 4) == "buy_" then
local index = tonumber(field:sub(5))
if index then
local success, s = shopping.buy(player_name, index)
minetest.chat_send_player(player_name, s)
shopping.shop(player_name, page)
end
end
end
elseif fields.page then
local mod_storage = shopping.storage
local shop = minetest.deserialize(mod_storage:get_string("shop")) or {}
local total_pages = math.ceil(#shop / shopping.items_per_page)
if page < 1 then
page = 1
elseif page > 1 then
page = total_pages
end
shopping.shop(player_name, page)
return
end
end)
-- I had to insult AI to figure this out -_-
local function remove_held_item(player_name)
local player = minetest.get_player_by_name(player_name)
if not player then
-- Player not found, handle error
return
end
local wielded_item = player:get_wielded_item()
if wielded_item:is_empty() then
-- Player is not holding anything, no need to remove
return
end
local inv = player:get_inventory()
local wielded_index = player:get_wield_index()
-- Remove the wielded item from the player's inventory
inv:set_stack("main", wielded_index, ItemStack(nil))
end
-- Sell
function shopping.sell(name, itemstack, price)
if price < 0 then return false, "Bad price!" end
rc, s = add_item_to_shop(itemstack, price, name)
remove_held_item(name)
return rc, s
--return true, player_name .. " listed " .. item_name .. " for " .. price
end