Tutorial How to create your own customized achievements!

Discussion in 'Resources' started by teej107, Sep 1, 2014.

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

    teej107

    [​IMG]

    This tutorial will show you how to make your own customized achievements for anything you choose.

    Prerequisites:
    1. First things first, you want to add the plugin jar in your build path of your project and add CustomAchievements as a dependency in your plugin.yml.
    2. Next step, start creating your first customized achievement! You'll want to start by creating a class (named whatever you want) that extends CustomAchievement
      PHP:
      public class ExampleAchievement extends CustomAchievement
      {

      }
    3. You might notice that you get an error. Don't panic! We aren't done yet. What we need to do is to create a constructor and inside it needs to call super like this:
      PHP:
      public class ExampleAchievement extends CustomAchievement
      {
          public 
      ExampleAchievement()
          {
              
      // Must call super(name, material);
              
      super("Over 9000"Material.DIAMOND_AXE);
          }

      }
      The first argument of the parameter will be the name of you custom achievement. The second argument is a Material that will represent the achievement and will serve as an icon for the achievement. We'll call this one "Over 9000" and use a Diamond Axe as our material.
    4. What's next? Well there are many options you can use to customize the look of your achievement. Let's go over them:
      PHP:
      setColor(ChatColor.BLUE);
      This sets the color of the achievement text when you are awarded the achievement. This achievement's color will be Blue. The default color of achievements is Yellow if you don't call this method.
    5. PHP:
      getLore().add("IT'S OVER 9000");
      This method gets the lore (A List) or extra info of the achievement. You may show how to earn this achievement in the lore if you wish. However this example won't do that. The default lore of the achievements has "Custom Achievement" in the 0 index of the List. If you wish to replace the lore completely, you may use this method:
      PHP:
      setLore(list);
    6. The last option you may use to change the looks of your achievement is this:
      PHP:
      setDisplayUnachieved(true);
      This method will allow you to hide or show the lore to players who do not have the achievement. We'll make the lore available to all players even if they haven't earned it yet.
    7. Now that we are all done making our customized achievement look pretty and nice, lets show you how a player can earn an achievement. In this example we'll give the player the achievement when they mine their 9001st block.
    8. Let's add a way to keep track of the number of blocks mined for each players. We'll use a HashMap. So far, this is what my class looks like:
      PHP:
      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      import java.util.UUID;

      import org.bukkit.ChatColor;
      import org.bukkit.Material;
      import org.bukkit.entity.Player;
      import org.bukkit.event.EventHandler;
      import org.bukkit.event.block.BlockBreakEvent;

      import com.teej107.customachievement.CustomAchievement;

      public class 
      ExampleAchievement extends CustomAchievement
      {
          
      // Keep track of number of block breaks so the player can earn the
          // achievement.
          //NOTE: You'll have to find your own way to save this to a file if you want it to survive through plugin reloads/server restarts.
          
      private Map<UUIDIntegerblockBreaks;

          public 
      ExampleAchievement()
          {
              
      // Must call super(name, material);
              
      super("Over 9000"Material.DIAMOND_AXE);
              
              
      // Lets set this achievement's color
              // Default color is set to Yellow. Lets make this one Blue.
              
      setColor(ChatColor.BLUE);

              
      // Lets show the requirements for this achievement for the players that
              // do not have it.
              
      setDisplayUnachieved(true);

              
      // We can either add to the current lore or make a brand new one.

              // Replacing the lore...
              //List<String> list = new ArrayList<String>();
              //setLore(list);

              // Adding onto the lore... (with replacing it or not)
              // The default non-replaced lore has "Custom Achievement" at index 0 in
              // the list.
              
      getLore().add("IT'S OVER 9000");

              
      blockBreaks = new HashMap<UUIDInteger>();
          }
      }
    9. Blocks Mined? We'll need a BlockBreakEvent for that. After you have made all of the necessary checks to see if a player has mined the 9001st block, you would call this method:
      PHP:
      giveAchievement(player);
      You don't need to check if the player already has the achievement, the plugin already takes care of that. (Or you would be earning achievements for every number of blocks mined over 9000 in this example)
    10. All done! You have made a customized achievement. Here is the full class.
      PHP:
      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      import java.util.UUID;

      import org.bukkit.ChatColor;
      import org.bukkit.Material;
      import org.bukkit.entity.Player;
      import org.bukkit.event.EventHandler;
      import org.bukkit.event.block.BlockBreakEvent;

      import com.teej107.customachievement.CustomAchievement;

      public class 
      ExampleAchievement extends CustomAchievement
      {
          
      // Keep track of number of block breaks so the player can earn the
          // achievement.
          //NOTE: You'll have to find your own way to save this to a file if you want it to survive through plugin reloads/server restarts.
          
      private Map<UUIDIntegerblockBreaks;

          public 
      ExampleAchievement()
          {
              
      // Must call super(name, material);
              
      super("Over 9000"Material.DIAMOND_AXE);
              
              
      // Lets set this achievement's color
              // Default color is set to Yellow. Lets make this one Blue.
              
      setColor(ChatColor.BLUE);

              
      // Lets show the requirements for this achievement for the players that
              // do not have it.
              
      setDisplayUnachieved(true);

              
      // We can either add to the current lore or make a brand new one.

              // Replacing the lore...
              //List<String> list = new ArrayList<String>();
              //setLore(list);

              // Adding onto the lore... (with replacing it or not)
              // The default non-replaced lore has "Custom Achievement" at index 0 in
              // the list.
              
      getLore().add("IT'S OVER 9000");

              
      blockBreaks = new HashMap<UUIDInteger>();
          }

          
      // No need to have the class implement Listener and no need to register the event.
          // This is already done for you when you register the achievement.
          
      @EventHandler
          
      public void onBlockBreak(BlockBreakEvent event)
          {
              
      Player player event.getPlayer();
              
      UUID uuid player.getUniqueId();

              
      // Check to see if the player has a place in the map.
              
      if (!blockBreaks.containsKey(uuid))
              {
                  
      blockBreaks.put(uuid0);
              }
              
              
      // Adding one to the number of blocks broken
              
      blockBreaks.put(uuidblockBreaks.get(uuid) + 1);

              
      // Lets check to see if the player deserves the achievement!
              
      if (blockBreaks.get(uuid) > 9000)
              {
                  
      // Award the achievement. The method already does checks to see if the player already has it.
                  
      giveAchievement(player);
              }
          }

      }
    [​IMG]
    Here are the JavaDocs: CustomAchievementJavaDoc
    I apologize in advance if I didn't make the JavaDocs clear enough.
    Got a problem with this tutorial? Leave a comment. I also appreciate constructive criticism.

    I also forgot one big step.
    Here is how you register your achievement:
    The getInstance() method requires a Plugin in the parameters.

    I've updated the API. To get access to it, just call CAPluginAPI.getInstance(); It does not require a plugin in the parameters. I have deprecated the old getInstance() method but it is the exact same as the new one. All of the code I posted above is still legit and will work with the updated version.

    PHP:
    CAPluginAPI ca CAPluginAPI.getInstance();
    ca.registerAchievement(customAchievementplugin);
    Then you call .registerAchievement(CustomAchievement, Plugin). You do not need to register your CustomAchievement as an Event. The plugin does this when you call .registerAchievement().

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 10, 2016
    B4U7, GrandmaJam, nelson2tm and 4 others like this.
  2. Offline

    MiniDigger

    teej107 looks pretty cool, will try it out, when the plugin gets approved (or you send me a beta build :D)
    But I don't realy like bobacadodl's JSONChatLib, I prefer mkremins's fanciful. Is there a ways to implement that or give the option to pass a json string to getMessage?
    EDIT:
    Just saw, that it was just a getter without a setter, so I think the method is internal used I so I don't care about what you use. A costumizable message would be cool tho :D
     
  3. Offline

    teej107

    Yes, you do not need to use the getMessage() method. It is used by the CAPluginAPI. I prefer using bobacadodl's JSONChatLib as I never has much luck with fanciful. In fact for some reason fanciful didn't display the JSON message correctly. I feel like allowing an option for custom text would detract from the Minecraft feel of being awarded achievements. The current text is exactly the way Minecraft would announce it.
     
  4. Offline

    MiniDigger

    teej107 you should the developer or user decide that ;D
     
  5. Offline

    teej107

    Eh, still not fond of that idea but I can add it in a future update. You can always override the method to return a custom message.
     
  6. Offline

    The Fancy Whale

    Sadly, because you put these into large code blocks, people are not going to read this. People will probably copy paste the code. However, it looks cool so nice job!
     
  7. Offline

    teej107

    Yeah I put that into account. People will always copy and paste posted code. The public methods and JavaDocs (hopefully) should be pretty straight forward. I tried to make this as easy as possible to make an achievement.
     
  8. Offline

    MrDplugins

    teej107 maybe a pre-release download link? or a way to do this without the CustomAchivements Jar?
     
  9. Offline

    teej107

    Since BukkitDev takes a while: Download Link (non-Bukkit Dev).
     
  10. Offline

    MrDplugins

    teej107 Thanks!

    EDIT: SOLVED

    teej107 How Do I remove the "Over 9000" Achievement from it being their by default?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 10, 2016
  11. Offline

    teej107

    EDIT: What do you mean?
     
  12. Offline

    MrDplugins

    teej107 when you run the command /acheivementview it opens the gui but theres a white glass pane with the "Over 9000" acheivement on it.
     
  13. Offline

    teej107

    MrDplugins Yes. The white glass represents that you haven't earned the achievement yet. When you have earned it, the Material you have specified in the constructor of your achievement will show instead of the white stained glass.
     
  14. Offline

    MrDplugins

    teej107 I know that but how do I REMOVE that achievement?
     
  15. Offline

    teej107

    Woops, turns out I forgot to remove the code where I registered the example achievement. It is now removed and I have re-uploaded the jar
     
  16. Offline

    LCastr0

    This is cool. I am doing a 'bigger' version of it, thanks for the 'idea' and method (I am doing it a bit different though)
     
    teej107 likes this.
  17. Offline

    teej107

    Would love to see how it turns out.
     
  18. Offline

    MrDplugins

  19. Offline

    teej107

    However, the new build is awaiting approval on BukkitDev.
     
  20. Offline

    ChipDev

    Why do we want another instance? :l
    Otherwise, good tutorial
     
  21. Offline

    AoH_Ruthless

    You need an instance of the API to be able to use it in your code.
     
  22. Offline

    ChipDev

    I know, but it would be nicer to be able to just use the Bukkit API to do this.
     
  23. Offline

    teej107

    You can. The thing with this API is that the plugin that comes with it keeps track of the achievements that the players earn and provides an inventory GUI of all the achievements.
     
    ChipDev likes this.
  24. Offline

    Skionz

    teej107 I haven't seen this tutorial until now but I have to say, this is a very unique idea! Nice tutorial :D
     
    nelson2tm, ChipDev and teej107 like this.
  25. Offline

    nelson2tm

    @teej107 How can I give the player a reward when he gets the achievement with /ca give <achievement> <player>?
     
  26. Offline

    teej107

    @nelson2tm There is no way to do this within the API. You will have to listen in a PlayerCommandPreprocessEvent. Maybe I should add something in for that.
     
Thread Status:
Not open for further replies.

Share This Page