Juraj Vajda 2018-10-13 19:19:42 -04:00
commit c7f0feb86d
5 changed files with 166 additions and 23 deletions

37
API.md Normal file
View File

@ -0,0 +1,37 @@
# Easyvend API
Use this API if you want to make an container compatible with vending and
depositing machines.
## How it works
* Add `easyvend` as optional dependency
* Check for existence of `easyvend` mod in code
* Call `easyvend.register_chest` for all containers you want to be compatible
## `easyvend.register_chest = function(node_name, inv_list, meta_owner)`
Registers a node (called “chest”) for use with Easyvend. After calling this function,
the node will be recognized as storage for vending and depositing machines.
Easyvend makes the following assumptions about the chest:
* It has an inventory
* The inventory does not restrict the types of items you can put and take
* The chest is owned by a player
* The owner is specified in metadata
### Parameters
* `node_name`: Name of the chest node
* `inv_list`: Name of the inventory list for exchanging items
* `meta_owner`: Identifier of the metadata variable storing the owner name
### Example
Register the node `example:superchest` as container:
```
if minetest.get_modpath("easyvend") then
easyvend.register_chest("example:superchest", "main", "owner")
end
```
The `if` check is a common trick to check for the existence of the `easyvend`
and allows you to make the dependency optional.

View File

@ -1,11 +1,48 @@
# Easy Vending Machines [`easyvend`]
Version: 0.4.3
Adds vending and depositing machines which allow to buy and sell items from other players.
Adds vending and depositing machines which allow to buy and sell items from
other players, using a currency item.
Help is included as help entry for Item Documentation [`doc_items`].
## Requirements
Runs natively in Minetest Game.
## Converting machines from `vendor` mod (experimental)
May also run in other games if they have the `default` mod and locked chest
(`default:chest_locked`).
Locked chests from other mods are not supported, but mods can choose
to add support for Easyvend on their own (see developer information below).
You can optionally add the `select_item` mod. This adds a button to select
an item from a list of items.
This feature is very useful for depositing machines because you can select
any item, not just those you have already in your inventory.
## How to use
Help is also included as help entry for Item Documentation [`doc_items`].
### Summary
Vending machines TAKE currency (gold ingots by default) and GIVE items
of the owner's choice.
Depositing machines GIVE currency and TAKE items of the owner's choice.
To operate your own machine, place a locked chest above or below and fill
it with items to exchange. If the green status LED (the upper one) lights
up, the machine is operational. You can stack these locked chests for
extended storage.
### Currency item
The currency of all machines is gold ingots by default.
But it can be changed via the setting `easyvend_currency`.
## Appendix
### Developer information
If you want to a container node compatible with vending/depositing machines,
use the Easyvend API, see the file `API.md`.
### Converting machines from `vendor` mod (experimental)
This mod is able to automatically transform the vending and depositing
machines from Bad\_Command\_'s Vending machines [`vendor`] mod on loading
and turn them into the new machines from `easyvend`. This is useful if
@ -15,7 +52,7 @@ you want to switch a world from `vendor` to `easyvend`.
before doing this. This feature is also incomplete; items are currently
**not** transformed in the process.
### Conversion process
#### Conversion process
To transform all nodes from the `vendor` mod, disable the `vendor` mod (if
it is not already disabled), enable the setting `easyvend_convert_vendor`
and start or restart the game.
@ -25,7 +62,7 @@ Now all nodes from the `vendor` mod will be replaced with `easyvend` ones.
If you run a server, you should inform players of this change because a few
machines might need a reconfiguration.
### Details
#### Details
The machine configuration will be kept in the process and the machines will
stay in operation provided their configuration is valid. The mod tries to
keep as many machines in operation as possible. Machines with very high values
@ -33,7 +70,7 @@ keep as many machines in operation as possible. Machines with very high values
be reconfigured by their owners. Most machines which worked before will likely
stay in operation afterwards.
## Credits and licenses
### Credits and licenses
- Code
- License: [LGPL 2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)
- Source: Forked from mod “Vending Machines” [vendor] by Bad\_Command\_.

View File

@ -1,5 +1,6 @@
default
default?
screwdriver?
select_item?
doc?
doc_items?
awards?

View File

