# Preload

## Description

```
'preload <type> <asset> [blocking]'
'preload character <id> <sprite> [blocking]'
'preload block <block_id> [blocking]'
```

The preload action allows you to load assets into memory before they are needed. This prevents lag or loading delays during gameplay, ensuring a smooth experience for the player.

**Action ID**: `Preload`

**Reversible**: No (Reverting does nothing)

**Requires User Interaction**: No

## Parameters

| Parameter  | Description                                                                                                            |
| ---------- | ---------------------------------------------------------------------------------------------------------------------- |
| `type`     | The category of the asset (see [Supported Categories](#supported-categories) below).                                   |
| `asset`    | The name/identifier of the asset to preload (as registered in `monogatari.assets()`).                                  |
| `id`       | When preloading a character, the character's ID.                                                                       |
| `sprite`   | When preloading a character, the sprite name (as defined in the character's `sprites` object).                         |
| `block_id` | When using `preload block`, the ID of the defined preload block to load.                                               |
| `blocking` | (Optional) If included, the game will wait for the asset(s) to finish loading before proceeding to the next statement. |

## Supported Categories

### Default Audio Categories (use `audio` loader)

* `music` - Background music tracks
* `sounds` or `sound` - Sound effects
* `voices` or `voice` - Voice clips

### Default Image Categories (use `image` loader)

* `scenes` or `scene` - Scene backgrounds
* `images` or `image` - General images
* `characters` - Character sprites (uses special syntax, see examples)

Note: Singular forms (`sound`, `voice`, `scene`, `image`) are aliases for their plural counterparts.

## Examples

### Preload a single music track

```javascript
'preload music theme_song'
```

### Preload a scene (blocking)

```javascript
'preload scene library blocking'
```

### Preload a sound effect

```javascript
'preload sound explosion blocking'
```

### Preload a character sprite

```javascript
'preload character y happy blocking'
```

### Preload a predefined block of assets

```javascript
'preload block Chapter1'
```

## Preload Blocks

Preload blocks allow you to group multiple assets together to be preloaded at once. These are defined using `monogatari.action('Preload').blocks()`.

### The `default` Block

The `default` block is a **special preload block** that runs automatically during the game's initial loading screen. Assets defined in the `default` block are:

* **Decoded and cached** - Audio is decoded to AudioBuffers, images are pre-decoded for immediate display
* **Loaded before gameplay** - Players see the loading progress bar while these assets load
* **Ready for instant playback** - No delay when first using these assets in-game

```javascript
monogatari.action('Preload').blocks({
    'default': {
        music: ['main_theme', 'menu_music'],
        scenes: ['title_screen', 'chapter1_intro'],
        sounds: ['click', 'notification'],
        characters: {
            'y': ['normal', 'happy', 'sad']
        }
    }
});
```

> \[!TIP] Use the `default` block for assets needed immediately or frequently throughout the game. For chapter-specific assets, use named blocks and the `preload block` action.

### Default Block vs. Legacy Preloading

| With `default` Block                | Without `default` Block (Legacy)         |
| ----------------------------------- | ---------------------------------------- |
| Only specified assets are preloaded | ALL registered assets are preloaded      |
| Audio is decoded to AudioBuffers    | Audio is only fetched to browser cache   |
| Images are pre-decoded              | Images are only fetched to browser cache |
| Faster first playback               | May have slight delay on first use       |
| More control over initial load time | Longer initial load with many assets     |

### Defining Named Blocks

Named blocks are loaded on-demand using `preload block <name>` in your script:

```javascript
monogatari.action('Preload').blocks({
    'default': {
        // Loaded automatically at game start
        music: ['main_theme'],
        scenes: ['intro']
    },
    'Chapter1': {
        // Loaded when you use 'preload block Chapter1'
        music: ['theme_song', 'battle_music'],
        scenes: ['school_gate', 'classroom'],
        sounds: ['door_open', 'footsteps'],
        characters: {
            'y': ['happy', 'sad', 'normal']
        }
    },
    'Chapter2': {
        music: ['dramatic_theme'],
        scenes: ['rooftop'],
        images: ['sunset_photo']
    }
});
```

### Block Structure

```typescript
interface PreloadBlock {
    music?: string[];       // Asset names from monogatari.assets('music', {...})
    sounds?: string[];      // Asset names from monogatari.assets('sounds', {...})
    voices?: string[];      // Asset names from monogatari.assets('voices', {...})
    scenes?: string[];      // Asset names from monogatari.assets('scenes', {...})
    images?: string[];      // Asset names from monogatari.assets('images', {...})
    characters?: {          // Character sprite names
        [characterId: string]: string[]  // Sprite names from character's sprites object
    };
    [customCategory: string]: string[] | undefined;  // Custom categories (see below)
}
```

### Using Blocks in Scripts

```javascript
monogatari.script({
    'Start': [
        'Before the chapter begins, let\'s load assets...',
        'preload block Chapter1 blocking',
        'All assets are now loaded!',
        // ... rest of chapter
    ]
});
```

## Blocking vs Non-Blocking

By default, preload is **non-blocking** - the game immediately advances to the next statement while assets load in the background. This is useful for preloading assets you'll need later.

Adding the `blocking` keyword makes the action wait for the preload to complete before advancing. This is useful when you need the asset immediately after the preload statement.

```javascript
// Non-blocking: loads in background while dialogue continues
'preload music boss_battle',
'The hero approaches the castle...',

// Blocking: waits for asset to load before continuing
'preload scene castle_interior blocking',
'show scene castle_interior'
```

## Advanced: Custom Categories

You can register custom asset categories to use with the preload system.

### Registering a Custom Category

```javascript
// Register a custom category 'posters' that uses the image loader
monogatari.action('Preload').registerCategory('posters', 'image');

// Configure the assets path for your custom category
const assetsPath = monogatari.setting('AssetsPath');
assetsPath.posters = 'images/posters';
monogatari.setting('AssetsPath', assetsPath);

// Register assets for your custom category
monogatari.assets('posters', {
    'movie_poster': 'avengers.jpg',
    'concert_poster': 'live_show.png'
});
```

### Using Custom Categories

Once registered, custom categories work like built-in ones:

```javascript
// Single asset preload
'preload posters movie_poster blocking'

// In preload blocks
monogatari.action('Preload').blocks({
    'theater_scene': {
        posters: ['movie_poster', 'concert_poster'],
        music: ['theater_ambience']
    }
});
```

## Advanced: Custom Loaders

For advanced use cases, you can register entirely custom loaders for new asset types.

### Registering a Custom Loader

```javascript
monogatari.action('Preload').registerLoader('video', {
    loader: async (url, engine) => {
        // Custom loading logic
        const video = document.createElement('video');
        video.src = url;
        await new Promise((resolve, reject) => {
            video.onloadeddata = resolve;
            video.onerror = reject;
        });
        return video;
    },
    cache: {
        get: (engine, key) => engine.videoCache?.(key),
        set: (engine, key, value) => engine.videoCache?.(key, value),
        delete: (engine, key) => engine.videoUncache?.(key),
        clear: (engine, prefix) => engine.videoClearCache?.(prefix)
    }
});

// Then register categories to use this loader
monogatari.action('Preload').registerCategory('videos', 'video');
```

## Related Actions

* [Unload](/documentation/script-actions/unload.md) - Release assets from memory when no longer needed


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.monogatari.io/documentation/script-actions/preload.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
