Skip to content

Titles

A title is a name a player earns and may wear: shown after their name in the player list, gold on grey, Name - Chef of the Baratie. Players pick theirs in the Titles screen, the "Titles" plank of Mine Mine no Mi's character screen: titles by category, the held ones in ink, the worn one in gold, the rest greyed with how to earn them.

Titles come from three places, all alike once loaded:

  • a mod's code, AkumaTitles.register;
  • a profession's level titles, Profession.withTitle;
  • a data pack, data/<namespace>/titles/<path>.json.

A player holds a title while its condition is met, or once a mod has granted it to them. They wear one at a time; a worn title they stop holding (a level lost, another trade chosen in Crew mode) is hidden, and comes back with it.

Profession titles

() -> new Profession(ProfessionKind.CRAFTING)
        .withTitle(25, "mymod.title.cook.25")
        .withTitle(100, "mymod.title.cook.100")

Each is held from its level on, in a profession the player practises, and listed in the Professions category, a trade's titles together. Its id is <namespace>:profession/<path>/<level>: AkumaTitles.professionTitleId(profession, level). A profession has at most one title per level: getTitles() lists them as LevelTitle(level, translationKey), and getTitle(level) gives the one granted at exactly that level, or null.

A mod's titles

AkumaTitles.register(Title.builder(new ResourceLocation(MODID, "sky_king"),
                Component.translatable("mymod.title.sky_king"))
        .category(new ResourceLocation(MODID, "exploration"))
        .icon(() -> new ItemStack(MyItems.CLOUD.get()))
        .description(Component.translatable("mymod.title.sky_king.how"))
        .build());

Register once, before the server starts (common setup). Then, on the server:

Call Does
AkumaTitles.grant(player, id) Gives the title for good, whatever its condition. The id need not be loaded yet.
AkumaTitles.revoke(player, id) Takes a granted title back.
AkumaTitles.wear(player, id) Wears it, or none with null; refused if the player does not hold it.
AkumaTitles.getWorn(player) The title worn, if still held.
AkumaTitles.held(player) Every title held.
AkumaTitles.refresh(player) Checks the conditions again and tells the client and the player list.

The builder's other options: iconTexture (a square texture of any size, drawn in place of the item), order (lowest first, then by name), hidden (listed only once held), and condition:

Condition Held when
TitleCondition.GRANTED (default) granted only
TitleCondition.professionLevel(profession, level) at that level, practising the profession
TitleCondition.advancement(id) the advancement is done
your own TitleCondition test(ServerPlayer) is true

A Title gives all of it back: getName(), getCategory(), getOrder(), isHidden() and getCondition().

Conditions are checked again on every profession progress sync, advancement, login and reload. A condition of your own that changes at another time needs an AkumaTitles.refresh(player).

A category's name is the translation of title_category.<namespace>.<path>, or its path, capitalised. akumalib:professions is listed first, akumalib:general (a title's default) last.

Data pack titles

data/mypack/titles/storm_chaser.json:

{
  "name": { "text": "Storm Chaser" },
  "description": { "text": "Sail through a storm" },
  "category": "mypack:events",
  "icon": "minecraft:trident",
  "order": 10,
  "hidden": false,
  "condition": { "type": "advancement", "advancement": "mypack:storm/chaser" }
}

Only name is needed (a text component, translate works too). The conditions are {"type": "advancement", "advancement": id}, {"type": "profession", "profession": id, "level": n}, and {"type": "granted"}, which is also what no condition means. A data pack title cannot replace a mod's; a file that does not parse is logged and skipped. /reload picks up changes.