API

Apr 14, 2019
API
  • How to hook into BossShopPro?
    The source code of existing BossShopPro addons can be found here.

    First of all, add the BossShopPro.jar to your libraries.
    You can access the API following way:
    Code (Java):
    import org.black_ixx.bossshop.BossShop;
    import org.black_ixx.bossshop.api.BossShopAPI;
    import org.bukkit.Bukkit;
    import org.bukkit.plugin.Plugin;

    public class BSPHook {

        private BossShop bs; //BossShopPro Plugin Instance

        public BSPHook() {
            Plugin plugin = Bukkit.getPluginManager().getPlugin("BossShopPro"); // Get BossShopPro instance
     
            if (plugin == null) { // Not installed?
                System.out.print("[BSP Hook] BossShopPro was not found... you can download it here: https://www.spigotmc.org/resources/25699/");
                return;
            }
     
            bs = (BossShop) plugin; // Success :)
     
        }


        public BossShopAPI getBSPAPI() {
            return bs.getAPI(); // Returns BossShopPro API class instance
        }

    }
       
    Opening a shop
    Code (Java):
        public boolean openShop(Player p, String shop_name) {
     
            BSShop shop = bs.getAPI().getShop(shop_name);
            if (shop == null) {
                p.sendMessage(ChatColor.RED+"Shop "+shop_name+" not found...");
                return false;
            }
     
            bs.getAPI().openShop(p, shop);
     
            return true;
        }

    Checking if an inventory belongs to BossShopPro

    Code (Java):
        // Example: InventoryEvent
            if (bs.getAPI().isValidShop(event.getInventory())) {
                // Do Shop Inventory Action
            }else{
                //Rest
            }
    Adding a shopitem to a shop
    Code (Java):
            // Create a custom BSBuy instance (Shop Item)
                    BSBuy buy = bs.getAPI().createBSBuy(BSRewardType.Shop, BSPriceType.Nothing, "item_shop", null, null, 1, "OpenShop.Item_Shop");
     
                    //Get a Shop
                    BSShop shop = bs.getAPI().getShop("menu");
     
                    //Add it to the Shop
                    ItemStack menu_item = [...]
                    bs.getAPI().addItemToShop(menu_item, buy, shop);
    Registering a custom points plugin
    Your plugin first needs to load before BossShopPro is loaded.

    plugin.yml:
    Code (Text):
    loadbefore: [BossShopPro]
    Extend the BSPointsPlugin class and implement all the necessary methods.

    More examples of custom point plugin classes can be found here.
    Code (Java):
    public class BSPointsPluginPlayerPoints extends BSPointsPlugin {
        private PlayerPoints pp;

        public BSPointsPluginPlayerPoints() {
            super("PlayerPoints", "PlayerPoint", "PP");

            Plugin plugin = Bukkit.getServer().getPluginManager().getPlugin("PlayerPoints");
            if (plugin != null) {
                pp = (PlayerPoints.class.cast(plugin));
            }
        }

        @Override
        public double getPoints(OfflinePlayer player) {
            return pp.getAPI().look(player.getUniqueId());
        }

        @Override
        public double setPoints(OfflinePlayer player, double points) {
            pp.getAPI().set(player.getUniqueId(), (int) points);
            return points;
        }

        @Override
        public double takePoints(OfflinePlayer player, double points) {
            pp.getAPI().take(player.getUniqueId(), (int) points);
            return getPoints(player);
        }

        @Override
        public double givePoints(OfflinePlayer player, double points) {
            pp.getAPI().give(player.getUniqueId(), (int) points);
            return getPoints(player);
        }

        @Override
        public boolean usesDoubleValues() {
            return false;
        }

    }

    Code (Java):
    import org.bukkit.Bukkit;
    import org.bukkit.OfflinePlayer;
    public abstract class BSPointsPlugin {

        private final String name;
        private final String[] nicknames;
        private final boolean available;

        public BSPointsPlugin(String main_name, String... nicknames) {
            this.name = main_name;
            this.nicknames = nicknames;
            this.available = Bukkit.getPluginManager().getPlugin(name) != null;
        }

        public String getName() {
            return name;
        }
     
        public String[] getNicknames(){
            return nicknames;
        }
     
        public boolean isAvailable(){
            return available;
        }

        public abstract double getPoints(OfflinePlayer player);
        public abstract double setPoints(OfflinePlayer player, double points);
        public abstract double takePoints(OfflinePlayer player, double points);
        public abstract double givePoints(OfflinePlayer player, double points);
     
        public abstract boolean usesDoubleValues();
     
        public void register() {
            BSPointsAPI.register(this);
        }
    }

    Then within your onEnable, instantiate your class, and call the register method:
    Code (Java):
    new BSPointsPluginPlayerPoints ().register();

    How to create an Addon?
    The source code of existing BossShopPro addons can be found here.

    First of all add the BossShopPro.jar to your libraries. Normally the main class of Minecraft Bukkit plugins extends org.bukkit.plugin.java.JavaPlugin, however when creating a BossShopPro Addon you need to extend one of the following:
    • org.black_ixx.bossshop.api.BossShopAddon - For simple Addons
    • org.black_ixx.bossshop.api.BossShopAddonConfigurable - Provides additional support for a config file that will be created in "plugins/BossShopPro/Addons/<addon name>/"
    Code (Java):
    import org.black_ixx.bossshop.api.BSAddonStorage;
    import org.black_ixx.bossshop.api.BossShopAddon;
    import org.bukkit.command.CommandSender;

    public class BSPAddon extends BossShopAddon{

        @Override
        public String getAddonName() {
            return "ExampleAddon"; // Here you put the name you want the Addon to have
        }
        @Override
        public String getRequiredBossShopVersion() {
            return "1.1.7"; // Here you put in the name of the oldest BSP build that supports your Addon (only numbers and dots; without "v" prefix)
        }

        @Override
        public void enableAddon() {
            // This method is executed when the Addon is enabled (Which takes place when the BossShopPro core is loaded; shops, shopitems, rewardtypes etc. are still missing)
     
            // Helpful Addon method: Creating custom storage files inside the Addons folder
            // This kind of storage files are currently limited to a set of methods and do not grant direct access to the Bukkit FileConfiguration instance,
            // because in the future other storage types might be introduced
            // The following examples show a part of what you can do. Of course, the storage class provides more options than shown in the examples.
            BSAddonStorage storage = this.createStorage(this, "StorageFileName"); // Creates and loads a storage file

            storage.set("Number", 2); // Sets an integer value
            storage.set("Text", "This is some text"); // Sets a string value
     
            int number = storage.getInt("Value", -1); // Reads value (if no value would be found, default value "-1" would be returned)
            String text = storage.getString("Text", null); // Reads value and returns null in case of failure
     
            storage.save(); // Saves the file
            storage.saveAsync(); // Saves file asynchronously
        }

        @Override
        public void disableAddon() {
            // This method is executed when the Addon is disabled
        }

        @Override
        public void bossShopFinishedLoading() {
            // This method is executed when BossShopPro is completely loaded (Including shops, shopitems, rewardtypes etc.)
        }

        @Override
        public void bossShopReloaded(CommandSender sender) {
            // This method is executed when BossShopPro is reloaded manually ("/bossshop reload")
        }


    }
    Code (Java):
    import org.black_ixx.bossshop.api.BSAddonConfig;
    import org.black_ixx.bossshop.api.BossShopAddonConfigurable;
    import org.black_ixx.bossshop.managers.config.FileHandler;
    import org.bukkit.command.CommandSender;
    import org.bukkit.configuration.file.FileConfiguration;

    public class BSPAddonConfigurable extends BossShopAddonConfigurable {

        @Override
        public String getAddonName()  {
            return "ExampleAddonConfigurable"; // Here you put the name you want the Addon to have
        }
        @Override
        public String getRequiredBossShopVersion() {
            return "1.1.7"; // Here you put in the name of the oldest BSP build that supports your Addon (only numbers and dots; without "v" prefix)
        }

        @Override
        public void enableAddon() {
            // This method is executed when the Addon is enabled (Which takes place when the BossShopPro core is loaded; shops, shopitems, rewardtypes etc. are still missing)
     
            // Config file way A:
            if (!getAddonConfig().getFile().exists()) {
                new FileHandler().copyFromJar(this, "config.yml"); // This filehandler code allows to copy the complete config file from your addon.jar file
            }
     
            // Config file way B:
            getConfig().options().copyDefaults(true);
            getConfig().addDefault("PointsPlugin", "TokenEnchant");
            getConfig().addDefault("Message.NotEnoughPoints", "&cYou don't have enough Tokens!");
            getConfig().addDefault("Placeholder.DisplayPoints", "%points2% Tokens");
            getConfig().addDefault("PointsDisplay.Enabled", false);
            saveConfig(); //works since v1.2.1. Before you had to use "getAddonConfig().save();"
     
     
            // You can either access the FileConfiguration directly and handle it just like you are used to:
            FileConfiguration config = getConfig();
     
            // or you can access the BSAddonConfig, which provides some additional methods
            BSAddonConfig addonconfig = getAddonConfig();
            addonconfig.saveAsync(); // Saves file asynchronously
            addonconfig.deleteAll("Key"); // Deletes all config entries that start with "Key."
     
        }

        @Override
        public void disableAddon() {
            // This method is executed when the Addon is disabled
        }

        @Override
        public void bossShopFinishedLoading() {
            // This method is executed when BossShopPro is completely loaded (Including shops, shopitems, rewardtypes etc.)
        }

        @Override
        public void bossShopReloaded(CommandSender sender) {
            // This method is executed when BossShopPro is reloaded manually ("/bossshop reload")
        }

        @Override
        public boolean saveConfigOnDisable() {
            return false; // If true the config file will be saved every time the addon is disabled
        }


    }


    How to add custom RewardTypes?
    1. Extend the BossShopPro class "BSRewardType"
    2. Implement all given methods
    3. Create a listener which listens to the "BSRegisterTypesEvent" and creates an instance of your custom BSRewardType. Additionally, call the "register" method of that instance.

    Example Reward implementations can be found here.

    First of all you need to create the reward class:
    Code (Java):
    import java.util.List;


    import org.black_ixx.bossshop.core.BSBuy;
    import org.black_ixx.bossshop.core.rewards.BSRewardType;
    import org.black_ixx.bossshop.managers.ClassManager;
    import org.black_ixx.bossshop.managers.misc.InputReader;
    import org.black_ixx.bossshop.managers.misc.StringManipulationLib;
    import org.bukkit.entity.Player;
    import org.bukkit.event.inventory.ClickType;

    import net.milkbowl.vault.permission.Permission;

    public class BSRewardTypePermission extends BSRewardType {


        public Object createObject(Object o, boolean force_final_state) { // force_final_state will always be true except being accessed by the BossShopProConfigure tool
            return InputReader.readStringList(o); // Here you can transform the object given in the config file into whatever you want. The object returned here will be used later.
        }

        public boolean validityCheck(String item_name, Object o) { // This method is executed after "createObject" has been called. Here you can check if the object is valid.
            if (o!=null) {
                return true;
            }
            ClassManager.manager.getBugFinder().severe("Was not able to create ShopItem "+item_name+"! The reward object needs to be a list of permissions (text lines).");
            return false;
        }

        public void enableType() { // If your RewardTypes needs any additional libraries or features enabled, you can do that here
            ClassManager.manager.getSettings().setPermissionsEnabled(true);
            ClassManager.manager.getSettings().setVaultEnabled(true);
        }

        @Override
        public boolean canBuy(Player p, BSBuy buy, boolean message_if_no_success, Object reward, ClickType clickType) { // Here you can allow/deny the player to purchase the item
            for (String s : (List<String>) reward) {
                if (!p.hasPermission(s)) {
                    return true; // Player is missing one of the permissions? Can buy!
                }
            }
            if (message_if_no_success) {
                ClassManager.manager.getMessageHandler().sendMessage("Main.AlreadyBought", p); // In case of permissions it makes sense to deny the purchase if the player already has all listed permissions
            }
            return false;
        }

        @Override
        public void giveReward(Player p, BSBuy buy, Object reward, ClickType clickType) { // If everything went successful the player is rewarded here
            List<String> permissions = (List<String>) reward;

            Permission per = ClassManager.manager.getVaultHandler().getPermission();
            for (String s : permissions) {
                per.playerAdd(p, s);
            }
        }

        @Override
        public String getDisplayReward(Player p, BSBuy buy, Object reward, ClickType clickType) { // Here you define the way the "%reward%" placeholder will display this kind of reward
            List<String> permissions = (List<String>) reward;
            String permissions_formatted = StringManipulationLib.formatList(permissions);
            return ClassManager.manager.getMessageHandler().get("Display.Permission").replace("%permissions%", permissions_formatted);
        }

        @Override
        public String[] createNames() { // Here you define all names that will lead to your reward, with the first entry being the official main name.
            return new String[]{"permission", "permissions"};
        }

        @Override
        public boolean mightNeedShopUpdate() { // Here you can define if the shop should be updated after this reward is purchased
            return true;
        }

        // Following methods are optional:

        @Override
        public boolean logTransaction() {
            return false; // True by default. If you don't want transactions related to this reward to be logged, set this to false
        }


    }
    If your reward is numerical and you want it to be completely supported by all BossShopPro features like the "ItemAll" pricetype, extend BSRewardTypeNumber instead:

    Code (Java):
    import org.black_ixx.bossshop.core.BSBuy;
    import org.black_ixx.bossshop.core.rewards.BSRewardTypeNumber;
    import org.black_ixx.bossshop.managers.ClassManager;
    import org.black_ixx.bossshop.managers.misc.InputReader;
    import org.bukkit.entity.Player;
    import org.bukkit.event.inventory.ClickType;


    public class BSRewardTypeExp extends BSRewardTypeNumber {


        public Object createObject(Object o, boolean force_final_state) { //force_final_state will always be true except being accessed by the BossShopProConfigure tool
            return InputReader.getInt(o, -1); // Trying to read the reward object in the config as integer number; returning -1 in case of failure
        }

        public boolean validityCheck(String item_name, Object o){ // This method is executed after "createObject" has been called. Here you can check if the object is valid.
            if ((Integer)o!=-1) {
                return true;
            }
            ClassManager.manager.getBugFinder().severe("Was not able to create ShopItem "+item_name+"! The reward object needs to be a valid Integer number. Example: '7' or '12'.");
            return false;
        }

        public void enableType(){ // If your RewardTypes needs any additional libraries or features enabled, you can do that here
        }

        @Override
        public boolean canBuy(Player p, BSBuy buy, boolean message_if_no_success, Object reward, ClickType clickType) { // Here you can allow/deny the player to purchase the item
            return true;
        }

        @Override
        public void giveReward(Player p, BSBuy buy, Object reward, ClickType clickType) { // If everything went successfully the player is rewarded here
            int exp = (int) ClassManager.manager.getMultiplierHandler().calculateRewardWithMultiplier(p, buy, clickType, ((Integer) reward), false); // Use the multiplierhandler if you want multipliers to be supported. Important: In that case you need to set up a pricetype with the same name of your rewardtype
            p.setLevel(p.getLevel() + exp);
        }

        @Override
        public String getDisplayReward(Player p, BSBuy buy, Object reward, ClickType clickType) { // Here you define the way the "%reward%" placeholder will display this kind of reward
            int exp = (int) ClassManager.manager.getMultiplierHandler().calculateRewardWithMultiplier(p, buy, clickType, ((Integer) reward), true);
            return ClassManager.manager.getMessageHandler().get("Display.Exp").replace("%levels%", String.valueOf(exp));
        }

        @Override
        public String[] createNames() { // Here you define all names that will lead to your reward, with the first entry being the official main name.
            return new String[]{"exp", "xp", "level", "levels"};
        }


        @Override
        public boolean mightNeedShopUpdate() { // Here you can define if the shop should be updated after this reward is purchased
            return true;
        }

        @Override
        public boolean isIntegerValue() { // Here you define if this reward either is made for integer values or double values
            return true;
        }


    }

    Custom PriceType example
    1. Extend the BossShopPro class "BSPriceType"
    2. Implement all given methods
    3. Create a listener which listens to the "BSRegisterTypesEvent" and creates an instance of your custom BSPriceType. Additionally, call the "register" method of that instance.

    Example Price implementations can be found here.

    Code (Java):
    import org.black_ixx.bossshop.core.BSBuy;
    import org.black_ixx.bossshop.core.prices.BSPriceTypeNumber;
    import org.black_ixx.bossshop.managers.ClassManager;
    import org.black_ixx.bossshop.managers.misc.InputReader;
    import org.black_ixx.bossshop.misc.MathTools;
    import org.bukkit.entity.Player;
    import org.bukkit.event.inventory.ClickType;

    public class BSPriceTypeThirdCurrencyVariable extends BSPriceTypeNumber {

        private CustomPoints cp;

        public BSPriceTypeThirdCurrencyVariable(CustomPoints points) {
            this.cp = points;
            updateNames(); //updates the name users need to enter in their shop configs in order to use this PriceType: Now as CustomPoints is set the name of the points currency is actually used (see #createNames())
        }


        // receives the price object from the config and transforms it into the type of object needed later
        public Object createObject(Object o, boolean force_final_state) {
            return InputReader.getDouble(o, -1);
        }

        public boolean validityCheck(String item_name, Object o){ // validates the price object
            if ((Double)o!=-1) {
                return true;
            }
            ClassManager.manager.getBugFinder().severe("Was not able to create ShopItem "+item_name+"! The price object needs to be a valid number. Example: '7' or '12'.");
            return false;
        }

        public void enableType(){ // executed once when BSP starts in case the PriceType is used in a shop
        // can be used to register dependencies like Vault
        }


        @Override
        public boolean hasPrice(Player p, BSBuy buy, Object price, ClickType clickType, int multiplier, boolean messageOnFailure) {
            double points = ClassManager.manager.getMultiplierHandler().calculatePriceWithMultiplier(p, buy, clickType, (Double) price) * multiplier;
            if (cp.getPointsManager().getPoints(p) < points) {
                String message = cp.getMessageNotEnoughPoints();
                if (message != null && messageOnFailure) {
                    p.sendMessage(ClassManager.manager.getStringManager().transform(message, buy, buy.getShop(), null, p));
                }
                return false;
            }
            return true;
        }

        @Override
        public String takePrice(Player p, BSBuy buy, Object price, ClickType clickType, int multiplier) {
            double points = ClassManager.manager.getMultiplierHandler().calculatePriceWithMultiplier(p, buy, clickType, (Double) price) * multiplier;
     
            cp.getPointsManager().takePoints(p, points);
            return getDisplayBalance(p, buy, price, clickType);
        }

        @Override
        public String getDisplayBalance(Player p, BSBuy buy, Object price, ClickType clickType) {
            double balance_points = cp.getPointsManager().getPoints(p);
            return cp.getPlaceholderPoints().replace("%"+cp.getName()+"%", MathTools.displayNumber(balance_points, cp.getSpecialDisplayFormatting(), !cp.getPointsManager().usesDoubleValues()));
        }
     
        @Override
        public String getDisplayPrice(Player p, BSBuy buy, Object price, ClickType clickType) {
            return ClassManager.manager.getMultiplierHandler().calculatePriceDisplayWithMultiplier(p, buy, clickType, (Double) price, cp.getPlaceholderPoints().replace("%"+cp.getName()+"%", "%number%"), cp.getSpecialDisplayFormatting(), true);
        }


        @Override
        public String[] createNames() { // the names of the PriceType users can enter in their shop configs
            if (cp == null) {
            return new String[]{"thirdcurrency", "points2", "point2"};
            }else{
                return new String[]{ cp.getName() };
            }
        }

        public boolean supportsMultipliers() {
            return true; // makes RewardTypes like BuyAll possible
        }

        @Override
        public boolean mightNeedShopUpdate() {
            return true; // whether the execution of this PriceType requires the shop to be updated (for example because placeholders might have changed)
        }

        @Override
        public boolean isIntegerValue() {
            return false; // needs to be defined because the class extends BSPriceTypeNumber
        }
     




    How to register own itemdata parts?
    1. Extend the BossShopPro class "ItemDataPart"
    2. Implement all given methods
    3. Create a listener which listens to the "BSRegisterTypesEvent" and creates an instance of your custom ItemDataPart. Additionally, call the "register" method of that instance.

    Example ItemData implementations can be found here.


    Example ItemDataPart:
    Code (Java):
    public class ItemDataPartMaterial extends ItemDataPart {
      public ItemStack transform(ItemStack item, String used_name, String argument)  {
        short durability = 0;
        Material m = Material.STONE;

        if (argument.contains(":")) {
          String[] parts = argument.split(":");
          if (parts.length > 1) {
            durability = (short)InputReader.getInt(parts[1].trim(), 0);
          }
          argument = parts[0].trim();
        }

        m = InputReader.readMaterial(argument);

        if (m == null) {
          ClassManager.manager.getBugFinder().severe("Mistake in Config: '" + argument + "' is not a valid '" + used_name + "'. Unable to find a fitting material.");
          return item;
        }

        item.setType(m);
        item.setDurability(durability);
        return item;
      }

      public int getPriority()  {
        return PRIORITY_MOST_EARLY;
      }

      public boolean removeSpaces()  {
        return true;
      }

      public String[] createNames()  {
        return new String[] { "type", "id", "material" };
      }

      public List<String> read(ItemStack i, List<String> output)  {
        output.add("type:" + i.getType().name());
        return output;
      }

      public boolean isSimilar(ItemStack shop_item, ItemStack player_item, BSBuy buy, Player p)  {
        return shop_item.getType() == player_item.getType();
      }
    }
    Example listener
    Code (Text):
      @EventHandler
      public void onRegister(BSRegisterTypesEvent event)  {
        new ItemDataPartMaterial().register();
      }
  • Loading...
  • Loading...