Introduce Market API
justisr opened this issue · 2 comments
There's a TL;DR at the bottom, feel free to skip to it.
Vault currently provides an API for chat, permissions, and player economy.
Something all of these share in common is that there are countless plugins with different implementations for fulfilling their purposes, but each category fulfills the same basic purposes.
Vault exists so that plugins wanting to interact with the chat/permission/econ plugin that the server is using can do so without knowing what plugin the server is using, and without needing to manually support every possible implementation, or the reverse.
Markets meet that same criteria. There are countless different market plugins. ShopGUI+, Essentials, ShopChest, Shop, BossShop, SignShop, BetterShops, it goes on and on. Just look at all of the top Economy related plugins, and you will see so many of them are related to a market, not a player economy: https://www.spigotmc.org/resources/categories/economy.23/
Among them, you will also see many plugins which attempt to provide specific features to a server's market, such as plugins which sell crops as they mature, then replant them, or VoidChest, which will auto-sell the contents input into a chest, or similar functionality for things like prison servers where either blocks are sold as they are mined, or one's inventory is auto-sold or they drop it into a GUI which sells them.
An issue with all of these plugins attempting to interact with the market is that they either need to have their own configurations deciding the price of all items which are purchased/sold, thus essentially creating two different market instances, or they only support markets that they know of. Essentials being the most popular choice, with prices set in essentials' worth.yml
Over the past two years I've been creating a plugin which automatically adjusts the prices of items with supply and demand. The problem is that server owners will not be able to synchronize the prices that items are being sold for across plugins, because the prices that items are being sold for through my plugin will almost always be different than whatever static prices are in essentials' worth.yml or whatever configuration the prices are set in.
If Vault introduces a Market interface, which these 3rd party plugins can hook into and automatically support buying/selling for any market implementation the server has installed, then there won't be the need for redundant configurations for determining prices, nor needing to manually support every possible market plugin being used.
TL;DR
I'm more than happy add a Market API myself, and send a pull request, but I'd only want to spend my time doing so if it has a chance of being accepted.
Would the current Vault maintainers be interested and willing in extending Vault's supported functionality to market buying and selling?
My proposed market interface (without documentation that will be added if accepted):
import java.util.List;
import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack;
public interface Market {
public boolean isEnabled();
public String getName();
public double buy(OfflinePlayer buyer, ItemStack item, int amt);
public double buy(OfflinePlayer buyer, String label, int amt);
public double sell(OfflinePlayer seller, ItemStack item, int amt);
public double sell(OfflinePlayer seller, String label, int amt);
public boolean hasMarketAccess(OfflinePlayer player);
public boolean isDamagedItemSellingSupported(OfflinePlayer player);
public List<ItemStack> getTransactableItems(OfflinePlayer player);
public List<String> getTransactableLabels(OfflinePlayer player);
public boolean isBuyable(OfflinePlayer player, ItemStack item);
public boolean isBuyable(OfflinePlayer player, String label);
public boolean isSellable(OfflinePlayer player, ItemStack item);
public boolean isSellable(OfflinePlayer player, String label);
public double getBuyPrice(OfflinePlayer player, ItemStack item, int amt);
public double getBuyPrice(OfflinePlayer player, String label, int amt);
public double getSellPrice(OfflinePlayer player, ItemStack item, int amt);
public double getSellPrice(OfflinePlayer player, String label, int amt);
}
My reason for using OfflinePlayer in each of the methods which interact with the market is due to the fact that every actual transaction will involve a player, as well as the probability that multiple markets may exist on the server, either in permissible groups (for donors as an example) or individual markets (per player). Or perhaps certain players get a discount on certain purchases. If the player is online, the market will also be able to determine what world the transaction is occurring in and do something with that. Regardless, in any such case, prices will depend on the transacting player.
Passing the player information ensures that whatever market implementation exists, it has all the information it needs to perform accurately. If the market implementation doesn't care about the player, it can simply ignore the player it was provided.
My reason for the string label alternative is due to the fact that, just like any Object, every transactable entity will have a string representation. Additionally there's the probability that non-ItemStacks may be transactable. A fully fleshed out market implementation may want to allow the purchase/sale of intangible goods, such as permissions, "tickets", raffles, perks, bonuses, etc.
@justisr hey thanks for taking the initiative here. Vault was actually already built with shop plugins in mind. it is already the most useful pieces of what we used in our own shop plugin built into an API. It's been around long enough that it's the standard, but adding new features wont really get the same kind of adoption for other ideals. I'm not really looking to add new API as that increases the maintenance burden. I'd recommend looking at generating your own Vualt-like plugin if you'd like to provide and maintain the example API you've proposed.