# Notecards

> lsl.dev (unofficial LSL docs). Full API: https://lsl.dev/api.json · Index for LLMs: https://lsl.dev/llms.txt

> Reading notecards: synchronous reads from the cache, dataserver reads, line counts, searching and reloading on change.

Notecards are text in the object's inventory. Scripts can read them but not write them, which makes them good for configuration that users edit by hand. Part of the [Data Storage](/features/data-storage/) feature.

## Concepts

- [`llGetNotecardLine`](/functions/llGetNotecardLine/) requests a line, which arrives in [`dataserver`](/events/dataserver/); lines start at 0
  - A line past the end returns [`EOF`](/constants/EOF/)
- [`llGetNotecardLineSync`](/functions/llGetNotecardLineSync/) returns a line immediately if the region has the notecard cached
  - It returns [`NAK`](/constants/NAK/) when the notecard is not cached; fall back to `llGetNotecardLine`, or read the line count first to load it into the cache
  - The cache drops the least recently read notecards first, so never assume a notecard is still cached
  - No `dataserver` event is raised, and memory is not garbage-collected inside a tight read loop
- [`llGetNumberOfNotecardLines`](/functions/llGetNumberOfNotecardLines/) returns the line count through `dataserver`
- [`llFindNotecardTextSync`](/functions/llFindNotecardTextSync/) searches a cached notecard with a regular expression, returning up to 64 matches as row, column and length
- Lines longer than 1024 bytes are truncated
- A notecard with embedded inventory items, such as landmarks, returns `EOF` for every line
- When a user edits the notecard, [`changed`](/events/changed/) reports [`CHANGED_INVENTORY`](/constants/CHANGED_INVENTORY/); reload the configuration then

## Functions and events

- `key` [`llGetNotecardLine`](/functions/llGetNotecardLine/) `(string name, integer line)`
- `string` [`llGetNotecardLineSync`](/functions/llGetNotecardLineSync/) `(string name, integer line)`
- `key` [`llGetNumberOfNotecardLines`](/functions/llGetNumberOfNotecardLines/) `(string name)`
- `list` [`llFindNotecardTextSync`](/functions/llFindNotecardTextSync/) `(string name, string pattern, integer start, integer count, list options)`
- `event` [`dataserver`](/events/dataserver/) `(key queryid, string data)`

## Scripting Details

- `string` [`llGetNotecardLineSync`](/functions/llGetNotecardLineSync/) `(string name, integer line)`: Synchronously reads the line index line of the notecard name from the region's cache, immediately returning its text without raising a dataserver event. Returns 'NAK' if not cached or 'EOF' if out of bounds.
- `key` [`llGetNotecardLine`](/functions/llGetNotecardLine/) `(string name, integer line)`: Asynchronously requests the line index line of the notecard name from the dataserver. Returns a key query handle for the dataserver event, which will return 'EOF' when reaching past the end of the notecard.
- `key` [`llGetNumberOfNotecardLines`](/functions/llGetNumberOfNotecardLines/) `(string name)`: Asynchronously requests the total line count of the notecard name. Returns a key query handle for the dataserver event.
- `list` [`llFindNotecardTextSync`](/functions/llFindNotecardTextSync/) `(string name, string pattern, integer start, integer count, list options)`: Synchronously searches a cached notecard name for lines containing pattern, returning a list of line and column numbers. Returns a list containing 'NAK' if the notecard is not cached, or an empty list if no matches are found.
- `key` [`llFindNotecardTextCount`](/functions/llFindNotecardTextCount/) `(string notecardname, string pattern, list options)`: Searches the text of a cached notecard for lines containing the given pattern and returns the number of matches found through a dataserver event.
- `event` [`dataserver`](/events/dataserver/) `(key queryid, string data)`: Triggered when requested data is returned to the script (e.g., from llRequestAgentData, llRequestInventoryData, or llGetNotecardLine).
- `event` [`changed`](/events/changed/) `(integer changes)`: Triggered when various properties of the object change. The parameter changes is a bitfield of CHANGED_* flags.

## Example

Reads a whole notecard, using the cache where possible.

```lsl
string NOTECARD = "config";
integer line;
key request;

readLines()
{
    string data = llGetNotecardLineSync(NOTECARD, line);
    while (data != NAK && data != EOF)
    {
        llOwnerSay((string)line + ": " + data);
        data = llGetNotecardLineSync(NOTECARD, ++line);
    }
    if (data == NAK)
        request = llGetNotecardLine(NOTECARD, line);  // not cached: ask the dataserver
}

default
{
    state_entry()
    {
        line = 0;
        readLines();
    }

    dataserver(key id, string data)
    {
        if (id != request || data == EOF) return;
        llOwnerSay((string)line + ": " + data);
        ++line;
        readLines();
    }

    changed(integer change)
    {
        if (change & CHANGED_INVENTORY) llResetScript();
    }
}
```

## Related

See also: [Data Storage](/features/data-storage/), [Notecard](/categories/notecard/), [Inventory](/features/inventory/), [LSL Notecard (Second Life Wiki)](https://wiki.secondlife.com/wiki/Category:LSL_Notecard)
   (planned: Guide: reading a configuration notecard)

## Related features

- [Data Storage](/features/data-storage/)
- [Inventory](/features/inventory/)

## Categories

- [Notecard](/categories/notecard/)
- [Dataserver](/categories/dataserver/)

---

From lsl.dev: https://lsl.dev/features/data-storage/notecards/
