easyvend/easyvend.lua

1375 lines
46 KiB
Lua
Raw Normal View History

-- TODO: Improve mod compability
local slots_max = 31
2016-09-03 08:31:11 -07:00
2019-03-19 04:36:21 -07:00
local S = minetest.get_translator("easyvend")
local F = minetest.formspec_escape
local traversable_node_types = {
["easyvend:vendor"] = true,
["easyvend:depositor"] = true,
["easyvend:vendor_on"] = true,
["easyvend:depositor_on"] = true,
}
2016-09-02 11:38:32 -07:00
local registered_chests = {}
local cost_stack_max = minetest.registered_items[easyvend.currency].stack_max
local maxcost = cost_stack_max * slots_max
local joketimer_start = 3
2018-05-14 13:04:45 -07:00
local active_item_selection = {}
2016-09-02 11:38:32 -07:00
-- Allow for other mods to register custom chests
easyvend.register_chest = function(node_name, inv_list, meta_owner)
registered_chests[node_name] = { inv_list = inv_list, meta_owner = meta_owner }
traversable_node_types[node_name] = true
2016-09-02 11:38:32 -07:00
end
2018-05-14 13:04:45 -07:00
if minetest.get_modpath("select_item") then
-- When player selects item via "select item" dialog, switch the
-- machine's selected item and update the formspec.
2018-05-17 06:18:19 -07:00
select_item.register_on_select_item(function(playername, dialogname, itemstring)
if dialogname == "easyvend:trade_item" then
local player = minetest.get_player_by_name(playername)
if not player then
2018-05-14 13:04:45 -07:00
return
end
2018-05-17 06:18:19 -07:00
local pos = active_item_selection[playername]
if pos then
local node = minetest.get_node(pos)
if not easyvend.is_machine(node.name) then
return
end
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
if playername == owner then
local inv = meta:get_inventory()
local stack = ItemStack(itemstring)
if stack == nil then
inv:set_stack( "item", 1, nil )
else
inv:set_stack( "item", 1, stack)
meta:set_string("itemname", itemstring)
easyvend.set_formspec(pos, player)
end
2018-05-14 13:04:45 -07:00
end
end
2018-05-17 06:18:19 -07:00
active_item_selection[playername] = nil
2018-05-14 13:04:45 -07:00
end
end)
end
-- Partly a wrapper around contains_item, but does special treatment if the item
-- is a tool. Basically checks whether the items exist in the supplied inventory
-- list. If check_wear is true, only counts items without wear.
easyvend.check_and_get_items = function(inventory, listname, itemtable, check_wear)
local itemstring = itemtable.name
local minimum = itemtable.count
2016-09-02 19:21:01 -07:00
if check_wear == nil then check_wear = false end
local get_items = {}
-- Tool workaround
if minetest.registered_tools[itemstring] ~= nil then
local count = 0
for i=1,inventory:get_size(listname) do
2016-09-02 19:21:01 -07:00
local stack = inventory:get_stack(listname, i)
if stack:get_name() == itemstring then
if not check_wear or stack:get_wear() == 0 then
count = count + 1
table.insert(get_items, {id=i, item=stack})
2016-09-02 19:21:01 -07:00
if count >= minimum then
return true, get_items
2016-09-02 19:21:01 -07:00
end
end
end
end
return false
else
-- Normal Minetest check
return inventory:contains_item(listname, ItemStack(itemtable))
end
end
2016-09-02 11:38:32 -07:00
if minetest.get_modpath("default") ~= nil then
easyvend.register_chest("default:chest_locked", "main", "owner")
end
easyvend.free_slots= function(inv, listname)
local size = inv:get_size(listname)
local free = 0
for i=1,size do
local stack = inv:get_stack(listname, i)
if stack:is_empty() then
free = free + 1
end
end
return free
end
2016-09-02 06:49:28 -07:00
easyvend.buysell = function(nodename)
local buysell = nil
if ( nodename == "easyvend:depositor" or nodename == "easyvend:depositor_on" ) then
buysell = "buy"
elseif ( nodename == "easyvend:vendor" or nodename == "easyvend:vendor_on" ) then
buysell = "sell"
end
return buysell
end
2018-05-14 13:04:45 -07:00
easyvend.is_machine = function(nodename)
return ( nodename == "easyvend:depositor_on" or nodename == "easyvend:vendor_on" or nodename == "easyvend:depositor" or nodename == "easyvend:vendor" )
end
2016-09-06 00:30:11 -07:00
easyvend.is_active = function(nodename)
if ( nodename == "easyvend:depositor_on" or nodename == "easyvend:vendor_on" ) then
return true
elseif ( nodename == "easyvend:depositor" or nodename == "easyvend:vendor" ) then
return false
else
return nil
end
end
2016-09-01 12:56:09 -07:00
easyvend.set_formspec = function(pos, player)
local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
2012-09-12 14:55:10 -07:00
local description = minetest.registered_nodes[node.name].description;
2012-09-12 14:55:10 -07:00
local number = meta:get_int("number")
local cost = meta:get_int("cost")
2016-09-06 02:50:42 -07:00
local itemname = meta:get_string("itemname")
local bg = ""
local configmode = meta:get_int("configmode") == 1
-- Support legacy background from default mod (MT<=0.4.17)
if minetest.get_modpath("default") and default.gui_bg then
bg = default.gui_bg .. default.gui_bg_img .. default.gui_slots
end
2012-09-12 14:55:10 -07:00
local numbertext, costtext, buysellbuttontext
2019-03-19 04:36:21 -07:00
local itemcounttooltip = S("Item count (append “s” to multiply with maximum stack size)")
2016-09-14 16:44:35 -07:00
local buysell = easyvend.buysell(node.name)
if buysell == "sell" then
2019-03-19 04:36:21 -07:00
numbertext = S("Offered item")
costtext = S("Price")
buysellbuttontext = S("Buy")
2016-09-14 16:44:35 -07:00
elseif buysell == "buy" then
2019-03-19 04:36:21 -07:00
numbertext = S("Requested item")
costtext = S("Payment")
buysellbuttontext = S("Sell")
2016-09-14 16:44:35 -07:00
else
2016-09-02 06:49:28 -07:00
return
end
2016-09-02 08:37:03 -07:00
local status = meta:get_string("status")
2019-03-19 04:36:21 -07:00
if status == "" then status = S("Unknown.") end
2016-09-02 08:37:03 -07:00
local message = meta:get_string("message")
2019-03-19 04:36:21 -07:00
if message == "" then message = S("No message.") end
local status_image
if node.name == "easyvend:vendor_on" or node.name == "easyvend:depositor_on" then
status_image = "easyvend_status_on.png"
else
status_image = "easyvend_status_off.png"
end
2016-09-02 06:49:28 -07:00
2016-09-06 02:50:42 -07:00
-- TODO: Expose number of items in stock
local formspec = "size[8,7.3;]"
2016-09-14 16:44:35 -07:00
.. bg
2019-03-19 04:36:21 -07:00
.."label[3,-0.2;" .. F(description) .. "]"
.."image[7.5,0.2;0.5,1;" .. status_image .. "]"
2020-04-06 05:02:53 -07:00
.."textarea[2.8,0.2;5.1,1.45;;"..F(S("Status: @1", status)) .. ";]"
.."textarea[2.8,1.3;5.6,1.45;;"..F(S("Message: @1", message)) .. ";]"
2012-09-12 14:55:10 -07:00
2019-03-19 04:36:21 -07:00
.."label[0,-0.15;"..F(numbertext).."]"
.."label[0,1.2;"..F(costtext).."]"
2016-09-14 16:44:35 -07:00
.."list[current_player;main;0,3.5;8,4;]"
2016-09-06 02:50:42 -07:00
if configmode then
local wear = "false"
if meta:get_int("wear") == 1 then wear = "true" end
2020-03-19 02:55:54 -07:00
local desc = ItemStack(easyvend.currency):get_description()
formspec = formspec
2020-03-19 02:55:54 -07:00
.."item_image[0,1.65;1,1;"..easyvend.currency.."]"
.."tooltip[0,1.65;0.8,0.8;"..F(desc).."]"
2016-09-14 16:44:35 -07:00
.."list[current_name;item;0,0.35;1,1;]"
.."listring[current_player;main]"
.."listring[current_name;item]"
.."field[1.3,0.65;1.5,1;number;;" .. number .. "]"
2019-03-19 04:36:21 -07:00
.."tooltip[number;"..F(itemcounttooltip).."]"
.."field[1.3,1.95;1.5,1;cost;;" .. F(cost) .. "]"
.."tooltip[cost;"..F(itemcounttooltip).."]"
.."button[6,2.8;2,0.5;save;"..F(S("Confirm")).."]"
.."tooltip[save;"..F(S("Confirm configuration and activate machine (only for owner)")).."]"
2018-05-14 13:04:45 -07:00
if minetest.get_modpath("select_item") then
2019-03-19 04:36:21 -07:00
formspec = formspec .. "button[0,2.8;2,0.5;select_item;"..F(S("Select item")).."]"
2018-05-14 13:04:45 -07:00
end
2016-09-02 16:25:03 -07:00
local weartext, weartooltip
if buysell == "buy" then
2019-03-19 04:36:21 -07:00
weartext = S("Buy worn tools")
weartooltip = S("If disabled, only tools in perfect condition will be bought from sellers (only settable by owner)")
2016-09-02 16:25:03 -07:00
else
2019-03-19 04:36:21 -07:00
weartext = S("Sell worn tools")
weartooltip = S("If disabled, only tools in perfect condition will be sold (only settable by owner)")
2016-09-02 16:25:03 -07:00
end
2016-09-06 02:50:42 -07:00
if minetest.registered_tools[itemname] ~= nil then
2019-03-19 04:36:21 -07:00
formspec = formspec .."checkbox[2,2.4;wear;"..F(weartext)..";"..wear.."]"
.."tooltip[wear;"..F(weartooltip).."]"
end
else
2020-03-19 02:55:54 -07:00
local desc_c = ItemStack(easyvend.currency):get_description()
local tt_i = ""
if minetest.registered_items[itemname] then
local desc_i = ItemStack(itemname):get_description()
2020-03-19 04:16:35 -07:00
tt_i = "tooltip[0,0.35;0.8,0.8;"..F(desc_i).."]"
2020-03-19 02:55:54 -07:00
end
formspec = formspec
2020-03-19 02:55:54 -07:00
.."item_image[0,1.65;1,1;"..easyvend.currency.."]"
2020-03-19 04:16:35 -07:00
.."tooltip[0,1.65;0.8,0.8;"..F(desc_c).."]"
2020-03-19 02:55:54 -07:00
.."item_image[0,0.35;1,1;"..itemname.."]"
..tt_i
.."label[1,1.85;×" .. cost .. "]"
.."label[1,0.55;×" .. number .. "]"
2019-03-19 04:36:21 -07:00
.."button[6,2.8;2,0.5;config;"..F(S("Configure")).."]"
2016-09-05 23:50:05 -07:00
if buysell == "sell" then
2019-03-19 04:36:21 -07:00
formspec = formspec .. "tooltip[config;"..F(S("Configure offered items and price (only for owner)")).."]"
2016-09-05 23:50:05 -07:00
else
2019-03-19 04:36:21 -07:00
formspec = formspec .. "tooltip[config;"..F(S("Configure requested items and payment (only for owner)")).."]"
2016-09-05 23:50:05 -07:00
end
2019-03-19 04:36:21 -07:00
formspec = formspec .."button[0,2.8;2,0.5;buysell;"..F(buysellbuttontext).."]"
2016-09-02 19:48:43 -07:00
if minetest.registered_tools[itemname] ~= nil then
local weartext
if meta:get_int("wear") == 0 then
if buysell == "buy" then
2019-03-19 04:36:21 -07:00
weartext = S("Only intact tools are bought.")
2016-09-02 19:48:43 -07:00
else
2019-03-19 04:36:21 -07:00
weartext = S("Only intact tools are sold.")
2016-09-02 19:48:43 -07:00
end
2016-09-09 13:55:47 -07:00
else
if buysell == "sell" then
2019-03-19 04:36:21 -07:00
weartext = S("Note: Might sell worn tools.")
2016-09-09 13:55:47 -07:00
else
2019-03-19 04:36:21 -07:00
weartext = S("Accepts worn tools.")
2016-09-09 13:55:47 -07:00
end
2016-09-02 19:48:43 -07:00
end
if weartext ~= nil then
2020-04-06 05:02:53 -07:00
formspec = formspec .."textarea[2.3,2.6;4,1;;"..F(weartext)..";]"
2016-09-02 19:48:43 -07:00
end
end
end
2012-09-12 14:55:10 -07:00
meta:set_string("formspec", formspec)
2012-09-12 14:55:10 -07:00
end
easyvend.machine_disable = function(pos, node, playername)
if node.name == "easyvend:vendor_on" then
2016-09-14 16:44:35 -07:00
easyvend.sound_disable(pos)
minetest.swap_node(pos, {name="easyvend:vendor", param2 = node.param2})
2016-09-01 21:42:43 -07:00
return true
elseif node.name == "easyvend:depositor_on" then
2016-09-14 16:44:35 -07:00
easyvend.sound_disable(pos)
minetest.swap_node(pos, {name="easyvend:depositor", param2 = node.param2})
2016-09-01 21:42:43 -07:00
return true
else
if playername ~= nil then
easyvend.sound_error(playername)
end
return false
end
end
easyvend.machine_enable = function(pos, node)
2016-09-14 16:44:35 -07:00
if node.name == "easyvend:vendor" then
easyvend.sound_setup(pos)
minetest.swap_node(pos, {name="easyvend:vendor_on", param2 = node.param2})
2016-09-01 21:42:43 -07:00
return true
elseif node.name == "easyvend:depositor" then
2016-09-14 16:44:35 -07:00
easyvend.sound_setup(pos)
minetest.swap_node(pos, {name="easyvend:depositor_on", param2 = node.param2})
2016-09-01 21:42:43 -07:00
return true
else
return false
end
end
easyvend.machine_check = function(pos, node)
local active = true
2019-03-19 05:20:19 -07:00
local status = S("Ready.")
local meta = minetest.get_meta(pos)
local machine_owner = meta:get_string("owner")
2016-09-02 05:52:33 -07:00
local number = meta:get_int("number")
local cost = meta:get_int("cost")
local itemname = meta:get_string("itemname")
local check_wear = meta:get_int("wear") == 0
2016-09-02 05:52:33 -07:00
local inv = meta:get_inventory()
local itemstack = inv:get_stack("item",1)
local buysell = easyvend.buysell(node.name)
local chest_pos_remove, chest_error_remove, chest_pos_add, chest_error_add
if buysell == "sell" then
chest_pos_remove, chest_error_remove = easyvend.find_connected_chest(machine_owner, pos, itemname, check_wear, number, true)
2016-09-14 16:44:35 -07:00
chest_pos_add, chest_error_add = easyvend.find_connected_chest(machine_owner, pos, easyvend.currency, check_wear, cost, false)
else
chest_pos_remove, chest_error_remove = easyvend.find_connected_chest(machine_owner, pos, easyvend.currency, check_wear, cost, true)
2016-09-14 16:44:35 -07:00
chest_pos_add, chest_error_add = easyvend.find_connected_chest(machine_owner, pos, itemname, check_wear, number, false)
end
if chest_pos_remove and chest_pos_add then
local rchest, rchestdef, rchest_meta, rchest_inv
rchest = minetest.get_node(chest_pos_remove)
rchestdef = registered_chests[rchest.name]
rchest_meta = minetest.get_meta(chest_pos_remove)
rchest_inv = rchest_meta:get_inventory()
2016-09-14 16:44:35 -07:00
local checkstack, checkitem
if buysell == "buy" then
checkitem = easyvend.currency
else
checkitem = itemname
end
local stock = 0
-- Count stock
-- FIXME: Ignore tools with bad wear level
for i=1,rchest_inv:get_size(rchestdef.inv_list) do
checkstack = rchest_inv:get_stack(rchestdef.inv_list, i)
if checkstack:get_name() == checkitem then
stock = stock + checkstack:get_count()
2016-09-06 02:50:42 -07:00
end
2016-09-14 16:44:35 -07:00
end
meta:set_int("stock", stock)
if not itemstack:is_empty() then
local number_stack_max = itemstack:get_stack_max()
local maxnumber = number_stack_max * slots_max
if not(number >= 1 and number <= maxnumber and cost >= 1 and cost <= maxcost) then
active = false
2016-09-14 16:44:35 -07:00
if buysell == "sell" then
2019-03-19 04:36:21 -07:00
status = S("Invalid item count or price.")
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
status = S("Invalid item count or payment.")
2016-09-14 16:44:35 -07:00
end
end
2016-09-14 16:44:35 -07:00
else
active = false
2019-03-19 04:36:21 -07:00
status = S("Awaiting configuration by owner.")
2016-09-14 16:44:35 -07:00
end
else
active = false
2016-09-13 06:17:48 -07:00
meta:set_int("stock", 0)
if chest_error_remove == "no_chest" and chest_error_add == "no_chest" then
2019-03-19 04:36:21 -07:00
status = S("No storage; machine needs to be connected with a locked chest.")
elseif chest_error_remove == "not_owned" or chest_error_add == "not_owned" then
2019-03-19 04:36:21 -07:00
status = S("Storage cant be accessed because it is owned by a different person!")
elseif chest_error_remove == "no_stock" then
2016-09-13 06:17:48 -07:00
if buysell == "sell" then
2019-03-19 04:36:21 -07:00
status = S("The vending machine has insufficient materials!")
2016-09-13 06:17:48 -07:00
else
2019-03-19 04:36:21 -07:00
status = S("The depositing machine is out of money!")
2016-09-13 06:17:48 -07:00
end
elseif chest_error_add == "no_space" then
2019-03-19 04:36:21 -07:00
status = S("No room in the machines storage!")
2016-09-13 06:17:48 -07:00
else
2019-03-19 04:36:21 -07:00
status = S("Unknown error!")
2016-09-13 06:17:48 -07:00
end
2016-09-14 16:44:35 -07:00
end
if meta:get_int("configmode") == 1 then
active = false
2019-03-19 04:36:21 -07:00
status = S("Awaiting configuration by owner.")
end
2016-09-14 16:44:35 -07:00
if itemname == easyvend.currency and number == cost and active then
local jt = meta:get_int("joketimer")
if jt > 0 then
jt = jt - 1
end
if jt == 0 then
if buysell == "sell" then
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Item bought."))
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Item sold."))
2016-09-14 16:44:35 -07:00
end
jt = -1
end
meta:set_int("joketimer", jt)
end
2016-09-02 08:37:03 -07:00
meta:set_string("status", status)
meta:set_string("infotext", easyvend.make_infotext(node.name, machine_owner, cost, number, itemname))
2016-09-02 06:11:51 -07:00
itemname=itemstack:get_name()
meta:set_string("itemname", itemname)
2016-09-02 05:52:33 -07:00
2016-11-02 12:05:40 -07:00
if minetest.get_modpath("awards") and buysell == "sell" then
if minetest.get_player_by_name(machine_owner) then
local earnings = meta:get_int("earnings")
if earnings >= 1 then
awards.unlock(machine_owner, "easyvend_seller")
end
if earnings >= easyvend.powerseller then
awards.unlock(machine_owner, "easyvend_powerseller")
end
end
end
2016-09-02 08:37:03 -07:00
local change
if node.name == "easyvend:vendor" or node.name == "easyvend:depositor" then
2016-09-02 08:37:03 -07:00
if active then change = easyvend.machine_enable(pos, node) end
elseif node.name == "easyvend:vendor_on" or node.name == "easyvend:depositor_on" then
2016-09-02 08:37:03 -07:00
if not active then change = easyvend.machine_disable(pos, node) end
end
2016-09-14 16:44:35 -07:00
easyvend.set_formspec(pos)
2016-09-02 08:37:03 -07:00
return change
end
easyvend.on_receive_fields_config = function(pos, formname, fields, sender)
2016-09-14 16:44:35 -07:00
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
2016-09-14 16:44:35 -07:00
local inv_self = meta:get_inventory()
local itemstack = inv_self:get_stack("item",1)
local buysell = easyvend.buysell(node.name)
2016-09-14 16:44:35 -07:00
if fields.config then
meta:set_int("configmode", 1)
local was_active = easyvend.is_active(node.name)
if was_active then
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Configuration mode activated; machine disabled."))
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Configuration mode activated."))
2016-09-14 16:44:35 -07:00
end
easyvend.machine_check(pos, node)
return
2016-09-06 00:30:11 -07:00
end
2016-09-14 16:44:35 -07:00
if not fields.save then
return
end
local number = fields.number
local cost = fields.cost
2016-09-14 16:44:35 -07:00
--[[ Convenience function:
When appending s or S to the number, it is multiplied
2018-05-13 14:59:12 -07:00
by the maximum stack size. ]]
2016-09-14 16:44:35 -07:00
local number_stack_max = itemstack:get_stack_max()
local ss = string.sub(number, #number, #number)
if ss == "s" or ss == "S" then
local n = tonumber(string.sub(number, 1, #number-1))
if string.len(number) == 1 then n = 1 end
if n ~= nil then
number = n * number_stack_max
end
end
2016-09-14 16:44:35 -07:00
ss = string.sub(cost, #cost, #cost)
if ss == "s" or ss == "S" then
local n = tonumber(string.sub(cost, 1, #cost-1))
if string.len(cost) == 1 then n = 1 end
if n ~= nil then
cost = n * cost_stack_max
end
end
2016-09-14 16:44:35 -07:00
number = tonumber(number)
cost = tonumber(cost)
2016-09-14 16:44:35 -07:00
local itemname=""
2016-09-14 16:44:35 -07:00
local oldnumber = meta:get_int("number")
local oldcost = meta:get_int("cost")
local maxnumber = number_stack_max * slots_max
2012-09-12 14:55:10 -07:00
2016-09-14 16:44:35 -07:00
if ( itemstack == nil or itemstack:is_empty() ) then
2019-03-19 04:36:21 -07:00
meta:set_string("status", S("Awaiting configuration by owner."))
meta:set_string("message", S("No item specified."))
2016-09-14 16:44:35 -07:00
easyvend.sound_error(sender:get_player_name())
easyvend.set_formspec(pos, sender)
return
elseif ( not itemstack:is_known() ) then
2019-03-19 04:36:21 -07:00
meta:set_string("status", S("Awaiting configuration by owner."))
meta:set_string("message", S("Unknown item specified."))
easyvend.sound_error(sender:get_player_name())
easyvend.set_formspec(pos, sender)
return
elseif ( number == nil or number < 1 or number > maxnumber ) then
2016-09-14 16:44:35 -07:00
if maxnumber > 1 then
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Invalid item count; must be between 1 and @1!", maxnumber))
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Invalid item count; must be exactly 1!"))
2016-09-14 16:44:35 -07:00
end
meta:set_int("number", oldnumber)
easyvend.sound_error(sender:get_player_name())
easyvend.set_formspec(pos, sender)
return
elseif ( cost == nil or cost < 1 or cost > maxcost ) then
2016-09-14 16:44:35 -07:00
if maxcost > 1 then
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Invalid cost; must be between 1 and @1!", maxcost))
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Invalid cost; must be exactly 1!"))
2016-09-14 16:44:35 -07:00
end
meta:set_int("cost", oldcost)
easyvend.sound_error(sender:get_player_name())
easyvend.set_formspec(pos, sender)
return
end
meta:set_int("number", number)
meta:set_int("cost", cost)
itemname=itemstack:get_name()
meta:set_string("itemname", itemname)
2016-09-14 16:44:35 -07:00
meta:set_int("configmode", 0)
2016-09-14 16:44:35 -07:00
if itemname == easyvend.currency and number == cost and cost <= cost_stack_max then
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Configuration successful. I am feeling funny."))
2016-09-14 16:44:35 -07:00
meta:set_int("joketimer", joketimer_start)
meta:set_int("joke_id", easyvend.assign_joke(buysell))
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Configuration successful."))
2016-09-14 16:44:35 -07:00
end
2016-09-02 05:52:33 -07:00
2016-09-14 16:44:35 -07:00
local change = easyvend.machine_check(pos, node)
2016-09-06 00:57:55 -07:00
2016-09-01 21:42:43 -07:00
if not change then
if (node.name == "easyvend:vendor_on" or node.name == "easyvend:depositor_on") then
easyvend.sound_setup(pos)
else
easyvend.sound_disable(pos)
end
end
end
2016-09-02 05:52:33 -07:00
easyvend.make_infotext = function(nodename, owner, cost, number, itemstring)
local d = ""
if itemstring == nil or itemstring == "" or number == 0 or cost == 0 then
if easyvend.buysell(nodename) == "sell" then
2019-03-19 04:36:21 -07:00
d = S("Inactive vending machine (owned by @1)", owner)
else
2019-03-19 04:36:21 -07:00
d = S("Inactive depositing machine (owned by @1)", owner)
end
return d
end
2017-01-12 06:27:54 -08:00
local iname
if minetest.registered_items[itemstring] then
iname = minetest.registered_items[itemstring].description
else
2019-03-19 04:36:21 -07:00
iname = S("Unknown Item (@1)", itemstring)
2017-01-12 06:27:54 -08:00
end
2016-09-02 05:52:33 -07:00
if iname == nil then iname = itemstring end
2016-09-02 11:53:04 -07:00
local printitem, printcost
if number == 1 then
printitem = iname
else
2019-03-19 04:36:21 -07:00
printitem = S("@1×@2", number, iname)
2016-09-02 11:53:04 -07:00
end
if cost == 1 then
printcost = easyvend.currency_desc
2016-09-02 11:53:04 -07:00
else
2019-03-19 04:36:21 -07:00
printcost = S("@1×@2", cost, easyvend.currency_desc)
2016-09-02 11:53:04 -07:00
end
2016-09-06 00:04:17 -07:00
if nodename == "easyvend:vendor_on" then
2019-03-19 04:36:21 -07:00
d = S("Vending machine (owned by @1)", owner).."\n"..S("Selling: @1", printitem).."\n"..S("Price: @1", printcost)
2016-09-06 00:04:17 -07:00
elseif nodename == "easyvend:vendor" then
2019-03-19 04:36:21 -07:00
d = S("Inactive vending machine (owned by @1)", owner).."\n"..S("Selling: @1", printitem).."\n"..S("Price: @1", printcost)
2016-09-06 00:04:17 -07:00
elseif nodename == "easyvend:depositor_on" then
2019-03-19 04:36:21 -07:00
d = S("Depositing machine (owned by @1)", owner).."\n"..S("Buying: @1", printitem).."\n"..S("Payment: @1", printcost)
2016-09-06 00:04:17 -07:00
elseif nodename == "easyvend:depositor" then
2019-03-19 04:36:21 -07:00
d = S("Inactive depositing machine (owned by @1)", owner).."\n"..S("Buying: @1", printitem).."\n"..S("Payment: @1", printcost)
2016-09-02 05:52:33 -07:00
end
return d
end
2016-11-02 12:05:40 -07:00
if minetest.get_modpath("awards") then
awards.register_achievement("easyvend_seller",{
2019-03-19 04:36:21 -07:00
title = S("First Sale"),
description = S("Sell something with a vending machine."),
2016-11-02 12:05:40 -07:00
icon = "easyvend_vendor_front_on.png^awards_level1.png",
})
local desc_powerseller
if easyvend.currency == "default:gold_ingot" then
2019-03-19 04:36:21 -07:00
desc_powerseller = S("Earn @1 gold ingots by selling goods with a single vending machine.", easyvend.powerseller)
2016-11-02 12:05:40 -07:00
else
2019-03-19 04:36:21 -07:00
desc_powerseller = S("Earn @1 currency items by selling goods with a single vending machine.", easyvend.powerseller)
2016-11-02 12:05:40 -07:00
end
awards.register_achievement("easyvend_powerseller",{
2019-03-19 04:36:21 -07:00
title = S("Power Seller"),
2016-11-02 12:05:40 -07:00
description = desc_powerseller,
icon = "easyvend_vendor_front_on.png^awards_level2.png",
})
end
easyvend.check_earnings = function(buyername, nodemeta)
local owner = nodemeta:get_string("owner")
if buyername ~= owner then
local cost = nodemeta:get_int("cost")
local itemname = nodemeta:get_string("itemname")
-- First sell
if minetest.get_modpath("awards") and minetest.get_player_by_name(owner) ~= nil then
2016-11-02 12:05:40 -07:00
awards.unlock(owner, "easyvend_seller")
end
if itemname ~= easyvend.currency then
local newearnings = nodemeta:get_int("earnings") + cost
if newearnings >= easyvend.powerseller and minetest.get_modpath("awards") then
if minetest.get_player_by_name(owner) ~= nil then
awards.unlock(owner, "easyvend_powerseller")
end
end
nodemeta:set_int("earnings", newearnings)
end
end
end
easyvend.on_receive_fields_buysell = function(pos, formname, fields, sender)
2016-09-14 16:44:35 -07:00
local sendername = sender:get_player_name()
local meta = minetest.get_meta(pos)
2016-09-14 16:44:35 -07:00
if not fields.buysell then
return
end
local node = minetest.get_node(pos)
2016-09-14 16:44:35 -07:00
local number = meta:get_int("number")
local cost = meta:get_int("cost")
local itemname=meta:get_string("itemname")
local item=meta:get_inventory():get_stack("item", 1)
local check_wear = meta:get_int("wear") == 0 and minetest.registered_tools[itemname] ~= nil
2016-11-02 12:05:40 -07:00
local machine_owner = meta:get_string("owner")
2016-09-02 06:49:28 -07:00
2016-09-14 16:44:35 -07:00
local buysell = easyvend.buysell(node.name)
2012-09-12 14:55:10 -07:00
2016-09-14 16:44:35 -07:00
local number_stack_max = item:get_stack_max()
local maxnumber = number_stack_max * slots_max
if ( number == nil or number < 1 or number > maxnumber ) or
( cost == nil or cost < 1 or cost > maxcost ) or
2016-09-01 13:52:30 -07:00
( itemname == nil or itemname=="") then
2019-03-19 04:36:21 -07:00
meta:set_string("status", S("Invalid item count or price!"))
2016-09-14 16:44:35 -07:00
easyvend.machine_disable(pos, node, sendername)
return
2012-09-12 14:55:10 -07:00
end
2016-09-01 13:52:30 -07:00
2016-09-14 16:44:35 -07:00
local chest_pos_remove, chest_error_remove, chest_pos_add, chest_error_add
if buysell == "sell" then
2016-11-02 12:05:40 -07:00
chest_pos_remove, chest_error_remove = easyvend.find_connected_chest(machine_owner, pos, itemname, check_wear, number, true)
chest_pos_add, chest_error_add = easyvend.find_connected_chest(machine_owner, pos, easyvend.currency, check_wear, cost, false)
2016-09-14 16:44:35 -07:00
else
2016-11-02 12:05:40 -07:00
chest_pos_remove, chest_error_remove = easyvend.find_connected_chest(machine_owner, pos, easyvend.currency, check_wear, cost, true)
chest_pos_add, chest_error_add = easyvend.find_connected_chest(machine_owner, pos, itemname, check_wear, number, false)
2016-09-14 16:44:35 -07:00
end
2016-09-14 16:44:35 -07:00
if chest_pos_remove ~= nil and chest_pos_add ~= nil and sender and sender:is_player() then
local rchest = minetest.get_node(chest_pos_remove)
local rchestdef = registered_chests[rchest.name]
local rchest_meta = minetest.get_meta(chest_pos_remove)
local rchest_inv = rchest_meta:get_inventory()
local achest = minetest.get_node(chest_pos_add)
local achestdef = registered_chests[achest.name]
local achest_meta = minetest.get_meta(chest_pos_add)
local achest_inv = achest_meta:get_inventory()
local player_inv = sender:get_inventory()
local stack = {name=itemname, count=number, wear=0, metadata=""}
local price = {name=easyvend.currency, count=cost, wear=0, metadata=""}
local chest_has, player_has, chest_free, player_free, chest_out, player_out
local msg = ""
2016-09-14 15:15:16 -07:00
if buysell == "sell" then
2016-09-14 16:44:35 -07:00
chest_has, chest_out = easyvend.check_and_get_items(rchest_inv, rchestdef.inv_list, stack, check_wear)
player_has, player_out = easyvend.check_and_get_items(player_inv, "main", price, check_wear)
chest_free = achest_inv:room_for_item(achestdef.inv_list, price)
player_free = player_inv:room_for_item("main", stack)
if chest_has and player_has and chest_free and player_free then
if cost <= cost_stack_max and number <= number_stack_max then
easyvend.machine_enable(pos, node)
player_inv:remove_item("main", price)
if check_wear then
rchest_inv:set_stack(rchestdef.inv_list, chest_out[1].id, "")
player_inv:add_item("main", chest_out[1].item)
else
stack = rchest_inv:remove_item(rchestdef.inv_list, stack)
player_inv:add_item("main", stack)
end
achest_inv:add_item(achestdef.inv_list, price)
if itemname == easyvend.currency and number == cost and cost <= cost_stack_max then
meta:set_string("message", easyvend.get_joke(buysell, meta:get_int("joke_id")))
meta:set_int("joketimer", joketimer_start)
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Item bought."))
2016-09-14 16:44:35 -07:00
end
2016-11-02 12:05:40 -07:00
easyvend.check_earnings(sendername, meta)
2016-09-14 16:44:35 -07:00
easyvend.sound_vend(pos)
easyvend.machine_check(pos, node)
else
-- Large item counts (multiple stacks)
local coststacks = math.modf(cost / cost_stack_max)
local costremainder = math.fmod(cost, cost_stack_max)
local numberstacks = math.modf(number / number_stack_max)
local numberremainder = math.fmod(number, number_stack_max)
local numberfree = numberstacks
local costfree = coststacks
if numberremainder > 0 then numberfree = numberfree + 1 end
if costremainder > 0 then costfree = costfree + 1 end
if not player_free and easyvend.free_slots(player_inv, "main") < numberfree then
if numberfree > 1 then
2019-03-19 04:36:21 -07:00
msg = S("No room in your inventory (@1 empty slots required)!", numberfree)
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
msg = S("No room in your inventory!")
2016-09-14 16:44:35 -07:00
end
meta:set_string("message", msg)
elseif not chest_free and easyvend.free_slots(achest_inv, achestdef.inv_list) < costfree then
2019-03-19 04:36:21 -07:00
meta:set_string("status", S("No room in the machines storage!"))
2016-09-14 16:44:35 -07:00
easyvend.machine_disable(pos, node, sendername)
else
-- Remember items for transfer
local cheststacks = {}
easyvend.machine_enable(pos, node)
for i=1, coststacks do
price.count = cost_stack_max
player_inv:remove_item("main", price)
end
if costremainder > 0 then
price.count = costremainder
player_inv:remove_item("main", price)
end
if check_wear then
for o=1,#chest_out do
rchest_inv:set_stack(rchestdef.inv_list, chest_out[o].id, "")
end
else
for i=1, numberstacks do
stack.count = number_stack_max
table.insert(cheststacks, rchest_inv:remove_item(rchestdef.inv_list, stack))
end
end
if numberremainder > 0 then
stack.count = numberremainder
table.insert(cheststacks, rchest_inv:remove_item(rchestdef.inv_list, stack))
end
for i=1, coststacks do
price.count = cost_stack_max
achest_inv:add_item(achestdef.inv_list, price)
end
if costremainder > 0 then
price.count = costremainder
achest_inv:add_item(achestdef.inv_list, price)
end
if check_wear then
for o=1,#chest_out do
player_inv:add_item("main", chest_out[o].item)
end
else
for i=1,#cheststacks do
player_inv:add_item("main", cheststacks[i])
end
end
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Item bought."))
2016-11-02 12:05:40 -07:00
easyvend.check_earnings(sendername, meta)
2016-09-14 16:44:35 -07:00
easyvend.sound_vend(pos)
easyvend.machine_check(pos, node)
end
end
elseif chest_has and player_has then
if not player_free then
2019-03-19 04:36:21 -07:00
msg = S("No room in your inventory!")
2016-09-14 16:44:35 -07:00
meta:set_string("message", msg)
easyvend.sound_error(sendername)
elseif not chest_free then
2019-03-19 04:36:21 -07:00
msg = S("No room in the machines storage!")
2016-09-14 16:44:35 -07:00
meta:set_string("status", msg)
easyvend.machine_disable(pos, node, sendername)
end
else
if not chest_has then
2019-03-19 04:36:21 -07:00
msg = S("The vending machine has insufficient materials!")
2016-09-14 16:44:35 -07:00
meta:set_string("status", msg)
easyvend.machine_disable(pos, node, sendername)
elseif not player_has then
2019-03-19 04:36:21 -07:00
msg = S("You cant afford this item!")
2016-09-14 16:44:35 -07:00
meta:set_string("message", msg)
easyvend.sound_error(sendername)
end
end
2016-09-14 15:15:16 -07:00
else
2016-09-14 16:44:35 -07:00
chest_has, chest_out = easyvend.check_and_get_items(rchest_inv, rchestdef.inv_list, price, check_wear)
player_has, player_out = easyvend.check_and_get_items(player_inv, "main", stack, check_wear)
chest_free = achest_inv:room_for_item(achestdef.inv_list, stack)
player_free = player_inv:room_for_item("main", price)
if chest_has and player_has and chest_free and player_free then
if cost <= cost_stack_max and number <= number_stack_max then
easyvend.machine_enable(pos, node)
if check_wear then
player_inv:set_stack("main", player_out[1].id, "")
achest_inv:add_item(achestdef.inv_list, player_out[1].item)
else
stack = player_inv:remove_item("main", stack)
achest_inv:add_item(achestdef.inv_list, stack)
end
rchest_inv:remove_item(rchestdef.inv_list, price)
player_inv:add_item("main", price)
2019-03-19 04:36:21 -07:00
meta:set_string("status", S("Ready."))
2016-09-14 16:44:35 -07:00
if itemname == easyvend.currency and number == cost and cost <= cost_stack_max then
meta:set_string("message", easyvend.get_joke(buysell, meta:get_int("joke_id")))
meta:set_int("joketimer", joketimer_start)
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Item sold."))
2016-09-14 16:44:35 -07:00
end
easyvend.sound_deposit(pos)
easyvend.machine_check(pos, node)
else
-- Large item counts (multiple stacks)
local coststacks = math.modf(cost / cost_stack_max)
local costremainder = math.fmod(cost, cost_stack_max)
local numberstacks = math.modf(number / number_stack_max)
local numberremainder = math.fmod(number, number_stack_max)
local numberfree = numberstacks
local costfree = coststacks
if numberremainder > 0 then numberfree = numberfree + 1 end
if costremainder > 0 then costfree = costfree + 1 end
if not player_free and easyvend.free_slots(player_inv, "main") < costfree then
if costfree > 1 then
2019-03-19 04:36:21 -07:00
msg = S("No room in your inventory (@1 empty slots required)!", costfree)
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
msg = S("No room in your inventory!")
2016-09-14 16:44:35 -07:00
end
meta:set_string("message", msg)
easyvend.sound_error(sendername)
elseif not chest_free and easyvend.free_slots(achest_inv, achestdef.inv_list) < numberfree then
2019-03-19 04:36:21 -07:00
meta:set_string("status", S("No room in the machines storage!"))
2016-09-14 16:44:35 -07:00
easyvend.machine_disable(pos, node, sendername)
else
easyvend.machine_enable(pos, node)
-- Remember removed items for transfer
local playerstacks = {}
for i=1, coststacks do
price.count = cost_stack_max
rchest_inv:remove_item(rchestdef.inv_list, price)
end
if costremainder > 0 then
price.count = costremainder
rchest_inv:remove_item(rchestdef.inv_list, price)
end
if check_wear then
for o=1,#player_out do
player_inv:set_stack("main", player_out[o].id, "")
end
else
for i=1, numberstacks do
stack.count = number_stack_max
table.insert(playerstacks, player_inv:remove_item("main", stack))
end
end
if numberremainder > 0 then
stack.count = numberremainder
table.insert(playerstacks, player_inv:remove_item("main", stack))
end
for i=1, coststacks do
price.count = cost_stack_max
player_inv:add_item("main", price)
end
if costremainder > 0 then
price.count = costremainder
player_inv:add_item("main", price)
end
if check_wear then
for o=1,#player_out do
achest_inv:add_item(achestdef.inv_list, player_out[o].item)
end
else
for i=1,#playerstacks do
achest_inv:add_item(achestdef.inv_list, playerstacks[i])
end
end
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Item sold."))
2016-09-14 16:44:35 -07:00
easyvend.sound_deposit(pos)
easyvend.machine_check(pos, node)
end
end
elseif chest_has and player_has then
if not player_free then
2019-03-19 04:36:21 -07:00
msg = S("No room in your inventory!")
2016-09-14 16:44:35 -07:00
meta:set_string("message", msg)
easyvend.sound_error(sendername)
elseif not chest_free then
2019-03-19 04:36:21 -07:00
msg = S("No room in the machines storage!")
2016-09-14 16:44:35 -07:00
meta:set_string("status", msg)
easyvend.machine_disable(pos, node, sendername)
end
else
if not player_has then
2019-03-19 04:36:21 -07:00
msg = S("You have insufficient materials!")
2016-09-14 16:44:35 -07:00
meta:set_string("message", msg)
easyvend.sound_error(sendername)
elseif not chest_has then
2019-03-19 04:36:21 -07:00
msg = S("The depositing machine is out of money!")
2016-09-14 16:44:35 -07:00
meta:set_string("status", msg)
easyvend.machine_disable(pos, node, sendername)
end
end
2016-09-14 15:15:16 -07:00
end
else
2016-09-14 17:02:35 -07:00
local status
2016-09-14 16:44:35 -07:00
meta:set_int("stock", 0)
if chest_error_remove == "no_chest" and chest_error_add == "no_chest" then
2019-03-19 04:36:21 -07:00
status = S("No storage; machine needs to be connected with a locked chest.")
2016-09-14 16:44:35 -07:00
elseif chest_error_remove == "not_owned" or chest_error_add == "not_owned" then
2019-03-19 04:36:21 -07:00
status = S("Storage cant be accessed because it is owned by a different person!")
2016-09-14 16:44:35 -07:00
elseif chest_error_remove == "no_stock" then
if buysell == "sell" then
2019-03-19 04:36:21 -07:00
status = S("The vending machine has insufficient materials!")
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
status = S("The depositing machine is out of money!")
2016-09-14 16:44:35 -07:00
end
elseif chest_error_add == "no_space" then
2019-03-19 04:36:21 -07:00
status = S("No room in the machines storage!")
2016-09-14 16:44:35 -07:00
else
2019-03-19 04:36:21 -07:00
status = S("Unknown error!")
2016-09-14 16:44:35 -07:00
end
2016-09-14 17:02:35 -07:00
meta:set_string("status", status)
2016-09-14 16:44:35 -07:00
easyvend.sound_error(sendername)
2016-09-14 15:15:16 -07:00
end
2016-09-14 16:44:35 -07:00
easyvend.set_formspec(pos, sender)
2012-09-12 14:55:10 -07:00
end
2016-09-01 12:56:09 -07:00
easyvend.after_place_node = function(pos, placer)
2016-09-14 16:44:35 -07:00
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
2016-09-14 16:44:35 -07:00
local inv = meta:get_inventory()
local player_name = placer:get_player_name()
inv:set_size("item", 1)
inv:set_size("gold", 1)
inv:set_stack( "gold", 1, easyvend.currency )
local d = ""
if node.name == "easyvend:vendor" then
2019-03-19 04:36:21 -07:00
d = S("Inactive vending machine (owned by @1)", player_name)
2016-09-14 16:44:35 -07:00
meta:set_int("wear", 1)
2016-11-02 12:05:40 -07:00
-- Total number of currency items earned for the machine's life time (excluding currency-currency trading)
meta:set_int("earnings", 0)
2016-09-14 16:44:35 -07:00
elseif node.name == "easyvend:depositor" then
2019-03-19 04:36:21 -07:00
d = S("Inactive depositing machine (owned by @1)", player_name)
2016-09-14 16:44:35 -07:00
meta:set_int("wear", 0)
end
meta:set_string("infotext", d)
2019-03-19 04:36:21 -07:00
meta:set_string("status", S("Awaiting configuration by owner."))
meta:set_string("message", S("Please select an item and amount, then confirm."))
2016-09-14 16:44:35 -07:00
meta:set_int("number", 1)
meta:set_int("cost", 1)
meta:set_int("stock", -1)
meta:set_int("configmode", 1)
meta:set_int("joketimer", -1)
meta:set_int("joke_id", 1)
meta:set_string("itemname", "")
2012-09-12 14:55:10 -07:00
2016-09-01 15:19:45 -07:00
meta:set_string("owner", player_name or "")
2016-09-14 16:44:35 -07:00
easyvend.set_formspec(pos, placer)
2012-09-12 14:55:10 -07:00
end
2016-09-01 12:56:09 -07:00
easyvend.can_dig = function(pos, player)
2016-09-14 16:44:35 -07:00
local meta = minetest.get_meta(pos)
local name = player:get_player_name()
local owner = meta:get_string("owner")
-- Owner can always dig shop
if owner == name then
return true
end
2016-09-14 17:04:25 -07:00
local chest_pos = easyvend.find_connected_chest(owner, pos)
2016-09-14 16:44:35 -07:00
local chest, meta_chest
if chest_pos then
chest = minetest.get_node(chest_pos)
meta_chest = minetest.get_meta(chest_pos)
2016-09-21 05:10:54 -07:00
else
return true --if no chest, enyone can dig this shop
2016-09-14 16:44:35 -07:00
end
if registered_chests[chest.name] then
if player and player:is_player() then
local owner_chest = meta_chest:get_string(registered_chests[chest.name].meta_owner)
if name == owner_chest then
return true --chest owner can also dig shop
end
end
return false
else
return true --if no chest, enyone can dig this shop
end
2012-09-12 14:55:10 -07:00
end
2016-09-01 12:56:09 -07:00
easyvend.on_receive_fields = function(pos, formname, fields, sender)
local meta = minetest.get_meta(pos)
2016-09-02 16:25:03 -07:00
local node = minetest.get_node(pos)
local owner = meta:get_string("owner")
2016-11-18 10:10:43 -08:00
local sendername = sender:get_player_name()
2016-09-14 16:44:35 -07:00
2016-11-18 10:10:43 -08:00
if fields.doc then
if minetest.get_modpath("doc") and minetest.get_modpath("doc_items") then
if easyvend.buysell(node.name) == "buy" then
doc.show_entry(sendername, "nodes", "easyvend:depositor", true)
else
doc.show_entry(sendername, "nodes", "easyvend:vendor", true)
end
end
elseif fields.config or fields.save or fields.usermode then
2018-05-14 13:04:45 -07:00
if sendername == owner then
easyvend.on_receive_fields_config(pos, formname, fields, sender)
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Only the owner may change the configuration."))
easyvend.sound_error(sendername)
easyvend.set_formspec(pos, sender)
return
end
2018-05-14 13:04:45 -07:00
elseif fields.select_item then
if minetest.get_modpath("select_item") then
if sendername == owner then
active_item_selection[sendername] = pos
2018-05-17 06:18:19 -07:00
select_item.show_dialog(sendername, "easyvend:trade_item", select_item.filters.creative)
2018-05-14 13:04:45 -07:00
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Only the owner may change the configuration."))
2018-05-14 13:04:45 -07:00
easyvend.sound_error(sendername)
easyvend.set_formspec(pos, sender)
return
end
end
elseif fields.wear ~= nil then
if sender:get_player_name() == owner then
if fields.wear == "true" then
2016-09-02 16:25:03 -07:00
if easyvend.buysell(node.name) == "buy" then
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Used tools are now accepted."))
2016-09-02 16:25:03 -07:00
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Used tools are now for sale."))
2016-09-02 16:25:03 -07:00
end
meta:set_int("wear", 1)
elseif fields.wear == "false" then
2016-09-02 16:25:03 -07:00
if easyvend.buysell(node.name) == "buy" then
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Used tools are now rejected."))
2016-09-02 16:25:03 -07:00
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Used tools wont be sold anymore."))
2016-09-02 16:25:03 -07:00
end
meta:set_int("wear", 0)
end
easyvend.set_formspec(pos, sender)
return
else
2019-03-19 04:36:21 -07:00
meta:set_string("message", S("Only the owner may change the configuration."))
easyvend.sound_error(sendername)
easyvend.set_formspec(pos, sender)
return
end
elseif fields.buysell then
easyvend.on_receive_fields_buysell(pos, formname, fields, sender)
2012-09-12 14:55:10 -07:00
end
end
-- Jokes: Appear when machine exchanges currency for currency at equal rate
-- Vendor
local jokes_vendor = {
2019-03-19 04:36:21 -07:00
S("Thank you. You have made a vending machine very happy."),
S("Humans have a strange sense of humor."),
S("Lets get this over with …"),
S("Item “bought”."),
S("Tit for tat."),
S("Do you realize what youve just bought?"),
}
-- Depositor
local jokes_depositor = {
2019-03-19 04:36:21 -07:00
S("Thank you, the money started to smell inside."),
S("Money doesnt grow on trees, you know?"),
S("Sanity sold."),
S("Well, that was an awkward exchange."),
S("Are you having fun?"),
S("Is this really trading?"),
}
easyvend.assign_joke = function(buysell)
local jokes
if buysell == "sell" then
jokes = jokes_vendor
elseif buysell == "buy" then
jokes = jokes_depositor
end
local r = math.random(1,#jokes)
return r
end
easyvend.get_joke = function(buysell, id)
2016-09-06 06:13:46 -07:00
local joke
if buysell == nil or id == nil then
-- Fallback message (should never happen)
2019-03-19 04:36:21 -07:00
return S("Items exchanged.")
end
if buysell == "sell" then
joke = jokes_vendor[id]
if joke == nil then joke = jokes_vendor[1] end
elseif buysell == "buy" then
joke = jokes_depositor[id]
if joke == nil then joke = jokes_depositor[1] end
end
return joke
end
2016-09-01 13:01:39 -07:00
easyvend.sound_error = function(playername)
2020-04-05 15:45:11 -07:00
minetest.sound_play("easyvend_error", {to_player = playername, gain = 0.25}, true)
2016-09-01 13:01:39 -07:00
end
2016-09-01 21:42:43 -07:00
easyvend.sound_setup = function(pos)
2020-04-05 15:45:11 -07:00
minetest.sound_play("easyvend_activate", {pos = pos, gain = 0.5, max_hear_distance = 12,}, true)
end
easyvend.sound_disable = function(pos)
2020-04-05 15:45:11 -07:00
minetest.sound_play("easyvend_disable", {pos = pos, gain = 0.9, max_hear_distance = 12,}, true)
end
easyvend.sound_vend = function(pos)
2020-04-05 15:45:11 -07:00
minetest.sound_play("easyvend_vend", {pos = pos, gain = 0.4, max_hear_distance = 5,}, true)
2012-09-12 14:55:10 -07:00
end
2016-09-01 12:56:09 -07:00
easyvend.sound_deposit = function(pos)
2020-04-05 15:45:11 -07:00
minetest.sound_play("easyvend_deposit", {pos = pos, gain = 0.4, max_hear_distance = 5,}, true)
2016-09-01 12:35:50 -07:00
end
2012-09-12 14:55:10 -07:00
--[[ Tower building ]]
easyvend.is_traversable = function(pos)
local node = minetest.get_node_or_nil(pos)
if (node == nil) then
return false
end
return traversable_node_types[node.name] == true
end
easyvend.neighboring_nodes = function(pos)
local check = {
{x=pos.x, y=pos.y-1, z=pos.z},
2016-09-09 16:07:39 -07:00
{x=pos.x, y=pos.y+1, z=pos.z},
}
local trav = {}
for i=1,#check do
if easyvend.is_traversable(check[i]) then
2016-09-09 16:07:39 -07:00
table.insert(trav, check[i])
end
end
return trav
end
2016-09-14 15:04:38 -07:00
easyvend.find_connected_chest = function(owner, pos, nodename, check_wear, amount, removing)
local nodes = easyvend.neighboring_nodes(pos)
if (#nodes < 1 or #nodes > 2) then
2016-09-13 06:17:48 -07:00
return nil, "no_chest"
end
-- Find the stack direction
local first = nil
local second = nil
for i=1,#nodes do
if ( first == nil ) then
first = nodes[i]
else
second = nodes[i]
end
end
2016-09-13 06:17:48 -07:00
local chest_pos, chest_internal
if (first ~= nil and second ~= nil) then
local dy = (first.y - second.y)/2
2016-09-14 15:04:38 -07:00
chest_pos, chest_internal = easyvend.find_chest(owner, pos, dy, nodename, check_wear, amount, removing)
if ( chest_pos == nil ) then
2016-09-14 15:04:38 -07:00
chest_pos, chest_internal = easyvend.find_chest(owner, pos, -dy, nodename, check_wear, amount, removing, chest_internal)
end
else
local dy = first.y - pos.y
2016-09-14 15:04:38 -07:00
chest_pos, chest_internal = easyvend.find_chest(owner, pos, dy, nodename, check_wear, amount, removing)
2016-09-13 06:17:48 -07:00
end
2016-09-14 14:28:40 -07:00
if chest_internal.chests == 0 then
return nil, "no_chest"
elseif chest_internal.chests == chest_internal.other_chests then
return nil, "not_owned"
elseif removing and chest_internal.stock < 1 then
2016-09-14 14:28:40 -07:00
return nil, "no_stock"
elseif not removing and chest_internal.space < 1 then
2016-09-14 14:28:40 -07:00
return nil, "no_space"
elseif chest_pos ~= nil then
2016-09-13 06:17:48 -07:00
return chest_pos
2016-09-14 14:28:40 -07:00
else
return nil, "unknown"
end
end
2016-09-14 15:04:38 -07:00
easyvend.find_chest = function(owner, pos, dy, itemname, check_wear, amount, removing, internal)
2016-09-09 16:07:39 -07:00
pos = {x=pos.x, y=pos.y + dy, z=pos.z}
2016-09-13 06:17:48 -07:00
if internal == nil then
internal = {}
internal.chests = 0
internal.other_chests = 0
internal.stock = 0
internal.space = 0
end
local node = minetest.get_node_or_nil(pos)
if ( node == nil ) then
2016-09-13 06:17:48 -07:00
return nil, internal
end
local chestdef = registered_chests[node.name]
if (chestdef ~= nil) then
2016-09-13 06:17:48 -07:00
internal.chests = internal.chests + 1
local meta = minetest.get_meta(pos)
2016-09-13 06:17:48 -07:00
if (owner ~= meta:get_string(chestdef.meta_owner)) then
internal.other_chests = internal.other_chests + 1
return nil, internal
end
local inv = meta:get_inventory()
if (inv ~= nil) then
2017-01-12 06:27:54 -08:00
if (itemname ~= nil and minetest.registered_items[itemname] and amount ~= nil and removing ~= nil and check_wear ~= nil) then
2016-09-14 13:02:39 -07:00
local chest_has, chest_free
local stack = {name=itemname, count=amount, wear=0, metadata=""}
local stack_max = minetest.registered_items[itemname].stack_max
local stacks = math.modf(amount / stack_max)
local stacksremainder = math.fmod(amount, stack_max)
local free = stacks
if stacksremainder > 0 then free = free + 1 end
2016-09-14 14:28:40 -07:00
chest_has = easyvend.check_and_get_items(inv, chestdef.inv_list, stack, check_wear)
2016-09-14 16:44:35 -07:00
if chest_has then
2016-09-14 14:28:40 -07:00
internal.stock = internal.stock + 1
end
2016-09-14 17:17:47 -07:00
chest_free = inv:room_for_item(chestdef.inv_list, stack) and easyvend.free_slots(inv, chestdef.inv_list) >= free
2016-09-14 16:44:35 -07:00
if chest_free then
2016-09-14 14:28:40 -07:00
internal.space = internal.space + 1
end
2016-09-14 13:02:39 -07:00
if (removing and internal.stock == 0) or (not removing and internal.space == 0) then
2016-09-14 15:28:18 -07:00
return easyvend.find_chest(owner, pos, dy, itemname, check_wear, amount, removing, internal)
else
return pos, internal
end
2017-01-12 06:27:54 -08:00
else
return nil, internal
end
2017-01-12 06:27:54 -08:00
else
return nil, internal
end
2018-05-14 13:04:45 -07:00
elseif not easyvend.is_machine(node.name) then
2016-09-13 06:17:48 -07:00
return nil, internal
end
2016-09-14 15:04:38 -07:00
return easyvend.find_chest(owner, pos, dy, itemname, check_wear, amount, removing, internal)
end
-- Pseudo-inventory handling
2016-09-01 12:56:09 -07:00
easyvend.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
2016-09-14 16:44:35 -07:00
if listname=="item" then
local meta = minetest.get_meta(pos);
local owner = meta:get_string("owner")
local name = player:get_player_name()
if name == owner then
local inv = meta:get_inventory()
2018-05-14 13:04:45 -07:00
if stack == nil then
2016-09-14 16:44:35 -07:00
inv:set_stack( "item", 1, nil )
else
inv:set_stack( "item", 1, stack:get_name() )
meta:set_string("itemname", stack:get_name())
easyvend.set_formspec(pos, player)
end
end
end
return 0
end
2012-09-12 14:55:10 -07:00
2016-09-01 12:56:09 -07:00
easyvend.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
return 0
2012-09-12 14:55:10 -07:00
end
2016-09-01 12:56:09 -07:00
easyvend.allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return 0
2014-11-22 15:19:44 -08:00
end
minetest.register_abm({
nodenames = {"easyvend:vendor", "easyvend:vendor_on", "easyvend:depositor", "easyvend:depositor_on"},
interval = 5,
chance = 1,
catch_up = false,
action = function(pos, node, active_object_count, active_object_count_wider)
easyvend.machine_check(pos, node)
end
})
2016-09-09 12:05:25 -07:00
-- Legacy support for vendor mod:
-- Transform the world and items to use the easyvend nodes/items
-- For safety reasons, only do this when player requested so
2019-03-20 00:52:44 -07:00
if minetest.settings:get_bool("easyvend_convert_vendor") == true then
2016-09-09 12:05:25 -07:00
-- Replace vendor nodes
minetest.register_lbm({
name = "easyvend:replace_vendor",
nodenames = { "vendor:vendor", "vendor:depositor" },
run_at_every_load = true,
action = function(pos, node)
-- Replace node
2016-09-09 12:05:25 -07:00
local newnodename
if node.name == "vendor:vendor" then
newnodename = "easyvend:vendor"
elseif node.name == "vendor:depositor" then
newnodename = "easyvend:depositor"
end
2016-09-09 13:42:15 -07:00
-- Remove axis rotation; only allow 4 facedirs
local p2 = math.fmod(node.param2, 4)
minetest.swap_node(pos, { name = newnodename, param2 = p2 })
-- Initialize metadata
local meta = minetest.get_meta(pos)
2016-11-02 12:05:40 -07:00
if node.name == "vendor:vendor" then
meta:set_int("earnings", 0)
end
2016-09-09 12:05:25 -07:00
meta:set_int("stock", -1)
meta:set_int("joketimer", -1)
meta:set_int("joke_id", 1)
local inv = meta:get_inventory()
inv:set_size("item", 1)
inv:set_size("gold", 1)
inv:set_stack("gold", 1, easyvend.currency)
-- In vendor, all machines accepted worn tools
meta:set_int("wear", 1)
-- Set item
2016-09-09 12:05:25 -07:00
local itemname = meta:get_string("itemname")
if itemname == "" or itemname == nil then
itemname = meta:get_string("itemtype")
end
if itemname ~= "" and itemname ~= nil then
inv:set_stack("item", 1, itemname)
meta:set_string("itemname", itemname)
end
-- Check for valid item, item count and price
2016-09-09 14:17:49 -07:00
local configmode = 1
2016-09-09 12:05:25 -07:00
if itemname ~= "" and itemname ~= nil then
local itemstack = inv:get_stack("item", 1)
local number_stack_max = itemstack:get_stack_max()
local maxnumber = number_stack_max * slots_max
local cost = meta:get_int("cost")
local number = meta:get_int("number")
if number >= 1 and number <= maxnumber and cost >= 1 and cost <= maxcost then
2016-09-09 14:17:49 -07:00
-- Everything's OK, get out of config mode!
2016-09-09 12:05:25 -07:00
configmode = 0
end
end
-- Final initialization stuff
meta:set_int("configmode", configmode)
2016-09-09 12:05:25 -07:00
local owner = meta:get_string("owner")
if easyvend.buysell(newnodename) == "sell" then
2019-03-19 04:36:21 -07:00
meta:set_string("infotext", S("Vending machine (owned by @1)", owner))
2016-09-09 12:05:25 -07:00
else
2019-03-19 04:36:21 -07:00
meta:set_string("infotext", S("Depositing machine (owned by @1)", owner))
2016-09-09 12:05:25 -07:00
end
2019-03-19 04:36:21 -07:00
meta:set_string("status", S("Initializing …"))
meta:set_string("message", S("Upgrade successful."))
2016-09-09 12:05:25 -07:00
easyvend.machine_check(pos, node)
end,
})
end