Skip to content

Advancements

fren_gor edited this page Aug 11, 2021 · 33 revisions

Advancement Classes

UltimateAdvancementAPI provides various classes to work with advancements. There are four types of classes:

  • Fundamental Classes, which are used throughout the API, as the Advancement class.
  • Abstract Classes, which are used to define a standard to work with the API, as the AbstractMultiTasksAdvancement class.
  • Implementation Classes, which are an implementation of an abstract class, as the MultiTasksAdvancement class. These classes only provide a default implementation, so any user can make their own.
  • Utility Classes, which are used by other advancement classes, as the TaskAdvancement class that is used by MultiTasksAdvancement to represent a task.

Let's see them in detail.

Fundamental Classes

There are five fundamental classes: Advancement, RootAdvancement, and BaseAdvancement.

Advancement

Advancement class is the super class of every advancement. It is extended only by RootAdvancement and BaseAdvancement, which will be explained later. Thus, to make a custom Advancement, it is only possible to extend one of RootAdvancement, BaseAdvancement, or every sub-class of them. It is not possible to extend the Advancement class directly. Since advancements are

The Advancement class is the parent class of every advancement. It provides the basic methods and fields to work with advancements. It is extended only by RootAdvancement and BaseAdvancement (which will be explained in the next paragraphs), and no other class can extend it. This makes sure the only possible types of Advancements are those two. Every other advancement child class extends RootAdvancement or BaseAdvancement.

Two example advancements

Let's go over what information Advancement class stores/provides (or, which properties every advancement has):

  • Every advancement is represented by a unique namespaced key (i.e. "advtab1:myadvancement"), which is stored into an AdvancementKey instance. It is composed by a namespace (the part before colon :), which is the namespace of their advancement tab, and a key (the part after colon :). So, for example, an advancement with key "mytab:myadv" is an advancement inside "mytab" tab and with key "myadv". Also, every advancement inside a tab must have a unique key. Note that the namespaced key is not visible to the players in the advancement GUI.

Advancement is an abstract class, it can't be extended but is it is important to undestand how this API works

Ogni advancement ha una advancement key univoca, formata da "nome_tab:id_advancement".

La parte visibile dell' advancement viene descritta nella classe dell' AdvancementDisplay; per saperne di più visita questa pagina.

Il maxCriteria indica quante volte deve esser fatta un'azione o una quantità di qualcosa. Di solito viene mostrato dopo il titolo dell' andvancement, se visibile, perchè quando questo valore è settato su 1, non viene mostrato nulla.

maxCriteria at 1:

maxCriteria at 3:

Per la gestione degli eventi e per gestire l' avanzamento dell' advancement si utilizza l'api degli eventi EventAPI (link alla pagina)

Visibility Ogni advancement può essere mostrato o nascosto ad un player, questo viene deciso nel metodo isVisible() che può essere sovrascritto e di conseguenza modificato. Oppure è possibile creare un' interfaccia che estende IVisibility per creare uno standard di visibilità
Alcune interfacce sono messe a disposizione e possono facilitare la gestione della visibilità:
HiddenVisibility - l' advancement è visibile Se la progressione dell' advancement è maggiore di 0 o è stato completato
ParentGrantedVisibility - l' advancement è visibile Se il Parent o i Parents dell' advancement sono mostrati
VanillaVisibility - l' advancement è visibile se il parent o il grandparent sono visibili
Se non si estende nulla o non viene sovrascritto il metodo, l' advancement risuliterà sempre visibile

rootadvancement:

the rootadvancement is the main advancement, where all the others gradually connect. it is present only once for each tab Al suo interno si trova il path per il backgound del tab. Ad esempio per settare la texture del blocco di stone: "textures/block/stone.png"

La texture può variare in base alle texture pack del player.

un piccolo esempio di come usare i rootadvancement

AdvancementDisplay rootDisplay = new AdvancementDisplay(Material.GRASS, "Example root", AdvancementFrameType.TASK, false, false, 0, 0, "description");

root = new RootAdvancement(advancementTab, "root", rootDisplay, "textures/block/stone.png");

BaseAdvancement
Il base advancement definisce un classico advancement con tutte le sue funzionalità

Un esempio:

public class Pickaxe extends BaseAdvancement implements ParentGrantedVisibility {
    public Pickaxe( @NotNull String key, @NotNull AdvancementDisplay display, @NotNull Advancement parent) {
        super(key, display, parent);

        registerEvent(CraftItemEvent.class, e -> {
            Player p = (Player) e.getWhoClicked();
            if (isVisible(p) && !isGranted(p) && e.getRecipe().getResult().getType() == Material.STONE_PICKAXE) {
                incrementTeamCriteria(p);
            }
        });

    }

    @Override
    public void giveReward(@NotNull Player player) {
        //things
    }
}

TaskAdvancement I TaskAdvancement sono degli avancement che vengono salvati su database ma non possono essere mostrati ai player nei tab. Servono a tenere traccia di task o obiettivi e questi non vogliono essere mostrati ai player; ma utili nello sviluppo del codice. Richiedono come parametro un' istanza del multitask

MultiTask Il completamento di questo advancement richiede il completamento di alcuni task (taskadvancement). Il maxCriteria mostrato è la somma dei maxCriteria dei task e la progression mostrata è la somma delle progressione dei task. I task non devono essere registrati nel tab ma nel multitask

