API - Historical

Applied By Blackixx: Nov 27, 2018 at 11:33 AM

API
How to hook into BossShopPro?
First of all add the BossShopPro.jar to your libraries.
You can access the API following way:
Code (Text):
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 Plugin
 
        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
    }

}
   
Opening a shop
Code (Text):
    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 (Text):
    //Example: InventoryEvent
        if(bs.getAPI().isValidShop(event.getInventory())){
            //Do Shop Inventory Action
        }else{
            //Rest
        }
Adding a shopitem to a shop
Code (Text):
        //Create a custom BSBuy (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 BossShop

plugin.yml:
Code (Text):
loadbefore: [BossShop]
Extend the BSPointsPlugin class by implementing all neccessary methods.

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

How to create an Addon?
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 (Text):
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
        //These 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 (Text):
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?
First of all you need to create the reward class:
Code (Text):
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 (Text):
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 successful 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
Code (Text):
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 ItemDataPart:
Code (Text):
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();
  }







More info material cooming soon.