Tutorial [Tutorial] How to create a Kit Plugin

Discussion in 'Resources' started by AoH_Ruthless, Mar 2, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    AoH_Ruthless

    Hello! While there are other kit tutorials out there, I feel none of them do justice to the complexity of what you can actually do with kits. Either other authors do not go in-depth or do not explain their code.

    Kits have a variety of uses in today's plugins - They are helpful for minigames, as a standalone plugin, or more!

    1) First we need to make a separate class for the Kits.

    Code:java
    1. /**
    2. * @author Anand
    3. *
    4. */
    5. public class KitsManager
    6. {
    7. private /*Your Main Class*/ plugin;
    8.  
    9. /**
    10.   * Our constructor.
    11.   * @param plugin
    12.   */
    13. public KitsManager(/*Your Main Class*/ plugin) {
    14. this.plugin = plugin;
    15. }
    16.  
    17. public /*Your Main Class*/ getPlugin() {
    18. return plugin;
    19. }
    20. }


    2) Now, I am going to make my method to create Kits. For this tutorial, I will be creating kits based on the items the player has in their inventory.

    Code:java
    1. import java.util.ArrayList;
    2. import java.util.HashMap;
    3. import java.util.List;
    4. import java.util.Map;
    5.  
    6. import org.bukkit.Material;
    7. import org.bukkit.configuration.file.FileConfiguration;
    8. import org.bukkit.enchantments.Enchantment;
    9. import org.bukkit.entity.Player;
    10. import org.bukkit.inventory.ItemStack;
    11. import org.bukkit.inventory.PlayerInventory;
    12. /**
    13. *
    14. * @author Anand
    15. *
    16. */
    17. public class KitsManager
    18. {
    19. private Main plugin;
    20.  
    21. /**
    22.   * Our constructor.
    23.   * @param plugin
    24.   */
    25. public KitsManager(Main plugin) {
    26. this.plugin = plugin;
    27. }
    28.  
    29. /**
    30.   * This is the method used to create kits.
    31.   *
    32.   * @param p
    33.   * ~ The player who created the kit.
    34.   * @param kitName
    35.   * ~ The string which will from hereafter be the name of the kit.
    36.   */
    37. public void createKit(Player p, String kitName) {
    38. FileConfiguration config = plugin.getConfig(); // Replace with the configuration file YOU want to use.
    39. PlayerInventory inv = p.getInventory();
    40.  
    41. // Now, before creating a kit, we need to make sure that the kit does not already exist.
    42. if (config.getConfigurationSection("kits." + kitName) != null) {
    43. p.sendMessage(kitName + " already exists!");
    44. return;
    45. }
    46.  
    47. // We'll be using this path a lot to set items and stuff for the kits.
    48. String path = "kits." + kitName + ".";
    49. // Create a new Configuration Section
    50. config.createSection("kits." + kitName);
    51.  
    52. /*
    53.   * This is our for loop. It iterates through all the main inventory slots (Slots 0 - 35).
    54.   * If a player has an item there, it will set it in the config.
    55.   */
    56. for (int i = 0; i < 36; i++) {
    57. ItemStack is = inv.getItem(i);
    58.  
    59. // If null or air, continue, because we don't care anymore since that just wastes space in the config.
    60. if (is == null || is.getType() == Material.AIR)
    61. continue;
    62.  
    63. // For each number, representing the inventory slot, we'll need to set several things such as the material.
    64. String slot = path + "items." + i;
    65. // Material.GOLD_INGOT ==> gold_ingot - This is unnecessary but looks better in the config and easier to read (in my opinion)
    66. config.set(slot + ".type", is.getType().toString().toLowerCase());
    67. config.set(slot + ".amount", is.getAmount());
    68.  
    69. // Do not go any further if the item does not have any item meta.
    70. if (!is.hasItemMeta())
    71. continue;
    72.  
    73. /*
    74.   * Now, we are just going to be checking individually if there is a name, lore, etc..
    75.   */
    76. if (is.getItemMeta().hasDisplayName())
    77. config.set(slot + ".name", is.getItemMeta().getDisplayName());
    78.  
    79. if (is.getItemMeta().hasLore())
    80. config.set(slot + ".lore", is.getItemMeta().getLore());
    81.  
    82. // We are going to be adding enchantments as a stringlist.
    83. if (is.getItemMeta().hasEnchants()) {
    84. Map<Enchantment, Integer> enchants = is.getEnchantments();
    85. List<String> enchantList = new ArrayList<String>();
    86. for (Enchantment e : is.getEnchantments().keySet()) {
    87. int level = enchants.get(e);
    88. enchantList.add(e.getName().toLowerCase() + ":" + level);
    89. }
    90. config.set(slot + ".enchants", enchantList);
    91. }
    92. // While 'continue;' isn't always necessary, I feel it's good practice to put it.
    93. continue;
    94. }
    95.  
    96. /*
    97.   * Since ternary operators can be confusing: If the armor piece is not
    98.   * null, set it to the player's helmet. If it is null, set the config
    99.   * key to air (representing the material air).
    100.   *
    101.   * Material.DIAMOND_HELMET => diamond_helmet
    102.   */
    103. config.set(path + "armor.helmet", inv.getHelmet() != null ? inv
    104. .getHelmet().getType().toString().toLowerCase() : "air");
    105.  
    106. config.set(path + "armor.chestplate", inv.getChestplate() != null ? inv
    107. .getChestplate().getType().toString().toLowerCase() : "air");
    108.  
    109. config.set(path + "armor.leggings", inv.getLeggings() != null ? inv
    110. .getLeggings().getType().toString().toLowerCase() : "air");
    111.  
    112. config.set(path + "armor.boots", inv.getBoots() != null ? inv
    113. .getBoots().getType().toString().toLowerCase() : "air");
    114.  
    115. plugin.saveConfig();
    116. // Therefore, Operators have all kits by default.
    117.  
    118.  
    119. //NOTE: For the purpose of this tutorial, I will not be covering per-kit permissions unless I get many requests to add it.
    120. }
    121.  
    122. public Main getPlugin() {
    123. return plugin;
    124. }
    125. }


    3) I will not be showing a method to remove Kits. It's a basic method - Just check if the kit exists, and then set the configuration section to null.
    But, we need a method to give players kits:


    Code:java
    1. import java.util.ArrayList;
    2. import java.util.Arrays;
    3. import java.util.HashMap;
    4. import java.util.List;
    5. import java.util.Map;
    6.  
    7. import org.bukkit.ChatColor;
    8. import org.bukkit.Material;
    9. import org.bukkit.configuration.ConfigurationSection;
    10. import org.bukkit.configuration.file.FileConfiguration;
    11. import org.bukkit.enchantments.Enchantment;
    12. import org.bukkit.entity.Player;
    13. import org.bukkit.inventory.ItemStack;
    14. import org.bukkit.inventory.PlayerInventory;
    15. import org.bukkit.inventory.meta.ItemMeta;
    16. /**
    17. *
    18. * @author Anand
    19. *
    20. */
    21. public class KitsManager
    22. {
    23. private Main plugin;
    24.  
    25. /**
    26.   * Our constructor.
    27.   * @param plugin
    28.   */
    29. public KitsManager(Main plugin) {
    30. this.plugin = plugin;
    31. }
    32.  
    33. /**
    34.   * This is the method used to create kits.
    35.   *
    36.   * @param p
    37.   * ~ The player who created the kit.
    38.   * @param kitName
    39.   * ~ The string which will from hereafter be the name of the kit.
    40.   */
    41. public void createKit(Player p, String kitName) {
    42. FileConfiguration config = plugin.getConfig(); // Replace with the configuration file YOU want to use.
    43. PlayerInventory inv = p.getInventory();
    44.  
    45. // Now, before creating a kit, we need to make sure that the kit does not already exist.
    46. if (config.getConfigurationSection("kits." + kitName) != null) {
    47. p.sendMessage(kitName + " already exists!");
    48. return;
    49. }
    50.  
    51. // We'll be using this path a lot to set items and stuff for the kits.
    52. String path = "kits." + kitName + ".";
    53. // Create a new Configuration Section
    54. config.createSection("kits." + kitName);
    55.  
    56. /*
    57.   * This is our for loop. It iterates through all the main inventory slots (Slots 0 - 35).
    58.   * If a player has an item there, it will set it in the config.
    59.   */
    60. for (int i = 0; i < 36; i++) {
    61. ItemStack is = inv.getItem(i);
    62.  
    63. // If null or air, continue, because we don't care anymore since that just wastes space in the config.
    64. if (is == null || is.getType() == Material.AIR)
    65. continue;
    66.  
    67. // For each number, representing the inventory slot, we'll need to set several things such as the material.
    68. String slot = path + "items." + i;
    69. // Material.GOLD_INGOT ==> gold_ingot - This is unnecessary but looks better in the config and easier to read (in my opinion)
    70. config.set(slot + ".type", is.getType().toString().toLowerCase());
    71. config.set(slot + ".amount", is.getAmount());
    72.  
    73. // Do not go any further if the item does not have any item meta.
    74. if (!is.hasItemMeta())
    75. continue;
    76.  
    77. /*
    78.   * Now, we are just going to be checking individually if there is a name, lore, etc..
    79.   */
    80. if (is.getItemMeta().hasDisplayName())
    81. config.set(slot + ".name", is.getItemMeta().getDisplayName());
    82.  
    83. if (is.getItemMeta().hasLore())
    84. config.set(slot + ".lore", is.getItemMeta().getLore());
    85.  
    86. // We are going to be adding enchantments as a stringlist.
    87. if (is.getItemMeta().hasEnchants()) {
    88. Map<Enchantment, Integer> enchants = is.getEnchantments();
    89. List<String> enchantList = new ArrayList<String>();
    90. for (Enchantment e : is.getEnchantments().keySet()) {
    91. int level = enchants.get(e);
    92. enchantList.add(e.getName().toLowerCase() + ":" + level);
    93. }
    94. config.set(slot + ".enchants", enchantList);
    95. }
    96. // While 'continue;' isn't always necessary, I feel it's good practice to put it.
    97. continue;
    98. }
    99.  
    100. /*
    101.   * Since ternary operators can be confusing: If the armor piece is not
    102.   * null, set it to the player's helmet. If it is null, set the config
    103.   * key to air (representing the material air).
    104.   *
    105.   * Material.DIAMOND_HELMET => diamond_helmet
    106.   */
    107. config.set(path + "armor.helmet", inv.getHelmet() != null ? inv
    108. .getHelmet().getType().toString().toLowerCase() : "air");
    109.  
    110. config.set(path + "armor.chestplate", inv.getChestplate() != null ? inv
    111. .getChestplate().getType().toString().toLowerCase() : "air");
    112.  
    113. config.set(path + "armor.leggings", inv.getLeggings() != null ? inv
    114. .getLeggings().getType().toString().toLowerCase() : "air");
    115.  
    116. config.set(path + "armor.boots", inv.getBoots() != null ? inv
    117. .getBoots().getType().toString().toLowerCase() : "air");
    118.  
    119. plugin.saveConfig();
    120. // Therefore, Operators have all kits by default.
    121.  
    122.  
    123. //NOTE: For the purpose of this tutorial, I will not be covering per-kit permissions unless I get many requests to add it.
    124. }
    125.  
    126. /*
    127.   * This method has deprecation warnings: p.updateInventory() is the only deprecated method.
    128.   */
    129. @SuppressWarnings("deprecation")
    130. public void giveKit(Player p, String kitName) {
    131. FileConfiguration config = plugin.getConfig();
    132. // Sanity-checks
    133. if (config.getConfigurationSection("kits." + kitName) == null) {
    134. p.sendMessage(kitName + " does not exist!");
    135. return;
    136. }
    137.  
    138. // Clear the player's inventory so they don't have extra items
    139. p.getInventory().clear();
    140. // Again, we need this path.
    141. String path = "kits." + kitName + ".";
    142. // Because it exists, we can use the configuration section.
    143. ConfigurationSection s = config.getConfigurationSection(path + "items");
    144. // Loop through the different keys directly next in line, so to speak.
    145. for (String str : s.getKeys(false)) {
    146. int slot = Integer.parseInt(str);
    147. // Return (continue) if the slot is an invalid number.
    148. if (0 > slot && slot > 36)
    149. return;
    150.  
    151. // Just cast some variables for easy use. Our null checks are later on.
    152. String string = path + "items." + slot + ".";
    153. String type = config.getString(string + "type");
    154. String name = config.getString(string + "name");
    155. List<String> lore = config.getStringList(string + "lore");
    156. List<String> enchants = config.getStringList(string + "enchants");
    157. int amount = config.getInt(string + "amount");
    158.  
    159. // If you remember, we converted the name of the material to
    160. // lowercase. Because it's an enum we need to reconvert it.
    161. ItemStack is = new ItemStack(Material.matchMaterial(type.toUpperCase()), amount);
    162. ItemMeta im = is.getItemMeta();
    163.  
    164. // Continue if there is no itemMeta.
    165. if (im == null)
    166. continue;
    167.  
    168. if (name != null)
    169. im.setDisplayName(ChatColor.translateAlternateColorCodes('&', name));
    170.  
    171. if (lore != null)
    172. im.setLore(Arrays.asList(ChatColor.translateAlternateColorCodes('&', lore.toString())));
    173.  
    174. if (enchants != null) {
    175. // We attached enchantments to their levels - Now we need to
    176. // splice it. So we need to loop through each string list.
    177. for (String s1 : enchants) {
    178. String[] indiEnchants = s1.split(":");
    179. im.addEnchant(Enchantment.getByName(indiEnchants[0].toUppercase), Integer.parseInt(indiEnchants[1]), true);
    180. }
    181. }
    182.  
    183. is.setItemMeta(im);
    184. p.getInventory().setItem(slot, is);
    185. }
    186.  
    187. // We also need to give them armor.
    188. String helmet = config.getString(path + "armor.helmet").toUpperCase();
    189. String chestplate = config.getString(path + "armor.chestplate").toUpperCase();
    190. String leggings = config.getString(path + "armor.leggings").toUpperCase();
    191. String boots = config.getString(path + "armor.boots").toUpperCase();
    192.  
    193. // If each is null, set their armor piece to air. Else, set it to the config key.
    194. p.getInventory().setHelmet(new ItemStack(helmet != null ? Material.matchMaterial(helmet) : Material.AIR));
    195. p.getInventory().setChestplate(new ItemStack(chestplate != null ? Material.matchMaterial(chestplate) : Material.AIR));
    196. p.getInventory().setLeggings(new ItemStack(leggings != null ? Material.matchMaterial(leggings) : Material.AIR));
    197. p.getInventory().setBoots(new ItemStack(boots != null ? Material.matchMaterial(boots) : Material.AIR));
    198.  
    199. p.updateInventory();
    200. }
    201.  
    202. public Main getPlugin() {
    203. return plugin;
    204. }
    205. }



    In conclusion, this tutorial shows you how to create kits, and give them based on the player's inventory. In your onCommand, (or wherever), you can give kits to the player and have them create it. As I said, a removeKit method would simply be just setting the ConfigurationSection to null.

    Please refrain from copying and pasting this code. It is crucial that you understand how this code works.

    This tutorial is not complete! I hope to add some more regarding Kit signs, and maybe other features.

    Tell me what you thought so far! I need feedback :)

    Reserved.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 7, 2016
    TeamJesus, KaptanAykin and bennie3211 like this.
  2. Offline

    HungerCraftNL

    Looks great!
     
    AoH_Ruthless likes this.
  3. Offline

    AoH_Ruthless

  4. Offline

    AoH_Ruthless

    Enchantments were not working properly in createKit() because I set enchantments to a new HashMap rather than the itemstack's enchantments. That is fixed along with standardizing enchantments (Setting them to lowercase.)
     
  5. Offline

    iAmGuus

    Nice! Will keep this for the KitPvP plugin im creating for my server!
     
  6. Offline

    Bammerbom

    It looks like this doenst save the data (durability)
     
  7. Offline

    AoH_Ruthless

    Bammerbom
    Hmm nice observation. I will try to add that later.
     
Thread Status:
Not open for further replies.

Share This Page