code:

 private AdvancementTab advancementTab;
    private Root root;

    @Override
    public void onEnable() {

        Bukkit.getPluginManager().registerEvents(this, this);

        //if you want to the enable SqlLite
        main.enableSQLite(new File(getDataFolder(), "sqlLiteDbName"));

        advancementTab = UltimateAdvancementAPI.getInstance(this).createAdvancementTab("a_tab");

        AdvancementDisplay rootDisplay = new AdvancementDisplay(Material.GRASS_BLOCK, "Root         §c", AdvancementFrameType.TASK, false, false, 0, 0, "Your adventure start here");

        root = new Root(advancementTab, "root", rootDisplay, "textures/block/stone.png");

        AdvancementDisplay ad = new AdvancementDisplay(Material.ACACIA_LOG, "Dig!", AdvancementFrameType.TASK, true, true, 1, 0, "-Break 2 of Dirt", "-Break 4 of stone");

        MultiTasksExample multiTasksExample = new MultiTasksExample("eg", ad, root, 6);

      
        DirtTask dirtTask = new DirtTask("dirt", multiTasksExample, 2);
        StoneTask stoneTask = new StoneTask("stone", multiTasksExample, 4);

        multiTasksExample.registerTasks(dirtTask, stoneTask);

        advancementTab.registerAdvancements(root, multiTasksExample);

    }

    @EventHandler
    public void onJoin(PlayerLoadingCompletedEvent e) {

        Player p = e.getPlayer();
        advancementTab.showTab(p);
        root.grant(p);

    }
public class DirtTask extends TaskAdvancement {

    public DirtTask(@NotNull String key, @NotNull AbstractMultiTasksAdvancement multitask, @Range(from = 1L, to = 2147483647L) int maxCriteria) {
        super(key, multitask, maxCriteria);

        registerEvent(BlockBreakEvent.class, e -> {
            Player p = e.getPlayer();
            if (isVisible(p) && !isGranted(p) && e.getBlock().getType() == Material.DIRT) {
                incrementTeamCriteria(p);
            }
        });
    }
}
public class MultiTasksExample extends MultiTasksAdvancement {
    public MultiTasksExample(@NotNull String key, @NotNull AdvancementDisplay display, @NotNull Advancement parent, @Range(from = 1L, to = 2147483647L) int maxCriteria) {
        super(key, display, parent, maxCriteria);

    }

    @Override
    public void giveReward(@NotNull Player player) {

        player.sendMessage("You did it! You won nothing");
    }
}
public class StoneTask extends TaskAdvancement {

    public StoneTask(@NotNull String key, @NotNull AbstractMultiTasksAdvancement multitask, @Range(from = 1L, to = 2147483647L) int maxCriteria) {
        super(key, multitask, maxCriteria);

        registerEvent(BlockBreakEvent.class, e -> {
            Player p = e.getPlayer();
            if (isVisible(p) && !isGranted(p) && e.getBlock().getType() == Material.STONE) {
                incrementTeamCriteria(p);
            }
        });
    }
}

FakeAdvancement
I FakeAdvancement sono degli advancement che vengono creati ed utilizzati solo per ricreare linee visibili e collegare più advancement. Vengono usati nell'api per la gestione dei multiparent. Questi non vengono salvati sul database

Multiparent Sono advancement che hanno più parent, ovvero quando hanno più advancement che convergono nel multiparent. Vengono utilizzati dei FakeAdvancement per mostrare le linee mancanti. Il root non può essere uno dei genitori. I parent devono essere registrati nel tab prima del multiparent.

esempio:

private AdvancementTab advancementTab;
    private Root root;

    @Override
    public void onEnable() {

        Bukkit.getPluginManager().registerEvents(this, this);

        //if you want to the enable SqlLite
        main.enableSQLite(new File(getDataFolder(), "sqlLiteDbName"));

        advancementTab = UltimateAdvancementAPI.getInstance(this).createAdvancementTab("atab");

        AdvancementDisplay rootDisplay = new AdvancementDisplay(Material.GRASS_BLOCK, "Root         §c", AdvancementFrameType.TASK, false, false, 0, 1, "Your adventure start here");

        root = new Root(advancementTab, "root", rootDisplay, "textures/block/stone.png");

        AdvancementDisplay ad = new AdvancementDisplay(Material.ACACIA_LOG, "MultiParent!", AdvancementFrameType.TASK, true, true, 2, 1);

        AdvancementDisplay base = new AdvancementDisplay(Material.LAVA_BUCKET, "Advancement", AdvancementFrameType.TASK, true, true, 1, 0);
        AdvancementDisplay base2 = new AdvancementDisplay(Material.WATER_BUCKET, "Advancement", AdvancementFrameType.TASK, true, true, 1, 2);

        Adv adv1 = new Adv( "adv1", base, root);
        Adv adv2 = new Adv("adv2", base2, root);

        MultiparentExample multiParentsAdvancement = new MultiparentExample( "multipare", ad, adv1, adv2);

        advancementTab.registerAdvancements(root, adv1 , adv2,multiParentsAdvancement);

    }

    @EventHandler
    public void onJoin(PlayerLoadingCompletedEvent e) {

        Player p = e.getPlayer();
        advancementTab.showTab(p);
        root.grant(p);

    }
public class Adv extends BaseAdvancement {
    public Adv( @NotNull String key, @NotNull AdvancementDisplay display, @NotNull Advancement parent) {
        super( key, display, parent);
    }
    //todo
}
public class MultiparentExample extends MultiParentsAdvancement {
    public MultiparentExample(@NotNull String key, @NotNull AdvancementDisplay display, @NotNull BaseAdvancement... parents) {
        super(key, display, parents);
    }

    //todo
}