This commit is contained in:
Xeno333 2024-06-06 14:46:26 -05:00
commit eedd923582
4 changed files with 342 additions and 0 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Xeno333/TX_Miner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

94
init.lua Normal file
View File

@ -0,0 +1,94 @@
shopping = {}
shopping.storage = minetest.get_mod_storage()
local modpath = minetest.get_modpath(minetest.get_current_modname())
dofile(modpath.."/player_to_player_shop.lua")
minetest.register_privilege("server_shop_admin", {
description = "Lets player remove, add things to server shop, or nuke shop",
})
minetest.register_chatcommand("buy", {
params = "<index>",
description = "Buy from shop.",
privs = {
interact = true,
},
func = function(name, index)
index = tonumber(index)
if (not name) or (not index) then
return false, "Bad args!"
end
return shopping.buy(name, index)
end
})
minetest.register_chatcommand("shop", {
description = "Show shop.",
privs = {
interact = true,
},
func = function(name)
if not name then
return false, "Bad args!"
end
return shopping.shop(name, 1)
end
})
minetest.register_chatcommand("nukeshop", {
description = "Clears shop",
privs = {
server_shop_admin = true,
},
func = function()
local mod_storage = shopping.storage
mod_storage:set_string("shop", minetest.serialize({}))
return true, "Shop nuked!"
end
})
minetest.register_chatcommand("sell", {
params = "<price>",
description = "List for sale in player to player shop.",
privs = {
interact = true,
},
func = function(name, price)
if (not name) then
return false, "Bad args!"
end
--get price
local num_price = tonumber(price)
if not num_price then
return false, "Invalid price"
end
local player = minetest.get_player_by_name(name)
-- make sure player is valid
if not player then
return false, "Player not found."
end
-- get item_stack
local item_stack = player:get_wielded_item()
if item_stack:is_empty() then
return false, "You are not holding any item."
end
return shopping.sell(name, item_stack, num_price)
end
})

3
mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = shopping
description = A shopping mod for Jean's Economy (By TX_Miner aka Xeno333)
depends = default, jeans_economy

224
player_to_player_shop.lua Normal file
View File

@ -0,0 +1,224 @@
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["server_shop_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 (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]
formspec = formspec .. "item_image_button[" .. col .. "," .. row .. ";1,1;" .. item_stack .. ";buy_" .. i .. ";" .. "$" .. price .. "]"
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
if fields.next then
page = page + 1
shopping.shop(player_name, page)
return
elseif fields.prev then
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)
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