NovaFFA

Borders, Fillers and Heads

The three ways to decorate a menu, player heads on any item, and how to write both

Every menu under plugins/NovaFFA/menus/ has three separate ways to put a decorative item on a square. They look similar in the file and are easy to mix up, so this page covers what each one is for.

ToolWhere it goes in the fileWhat it is for
items.borderInside items:, alongside the buttonsThe fixed frame the menu ships with. One entry, however many squares you list
custom_itemsIts own block at the bottom of the fileAnything you add yourself. As many entries as you like, each with its own name
fillerIts own block at the bottom of the fileOnly fills the leftover content squares on a part full page. Off by default

A border and a filler are decoration only, clicking one does nothing, so a pane can never be taken out of the menu. A custom_items entry is decoration too until you give it a join or a commands line, see Items that do something.

Which menu takes which

Menuitems.bordercustom_itemsfiller
fight.ymlYesYesYes
kit_list.ymlYesYesYes
kit_editor.ymlYesYesNo
statistics.ymlYes, from 2.8.0YesNo

filler only exists on the two menus that page, because that is the only place a leftover square can appear. The statistics menu and the kit editor are one page each with a fixed set of squares, so use items.border or custom_items there.

items.border is read by name. A second decorative entry invented inside items:, such as items.border2, is not read by anything and will simply never be drawn, even though the file keeps it. Put extra decoration in custom_items instead, that block is read by every menu.

Writing a border

items:
  border:
    # true shows this item, false hides it and frees its squares
    enabled: true
    # Which squares it sits in, counted from 0 in the top left
    slots: [0, 1, 2, 3, 5, 6, 7, 8]
    item:
      material: black_stained_glass_pane
      amount: 1
      # A single space leaves the name blank
      name: ' '
      flags:
        - '*'

Squares are counted from 0 in the top left and run left to right, so row one is 0 to 8, row two is 9 to 17, and so on. A menu with size: 27 has squares 0 to 26, a size: 54 menu has 0 to 53.

flags: ['*'] hides the whole tooltip body, which is what keeps attack damage numbers and enchantment names off a decorative item.

Writing your own items

custom_items takes as many entries as you want, each written exactly like a border, each under a name of your choosing:

custom_items:
  discord:
    enabled: true
    slots: [8]
    item:
      material: player_head
      skull: 'player:Notch'
      amount: 1
      name: '&#00ccff&lOur Discord'
      lore:
        - '&#7fe5ff● &fdiscord.arrowtan.cc'
      flags:
        - '*'

  side_columns:
    enabled: true
    slots: [9, 17, 18, 26]
    item:
      material: gray_stained_glass_pane
      amount: 1
      name: ' '
      flags:
        - '*'

This block is kept untouched when the plugin updates your menu files, so anything you build here survives an upgrade.

Items that do something

A custom item does nothing when clicked unless you say what it should do. Three keys, all optional, all written beside slots rather than inside item:

KeyWhat it does
joinA kit name, or an arena name to join that arena with the kit it is linked to
commandsCommand lines run when the item is clicked, as the player unless the line says console
closeWhether the menu closes first. On by default for an item that joins, off otherwise
custom_items:
  nethpot:
    enabled: true
    slots: [30]
    # A kit name, or an arena name
    join: nethpot
    item:
      material: diamond_sword
      name: '&#00ccff&lNethpot'
      lore:
        - '&#7fe5ff● &fClick to fight'
      flags:
        - '*'

  our_store:
    enabled: true
    slots: [8]
    commands:
      - 'player: store'
      - 'console: say {viewer} opened the store'
    close: true
    item:
      material: emerald
      name: '&#00ccff&lStore'
      flags:
        - '*'

A join name is looked for as a kit first and as an arena second, so a kit and an arena sharing a name joins the kit, which is what the fight menu has always done. Joining by arena is the way to point one item at one arena when several arenas share a kit.

Command lines take {viewer} and {viewer_uuid}, the name and uuid of whoever clicked. A line with no prefix is run as the player, so - 'warp pvp' and - 'player: warp pvp' are the same thing, and a player running a command they have no permission for is refused by that command as usual.

An item that joins a fight is the fix for a menu button that looked like a kit but did nothing when clicked. The kit buttons the fight menu draws for you are separate, they come from your kits and always worked, see Fight Menu.

Writing a filler

filler:
  enabled: false
  item:
    material: gray_stained_glass_pane
    amount: 1
    name: ' '
    flags:
      - '*'

