> For the complete documentation index, see [llms.txt](https://docs.rainmad.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rainmad.com/resources/decal-v-graffiti-and-vehicle-sticker/adding-decals.md).

# Adding Decals

The catalog is `rm_decalv/decals.lua`, an open file of **category blocks**. Fields set on a block (`textureDict`, `jobs`, `gangs`, `identifiers`, `adminOnly`, `resolution`, `canUse`, `vehicleModels`) are inherited by every entry inside it; any entry can override them.

```lua
{
    category = 'My Crew',
    gangs = { 'ballas' },              -- whole block gang-locked
    decals = {
        { label = 'Crew Tag', fileName = 'crew_tag.webp' },
        { label = 'Boss Tag', fileName = 'boss_tag.webp', adminOnly = true },
    },
},
```

Every decal needs its image in `rm_decalv/assets/` (webp, png or jpg) even when a ytd texture is used, because the interface preview reads the image file. After editing, restart `rm_decalv`.

## Method 1: texture dictionary (recommended)

Streamed `.ytd` textures are how all bundled categories work: the game loads them through its normal texture streaming, the same way it loads vehicle and map textures. That means no image decoding at runtime, no small texture pool to fill up, and it scales to hundreds of decals. Prefer this for anything beyond a handful of custom decals.

```lua
{
    category = 'JDM',
    textureDict = 'rm_dcl_jdm',        -- ytd in rm_decalv_assets/stream/
    decals = {
        { label = 'Antisocial Kanji', fileName = 'antisocial_kanji.webp' },
        -- textureName defaults to the file name without extension
    },
},
```

{% stepper %}
{% step %}

## Build the texture dictionary

Build a `.ytd` containing one **DXT5** texture per decal (OpenIV: new texture dictionary, import images). Texture names must match each entry's `fileName` without the extension, or set `textureName` per entry.
{% endstep %}

{% step %}

## Put the file in the stream folder

Put the ytd in `rm_decalv_assets/stream/` and keep the preview images in `rm_decalv/assets/`.
{% endstep %}

{% step %}

## Set the block field

Set `textureDict` on the block.
{% endstep %}
{% endstepper %}

**Flip support:** the flip/true-mirror feature looks for a `<dict>_f` twin. Generate it from your ytd with the bundled tool, no OpenIV needed. The only requirement is [Node.js](https://nodejs.org/) (18 or newer) on the machine you run it on; the tool has no packages to install:

```bash
cd rm_decalv_assets/tools/ytd-flip
node index.js ../../stream/my_dict.ytd
```

It writes `my_dict_f.ytd` next to the input. Without a twin the decal simply renders unflipped and the interface greys the flip switch out.

## Method 2: plain image file (quick for a few decals)

{% stepper %}
{% step %}

## Add the image

Drop your image into `rm_decalv/assets/`.
{% endstep %}

{% step %}

## Add the entry

Add an entry to a category block **without** a `textureDict` (or with `textureDict = false` inside a dict-carrying block):

```lua
{ label = 'My New Decal', fileName = 'my_new_decal.webp' },
```

The texture is decoded at runtime into a small per-client pool (8× 256², 16× 512², 6× 1024² slots) and its resolution is read from the file automatically. Perfectly fine for a handful of decals, but the pool is finite, so packs belong in a dictionary.
{% endstep %}
{% endstepper %}

## Method 3: in-game import (admins)

The [admin panel](/resources/decal-v-graffiti-and-vehicle-sticker/admin-panel.md) adds decals without touching files:

* **Add from URL:** downloads any https image into `assets/` for you.
* **Add GIF:** same, for animated GIFs (needs `cfg.enableGifDecals`).
* **Decal editor:** compose text + images on a canvas, exported as a webp.

Each flow ends with a ready-to-paste `decals.lua` entry, e.g.:

```lua
{ label = 'My Import', fileName = 'url_my_import.webp', textureDict = false },
```

Paste it inside the category block you want and restart the resource. The `textureDict = false` is important: it keeps the entry an image file even inside a block that carries a block-level texture dictionary. Files that never get their entry pasted are reported at startup as unreferenced. Imports are image-source decals (Method 2 rules apply); once a batch grows, move it into its own dictionary.

## Entry field reference

| Field            | Type              | Meaning                                                                                                               |
| ---------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------- |
| `label`          | string            | Name shown in the catalog (must be set)                                                                               |
| `fileName`       | string            | Image in `assets/`, unique, extension included                                                                        |
| `textureDict`    | string \| `false` | Stream ytd to render from; `false` forces the image file                                                              |
| `textureName`    | string            | Texture inside the dict; defaults to `fileName` minus extension                                                       |
| `resolution`     | number            | Optional override for the runtime pool bucket (auto-read from the file otherwise)                                     |
| `jobs` / `gangs` | string\[]         | Only these jobs/gangs see and use the decal                                                                           |
| `identifiers`    | table             | `['license:...'] = true` style allow-list (citizenid works on qb/qbox)                                                |
| `adminOnly`      | boolean           | Admins only                                                                                                           |
| `vehicleModels`  | string\[]         | Sticker can only be applied to these models (server-enforced)                                                         |
| `canUse`         | function          | Server-side final gate, see [Events & Exports](/resources/decal-v-graffiti-and-vehicle-sticker/events-and-exports.md) |
