emeraldbank mod now focuses only on the bank and the economy API
The shops will be separated in another mod
14
LICENSE.txt
@ -15,20 +15,6 @@ You should have received a copy of the GNU Affero General Public License
|
|||||||
along with Emeraldbank. If not, see <https://www.gnu.org/licenses/>.
|
along with Emeraldbank. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
Textures License:
|
|
||||||
|
|
||||||
admin_depo.png
|
|
||||||
admin_vend.png
|
|
||||||
copier.png
|
|
||||||
inactive.png
|
|
||||||
player_depo.png
|
|
||||||
player_vend_front.png
|
|
||||||
player_vend.png
|
|
||||||
upgrade_front.png
|
|
||||||
|
|
||||||
Copyright (c) 2018 ChimneySwift, LadyK under MIT License
|
|
||||||
|
|
||||||
|
|
||||||
Sounds License:
|
Sounds License:
|
||||||
|
|
||||||
- cash.ogg:
|
- cash.ogg:
|
||||||
|
176
README.md
@ -1,4 +1,5 @@
|
|||||||
# Emerald Bank and Shops (MineClonia/MineClone2)
|
|
||||||
|
# Emerald Bank and Shops (MineClonia)
|
||||||
|
|
||||||
[![ContentDB](https://content.minetest.net/packages/NathanielFreeman/emeraldbank/shields/downloads/)](https://content.minetest.net/packages/NathanielFreeman/emeraldbank/)
|
[![ContentDB](https://content.minetest.net/packages/NathanielFreeman/emeraldbank/shields/downloads/)](https://content.minetest.net/packages/NathanielFreeman/emeraldbank/)
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ EmeraldBank Mod is [Libre/Free Software](https://www.gnu.org/philosophy/free-sw.
|
|||||||
|
|
||||||
Keep your Emeralds in a bank!
|
Keep your Emeralds in a bank!
|
||||||
|
|
||||||
Why Emeralds? In MineClonia/MineClone2 the emerald is money to trade with villagers!
|
Why Emeralds? In MineClonia the emerald is money to trade with villagers!
|
||||||
|
|
||||||
Multiplayer support!
|
Multiplayer support!
|
||||||
|
|
||||||
@ -26,151 +27,7 @@ Rightclick on bank open the bank interface, where you can deposit or withdraw yo
|
|||||||
|
|
||||||
You can transfer money to other players in Bank interface.
|
You can transfer money to other players in Bank interface.
|
||||||
|
|
||||||
## Shops (Like fancy_vend mod)
|
## Commands
|
||||||
|
|
||||||
The new shops are based in _fancy_vend_ mod shops
|
|
||||||
|
|
||||||
[Learn more about shops here](https://github.com/ChimneySwift/fancy_vend/blob/master/README.md)
|
|
||||||
|
|
||||||
There are many vendor mods for Minetest, but most have too few options, lack support for automation mods, or are too tedious to set up and maintain. Fancy vendors are entirely self-contained nodes which provide light, trade, display and store items. Fancy vendors are _pipeworks_, _digilines_ and _mcl_awards_ compatible, enabling a variety of automation-based features.
|
|
||||||
|
|
||||||
### Basic configuration
|
|
||||||
|
|
||||||
Each fancy vendor needs 2 nodes of room. If the area you wish to place the vendor doesn't have enough space, due to either a node or a protected area, the node will not be placed. If the vendor has sufficient room, it will place a vendor node in addition to a display node on top. The display node's only purpose is aesthetics, to "contain" the rotating display object.
|
|
||||||
|
|
||||||
Configuring a vendor is as simple as picking up and placing the input and output items into their respective slots as if they were regular inventories (items in these inventories are "ghosts", so don't actually take anything from the player's inventory) and setting the quantities for each item, as shown below:
|
|
||||||
|
|
||||||
![Setting up a vendor](https://github.com/ChimneySwift/fancy_vend/blob/master/screenshots/Setting%20up%20a%20vendor.PNG?raw=true "Setting up a vendor")
|
|
||||||
|
|
||||||
Stocking a vendor is as simple as placing the output item into the vendor's inventory (perhaps using one of the handy inventory movement buttons) as demonstrated below:
|
|
||||||
|
|
||||||
![Stocking a vendor](https://github.com/ChimneySwift/fancy_vend/blob/master/screenshots/Stocking%20a%20vendor.PNG?raw=true "Stocking a vendor")
|
|
||||||
|
|
||||||
After stocking a vendor, you may wish to press the "sort" button, which will combine unfilled stacks and sort the stacks in alphabetical order.
|
|
||||||
|
|
||||||
If the vendor is intended to be used to purchase items, you may wish to set the vendor to a depositor in the vendor settings, this will display the input item in the display case and change the vendor's appearance to make it clear to potential sellers the vendor's purpose. The previous example vendor set to a depositor can be seen below:
|
|
||||||
|
|
||||||
![A player depositor](https://github.com/ChimneySwift/fancy_vend/blob/master/screenshots/A%20player%20depositor.PNG?raw=true "A player depositor")
|
|
||||||
|
|
||||||
### Buying items
|
|
||||||
Regular players who can't access a fancy vendor's inventory or configuration will be displayed a purchase screen when they access a vendor. This screen displays vendor information and status, as well as buying options. Unlike many vendor mods, fancy vendors give buyers to buy multiple "lots" at once. Doing this can save a lot of clicking, as the number of input and output items traded is multiplied by this number.
|
|
||||||
|
|
||||||
There is also a button labeled "Fill lots to max" which will pre-load the lots field with the maximum number of lots that the player can purchase from the vendor (which will be either the maximum the player can afford, or the maximum the shop can sell, whichever is smaller).
|
|
||||||
|
|
||||||
An example image of the buyer formspec can be seen below:
|
|
||||||
|
|
||||||
![Buying from a fancy vendor](https://github.com/ChimneySwift/fancy_vend/blob/master/screenshots/Buying%20from%20a%20fancy%20vendor.PNG?raw=true "Buying from a fancy vendor")
|
|
||||||
|
|
||||||
### Advanced settings
|
|
||||||
Fancy vendors have many additional options which enable sellers to greatly customize vendors.
|
|
||||||
|
|
||||||
![Fancy Vendor settings](https://github.com/ChimneySwift/fancy_vend/blob/master/screenshots/Fancy%20Vendor%20settings.PNG?raw=true "Fancy Vendor settings")
|
|
||||||
|
|
||||||
**Banned Buyers:**
|
|
||||||
This field is a list of players (separated by commas) who won't be able to purchase from the vendor. This setting might be useful if you wish to stop players buying out your vendor's stock and reselling it for a higher margin.
|
|
||||||
|
|
||||||
**Co-Sellers:**
|
|
||||||
This field is a list of players (separated by commas) who will be able to access the vendor's inventory. **Please note: Anyone added to the list has full access to the vendor's inventory, however cannot modify the vendor settings nor dig the vendor.**
|
|
||||||
|
|
||||||
**Buy/sell worn tools:**
|
|
||||||
These options allow for the seller to stop the vendor from purchasing or selling worn tools. A message will display on the buyer formspec if one of these options is disabled.
|
|
||||||
|
|
||||||
**Inactive force:**
|
|
||||||
While the seller is reconfiguring a vendor, or in the process of creating a shop, the owner might wish for the vendor to be inactive so players cannot purchase from it, in which case they can enable this option.
|
|
||||||
|
|
||||||
**Autosort:**
|
|
||||||
If this option is enabled, the vendor's inventory will automatically sort when the vendor formspec is closed by someone who can access the inventory.
|
|
||||||
|
|
||||||
**Logs:**
|
|
||||||
The logs formspec displays the 40 most-recent transactions. While only people who can modify the vendor are allowed to access this formspec, these logs are kept in metadata which could be easily read client-side.
|
|
||||||
|
|
||||||
**Geminio Wand:**
|
|
||||||
This tool can be used to easily copy vendor settings from one vendor to another. Simply right click a vendor with it to copy the settings to the tool, and left click any other vendor to set that vendor's settings. **The Geminio Wand will not copy input and output items nor quantities.** You must be able to modify the settings of the vendor to do this. You can craft one with the following recipe:
|
|
||||||
|
|
||||||
![Crafting a Geminio Wand](https://github.com/ChimneySwift/fancy_vend/blob/master/screenshots/Crafting%20a%20Geminio%20Wand.PNG?raw=true "Crafting a Geminio Wand")
|
|
||||||
|
|
||||||
### Automation
|
|
||||||
Fancy Vendors are digilines and pipeworks compatible, enabling the creation of highly automated shops.
|
|
||||||
|
|
||||||
#### Pipeworks
|
|
||||||
Fancy vendors connect to pipeworks devices from the bottom, rear and sides. When the optional pipeworks dependancy is satisfied, a number of pipeworks-specific options will also appear in the settings menu:
|
|
||||||
|
|
||||||
![Pipeworks Settings](https://github.com/ChimneySwift/fancy_vend/blob/master/screenshots/Pipeworks%20Settings.PNG?raw=true "Pipeworks Settings")
|
|
||||||
|
|
||||||
**Split incoming stacks:**
|
|
||||||
This option enabled incoming stacks from pipeworks tubes to be split if only some of the stack can be accepted.
|
|
||||||
|
|
||||||
**Eject incoming currency:**
|
|
||||||
When this option is enabled, the input items will be sent out of the **bottom** of the fancy vendor instead of being added to the vendor's internal inventory.
|
|
||||||
|
|
||||||
**Accept output only:**
|
|
||||||
When this option is enabled, incoming items which aren't the output item will be rejected and not added to the vendor's inventory.
|
|
||||||
|
|
||||||
#### Hoppers
|
|
||||||
Fancy vendors are MCL hopper compatible. Also they have been tested to work with [TenPlus1's hopper mod](https://github.com/tenplus1/hopper) however should work with all hopper mods and forks. Hoppers can filter into vendors from the sides, however cannot be drained from the bottom as hoppers are protected and Fancy Vendors are locked. However, the shop owner is given the `Eject incoming currency` option which operates on hoppers similarly to how it does on pipeworks, by manually adding incoming currency to the inventory of a hopper placed below the vendor (or into the vendor's inventory if the hopper is full). Due to API limitations, `Accept output only` is not hopper-compatible and `Split incoming stacks` is not necessary.
|
|
||||||
|
|
||||||
#### Digilines
|
|
||||||
Fancy vendors are digilines compatible. When the digilines dependency is satisfied, an option to set the digiline channel will appear in settings. If this channel is set, every purchase will result in the following table being sent over that channel:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
local msg = {
|
|
||||||
buyer = player:get_player_name(), -- Purchaser's playername
|
|
||||||
lots = lots, -- Number of lots purchased
|
|
||||||
settings = settings, -- The settings table
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The default settings table can be seen below:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
local settings_default = {
|
|
||||||
input_item = "",
|
|
||||||
output_item = "",
|
|
||||||
input_item_qty = 1,
|
|
||||||
output_item_qty = 1,
|
|
||||||
admin_vendor = false,
|
|
||||||
depositor = false,
|
|
||||||
currency_eject = false,
|
|
||||||
accept_output_only = false,
|
|
||||||
split_incoming_stacks = false,
|
|
||||||
inactive_force = false,
|
|
||||||
accept_worn_input = true,
|
|
||||||
accept_worn_output = true,
|
|
||||||
digiline_channel = "",
|
|
||||||
co_sellers = "",
|
|
||||||
banned_buyers = "",
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Fancy Vendors and Fancy Vendor Display Nodes conduct digiline signals also.
|
|
||||||
|
|
||||||
This feature could theoretically make rewards-based shops feasable.
|
|
||||||
|
|
||||||
### Out Of Stock Mail
|
|
||||||
This mod integrates with [Athous Mail Mod](https://github.com/mt-mods/mail) to alert shop owners when their shops lose stock.
|
|
||||||
When a vendor empties, the mod sends mail telling them that their vendor is out of stock. In the event another mod empties, the previous message will be edited so as to avoid flooding their inbox if they have many vendors.
|
|
||||||
|
|
||||||
### Upgrading vendors
|
|
||||||
|
|
||||||
**NOTE:** If you wish to simply run this mod in parallel with existing vendor mods, simply load this mod (no configuration required)
|
|
||||||
|
|
||||||
Many servers already have vendor mods in place. Fancy Vend makes it easier for servers to upgrade with it's unique upgrading system. Fancy Vend will replace vendors from the supported vendor mods (money, vendor, easyvend and currency) with upgrade nodes. Upgrade nodes allow for sellers to empty the old node's inventory (if applicable), dig the upgrade node (which will drop a regular vendor) and set up a new shop. if a user tried to place an upgrade node, the stack is turned into a stack of regular vendors.
|
|
||||||
|
|
||||||
Since upgrade functionality can be achieved without the old mod loaded, the server owner must add the old vendor mod's name to `minetest.conf` as follows:
|
|
||||||
|
|
||||||
`fancy_vend_old_vendor_mods = money`
|
|
||||||
|
|
||||||
If there are multiple vendor mods the the owner wishes to enable this functionality on, they can add several mods to the list, separating each mod name with commas as follows:
|
|
||||||
|
|
||||||
`fancy_vend_old_vendor_mods = emeraldbank,money,vendor,easyvend`
|
|
||||||
|
|
||||||
If the owner wishes to keep the mod loaded, but still replace vendor nodes, the will need to add the mod to both `minetest.conf` and `mod.conf`.
|
|
||||||
|
|
||||||
Vendor upgrade:
|
|
||||||
|
|
||||||
![Vendor upgrade](https://github.com/ChimneySwift/fancy_vend/blob/master/screenshots/Vendor%20upgrade.PNG?raw=true "Vendor upgrade")
|
|
||||||
|
|
||||||
## User Commands
|
|
||||||
|
|
||||||
User /pay command. Pay emeralds to another player:
|
User /pay command. Pay emeralds to another player:
|
||||||
|
|
||||||
@ -184,7 +41,6 @@ User /money command. Show you the emeralds in your bank account in the chat.
|
|||||||
/money
|
/money
|
||||||
```
|
```
|
||||||
|
|
||||||
## Administration
|
|
||||||
EmeraldBank mod also include a variety of tools for server administrators.
|
EmeraldBank mod also include a variety of tools for server administrators.
|
||||||
|
|
||||||
**Admin Emerald command**
|
**Admin Emerald command**
|
||||||
@ -198,31 +54,9 @@ Add `<num>` emeralds to `<player>` account.
|
|||||||
|
|
||||||
If num is 0 return emeralds in player account.
|
If num is 0 return emeralds in player account.
|
||||||
|
|
||||||
**Temporarily disabling vendors:**
|
|
||||||
Any player with the disable_vendor privilege can run
|
|
||||||
|
|
||||||
```
|
|
||||||
/disable_all_vendors
|
|
||||||
```
|
|
||||||
|
|
||||||
to force all vendors into an inactive state. Please use this if you find a dangerous bug and are waiting for it to be fixed.
|
|
||||||
|
|
||||||
**Admin vendors:**
|
|
||||||
Admin vendors perform the same role as their regular counterparts, however they do so with no stock or inventory requirements, simply creating and destroying items as players purchase.
|
|
||||||
|
|
||||||
Since incorrectly configured admin vendors could be easily used to duplicate items, the `admin_vendor` privilege is required for the option to switch a vendor to one appears. If the user is ever revoked this privilege, all admin vendors they own will be forced into an inactive state until the privilege is re-granted or the vendor is set to a player vendor.
|
|
||||||
|
|
||||||
**Modifying vendors:**
|
|
||||||
If a user has the `protection_bypass` privilege, they will be able to access the full extent of the vendor as if they were the owner, including inventory and settings.
|
|
||||||
|
|
||||||
**Server and client load:**
|
|
||||||
Fancy vend uses only one infrequent abm to refresh vendor objects in the event of a clearobjects. No other vendor updating is done unless a player purchases from the vendor or adjusts settings.
|
|
||||||
|
|
||||||
Note: Some clients using mobile and/or older devices, including PCs, may experience additional lag if many fancy vendors are used in a small space, however not to an extent greater than the majority of shops where players use itemframes or pedestals to achieve the same functionality as the fancy vendor's display.
|
|
||||||
|
|
||||||
## More Info
|
## More Info
|
||||||
|
|
||||||
This mod is for [MineClonia](https://content.minetest.net/packages/ryvnf/mineclonia/) or [MineClone2](https://content.minetest.net/packages/Wuzzy/mineclone2/) Games, dont work with MTG
|
This mod is for [MineClonia](https://content.minetest.net/packages/ryvnf/mineclonia/) or [VoxeLibre](https://content.minetest.net/packages/Wuzzy/mineclone2/) Games, dont work with MTG
|
||||||
|
|
||||||
Feel free to contribute, send MR/PR or issues.
|
Feel free to contribute, send MR/PR or issues.
|
||||||
|
|
||||||
|
2
bank.lua
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
-- Copyright (C) 2021, 2023 Ale
|
-- Copyright (C) 2021, 2024 Sandro del Toro
|
||||||
|
|
||||||
-- This file is part of Emeraldbank Minetest Mod.
|
-- This file is part of Emeraldbank Minetest Mod.
|
||||||
|
|
||||||
|
18
commands.lua
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
-- Copyright (C) 2021, 2023 Ale
|
-- Copyright (C) 2021, 2024 Sandro del Toro
|
||||||
|
|
||||||
-- This file is part of Emeraldbank Minetest Mod.
|
-- This file is part of Emeraldbank Minetest Mod.
|
||||||
|
|
||||||
@ -96,19 +96,3 @@ core.register_chatcommand("emeralds", {
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
-- experimental upgrade command
|
|
||||||
core.register_chatcommand("upgrade", {
|
|
||||||
description = S("Admin Command! Upgrade a shop"),
|
|
||||||
privs = {server=true},
|
|
||||||
func = function(name, param)
|
|
||||||
local player = core.get_player_by_name(name)
|
|
||||||
local pos = player:get_pos()
|
|
||||||
local nodename = core.get_node(pos).name
|
|
||||||
if nodename == "emeraldbank:shop" or nodename == "emeraldbank:shop_empty" then
|
|
||||||
emeraldbank.upgrade_shop(pos)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
1781
fancyshop.lua
108
functions.lua
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
-- Copyright (C) 2021, 2023 Ale
|
-- Copyright (C) 2021, 2024 Sandro del Toro
|
||||||
|
|
||||||
-- This file is part of Emeraldbank Minetest Mod.
|
-- This file is part of Emeraldbank Minetest Mod.
|
||||||
|
|
||||||
@ -72,44 +72,6 @@ function emeraldbank.update_accounts()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function emeraldbank.inv_emeralds_to_stonks(pos)
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
local stonks = meta:get_int("stonks")
|
|
||||||
local fancy_inv = inv:get_list("main")
|
|
||||||
if not fancy_inv then return end
|
|
||||||
local has_emerald = inv:contains_item("main", "mcl_core:emerald 1", true)
|
|
||||||
if has_emerald then
|
|
||||||
meta:set_int("stonks", stonks+1)
|
|
||||||
inv:remove_item("main", "mcl_core:emerald 1")
|
|
||||||
emeraldbank.inv_emeralds_to_stonks(pos)
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function emeraldbank.get_stonks(pos)
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local owner = meta:get_string("owner")
|
|
||||||
local player = core.get_player_by_name(owner)
|
|
||||||
local is_online = core.player_exists(owner)
|
|
||||||
emeraldbank.inv_emeralds_to_stonks(pos)
|
|
||||||
local stonks = meta:get_int("stonks")
|
|
||||||
if not player or player.is_fake_player then return end
|
|
||||||
if is_online and stonks > 0 then
|
|
||||||
core.sound_play("cash", {
|
|
||||||
to_player = owner,
|
|
||||||
gain = 1.0,
|
|
||||||
fade = 0.0,
|
|
||||||
pitch = 1.0,
|
|
||||||
})
|
|
||||||
emeraldbank.add_emeralds(player, stonks)
|
|
||||||
meta:set_int("stonks", 0)
|
|
||||||
core.chat_send_player(owner, S("You've earned @1 Emeralds with your shops.", stonks))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function emeraldbank.transfer_emeralds(player1, player2, num)
|
function emeraldbank.transfer_emeralds(player1, player2, num)
|
||||||
-- Determine player names based on whether input is a string or player object
|
-- Determine player names based on whether input is a string or player object
|
||||||
local name1 = type(player1) == "string" and player1 or player1:get_player_name()
|
local name1 = type(player1) == "string" and player1 or player1:get_player_name()
|
||||||
@ -154,71 +116,3 @@ function emeraldbank.transfer_emeralds(player1, player2, num)
|
|||||||
core.chat_send_player(name1, S("Invalid pay"))
|
core.chat_send_player(name1, S("Invalid pay"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function emeraldbank.upgrade_shop(pos)
|
|
||||||
local oldnode = core.get_node(pos)
|
|
||||||
local old_meta = core.get_meta(pos)
|
|
||||||
local old_meta_table = core.get_meta(pos):to_table()
|
|
||||||
local nodename = core.get_node(pos).name
|
|
||||||
local old_inv = old_meta:get_inventory()
|
|
||||||
local old_list = old_inv:get_list("stock")
|
|
||||||
local old_stack = old_inv:get_stack("stock", 1)
|
|
||||||
|
|
||||||
-- set the new shop node
|
|
||||||
core.swap_node(pos, {name = "fancy_vend:player_vendor"})
|
|
||||||
|
|
||||||
-- setup the new shop node
|
|
||||||
-- Set variables for access later (for various checks, etc.)
|
|
||||||
|
|
||||||
pos.y = pos.y + 1
|
|
||||||
-- local above_node = minetest.get_node(pos).name
|
|
||||||
|
|
||||||
-- -- If node above is air or the display node, and it is not protected, attempt to place the vendor. If vendor sucessfully places, place display node above, otherwise alert the user
|
|
||||||
-- if (minetest.registered_nodes[above_node].buildable_to or above_node == "fancy_vend:display_node") and not minetest.is_protected(pos, owner) then
|
|
||||||
-- if above_node ~= "fancy_vend:display_node" then
|
|
||||||
-- minetest.set_node(pos, minetest.registered_nodes["fancy_vend:display_node"])
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- Set owner
|
|
||||||
local owner = old_meta:get_string("owner") or ""
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
meta:set_string("owner", owner)
|
|
||||||
|
|
||||||
-- Set default meta
|
|
||||||
meta:set_string("log", minetest.serialize({"Vendor placed by "..owner,}))
|
|
||||||
emeraldbank.reset_vendor_settings(pos)
|
|
||||||
emeraldbank.refresh_vendor(pos)
|
|
||||||
|
|
||||||
if minetest.get_modpath("pipeworks") then
|
|
||||||
pipeworks.after_place(pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- copy old metadata in new node
|
|
||||||
core.get_meta(pos):from_table(old_meta_table)
|
|
||||||
|
|
||||||
-- new node
|
|
||||||
local node = core.get_node(pos)
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local count = meta:get_int("count")
|
|
||||||
local price = meta:get_int("price")
|
|
||||||
local shop_item = meta:get_string("shop_item")
|
|
||||||
local settings = emeraldbank.get_vendor_settings(pos)
|
|
||||||
|
|
||||||
-- settings
|
|
||||||
settings.input_item = "mcl_core:emerald"
|
|
||||||
settings.input_item_qty = price
|
|
||||||
settings.output_item = shop_item
|
|
||||||
settings.output_item_qty = count
|
|
||||||
|
|
||||||
-- inv
|
|
||||||
-- local inv = meta:get_inventory()
|
|
||||||
-- inv:set_size("main", 15*6)
|
|
||||||
-- inv:set_size("wanted_item", 1*1)
|
|
||||||
-- inv:set_size("given_item", 1*1)
|
|
||||||
-- inv:set_stack("main", i, old_stack)
|
|
||||||
|
|
||||||
|
|
||||||
emeraldbank.set_vendor_settings(pos, settings)
|
|
||||||
emeraldbank.refresh_vendor(pos)
|
|
||||||
end
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
-- Copyright (C) 2021, 2023 Ale
|
-- Copyright (C) 2021, 2024 Sandro del Toro
|
||||||
|
|
||||||
-- This file is part of Emeraldbank Minetest Mod.
|
-- This file is part of Emeraldbank Minetest Mod.
|
||||||
|
|
||||||
|
2
init.lua
@ -41,8 +41,6 @@ dofile(modpath .. "/forms.lua") -- file adapted from atm mod
|
|||||||
dofile(modpath .. "/receive_fields.lua") -- file adapted from atm mod
|
dofile(modpath .. "/receive_fields.lua") -- file adapted from atm mod
|
||||||
dofile(modpath .. "/receive_fields_wt.lua") -- file from atm mod
|
dofile(modpath .. "/receive_fields_wt.lua") -- file from atm mod
|
||||||
dofile(modpath .. "/bank.lua")
|
dofile(modpath .. "/bank.lua")
|
||||||
dofile(modpath .. "/shop.lua")
|
|
||||||
dofile(modpath .. "/fancyshop.lua") -- file adapted from fancy_vend mod.
|
|
||||||
dofile(modpath .. "/commands.lua")
|
dofile(modpath .. "/commands.lua")
|
||||||
dofile(modpath .. "/hud.lua")
|
dofile(modpath .. "/hud.lua")
|
||||||
|
|
||||||
|
6
mod.conf
@ -1,5 +1,5 @@
|
|||||||
name = emeraldbank
|
name = emeraldbank
|
||||||
depends = mcl_core, mcl_sounds, mcl_inventory, mcl_formspec, mcl_title
|
depends = mcl_core, mcl_sounds, mcl_inventory, mcl_formspec, mcl_title
|
||||||
optional_depends = irc, yl_matterbridge, pipeworks, digilines, awards, hopper, tell, email, mail, beerchat
|
optional_depends = irc, yl_matterbridge, awards, mail, beerchat
|
||||||
description = Keep your Emeralds in a bank! And trade with shops.
|
description = Keep your Emeralds in a bank!.
|
||||||
supported_games = mineclonia, mineclone2
|
supported_games = mineclonia
|
||||||
|
@ -21,23 +21,3 @@ emeraldbank.income_period (time between income) int 1800
|
|||||||
|
|
||||||
# Length of time (in seconds) between updating emeralds player HUD
|
# Length of time (in seconds) between updating emeralds player HUD
|
||||||
emeraldbank.hud_time (HUD update time) int 3
|
emeraldbank.hud_time (HUD update time) int 3
|
||||||
|
|
||||||
[Shops]
|
|
||||||
|
|
||||||
# If true shop can be crafted
|
|
||||||
emeraldbank.shop_craft (shop craft) bool true
|
|
||||||
|
|
||||||
# If true old shop can be crafted
|
|
||||||
emeraldbank.old_shop_craft (old shop craft) bool false
|
|
||||||
|
|
||||||
# The node to copy as the display node
|
|
||||||
fancy_vend.display_node (Display Node) string mcl_core:glass
|
|
||||||
|
|
||||||
# Maximum number of mods to store per vender
|
|
||||||
fancy_vend.log_max (Log Max) int 40
|
|
||||||
|
|
||||||
# Speed of display item auto rotation
|
|
||||||
fancy_vend.autorotate_speed (Autorotate Speed) int 1
|
|
||||||
|
|
||||||
# Whether to not send mail alerts
|
|
||||||
fancy_vend.no_alerts (Don't Send Mail Alerts) bool false
|
|
||||||
|
327
shop.lua
@ -1,327 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
-- Copyright (C) 2021, 2023 Ale
|
|
||||||
|
|
||||||
-- This file is part of Emeraldbank Minetest Mod.
|
|
||||||
|
|
||||||
-- Emeraldbank is free software: you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU Affero General Public License as
|
|
||||||
-- published by the Free Software Foundation, either version 3 of the
|
|
||||||
-- License, or (at your option) any later version.
|
|
||||||
|
|
||||||
-- Emeraldbank is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
-- You should have received a copy of the GNU Affero General Public License
|
|
||||||
-- along with Emeraldbank. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
|
|
||||||
local S = core.get_translator(core.get_current_modname())
|
|
||||||
|
|
||||||
local oldshopcraft = core.settings:get_bool("emeraldbank.old_shop_craft") or false
|
|
||||||
|
|
||||||
-- privilege
|
|
||||||
core.register_privilege("admin_shop", {
|
|
||||||
description = S("Enables the user to set regular vendors to admin vendors, or edit other players shops."),
|
|
||||||
give_to_singleplayer = false,
|
|
||||||
})
|
|
||||||
|
|
||||||
emeraldbank.shop_timer = 5
|
|
||||||
|
|
||||||
local shop_timer = emeraldbank.shop_timer
|
|
||||||
|
|
||||||
local stock_h = 3
|
|
||||||
local stock_w = 5
|
|
||||||
|
|
||||||
local formspec_prefix = "emeraldbank:shop_formspec"
|
|
||||||
|
|
||||||
emeraldbank.player_inv =
|
|
||||||
"list[current_player;main;0,4.5;9,3;9]"..
|
|
||||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
|
||||||
"list[current_player;main;0,7.74;9,1;]"..
|
|
||||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
|
||||||
"listring[current_player;main]"
|
|
||||||
|
|
||||||
|
|
||||||
function emeraldbank.get_shop_fs(pos, clicker)
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local count = meta:get_int("count")
|
|
||||||
local price = meta:get_int("price")
|
|
||||||
local shop_item = meta:get_string("shop_item")
|
|
||||||
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
|
|
||||||
local pname = clicker:get_player_name()
|
|
||||||
local owner = meta:get_string("owner")
|
|
||||||
local player_press_key = clicker:get_player_control().aux1
|
|
||||||
local shop_fs = ""
|
|
||||||
local is_admin = core.check_player_privs(pname, {admin_shop=true})
|
|
||||||
if (pname == owner or is_admin) and not player_press_key then
|
|
||||||
shop_fs = "size[9,8.75]"..
|
|
||||||
"label[0,0;"..S("Your stock:").."]"..
|
|
||||||
"list["..list_name..";stock;0,0.5;"..stock_w..","..stock_h..";]"..
|
|
||||||
mcl_formspec.get_itemslot_bg(0,0.5,stock_w,stock_h)..
|
|
||||||
"field[6.5,2;2,1;count;"..S("Count")..";"..count.."]"..
|
|
||||||
"field[6.5,3;2,1;price;"..S("Price")..";"..price.."]"..
|
|
||||||
"label[6,0;"..S("In exchange, you give:").."]"..
|
|
||||||
"item_image[6.5,0.5;1,1;"..shop_item.."]"..
|
|
||||||
mcl_formspec.get_itemslot_bg(6.5,0.5,1,1)..
|
|
||||||
"label[0,4;"..S("Owner, Use (special key + right mouse button) for customer interface").."]"..
|
|
||||||
emeraldbank.player_inv
|
|
||||||
else
|
|
||||||
shop_fs = "size[9,8.75]"..
|
|
||||||
"label[3.7,0;"..S("Owner gives:").."]"..
|
|
||||||
"item_image[4,1;1,1;"..shop_item.."]"..
|
|
||||||
mcl_formspec.get_itemslot_bg(4,1,1,1)..
|
|
||||||
"label[5,1.5;"..S("x @1", count).."]"..
|
|
||||||
"label[4,2;"..S("Price: @1", price).."]"..
|
|
||||||
"button[3.5,3;2,1;exchange;"..S("Exchange").."]"..
|
|
||||||
emeraldbank.player_inv
|
|
||||||
end
|
|
||||||
|
|
||||||
return shop_fs
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function swap_shop(pos, closed)
|
|
||||||
local oldnode = core.get_node(pos)
|
|
||||||
local oldnodemeta = core.get_meta(pos):to_table()
|
|
||||||
local nodename = core.get_node(pos).name
|
|
||||||
if closed then
|
|
||||||
core.swap_node(pos, {name = "emeraldbank:shop_empty"})
|
|
||||||
else
|
|
||||||
core.swap_node(pos, {name = "emeraldbank:shop"})
|
|
||||||
end
|
|
||||||
core.get_meta(pos):from_table(oldnodemeta)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function set_item(pos, stack, player)
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local itemname = stack:get_name()
|
|
||||||
local itemcount = stack:get_count()
|
|
||||||
meta:set_string("shop_item", itemname)
|
|
||||||
core.show_formspec(player:get_player_name(), formspec_prefix..core.pos_to_string(pos), emeraldbank.get_shop_fs(pos, player) )
|
|
||||||
end
|
|
||||||
|
|
||||||
local function check_empty(pos)
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
local count = meta:get_int("count")
|
|
||||||
local shop_item = meta:get_string("shop_item")
|
|
||||||
if inv:is_empty("stock") then
|
|
||||||
meta:set_string("shop_item", "")
|
|
||||||
swap_shop(pos, true)
|
|
||||||
elseif not inv:contains_item("stock", shop_item.." "..count, true) then
|
|
||||||
swap_shop(pos, true)
|
|
||||||
else
|
|
||||||
swap_shop(pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function after_place_node(pos, placer, itemstack)
|
|
||||||
local owner = placer:get_player_name()
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
meta:set_string("infotext", S("Exchange shop (owned by @1)", owner))
|
|
||||||
meta:set_string("owner", owner)
|
|
||||||
meta:set_int("count", 10) -- default count
|
|
||||||
meta:set_int("price", 5) -- default price
|
|
||||||
core.get_node_timer(pos):start(shop_timer)
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
inv:set_size("stock", stock_w*stock_h)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_rightclick(pos, node, clicker, itemstack)
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local nodename = core.get_node(pos).name
|
|
||||||
local owner = meta:get_string("owner")
|
|
||||||
local pname = clicker:get_player_name()
|
|
||||||
emeraldbank.get_stonks(pos)
|
|
||||||
--if nodename == "emeraldbank:shop" or pname == owner then
|
|
||||||
core.show_formspec(pname, formspec_prefix..core.pos_to_string(pos), emeraldbank.get_shop_fs(pos, clicker))
|
|
||||||
--end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_punch(pos, node, puncher, pointed_thing)
|
|
||||||
emeraldbank.get_stonks(pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_metadata_inventory_put(pos, listname, index, stack, player)
|
|
||||||
set_item(pos, stack, player) -- this func already show the fs
|
|
||||||
check_empty(pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
|
||||||
check_empty(pos)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_metadata_inventory_take(pos, listname, index, stack, player)
|
|
||||||
-- check_empty(pos) -- CRASH
|
|
||||||
core.show_formspec(player:get_player_name(), formspec_prefix..core.pos_to_string(pos), emeraldbank.get_shop_fs(pos, player) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function on_timer(pos, elapsed)
|
|
||||||
core.get_node_timer(pos):start(shop_timer)
|
|
||||||
check_empty(pos)
|
|
||||||
emeraldbank.get_stonks(pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function can_dig(pos, player)
|
|
||||||
local pname = player:get_player_name()
|
|
||||||
local is_admin = core.check_player_privs(pname, {admin_shop=true})
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local owner = meta:get_string("owner")
|
|
||||||
local inv = meta:get_inventory()
|
|
||||||
return inv:is_empty("stock") and (pname == owner or is_admin)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- register shop node
|
|
||||||
core.register_node("emeraldbank:shop", {
|
|
||||||
description = S("Shop"),
|
|
||||||
_doc_items_longdesc = S("A shop to sell your items with emeralds."),
|
|
||||||
is_ground_content = false,
|
|
||||||
tiles = {
|
|
||||||
"default_tree.png",
|
|
||||||
"default_tree.png",
|
|
||||||
"default_tree.png^mcl_core_emerald.png"
|
|
||||||
},
|
|
||||||
stack_max = 64,
|
|
||||||
groups = {axey=1, handy=1, building_block=1},
|
|
||||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
|
||||||
_mcl_blast_resistance = 5,
|
|
||||||
_mcl_hardness = 1,
|
|
||||||
|
|
||||||
after_place_node = after_place_node,
|
|
||||||
on_rightclick = on_rightclick,
|
|
||||||
on_punch = on_punch,
|
|
||||||
on_metadata_inventory_put = on_metadata_inventory_put,
|
|
||||||
on_metadata_inventory_move = on_metadata_inventory_move,
|
|
||||||
on_metadata_inventory_take = on_metadata_inventory_take,
|
|
||||||
on_timer = on_timer,
|
|
||||||
can_dig = can_dig
|
|
||||||
})
|
|
||||||
|
|
||||||
-- register shop node
|
|
||||||
core.register_node("emeraldbank:shop_empty", {
|
|
||||||
description = S("Shop Empty"),
|
|
||||||
_doc_items_longdesc = S("A shop to sell your items with emeralds."),
|
|
||||||
is_ground_content = false,
|
|
||||||
tiles = {
|
|
||||||
"default_tree.png",
|
|
||||||
"default_tree.png",
|
|
||||||
"default_tree.png^mcl_core_emerald.png^mcl_core_barrier.png"
|
|
||||||
},
|
|
||||||
stack_max = 64,
|
|
||||||
groups = {axey=1, handy=1, building_block=1, not_in_creative_inventory=1},
|
|
||||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
|
||||||
drop = "emeraldbank:shop",
|
|
||||||
_mcl_blast_resistance = 5,
|
|
||||||
_mcl_hardness = 1,
|
|
||||||
|
|
||||||
after_place_node = after_place_node,
|
|
||||||
on_rightclick = on_rightclick,
|
|
||||||
on_punch = on_punch,
|
|
||||||
on_metadata_inventory_put = on_metadata_inventory_put,
|
|
||||||
on_metadata_inventory_move = on_metadata_inventory_move,
|
|
||||||
on_metadata_inventory_take = on_metadata_inventory_take,
|
|
||||||
on_timer = on_timer,
|
|
||||||
can_dig = can_dig
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
core.register_on_player_receive_fields(function(sender, formname, fields)
|
|
||||||
local prefix_len = string.len(formspec_prefix)
|
|
||||||
if formname:sub(1,prefix_len) == formspec_prefix then
|
|
||||||
|
|
||||||
local pos_string = formname:sub(prefix_len+1)
|
|
||||||
local pos = core.string_to_pos(pos_string)
|
|
||||||
local meta = core.get_meta(pos)
|
|
||||||
local name = sender:get_player_name()
|
|
||||||
local playermeta = sender:get_meta()
|
|
||||||
local player_pos = sender:get_pos()
|
|
||||||
local old_count = meta:get_int("count")
|
|
||||||
local new_count = tonumber(fields.count)
|
|
||||||
local old_price = meta:get_int("price")
|
|
||||||
local new_price = tonumber(fields.price)
|
|
||||||
local shop_item = meta:get_string("shop_item")
|
|
||||||
local minv = meta:get_inventory()
|
|
||||||
local pinv = sender:get_inventory()
|
|
||||||
atm.read_account(name)
|
|
||||||
local bankemeralds = atm.balance[name]
|
|
||||||
|
|
||||||
-- set or reset timer
|
|
||||||
core.get_node_timer(pos):start(shop_timer)
|
|
||||||
|
|
||||||
-- set item count
|
|
||||||
if fields.count and string.find(fields.count, "^[0-9]+$") then
|
|
||||||
if new_count >= 1 and new_count <= 64 and new_count ~= meta:get_int("count") then
|
|
||||||
meta:set_int("count", new_count)
|
|
||||||
check_empty(pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- set price
|
|
||||||
if fields.price and string.find(fields.price, "^[0-9]+$") then
|
|
||||||
if new_price >= 1 and new_price <= 10000 and new_price ~= meta:get_int("price") then
|
|
||||||
meta:set_int("price", new_price)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- someone hit exchange button
|
|
||||||
if fields.exchange ~= nil and fields.exchange ~= "" then
|
|
||||||
|
|
||||||
-- owner try exchanges
|
|
||||||
if meta:get_string("owner") == name then
|
|
||||||
core.chat_send_player(name, S("This is your own shop, you can't exchange to yourself!"))
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
local can_exchange = true
|
|
||||||
|
|
||||||
-- have u money?
|
|
||||||
if bankemeralds < old_price then
|
|
||||||
can_exchange = false
|
|
||||||
core.chat_send_player(name, S("Not enough Emeralds in your account"))
|
|
||||||
end
|
|
||||||
|
|
||||||
--there are enough items?
|
|
||||||
if not minv:contains_item("stock", shop_item.." "..old_count, true) then
|
|
||||||
can_exchange = false
|
|
||||||
core.chat_send_player(name, S("Out of Stock!"))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- do not trade air
|
|
||||||
if shop_item == "" or shop_item == "air" then
|
|
||||||
can_exchange = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if can_exchange then
|
|
||||||
minv:remove_item("stock", shop_item.." "..old_count)
|
|
||||||
core.add_item(player_pos, shop_item.." "..old_count)
|
|
||||||
emeraldbank.add_emeralds(sender, -old_price)
|
|
||||||
meta:set_int("stonks", meta:get_int("stonks")+old_price)
|
|
||||||
mcl_title.set(sender, "subtitle", {text=S("Exchanged!"), color="green"})
|
|
||||||
check_empty(pos)
|
|
||||||
core.show_formspec(sender:get_player_name(), formspec_prefix..core.pos_to_string(pos), emeraldbank.get_shop_fs(pos, sender) )
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
if oldshopcraft then
|
|
||||||
core.register_craft({
|
|
||||||
output = "emeraldbank:shop 3",
|
|
||||||
recipe = {
|
|
||||||
{"mcl_core:emerald", "mcl_core:emerald", "mcl_core:emerald"},
|
|
||||||
{"mcl_core:emerald", "mcl_core:tree", "mcl_core:emerald"},
|
|
||||||
{"mcl_core:emerald", "mcl_core:emerald", "mcl_core:emerald"},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end
|
|
Before Width: | Height: | Size: 303 B |
Before Width: | Height: | Size: 257 B |
Before Width: | Height: | Size: 227 B |
Before Width: | Height: | Size: 890 B |
Before Width: | Height: | Size: 565 B |
Before Width: | Height: | Size: 552 B |
Before Width: | Height: | Size: 526 B |
Before Width: | Height: | Size: 556 B |