Solved Checking and awarding advancements

Discussion in 'Spigot Plugin Development' started by SirPsp, May 20, 2017.

  1. Can someone please tell me how to check if a player has completed an advancement, and also how to award/revoke an advancement?
     
  2. Code (Text):
    Player p = e.getPlayer();

    //check for achievement
    p.hasAchievement(NAME)

    //give achievement
    p.awardAchievement(NAME);

    //remove achievement
    p.removeAchievement(NAME);
     
  3. Those are achievements. I'm asking about 1.12 advancements.
     
  4. I have seen that but I'm not sure how to use it.
     
  5. I ran into this same problem. Currently, I still haven't figured out what the NamespacedKey is used for, but I made this small bit of code that works by getting an advancement from all 'registered' ones and then checking whether the player finished that one.

    The string name should be something that is available as an advancement: minecraft:husbandry/break_diamond_hoe for example.
    You can however, if you made custom advancements, also check these. Lets say that I made the advancement "steampunk:story/riseofthemachines", the getAdvancement("steampunk:story/riseofthemachines") method would find that too.

    Hope you can find some good use for it!
    P.S I would appreciate it if someone would show a simpler way (Possibly explaining what NamespacedKey is used for :))

    Code (Text):
    import java.util.Iterator;

    import org.bukkit.Bukkit;
    import org.bukkit.advancement.Advancement;
    import org.bukkit.advancement.AdvancementProgress;
    import org.bukkit.entity.Player;

    public class UtilTechTree {

        public static boolean hasAdvancement(Player player, String name) {
            // name should be something like minecraft:husbandry/break_diamond_hoe
            Advancement a = getAdvancement(name);
            if(a == null){
                // advancement does not exists.
                return false;
            }
            AdvancementProgress progress = player.getAdvancementProgress(a);
            // getting the progress of this advancement.
            return progress.isDone();
            //returns true or false.
        }

        public static Advancement getAdvancement(String name) {
            Iterator<Advancement> it = Bukkit.getServer().advancementIterator();
            // gets all 'registered' advancements on the server.
            while (it.hasNext()) {
                // loops through these.
                Advancement a = it.next();
                if (a.getKey().toString().equalsIgnoreCase(name)) {
                    //checks if one of these has the same name as the one you asked for. If so, this is the one it will return.
                    return a;
                }
            }
            return null;
        }
    }
    Edit #1: To grant and revoke advancements, I would run the commands:
    - /advancement grant <player> only <name>
    - /advancement revoke <player> only <name>
    Simply using a Bukkit.dispatchCommand(Bukkit.getConsoleSender, "command");

    Seems a bit cheeky, but as far as I know, there is no 'better' way to do so yet!
     
    #6 JustDJplease, May 25, 2017
    Last edited: May 25, 2017
  6. Oh I forgot about this thread, I assumed nobody would help.

    I did figure it out, pretty much the same way you posted, but thanks.
    I also didn't use NamespacedKey because I wasn't sure about it, and that's what was confusing me in the first place. I thought it should be simpler than doing this.

    Code (Text):
        public static boolean hasAdvancement(Player player, String achname){
            Advancement ach = null;
            for (Iterator<Advancement> iter = Bukkit.getServer().advancementIterator(); iter.hasNext(); ) {
                Advancement adv = iter.next();
                if (adv.getKey().getKey().equalsIgnoreCase(achname)){
                    ach = adv;
                    break;
                }
            }
            AdvancementProgress prog = player.getAdvancementProgress(ach);
            if (prog.isDone()){
                return true;
            }
            return false;
        }
     
  7. Bit of a necro post, but could be useful for others searching for info on custom advancements...

    Here's a method I wrote for the TARDIS plugin that uses a NamespacedKey:

    Code (Text):

    public static void grantAdvancement(ADVANCEMENT adv, Player player) {
            NamespacedKey nsk = new NamespacedKey(TARDIS.plugin, "drwho/" + adv.getConfigName());
            Advancement a = TARDIS.plugin.getServer().getAdvancement(nsk);
            if (a != null) {
                AdvancementProgress avp = player.getAdvancementProgress(a);
                if (!avp.isDone()) {
                    TARDIS.plugin.getServer().dispatchCommand(TARDIS.plugin.getConsole(), "advancement grant " + player.getName() + " only tardis:drwho/" + adv.getConfigName());
                }
            } else {
                player.sendMessage(ChatColor.YELLOW + "Achievement Get!");
                player.sendMessage(ChatColor.WHITE + TARDIS.plugin.getAchievementConfig().getString(adv.getConfigName() + ".message"));
            }
        }
     
    Here's a really good thread on writing custom advancements - http://www.minecraftforum.net/forum...368-1-12-custom-advancements-aka-achievements

    As a reference, my directory structure for the TARDIS custom advancements is:

    Code (Text):
    world/data/advancements/tardis/drwho/<json files go here>
    custom_advancement_toast.jpg custom_advancements.jpg
     
    #8 eccentric, Aug 11, 2017
    Last edited: Aug 11, 2017
    • Useful Useful x 5