It has no slots list, because it does not claim squares of its own. It is drawn into whichever content squares the current page did not fill, so a last page holding three kits does not look broken. Turn it on by setting enabled: true.

How decoration and content share a menu

Decoration never covers a real item, whichever menu it is in.

  • Fight menu and kit list. Every square claimed by the border, the toolbar, the page buttons or your custom_items is taken out of the kit flow before kits are drawn, so kits arrange themselves around your decoration. Adding a pane in the middle of the kit area is a supported way to shape the layout. On the fight menu, a kit pinned with /ffa kit edit <kit> slot <square> to a square you later put a border on flows back in with the rest rather than disappearing, see Fight Menu.
  • Statistics menu and kit editor. The border and custom_items are drawn first, then the real content goes down on top. A pane sharing a square with a statistic, or with a square of the kit editor's grid, loses that square.

Player heads

Any item in any menu file can be a player head. Set material: player_head and add a skull line saying whose face it wears:

custom_items:
  my_head:
    enabled: true
    slots: [8]
    item:
      material: player_head
      skull: viewer
      amount: 1
      name: '&#00ccff&l{viewer}'
      flags:
        - '*'
Written asShows
viewerThe face of whoever is looking at the menu
player:SomeNameOne fixed player, by name
uuid:<uuid>One fixed player, by uuid. With or without the dashes
texture:<value>A head from a head site, from the long Base64 string those sites call the Value
url:<address>The same head written as its textures.minecraft.net address, which those sites call the Minecraft-URL
hash:<hash>The trailing part of that address on its own

The prefix is optional on everything but a player name. A uuid, an address, a Base64 value and a bare hash are each recognised from their own shape, so a value pasted straight off minecraft-heads.com works exactly as it was copied, line breaks included.

A head that does not resolve, a mistyped hash or an address on some other site, is drawn as a plain head rather than failing the item, so one bad line never empties the menu.

Where a player's skin comes from

texture:, url: and hash: carry the skin with them, so nothing is fetched and the client loads the address like any other skin.

viewer, player: and uuid: name a player instead, and a name or a uuid on its own has no skin attached to it. Something has to go and find the skin behind it, or the client draws the default face. Since 2.9.0 NovaFFA does, in this order:

  1. The player themselves, when they are online. Their live profile already carries whatever skin the server gave them, which costs nothing to read and is why the common case, skull: viewer, is instant.
  2. SkinsRestorer, when it is installed. This is the one that matters on a cracked server, where a player's uuid is made up locally and Mojang has never heard of it. Nothing to configure, the hook is found at start and reported in the console.
  3. Mojang, for anybody who has never been online here.

The last two are a network call, so the head is drawn plain and filled in the moment the answer lands, with the menu still open. Answers are kept for half an hour, and /ffa reload clears them, which is how a changed skin is picked up without waiting that out.

On a cracked server with no skin plugin, a head naming a player who is offline has no skin to find anywhere and stays plain. Install SkinsRestorer and it resolves, or use texture: for a head that must always be right.

The viewer

{viewer} and {viewer_uuid} are the name and uuid of the player the menu is being drawn for. They work in the name and lore of every item in every menu, and skull: viewer is the short way of writing skull: 'uuid:{viewer_uuid}'.

On the statistics menu, {viewer} is whoever ran the command and {target} is whose record is on screen. Those are the same player unless somebody ran /statistics <player> on someone else, which is why the shipped head there uses uuid:{uuid}, the target, rather than the viewer.

Item keys you can use

Every item: section in every menu file reads the same keys:

KeyWhat it does
materialThe Minecraft item, in lower case with underscores. Spaces also work
amountStack size, which is the small number drawn on the item
nameThe item's name. A single space leaves it blank
loreThe grey text under the name, one line per entry
flagsTooltip parts to hide. '*' hides all of them
glowtrue puts the enchanted shine on without an enchantment
unbreakabletrue stops the item losing durability
custom_model_dataA number your resource pack uses for a custom texture
enchantmentsEach with a level, for example sharpness: {level: 3}
skullOnly on player_head. See Player heads above for every way to write one

Colours are written in Prism syntax, so &a, &l and &#00ccff all work, see Messages and Language.

Seeing a change

/ffa reload

Re-reads every menu file, so a run of border edits is not a run of restarts. A menu already open on someone's screen keeps the old layout until they close and reopen it.

On this page