### Create and Register MultiTasks and TaskAdvancements Source: https://github.com/frengor/ultimateadvancementapi/wiki/Special-Advancement Example of setting up an advancement tab, a root advancement, and a MultiTasks advancement with associated TaskAdvancements for Dirt and Stone breaking. This demonstrates the core structure for managing complex advancement chains. ```java 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); } ``` -------------------------------- ### Root Advancement with Rewards and Notifications Source: https://github.com/frengor/ultimateadvancementapi/wiki/Examples This example demonstrates creating a root advancement that provides rewards and custom announcement messages upon completion. It also includes event registration for block breaking. ```java private AdvancementTab advancementTab; private RootAdv 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, true, true, 0, 0, "Break a grass block", "you will recived a gift!"); root = new RootAdv(advancementTab, "root", rootDisplay, "textures/block/stone.png"); advancementTab.registerAdvancements(root); } @EventHandler public void onJoin(PlayerLoadingCompletedEvent e) { Player p = e.getPlayer(); advancementTab.showTab(p); } ``` ```java public class RootAdv extends RootAdvancement { public RootAdv(@NotNull AdvancementTab advancementTab, @NotNull String key, @NotNull AdvancementDisplay display, @NotNull String backgroundTexture) { super(advancementTab, key, display, backgroundTexture); registerEvent(BlockBreakEvent.class, e -> { if (isVisible(e.getPlayer()) && e.getBlock().getType() == display.getIcon().getType()) { incrementTeamCriteria(e.getPlayer()); } }); } @Override public void giveReward(@NotNull Player player) { player.sendMessage("You recived a diamond shovel"); player.getInventory().addItem(new ItemStack(Material.DIAMOND_SHOVEL)); } @Override public BaseComponent[] getAnnounceMessage(@NotNull Player player) { ChatColor color = display.getFrame().getColor(); return new ComponentBuilder(player.getName() + " has completed the " + display.getFrame().getChatText() + ' ').color(ChatColor.WHITE).append(new ComponentBuilder("[").color(color).event(new HoverEvent(Action.SHOW_TEXT, display.getChatDescription())).append(display.getChatTitle()).append(new ComponentBuilder("]").reset().color(color).create()).create()).create()).create(); } } ``` -------------------------------- ### Example: Create, Initialize, and Update AdvancementTab Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Demonstrates the full lifecycle of an AdvancementTab: creation, defining advancements, registering them to initialize the tab, and updating a player's view. Attempting to re-register advancements after initialization will result in an IllegalStateException. ```java 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); ``` -------------------------------- ### Get UltimateAdvancementAPI Instance Source: https://github.com/frengor/ultimateadvancementapi/wiki/Start-Guide Obtain an instance of the API using the static getInstance method, passing your plugin instance. The API must be enabled on the server, otherwise an exception will be thrown. ```java UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(yourPluginInstance); ``` -------------------------------- ### Create and Display Custom Advancement Tab Source: https://github.com/frengor/ultimateadvancementapi/wiki/Start-Guide Example of creating a custom advancement tab with a root advancement and displaying it to players upon joining. Ensure 'UltimateAdvancementAPI' is listed in your plugin.yml dependencies. ```java public class MainClass extends JavaPlugin implements Listener { private AdvancementTab advancementTab; private RootAdvancement root; private UltimateAdvancementAPI api; @Override public void onEnable() { api = UltimateAdvancementAPI.getInstance(this); advancementTab = api.createAdvancementTab("your_tab_name"); AdvancementDisplay rootDisplay = new AdvancementDisplay(Material.GRASS_BLOCK, "Example root", AdvancementFrameType.TASK, true, true, 0, 0, "description"); root = new RootAdvancement(advancementTab, "root", rootDisplay, "textures/block/stone.png"); advancementTab.registerAdvancements(root); Bukkit.getPluginManager().registerEvents(this, this); } @EventHandler public void onJoin(PlayerLoadingCompletedEvent e) { // Called after a player has successfully been loaded by the API Player p = e.getPlayer(); // Here you can show tabs to players advancementTab.showTab(p); } } ``` -------------------------------- ### Create and Register Multiparent Advancement Source: https://github.com/frengor/ultimateadvancementapi/wiki/Special-Advancement This snippet demonstrates the setup of an AdvancementTab, a root advancement, two base advancements, and a multiparent advancement. It then registers all advancements and shows how to grant the root advancement and display the tab to a player upon loading. ```java 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); } ``` -------------------------------- ### Pickaxe Advancement Example Source: https://github.com/frengor/ultimateadvancementapi/wiki/Examples Advancement for crafting a stone pickaxe. It increments criteria when a player crafts a stone pickaxe while the advancement is visible and not yet granted. Implements ParentGrantedVisibility. ```java 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 } } ``` -------------------------------- ### Initialize and Manage UltimateAdvancementAPI Lifecycle Source: https://github.com/frengor/ultimateadvancementapi/wiki/Shadeable-Version Implement onLoad, onEnable, and onDisable methods to manage the API's lifecycle. Use onEnable to initialize the database connection, for example, with SQLite, and retrieve the API instance. Ensure disable() is called in onDisable. ```java public class MainClass extends JavaPlugin { private AdvancementMain main; private UltimateAdvancementAPI api; @Override public void onLoad() { main = new AdvancementMain(this); main.load(); // Rest of your code } @Override public void onEnable() { // Enable UltimateAdvancementAPI using a file based database (SQLite) // You can use other databases classes — like MySQL, InMemory or a custom one — instead of the next line // DBs with built-in support can be found in the com.fren_gor.ultimateAdvancementAPI.database.impl package main.enable(() -> new SQLite(main, new File(getDataFolder(), "database.db"))); // After the initialisation of AdvancementMain you can get an instance of the UltimateAdvancementAPI class api = UltimateAdvancementAPI.getInstance(this); // Rest of your code } @Override public void onDisable() { main.disable(); // Rest of your code } } ``` -------------------------------- ### Stone Advancement Example Source: https://github.com/frengor/ultimateadvancementapi/wiki/Examples Advancement for breaking stone blocks. It increments criteria when a player breaks a block matching the advancement's icon type. Requires a maximum criteria count. ```java public class Stone extends BaseAdvancement { public Stone( @NotNull String key, @NotNull AdvancementDisplay display, @NotNull Advancement parent, @Range(from = 1L, to = 2147483647L) int maxCriteria) { super( key, display, parent, maxCriteria); registerEvent(BlockBreakEvent.class, e -> { if (isVisible(e.getPlayer()) && e.getBlock().getType() == display.getIcon().getType()) { incrementTeamCriteria(e.getPlayer()); } }); } @Override public void giveReward(@NotNull Player player) { } } ``` -------------------------------- ### Getting a Registered AdvancementTab Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Retrieves a previously registered AdvancementTab using its unique namespace. This allows access to existing tabs for further management or updates. ```APIDOC ## Getting a Registered AdvancementTab ### Description Retrieves an AdvancementTab instance by its namespace. This method is useful for accessing tabs that have already been created and registered. ### Method Signature ```java UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(plugin); AdvancementTab tab = api.getAdvancementTab("namespace"); ``` ### Parameters * **namespace** (String) - Required - The unique namespace of the advancement tab to retrieve. ``` -------------------------------- ### Get a Registered AdvancementTab Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Retrieve a previously registered AdvancementTab using its unique namespace. This allows access to existing tabs for further manipulation or updates. ```java UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(plugin); AdvancementTab tab = api.getAdvancementTab("namespace"); ``` -------------------------------- ### Create and Register Advancements Source: https://github.com/frengor/ultimateadvancementapi/wiki/Advancements This snippet shows how to initialize the API, create an advancement tab, define a root advancement and a custom base advancement, and register them. It also includes an event listener to display the tab and grant the root advancement when a player finishes loading. ```java public class MainClass extends JavaPlugin { @Override public void onEnable() { UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(this); AdvancementTab tab = api.createAdvancementTab("mytab"); RootAdvancement root = new RootAdvancement(tab, "root", new AdvancementDisplay(Material.OAK_SAPLING, "Root Advancement", AdvancementFrameType.CHALLENGE, false, false, 0, 0), "textures/block/cobblestone.png"); MineAdv pickaxe = new MineAdv("pickaxe", new AdvancementDisplay(Material.STONE, "Mine Stone", AdvancementFrameType.TASK, true, true, 1.5f, 0, "Mine 10 blocks of stone."), root, 10); tab.registerAdvancements(root, pickaxe); // Show tab on player loading. Also grants the root tab.getEventManager().register(tab, PlayerLoadingCompletedEvent.class, event -> { tab.showTab(event.getPlayer()); tab.grantRootAdvancement(event.getPlayer()); }); } public static class MineAdv extends BaseAdvancement { public MineAdv(@NotNull String key, @NotNull AdvancementDisplay display, @NotNull Advancement parent, @Range(from = 1L, to = 2147483647L) int maxProgression) { super(key, display, parent, maxProgression); // Register the event via the tab's EventManager registerEvent(BlockBreakEvent.class, e -> { Player player = e.getPlayer(); if (isVisible(player) && e.getBlock().getType() == Material.STONE) { incrementProgression(player); } }); } @Override public void giveReward(@NotNull Player player) { // This code is called when the advancement is granted player.getInventory().addItem(new ItemStack(Material.STONE_BRICKS)); } } } ``` -------------------------------- ### Create a Root Advancement Source: https://github.com/frengor/ultimateadvancementapi/wiki/Examples This snippet shows how to create a basic root advancement tab and register it. It includes event handling for player joins to display the advancement tab. ```java private AdvancementTab advancementTab; private RootAdvancement 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, "Example root", AdvancementFrameType.TASK, false, false, 0, 0, "description"); root = new RootAdvancement(advancementTab, "root", rootDisplay, "textures/block/stone.png"); advancementTab.registerAdvancements(root); } @EventHandler public void onJoin(PlayerLoadingCompletedEvent e) { Player p = e.getPlayer(); advancementTab.showTab(p); } ``` -------------------------------- ### Configure MySQL Connection Settings Source: https://github.com/frengor/ultimateadvancementapi/wiki/Configuration Provides essential connection details for using MySQL as the storage type. Includes username, password, database name, host, and port. ```yaml mysql: username: "root" password: "" databaseName: "advancements" host: "127.0.0.1" port: 3306 ``` -------------------------------- ### Initializing an AdvancementTab Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab An AdvancementTab is initialized by registering its root and base advancements. Once initialized, the tab can be shown to players, and its methods can be called. Attempting to re-register advancements after initialization will result in an IllegalStateException. ```APIDOC ## Initializing an AdvancementTab ### Description Initializes the AdvancementTab by registering its advancements. This method must be called before the tab can be displayed or interacted with. After initialization, no more advancements can be added or removed. ### Method Signature ```java tab.registerAdvancements(RootAdvancement root, BaseAdvancement... advancements); ``` ### Parameters * **root** (RootAdvancement) - Required - The root advancement for the tab. * **advancements** (BaseAdvancement...) - Optional - A variable number of base advancements to register with the tab. ``` -------------------------------- ### Create an AdvancementTab Instance Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Obtain an instance of AdvancementTab by providing a unique namespace. This tab is initially not initialized and cannot be used until registered. ```java UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(plugin); AdvancementTab tab = api.createAdvancementTab("tabnamespace"); ``` -------------------------------- ### Add Gradle Repository for UltimateAdvancementAPI Source: https://github.com/frengor/ultimateadvancementapi/wiki/Start-Guide Include this repository in your Gradle build script to access the API. Ensure it's declared before JitPack if both are used. ```gradle repositories { maven { url 'https://nexus.frengor.com/repository/public/' } } ``` -------------------------------- ### Hierarchical Advancement Structure Source: https://github.com/frengor/ultimateadvancementapi/wiki/Examples This snippet illustrates setting up a main class to manage advancements, including creating a root advancement and subsequent child advancements like 'Stone' and 'Pickaxe'. It also handles player join events to display the tab and grant the root advancement. ```java public class MainClazz extends JavaPlugin implements Listener { private AdvancementMain main; @Override public void onLoad() { main = new AdvancementMain(this); main.load(); } 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 stoneD = new AdvancementDisplay(Material.STONE, "Stone", AdvancementFrameType.GOAL, true, true, 1, 0, "Break 3 blocks of stone"); Stone stone = new Stone("stone", stoneD, root, 3); AdvancementDisplay pickaxeD = new AdvancementDisplay(Material.STONE_PICKAXE, "Stone Pickaxe", AdvancementFrameType.CHALLENGE, true, true, 2, 1, "Craft a stone pickaxe"); Pickaxe pickaxe = new Pickaxe( "pickaxe", pickaxeD, stone); advancementTab.registerAdvancements(root, stone, pickaxe); } @EventHandler public void onJoin(PlayerLoadingCompletedEvent e) { Player p = e.getPlayer(); advancementTab.showTab(p); root.grant(p); } @Override public void onDisable() { main.disable(); main = null; } } ``` ```java public class Root extends RootAdvancement { ``` -------------------------------- ### Maven Repository Configuration Source: https://github.com/frengor/ultimateadvancementapi/blob/main/README.md Add this repository to your pom.xml to access the UltimateAdvancementAPI. ```xml fren_gor https://nexus.frengor.com/repository/public/ ``` -------------------------------- ### Create Root Advancement Source: https://github.com/frengor/ultimateadvancementapi/wiki/Standard-Advancement Instantiates a root advancement with display properties and a background texture for the advancement tab. This is the main advancement for a tab. ```java 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"); ``` -------------------------------- ### Configure SQLite Database File Source: https://github.com/frengor/ultimateadvancementapi/wiki/Configuration Defines the filename for the SQLite database when 'storage-type' is set to 'SQLite'. ```yaml sqlite: file: "database.db" ``` -------------------------------- ### Event Handling with Bukkit vs. EventManager Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Compares standard Bukkit event handling with EventManager. EventManager consolidates multiple handlers for the same event type into a single registration, reducing expensive reflection calls. ```java @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); } ``` ```java 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)); ``` -------------------------------- ### Add Gradle Dependency for UltimateAdvancementAPI Source: https://github.com/frengor/ultimateadvancementapi/wiki/Start-Guide Add this dependency to your Gradle build script to include the API in your project. Use 'compileOnly' as the API is expected to be present on the server. ```gradle dependencies { compileOnly 'com.frengor:ultimateadvancementapi:2.8.0' } ``` -------------------------------- ### Markdown Changelog Template for Modrinth/Hangar Source: https://github.com/frengor/ultimateadvancementapi/wiki/Publishing This Markdown template can be used for changelogs on platforms like Modrinth and Hangar. It includes sections for general and internal changes. ```markdown * Added support for Minecraft 1.X.X * Updated CommandAPI to X.X.X * Changelog here * Changelog here (by [User](https://github.com/user)) #### Internal changes: * Changelog here ``` -------------------------------- ### Define Base Advancement with Event Handling Source: https://github.com/frengor/ultimateadvancementapi/wiki/Standard-Advancement Extends BaseAdvancement to create a custom advancement that listens for specific events, like crafting an item, to grant progress. Implements ParentGrantedVisibility to control when the advancement is visible. ```java 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); } }); } } ``` -------------------------------- ### Maven Dependency for UltimateAdvancementAPI Source: https://github.com/frengor/ultimateadvancementapi/blob/main/README.md Include this dependency in your project to use the UltimateAdvancementAPI. Ensure the version matches your project's requirements. ```xml com.frengor ultimateadvancementapi 2.8.0 provided ``` -------------------------------- ### Root Advancement Constructor Source: https://github.com/frengor/ultimateadvancementapi/wiki/Examples Constructor for the Root advancement type. Requires advancement tab, key, display, and background texture. ```java public Root(@NotNull AdvancementTab advancementTab, @NotNull String key, @NotNull AdvancementDisplay display, @NotNull String backgroundTexture) { super(advancementTab, key, display, backgroundTexture); } } ``` -------------------------------- ### Creating an AdvancementTab Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab An AdvancementTab object represents a tab in the Minecraft advancement GUI and is used to register advancements. An instance can be obtained using the UltimateAdvancementAPI. An AdvancementTab must have a unique namespace. ```APIDOC ## Creating an AdvancementTab ### Description Creates a new AdvancementTab with a unique namespace. This tab is initially not initialized and cannot be shown to players until advancements are registered. ### Method Signature ```java UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(plugin); AdvancementTab tab = api.createAdvancementTab("tabnamespace"); ``` ### Parameters * **namespace** (String) - Required - A unique identifier for the advancement tab. ``` -------------------------------- ### Configure Advanced MySQL Settings Source: https://github.com/frengor/ultimateadvancementapi/wiki/Configuration Advanced settings for MySQL connections, including connection pool size and connection timeout. These settings should only be modified by users with a thorough understanding of database performance tuning. ```yaml mysql: advanced-settings: # Set these only if you know what you're doing poolSize: 5 connectionTimeout: 6000 ``` -------------------------------- ### Implement a Dirt Breaking TaskAdvancement Source: https://github.com/frengor/ultimateadvancementapi/wiki/Special-Advancement Defines a custom TaskAdvancement that tracks the breaking of Dirt blocks. It increments progression when a Dirt block is broken and the player has not yet been granted the advancement. ```java 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 (!isGranted(p) && e.getBlock().getType() == Material.DIRT) { incrementProgression(p); } }); } } ``` -------------------------------- ### Configure Maven Shade Plugin for Relocation Source: https://github.com/frengor/ultimateadvancementapi/wiki/Shadeable-Version Configure the maven-shade-plugin to relocate the UltimateAdvancementAPI package to prevent class conflicts. This ensures your shaded JAR contains the API without namespace collisions. ```xml org.apache.maven.plugins maven-shade-plugin false false com.fren_gor.ultimateAdvancementAPI *your package*.libs.com.fren_gor.ultimateAdvancementAPI package shade ``` -------------------------------- ### Add Player to Team with Callback Source: https://github.com/frengor/ultimateadvancementapi/wiki/Teams Use this method to move a player to another player's team. A callback function is provided to handle the result of the operation, including success or failure. ```java Player playerOne = Bukkit.getPlayer("fren_gor"); Player playerTwo = Bukkit.getPlayer("EscanorTargaryen"); api.updatePlayerTeam(playerOne, playerTwo, result -> { if (result.isSucceeded()) { playerOne.sendMessage("You're now part of " + playerTwo.getName() + " team!"); } else { // An error occurred playerOne.sendMessage("Something wrong happened while moving to " + playerTwo.getName() + " team"); result.getOccurredException().printStackTrace(); } }); ``` -------------------------------- ### Discord Announcement Message Template Source: https://github.com/frengor/ultimateadvancementapi/wiki/Publishing Use this template to post a new version announcement in the 'announcements' channel on Discord. It includes placeholders for version numbers, download links, and changelog details. ```markdown **X.X.X and 3.0.0-beta-X Update** Download it from: *Modrinth:* [X.X.X](https://modrinth.com/plugin/ultimateadvancementapi/version/X.X.X) / [3.0.0-beta-X](https://modrinth.com/plugin/ultimateadvancementapi/version/3.0.0-beta-X) *Hangar:* [X.X.X](https://hangar.papermc.io/DevHeim/UltimateAdvancementAPI/versions/X.X.X) / [3.0.0-beta-X](https://hangar.papermc.io/DevHeim/UltimateAdvancementAPI/versions/3.0.0-beta-X) *Spigot:* > **Changelog:** > * Added support for Minecraft 1.X.X > * Updated CommandAPI to X.X.X > * Changelog here > * Changelog here (by @User) > * Sublist title: > * Changelog here > * Changelog here (by @User) > > Internal changes: > * Changelog here ||@UltimateAdvancementAPI|| ``` -------------------------------- ### Implement a Stone Breaking TaskAdvancement Source: https://github.com/frengor/ultimateadvancementapi/wiki/Special-Advancement Defines a custom TaskAdvancement that tracks the breaking of Stone blocks. It increments progression when a Stone block is broken and the player has not yet been granted the advancement. ```java 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 (!isGranted(p) && e.getBlock().getType() == Material.STONE) { incrementProgression(p); } }); } } ``` -------------------------------- ### Update API Version with Maven Source: https://github.com/frengor/ultimateadvancementapi/wiki/Publishing Use the Maven versions plugin to set the new API version across all pom.xml files. Ensure you are on the 'dev' branch before executing. ```bash mvn org.codehaus.mojo:versions-maven-plugin:2.16.1:set -DgenerateBackupPoms=false -DprocessAllModules=true -DnewVersion=X.X.X ``` -------------------------------- ### Define a Custom MultiTasksAdvancement Source: https://github.com/frengor/ultimateadvancementapi/wiki/Special-Advancement A basic implementation of MultiTasksAdvancement. This class serves as a template for creating custom multi-task advancements, including defining rewards upon completion. ```java 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"); } } ``` -------------------------------- ### Define a Custom Advancement Source: https://github.com/frengor/ultimateadvancementapi/wiki/Special-Advancement A simple custom advancement class extending BaseAdvancement. It requires a key, display properties, and a parent advancement. ```java public class Adv extends BaseAdvancement { public Adv( @NotNull String key, @NotNull AdvancementDisplay display, @NotNull Advancement parent) { super( key, display, parent); } //todo } ``` -------------------------------- ### BB-Code Changelog Template for SpigotMC Source: https://github.com/frengor/ultimateadvancementapi/wiki/Publishing This BB-Code template is used for formatting changelogs on SpigotMC. Use [icode] for inline code. ```text [COLOR=#808080][B]Release X.X.X:[/B][/COLOR] [LIST] [*]Added support for Minecraft 1.X.X [*]Updated CommandAPI to X.X.X [*]Changelog here [*]Changelog here (by @User) [/LIST] Internal changes: [LIST] [*]Changelog here [/LIST] ``` -------------------------------- ### Show AdvancementTab to Player Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Make an AdvancementTab visible to a specific player. It's recommended to do this after the API has loaded player information, using events like PlayerLoadingCompletedEvent. ```java tab.showTab(player); ``` -------------------------------- ### Load Offline Player and Process TeamProgression Source: https://github.com/frengor/ultimateadvancementapi/wiki/Teams Loads a player's data if they are offline, processes their team progression, and prints member UUIDs. Handles potential errors during loading and ensures the player's data is not cached indefinitely. ```java UUID uuid = UUID.fromString("831e3f14-b54d-47fe-bd4e-06d9e6ce681b"); api.loadOfflinePlayer(uuid, CacheFreeingOption.DONT_CACHE(), result -> { if (result.isSucceeded()) { TeamProgression progression = result.getResult(); progression.forEachMember(memberUUID -> { System.out.println(memberUUID); }); } else { // An error occurred result.getOccurredException().printStackTrace(); } }); ``` -------------------------------- ### Updating Advancements for a Player Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Sends the current state of all advancements within a specific tab to a player. This is useful for ensuring a player sees the latest advancements after the tab has been initialized and potentially updated. ```APIDOC ## Updating Advancements for a Player ### Description Updates all advancements for a given player, ensuring they see the latest state of the advancements within this tab. This method can only be called after the tab has been initialized. ### Method Signature ```java tab.updateEveryAdvancement(Player aPlayer); ``` ### Parameters * **player** (Player) - Required - The player whose advancements need to be updated. ``` -------------------------------- ### Disable Vanilla Advancements Source: https://github.com/frengor/ultimateadvancementapi/wiki/Configuration Set to 'false' to enable all vanilla advancements. Be aware that disabling advancements may cause players to lose progress and can result in console messages upon player join. ```yaml disable-vanilla-advancements: false ``` -------------------------------- ### Customize Advancement Announce Message Source: https://github.com/frengor/ultimateadvancementapi/wiki/FAQ Override this method to customize the announcement message for an advancement. Ensure player is not null and utilize ChatColor for formatting. ```java @Override public BaseComponent[] getAnnounceMessage(@NotNull Player player) { Preconditions.checkNotNull(player, "Player is null."); ChatColor color = display.getFrame().getColor(); return new ComponentBuilder(player.getName() + " ha completato l\'obiettivo ") .color(ChatColor.WHITE) .append(new ComponentBuilder("[") .color(color) .event(new HoverEvent(Action.SHOW_TEXT, display.getChatDescription())) .create() , FormatRetention.NONE) .append(display.getChatTitle(), FormatRetention.EVENTS) .append(new ComponentBuilder("]") .color(color) .create() , FormatRetention.EVENTS) .create(); } ``` -------------------------------- ### Include Shadeable UltimateAdvancementAPI Dependency Source: https://github.com/frengor/ultimateadvancementapi/wiki/Shadeable-Version Add the shadeable artifact as a compile-time dependency in your Maven project. This replaces the standard API artifact. ```xml com.frengor ultimateadvancementapi-shadeable 2.8.0 compile ``` -------------------------------- ### Include Shadeable Mojang Mapped Legacy Dependency Source: https://github.com/frengor/ultimateadvancementapi/wiki/Shadeable-Version For older Minecraft versions using Mojang mapping, include the shadeable artifact with the 'mojang-mapped-legacy' classifier. ```xml com.frengor ultimateadvancementapi-shadeable 2.8.0 mojang-mapped-legacy compile ``` -------------------------------- ### Disable Vanilla Recipe Advancements Source: https://github.com/frengor/ultimateadvancementapi/wiki/Configuration Set to 'false' to enable vanilla recipe advancements. Disabling these may cause players to lose recipe advancement progress and can lead to console messages upon player join. ```yaml disable-vanilla-recipe-advancements: false ``` -------------------------------- ### Showing an AdvancementTab to a Player Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Makes a specific AdvancementTab visible to a player. It is recommended to call this method after the API has finished loading player information, potentially in response to PlayerLoadingCompletedEvent. ```APIDOC ## Showing an AdvancementTab to a Player ### Description Displays the AdvancementTab to the specified player. This makes the tab and its advancements visible in the player's advancement GUI. ### Method Signature ```java tab.showTab(Player player); ``` ### Parameters * **player** (Player) - Required - The player to whom the tab should be shown. ``` -------------------------------- ### Set Database Storage Type Source: https://github.com/frengor/ultimateadvancementapi/wiki/Configuration Specifies the storage mechanism for the API. Options include 'SQLite', 'MySQL', and 'InMemory'. 'InMemory' storage does not persist data between application restarts. ```yaml storage-type: SQLite ``` -------------------------------- ### Define a Multiparent Advancement Source: https://github.com/frengor/ultimateadvancementapi/wiki/Special-Advancement A custom multiparent advancement class extending MultiParentsAdvancement. It requires a key, display properties, and a variable number of parent advancements. ```java public class MultiparentExample extends MultiParentsAdvancement { public MultiparentExample(@NotNull String key, @NotNull AdvancementDisplay display, @NotNull BaseAdvancement... parents) { super(key, display, parents); } //todo } ``` -------------------------------- ### Commit Message Template for Version Update Source: https://github.com/frengor/ultimateadvancementapi/wiki/Publishing Use this template for your commit message when pushing version updates to GitHub. ```text * Updated version to X.X.X * Updated to Minecraft 1.X.X * Updated CommandAPI to X.X.X * Changelog * Changelog by @user ``` -------------------------------- ### Old Discord Announcement Message Format Source: https://github.com/frengor/ultimateadvancementapi/wiki/Publishing This is an older format for Discord announcements, used for single version updates. It contains similar information but is structured differently. ```markdown **X.X.X Update** Download it from: *Modrinth:* *Spigot:* *Hangar:* > **Changelog:** > * Added support for Minecraft 1.X.X > * Updated CommandAPI to X.X.X > * Changelog here > * Changelog here (by @User) > * Sublist title: > * Changelog here > * Changelog here (by @User) > > Internal changes: > * Changelog here ||@UltimateAdvancementAPI|| ``` -------------------------------- ### Registering PlayerLoadingCompletedEvent with EventManager Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Register an event listener within an AdvancementTab's EventManager. This ensures events are automatically unregistered when the tab is disposed, making it safe for advancement-related events like showing a tab upon player completion. ```java tab.getEventManager().register(listener, PlayerLoadingCompletedEvent.class, event -> tab.showTab(event.getPlayer())); ``` -------------------------------- ### Unregistering an AdvancementTab Source: https://github.com/frengor/ultimateadvancementapi/wiki/AdvancementTab Removes an AdvancementTab and its associated advancements from the players and disposes of the tab's resources. The tab's data is removed from players but not from the database. Calling methods on a disposed tab will result in a DisposedException. ```APIDOC ## Unregistering an AdvancementTab ### Description Unregisters and disposes of an AdvancementTab. This removes the tab and its advancements from players and cleans up associated resources. The tab's data persists in the database. ### Method Signature ```java UltimateAdvancementAPI api = UltimateAdvancementAPI.getInstance(plugin); api.unregisterAdvancementTab("namespace"); ``` ### Parameters * **namespace** (String) - Required - The unique namespace of the advancement tab to unregister. ```