@ -13,12 +13,48 @@ local maxcost = cost_stack_max * slots_max
local joketimer_start = 3
local active_item_selection = {}
-- 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
end
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.
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
return
end
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
end
end
active_item_selection[playername] = nil
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.
@ -76,6 +112,10 @@ easyvend.buysell = function(nodename)
return buysell
end
easyvend.is_machine = function(nodename)
return ( nodename == "easyvend:depositor_on" or nodename == "easyvend:vendor_on" or nodename == "easyvend:depositor" or nodename == "easyvend:vendor" )
end
easyvend.is_active = function(nodename)
if ( nodename == "easyvend:depositor_on" or nodename == "easyvend:vendor_on" ) then
return true
@ -138,12 +178,6 @@ easyvend.set_formspec = function(pos, player)
.."label[0,-0.15;"..numbertext.."]"
.."label[0,1.2;"..costtext.."]"
.."list[current_player;main;0,3.5;8,4;]"
if minetest.get_modpath("doc") and minetest.get_modpath("doc_items") then
if (doc.VERSION.MAJOR >= 1) or (doc.VERSION.MAJOR == 0 and doc.VERSION.MINOR >= 8) then
formspec = formspec .. "image_button[7.25,2;0.75,0.75;doc_button_icon_lores.png;doc;]" ..
"tooltip[doc;Help]"
end
end
if configmode then
local wear = "false"
@ -159,6 +193,9 @@ easyvend.set_formspec = function(pos, player)
.."tooltip[cost;"..itemcounttooltip.."]"
.."button[6,2.8;2,0.5;save;Confirm]"
.."tooltip[save;Confirm configuration and activate machine (only for owner)]"
if minetest.get_modpath("select_item") then
formspec = formspec .. "button[0,2.8;2,0.5;select_item;Select item]"
end
local weartext, weartooltip
if buysell == "buy" then
weartext = "Buy worn tools"
@ -194,9 +231,9 @@ easyvend.set_formspec = function(pos, player)
end
else
if buysell == "sell" then
weartext = "Warning: Might sell worn tools."
weartext = "Note: Might sell worn tools."
else
weartext = "Worn tools are bought, too."
weartext = "Accepts worn tools."
end
end
if weartext ~= nil then
@ -396,8 +433,7 @@ easyvend.on_receive_fields_config = function(pos, formname, fields, sender)
--[[ Convenience function:
When appending s or S to the number, it is multiplied
by the maximum stack size.
TODO: Expose this in user documentation ]]
by the maximum stack size. ]]
local number_stack_max = itemstack:get_stack_max()
local ss = string.sub(number, #number, #number)
if ss == "s" or ss == "S" then
@ -430,6 +466,12 @@ easyvend.on_receive_fields_config = function(pos, formname, fields, sender)
easyvend.sound_error(sender:get_player_name())
easyvend.set_formspec(pos, sender)
return
elseif ( not itemstack:is_known() ) then
meta:set_string("status", "Awaiting configuration by owner.")
meta:set_string("message", "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
if maxnumber > 1 then
meta:set_string("message", string.format("Invalid item count; must be between 1 and %d!", maxnumber))
@ -891,7 +933,7 @@ easyvend.after_place_node = function(pos, placer)
end
meta:set_string("infotext", d)
meta:set_string("status", "Awaiting configuration by owner.")
meta:set_string("message", "Welcome! Please prepare the machine.")
meta:set_string("message", "Please select an item and amount, then confirm.")
meta:set_int("number", 1)
meta:set_int("cost", 1)
meta:set_int("stock", -1)
@ -949,7 +991,7 @@ easyvend.on_receive_fields = function(pos, formname, fields, sender)
end
end
elseif fields.config or fields.save or fields.usermode then
if sender:get_player_name() == owner then
if sendername == owner then
easyvend.on_receive_fields_config(pos, formname, fields, sender)
else
meta:set_string("message", "Only the owner may change the configuration.")
@ -957,6 +999,18 @@ easyvend.on_receive_fields = function(pos, formname, fields, sender)
easyvend.set_formspec(pos, sender)
return
end
elseif fields.select_item then
if minetest.get_modpath("select_item") then
if sendername == owner then
active_item_selection[sendername] = pos
select_item.show_dialog(sendername, "easyvend:trade_item", select_item.filters.creative)
else
meta:set_string("message", "Only the owner may change the configuration.")
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
@ -1180,7 +1234,7 @@ easyvend.find_chest = function(owner, pos, dy, itemname, check_wear, amount, rem
else
return nil, internal
end
elseif (node.name ~= "easyvend:vendor" and node.name~="easyvend:depositor" and node.name~="easyvend:vendor_on" and node.name~="easyvend:depositor_on") then
elseif not easyvend.is_machine(node.name) then
return nil, internal
end
@ -1195,7 +1249,7 @@ easyvend.allow_metadata_inventory_put = function(pos, listname, index, stack, pl
local name = player:get_player_name()
if name == owner then
local inv = meta:get_inventory()
if stack==nil then
if stack == nil then
inv:set_stack( "item", 1, nil )
else
inv:set_stack( "item", 1, stack:get_name() )

View File

@ -88,7 +88,15 @@ vendor_on.drop = "easyvend:vendor"
local vendor_off = table.copy(machine_template)
vendor_off.description = vendor_on.description
vendor_off._doc_items_longdesc = string.format("A vending machine allows its owner to offer a certain item in exchange for money (%s). The users can pay with money and will some items in return.", easyvend.currency_desc)
vendor_off._doc_items_usagehelp = "For customers: The vending machine has to be ready to be used, which is the case if the green LED lights up. Point the vending machine to see its owner and what it has to offer and at which price (item count first). Rightclick it to open the buying menu. You can pay with the number of items shown at “Price” and you will get the item at “Offered item” in return. Click on “Buy” to buy this offer once, repeat this as often as you like.\nFor owners: First, place a locked chest and fill it with the item you want to sell, make sure you leave some inventory slots empty for the price. Place the vending machine above or below the locked chest. Any locked chest connected in a unbroken vertical line of locked chests, vending machines and depositing machines will be accessed as storage. Rightclick the machine. Set the offered item by moving an item from your invenory into the slot. The price item can not be changed. Now set the number of items per sale and their price and click on “Confirm” to confirm. Check the message and status for any errors. If the status is “Ready.”, the machine works properly. All other status messages are errors. The earnings of the vending machine can be retrieved from the locked chest."
vendor_off._doc_items_usagehelp = [[For customers:
Only if the upper green status LED lights up, the machine is ready for use. Point to see its owner and offer. Rightclick to open the buying menu. You can pay with the number of items shown at Price and you will get the item at Offered item in return. Click on Buy to buy this offer once.
For owners:
First, place a locked chest and fill it with the item you want to sell, make sure you leave some inventory slots empty for the price. Place the vending machine above or below the locked chest. Any locked chest connected in a unbroken vertical line of locked chests and vending/depositing machines will be accessed as storage.
Rightclick the machine. Set the offered item by moving an item from your invenory into the slot. The price item can not be changed. Now set the number of items per sale and their price and click on Confirm to confirm. If the upper green status LED lights up, you're done, if not, check the message.
The earnings will go into the locked chest.
Hint: If you enter an s after the item number, it will be multiplied with the maximum stack size.]]
vendor_off.tiles = table.copy(vendor_on.tiles)
vendor_off.tiles[6] = "easyvend_vendor_front_off.png"
@ -103,7 +111,13 @@ depositor_on.drop = "easyvend:depositor"
local depositor_off = table.copy(machine_template)
depositor_off.description = depositor_on.description
depositor_off._doc_items_longdesc = string.format("A depositing machine allows its owner to offer money (%s) in exchange for a certain item. The users can supply the depositing machine with the requested item and will get money in return.", easyvend.currency_desc)
depositor_off._doc_items_usagehelp = "For users: The depositing machine has to be ready to be used, which is the case if the green LED lights up. Point the depositing machine to see its owner and what item it asks for and at which payment (item count first). Rightclick it to open the selling menu. You can give the number of items shown at “Requested item” and you will get the items at “Payment” in return. Click on “Sell” to exchange items, repeat this as often as you like.\nFor owners: First, place a locked chest and supply it with the payment item, make sure you leave some inventory slots empty for the items you want to retrieve. Place the depositing machine above or below the locked chest. Any chest connected in a unbroken vertical stack of locked chests, vending machines and depositing machines will be accessed as storage. Rightclick the machine. Set the requested item by moving an item from your invenory into the slot. The payment item can not be changed. Now set the number of requested items and how much you pay for them and click on “Confirm” to confirm. Check the message and status for any errors. If the status is “Ready.”, the machine works properly, all other status messages are errors. The deposited items can be retrieved from the locked chest."
depositor_off._doc_items_usagehelp = [[For users:
To use a machine, check if its ready (the upper green LED lights up). Point the depositing machine to see its owner and the offer. Rightclick for the selling menu. You can give the number of items shown at Requested item and you will get the items at Payment in return. Click on Sell to exchange items, repeat this as often as you like.
For owners:
First, place a locked chest and supply it with the payment item, make sure you leave some inventory slots empty for the items you want to retrieve. Place the machine above or below the chest. Any chest connected in a unbroken vertical stack of locked chests and vending/depositing machines will be accessed.
Rightclick the machine. Set the requested item by moving an item from your inventory into the slot. The payment item can not be changed. Now set the number of requested items and your payment and click on Confirm to confirm. If the upper green LED lights up, everything works fine, otherwise, check the message. The deposited items will end up in the chest.
Hint: If you enter an s after the item number, it will be multiplied with the maximum stack size.]]
depositor_off.tiles = table.copy(depositor_on.tiles)
depositor_off.tiles[6] = "easyvend_depositor_front_off.png"