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.
| Tool | Where it goes in the file | What it is for |
|---|---|---|
items.border | Inside items:, alongside the buttons | The fixed frame the menu ships with. One entry, however many squares you list |
custom_items | Its own block at the bottom of the file | Anything you add yourself. As many entries as you like, each with its own name |
filler | Its own block at the bottom of the file | Only 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
| Menu | items.border | custom_items | filler |
|---|---|---|---|
fight.yml | Yes | Yes | Yes |
kit_list.yml | Yes | Yes | Yes |
kit_editor.yml | Yes | Yes | No |
statistics.yml | Yes, from 2.8.0 | Yes | No |
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: '�ccff&lOur Discord'
lore:
- 'fe5ff● &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:
| Key | What it does |
|---|---|
join | A kit name, or an arena name to join that arena with the kit it is linked to |
commands | Command lines run when the item is clicked, as the player unless the line says console |
close | Whether 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: '�ccff&lNethpot'
lore:
- 'fe5ff● &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: '�ccff&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_itemsis 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_itemsare 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: '�ccff&l{viewer}'
flags:
- '*'| Written as | Shows |
|---|---|
viewer | The face of whoever is looking at the menu |
player:SomeName | One 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:
- 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. - 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.
- 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:
| Key | What it does |
|---|---|
material | The Minecraft item, in lower case with underscores. Spaces also work |
amount | Stack size, which is the small number drawn on the item |
name | The item's name. A single space leaves it blank |
lore | The grey text under the name, one line per entry |
flags | Tooltip parts to hide. '*' hides all of them |
glow | true puts the enchanted shine on without an enchantment |
unbreakable | true stops the item losing durability |
custom_model_data | A number your resource pack uses for a custom texture |
enchantments | Each with a level, for example sharpness: {level: 3} |
skull | Only on player_head. See Player heads above for every way to write one |
Colours are written in Prism syntax, so &a, &l and �ccff all work, see Messages and Language.
Seeing a change
/ffa reloadRe-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.