> For the complete documentation index, see [llms.txt](https://edseries-plugins.gitbook.io/p/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://edseries-plugins.gitbook.io/p/pinnapass/reference/custom-textures.md).

# Custom Textures & Resource-Pack Menus

The pass menus (`plugins/PinnaPass/guis/`) can look like anything your resource pack can draw: a full picture as the background, your own icons and tooltip frames on every item, an XP bar that fills pixel by pixel and tier numbers up to 9999 drawn by your pack. This page shows how. You only edit the menu files and your pack.

## How it fits together

A resource-pack menu is still a normal chest menu, built from three layers that you set in the menu file:

1. **The background**: a picture from your pack, placed in the menu **title**.
2. **The buttons**: menu items that wear your pack's models and tooltip frames.
3. **Live values**: stack sizes, counters and bar pieces that change with the player's progress.

The server only sends the title and the items. The pack on the player's game does the drawing, so every player needs your pack loaded. Players without it see vanilla items and unreadable characters in the title.

## 1. The background picture

A menu title is text, and text can show font images ("glyphs") from your pack. A glyph as large as the chest window covers the vanilla texture and becomes the background.

```yaml
# plugins/PinnaPass/guis/pass.yml
title: '&f:offset_-18::pass_main:'
rows: 6
```

| Part           | What it does                                                                                                                                                                                                                                                                                              |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `&f`           | Makes the title white. Title text is dark grey by default and glyphs take the colour of the text, so without `&f` the picture looks dark.                                                                                                                                                                 |
| `:offset_-18:` | Moves the text cursor 18 pixels to the left. The title starts 8 pixels in from the left edge of the window, so the picture needs a negative offset to start at the edge. The right number depends on how your picture was drawn: change it one pixel at a time until the picture lines up with the slots. |
| `:pass_main:`  | The picture itself (here an ItemsAdder font image called `pass_main`).                                                                                                                                                                                                                                    |

Set `rows` to the menu height your picture was made for.

### Writing glyphs for your pack plugin

| Pack made with | Picture                                                                                                                         | Offset                                                     |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| ItemsAdder     | `:name:`, or `%img_name%` through PlaceholderAPI                                                                                | `:offset_-18:` (or `%img_offset_-18%`)                     |
| Nexo or Oraxen | the glyph's PlaceholderAPI placeholder (for example `%nexo_<glyph-id>%` or `%oraxen_<glyph-id>%`), or the glyph's own character | the plugin's shift placeholder or character (see its docs) |
| Your own pack  | the character you gave the picture in your font file                                                                            | a character of a `space` provider with a negative width    |

PinnaPass texts read `&` colour codes, `&#RRGGBB` and `<gradient:...>`, but no other MiniMessage tags, so tags such as `<glyph:...>` or `<shift:...>` are shown as plain text. Use the PlaceholderAPI form or the raw character instead (PlaceholderAPI must be installed for `%...%`).

### Using your own font

If you make the pack yourself, add the picture and a few negative spaces to a font, for example `assets/minecraft/font/default.json`. Use characters from Unicode's private use area, which no language uses: here U+E000 for the picture and U+F801, U+F808 and U+F810 for spaces of -1, -8 and -16 pixels.

In the examples below, `<U+E000>` stands for that one character. In the JSON file write it as a JSON escape (a backslash, the letter `u` and the four hex digits `E000`), or paste the character itself.

```json
{
  "providers": [
    { "type": "space", "advances": { "<U+F801>": -1, "<U+F808>": -8, "<U+F810>": -16 } },
    { "type": "bitmap", "file": "mypack:gui/pass_main.png", "ascent": 13, "height": 222, "chars": ["<U+E000>"] }
  ]
}
```

The picture goes in `assets/mypack/textures/gui/pass_main.png`. `height` is the height the picture is drawn at (222 = a 6-row chest window, 114 pixels plus 18 per row) and `ascent` how far it reaches above the title line (13 puts its top at the top of the window). `ascent` must never be larger than `height`, or the game ignores the whole font.

In the menu file, write the same escapes inside a double-quoted YAML string (YAML only reads escapes between double quotes), or paste the characters. -16, -1 and -1 make the same 18 pixel offset as `:offset_-18:`:

```yaml
title: "&f<U+F810><U+F801><U+F801><U+E000>"
```

### Text on top of the picture

After the picture the cursor stands at its right edge, and anything written after it is drawn over the picture. Move back with another negative offset first, then write your text with a normal colour:

```yaml
title: '&f:offset_-18::pass_main::offset_-160:&8Tier {tier}/{max_tier}'
```

The title takes every menu token and PlaceholderAPI placeholder. Whenever the menu redraws (for example with the menu's `update-interval`, or on a page change), a title that changed is put on the open window in place, without closing it.

## 2. Button textures

These item keys matter for a pack:

| Key                 | Use                                                                                                                                                                                                                                                                                                           |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `material`          | A vanilla material (`PAPER`...), `{icon}`, or an item of your pack plugin: `itemsadder:<namespace>:<id>` (or `ia:`), `nexo:<id>`, `oraxen:<id>`. Pack plugin items bring their own model. `texture-<base64>` makes a custom head and `head-<player>` a player's head. An unknown material shows as a barrier. |
| `texture`           | For a `PLAYER_HEAD`: `self` (the viewer's own skin) or a base64 texture value.                                                                                                                                                                                                                                |
| `custom-model-data` | The model number your pack gives that material, e.g. `20001`. A `{token}` works too. `0` or empty means none.                                                                                                                                                                                                 |
| `item-model`        | An item definition of your pack, `namespace:id` (Minecraft 1.21.4+). The item then uses that model whatever its material.                                                                                                                                                                                     |
| `tooltip-style`     | A tooltip frame from your pack, `namespace:id` (1.21.2+). Tokens work here.                                                                                                                                                                                                                                   |
| `hide-tooltip`      | `true` shows no tooltip at all on hover (1.20.5+). The item can still be clicked.                                                                                                                                                                                                                             |
| `glow`              | The enchant shimmer.                                                                                                                                                                                                                                                                                          |
| `color`             | Tint for leather armour and potions: `'#RRGGBB'` or `'R,G,B'`.                                                                                                                                                                                                                                                |
| `amount`            | Stack size (1-64).                                                                                                                                                                                                                                                                                            |

### Custom model data and item models

The `custom-model-data` number is read by the model in your pack. With `item-model`, one item definition of your own can hold all your menu icons: `item-model: 'mypack:pass_icons'` points at `assets/mypack/items/pass_icons.json`, and a `range_dispatch` on `custom_model_data` in it picks the icon by number:

```json
{
  "model": {
    "type": "minecraft:range_dispatch",
    "property": "minecraft:custom_model_data",
    "index": 0,
    "entries": [
      { "threshold": 20001, "model": { "type": "minecraft:model", "model": "mypack:item/gift_gold" } },
      { "threshold": 20002, "model": { "type": "minecraft:model", "model": "mypack:item/gift_gold_locked" } }
    ],
    "fallback": { "type": "minecraft:model", "model": "minecraft:item/paper" }
  },
  "oversized_in_gui": true
}
```

This keeps your icons away from the vanilla paper model. `"oversized_in_gui": true` (Minecraft 1.21.6+) lets an icon draw bigger than its slot: from 1.21.6 the game clips item models to the slot otherwise, which cuts XP bar pieces that are meant to join across slots. Without `item-model`, the number is read by the material's own model (`assets/minecraft/items/paper.json` on 1.21.4+, `overrides` in `models/item/paper.json` before). ItemsAdder, Nexo and Oraxen write these files for you: look up the number they gave your item, or use the item's id as `material`.

### Tooltip frames

`tooltip-style: 'mypack:gold'` uses `assets/mypack/textures/gui/sprites/tooltip/gold_background.png` and `gold_frame.png` from your pack (with `.png.mcmeta` files that set nine-slice scaling, like the vanilla tooltip).

### Invisible items

A common trick is to draw the buttons into the background picture and put an invisible item on each button slot. Give those items a model with a fully transparent texture. Add `hide-tooltip: true` to slots that should show nothing on hover, like the `filler`, and leave it out on buttons so players can still read their name and lore.

### A full button

The Gold Pass button, drawn with your icon and frame until the player owns it, and a second look once they do:

```yaml
items:
  gold-pass:
    slot: 1
    requirement: '{has_gold} = false'
    material: PAPER
    item-model: 'mypack:pass_icons'
    custom-model-data: 20004
    tooltip-style: 'mypack:gold'
    glow: true
    click-sound: 'ui.button.click 0.5 1.2'
    name: '&6&lGold Pass'
    lore:
      - '&7Unlocks every gold reward.'
      - ''
      - '&7Cost: &f{gold_cost} {currency}'
      - ''
      - '&eClick to buy'
    left-click-actions: [ 'buy gold' ]
  gold-pass-owned:
    slot: 1
    requirement: '{has_gold} = true'
    material: PAPER
    item-model: 'mypack:pass_icons'
    custom-model-data: 20007
    tooltip-style: 'mypack:gold'
    name: '&6&lGold Pass &a(owned)'
```

### The reward track

A state overrides any key of its track, so each state can have its own icon and frame:

```yaml
tier-items:
  gold:
    material: PAPER
    item-model: 'mypack:pass_icons'
    tooltip-style: 'mypack:gold'
    name: '&6Gold Tier {tier_number}'
    lore-header: [ '&7Rewards:' ]
    states:
      locked:    { custom-model-data: 20005, lore: [ '', '&7Reach this tier first' ] }
      claimable: { custom-model-data: 20004, glow: true, lore: [ '', '&aClick to claim' ] }
      claimed:   { custom-model-data: 20008, tooltip-style: 'mypack:common', lore: [ '', '&8Claimed' ] }
      no-pass:   { custom-model-data: 20006, lore: [ '', '&7Needs the Gold Pass' ] }
```

## 3. Numbers drawn with textures

### Stack size

`amount-from-tier: true` on `tier-markers` states and `tier-items` (or one of their states) makes the stack size the tier number. A stack stops at 64; for bigger numbers use a `counter`.

### `counter`: any number up to 9999

A `counter` section draws a number on the item with your pack (Minecraft 1.21.4+ server and game):

```yaml
tier-markers:
  slots: '28-34'
  locked:
    material: PAPER
    item-model: 'mypack:pass_icons'
    custom-model-data: 20031
    tooltip-style: 'mypack:common'
    amount-from-tier: true
    counter:
      value: '{tier_number}'
      base: 'node_locked'
      model: 'mypack:counted'
      above: 64
    name: '&7Tier {tier_number}'
```

| Key     | Meaning                                                                                                                                       |
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `value` | The number to show; tokens and placeholders work. Only its digits are kept, leading zeros are dropped and anything above 9999 shows 9999.     |
| `above` | Numbers from 1 up to this (at most 64) use the normal stack count and keep the item's own look. `0` (the default) always draws with the pack. |
| `base`  | The name of the icon your pack draws under the digits.                                                                                        |
| `model` | The item definition that draws icon + digits. Default `pinnapass:counted`.                                                                    |

When the pack draws the number, the item gets the item model `model`, a stack size of 1 and the `custom_model_data` strings: the first is `base`, then one per digit, units first (for 1250: `base`, `0`, `5`, `2`, `1`). On older servers the item keeps its normal look.

Your pack's item definition (`assets/mypack/items/counted.json` here) layers the icon and the digits with a `composite` model: a `select` on string 0 picks the icon, and a `select` on each following string picks that digit's model, which draws the digit at its place (units on the right). Strings that are not there fall back to an empty model, so short numbers show fewer digits. Shortened to two icons and the digits 0 and 1 (add a case per digit, and the same block with `index` 3 and 4 for hundreds and thousands):

```json
{
  "model": {
    "type": "minecraft:composite",
    "models": [
      {
        "type": "minecraft:select", "property": "minecraft:custom_model_data", "index": 0,
        "cases": [
          { "when": "node_locked", "model": { "type": "minecraft:model", "model": "mypack:item/node_locked" } },
          { "when": "node_done", "model": { "type": "minecraft:model", "model": "mypack:item/node_done" } }
        ],
        "fallback": { "type": "minecraft:model", "model": "mypack:item/node_locked" }
      },
      {
        "type": "minecraft:select", "property": "minecraft:custom_model_data", "index": 1,
        "cases": [
          { "when": "0", "model": { "type": "minecraft:model", "model": "mypack:item/digits/units_0" } },
          { "when": "1", "model": { "type": "minecraft:model", "model": "mypack:item/digits/units_1" } }
        ],
        "fallback": { "type": "minecraft:empty" }
      },
      {
        "type": "minecraft:select", "property": "minecraft:custom_model_data", "index": 2,
        "cases": [
          { "when": "0", "model": { "type": "minecraft:model", "model": "mypack:item/digits/tens_0" } },
          { "when": "1", "model": { "type": "minecraft:model", "model": "mypack:item/digits/tens_1" } }
        ],
        "fallback": { "type": "minecraft:empty" }
      }
    ]
  },
  "oversized_in_gui": true
}
```

Tip: a `select` on string 3 (it only exists for numbers with 3 or more digits) can switch to a smaller digit layout for long numbers. The same `counter` works in the Infinite menu's `level-markers` with `{level_number}`.

### An XP bar that fills pixel by pixel

The `progress-bar` of the pass and Infinite menus is a row of items. With pack pieces and a `partial` section, the piece where the bar ends shows how far into it the player is:

```yaml
progress-bar:
  slots: '9-17'
  filled:
    material: PAPER
    item-model: 'mypack:pass_icons'
    custom-model-data: 20013
    name: '&a{percent}%'
  empty:
    material: PAPER
    item-model: 'mypack:pass_icons'
    custom-model-data: 20012
    name: '&7{percent}%'
  partial:
    material: PAPER
    item-model: 'mypack:pass_icons'
    custom-model-data-steps: [20014, 20015, 20016, 20017]
    name: '&e{percent}%'
```

Pieces before the progress point are `filled`, pieces after it `empty`. The piece the bar ends in is split into one more part than there are steps: in the first part it shows `current` (when set, otherwise `empty`), then `partial` with the first, second... number of `custom-model-data-steps`. With 17 steps an 18 pixel piece fills one pixel at a time. The `partial` piece takes its other keys (name, lore, tooltip) from the `partial` section. Use `"oversized_in_gui": true` in the item definition so the pieces join across slots on 1.21.6+.

### A glyph text bar

The `{bar}` token of a menu comes from its `text-bar` (`length`, `filled`, `empty`). `filled` and `empty` are plain text, so they can be characters of your font, for example two different bar pieces, each followed by a negative space so the pieces touch.

### Glyphs from PlaceholderAPI

Titles, names and lore parse PlaceholderAPI, so a placeholder of another plugin that returns glyphs (for example a number written with your pack's digits) can be used anywhere in these menus. PinnaPass's own placeholders return plain text.

## Checklist

* Every player has your pack loaded (the server resource pack, or the hosting of your pack plugin), and it loads without errors.
* `&f` is the first thing in the title, and the offset lines the picture up with the slots.
* `tooltip-style` needs Minecraft 1.21.2+, `hide-tooltip` 1.20.5+, and `item-model`, `counter` and item definitions in `assets/<namespace>/items/` 1.21.4+, on the server and on the player's game. `oversized_in_gui` needs 1.21.6+.
* A barrier instead of your item means the `material` is misspelled, or its pack plugin isn't installed or doesn't know that id.
* After editing the menu files run `/pinnapass reload`. After changing the pack, rebuild it with your pack plugin and rejoin so the game loads the new version.
