-
Notifications
You must be signed in to change notification settings - Fork 7
AdvancementTab
AdvancementTab objects represent a tab in the minecraft advancement GUI. They are used to register advancements in order to be sent to the players.
An instance can be obtained using:
UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(plugin);
AdvancementTab tab = api.createAdvancementTab("tabnamespace");
Every tab must have a different namespace (it can be thought as an identifier, so it must be unique).
As can be noticed, no advancement is required to create an AdvancementTab. This is because Advancements require an AdvancementTab in their constructor, so they cannot be already present in the tab.
Thus, a newly created tab cannot be shown to any player, since it doesn't contain any advancement yet.
The AdvancementTab in this state is not initialised
and almost every method cannot be called without resulting in an IllegalStateException
.
It is initialised
by calling the AdvancementTab#registerAdvancements(RootAdvancement root, BaseAdvancement... advancements)
method, providing the advancements of the tab.
After this call, no advancement can be registered or unregistered from the tab and its methods can be used.
UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(plugin);
// Create a tab with namespace "mynamespace"
AdvancementTab tab = api.createAdvancementTab("mynamespace")`.
// Create two advancement to be registered in the tab
RootAdvancement root = new RootAdvancement(tab, "root", new AdvancementDisplay(/*display settings*/), "backgroundTexture");
BaseAdvancement adv = new BaseAdvancement("an-adv", new AdvancementDisplay(/*display settings*/), root);
// Initialise the tab with two advancements
tab.registerAdvancements(root, adv);
// Now methods can be called
Player aPlayer = Bukkit.getPlayer("fren_gor");
tab.updateEveryAdvancement(aPlayer); // Send the tab and its advancements to the player aPlayer
// This throws an IllegalStateException since the tab has already been initialised
tab.registerAdvancements(root, adv);
Every AdvancementTab is hidden to any player by default (meaning that players doesn't see any advancement by default). An AdvancementTab can be shown to a player by calling AdvancementTab#showTab(Player player)
.
It is always prefereable to show every tab to every player as soon as possible, that is when the API has finished loading their information from the database.
The API provides two events to handle that: PlayerLoadingCompletedEvent
and PlayerLoadingFailedEvent
:
- The first runs when a player has been successfully loaded and they are ready to receive advancements (some other libraries suggest to wait for some ticks before sending the advancements, this event already considers this minecraft problem and you shouldn't wait those ticks).
- The second is executed in case the loading was unsuccessful, and it is useful to handle this occasion (no advancement can be sent to they).
The API always keeps a reference to registered AdvancementTabs, so any tab can be retrieved using the UltimateAdvancementAPI#getAdvancementTab(String namespace)
method.
An AdvancementTab can be unregistered and disposed using the UltimateAdvancementAPI#unregisterAdvancementTab(String namespace)
method.
After being unregistered, the tab and its advancements will be removed from the players, but they will not be removed from the database.
The majority of the methods of a disposed tab will throw a DisposedException
when called.
Furthermore, events registered inside the AdvancementTab's EventManager will be unregistered too, avoiding calls to disposed tabs.
More on this in the next section.
EventManager is a class from the project EventManagerAPI. It is used to facilitate the handle of events.
The EventManager class is located under the com.fren_gor.ultimateAdvancementAPI.events
package.
In advancement tabs and advancements, it is used to provides an efficient way of registering several events which will be unregistered automatically on tab dispose. So, it can be used to register events related to advancements.
An example usage is the PlayerLoadingCompletedEvent
event. Since AdvancementTab can be disposed, it is safer to register events like PlayerLoadingCompletedEvent
inside of the
tab's EventManager:
tab.getEventManager().register(listener, PlayerLoadingCompletedEvent.class, event -> tab.showTab(event.getPlayer()));
The key feature provided by the EventManager class is the possibility to register many events with the minimum amount of listener.
This is useful when dealing with advancements, since usually their criteria is updated by events.
For example, the following code
@EventHandler
public void anEvent(PlayerJoinEvent event) {
event.setJoinMessage("Hello there!");
}
@EventHandler
public void anotherJoinEvent(PlayerJoinEvent event) {
event.getPlayer().sendTitle("Welcome", "To our server!", 30, 100, 15);
}
@EventHandler
public void aBreakEvent(BlockBreakEvent event) {
event.setCancelled(true);
}
is the same as
EventManager manager = new EventManager(plugin);
Object listener = new Object();
manager.register(listener, PlayerJoinEvent.class, event -> event.setJoinMessage("Hello there!"));
manager.register(listener, PlayerJoinEvent.class, event -> event.getPlayer().sendTitle("Welcome", "To our server!", 30, 100, 15));
manager.register(listener, BlockBreakEvent.class, event -> event.setCancelled(true));
There are two main differences between these snippets:
- The first difference is that any object can be used as the listener, even the EventManager itself (this is not suggested, though).
- The second difference is in how EventManager handles the two
PlayerJoinEvent
events. Where in the first code Bukkit will callanEvent
andanotherJoinEvent
using expensive reflections, EventManager tries to minimize those expensive calls. In this case, only onePlayerJoinEvent
will be registered, which will call the two Consumers provided in theregister
method. In this way, the expensive reflection call is done only one time!
UltimateAdvancementAPI Wiki © 2021 fren_gor, EscanorTargaryen is licensed under CC BY-SA 4.0.
Except where otherwise noted, code snippets inside the wiki are licensed under The Unlicense.