> For the complete documentation index, see [llms.txt](https://openjs.wiki.gd/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://openjs.wiki.gd/openjs-components/in-build-classes/diskapi.md).

# Loading and saving data

The Disk API allows you to persistently store and retrieve data for players or general use. Useful for tracking stats, progress, or saving any kind of JSON-compatible values between server restarts.

***

## Overview

| Method                                                 | Description                                                                                                                                                   |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DiskApi.loadFile(fileName, async, global)`            | Loads the contents of a file into memory. Must be called before accessing any stored values with `getVar`                                                     |
| `DiskApi.saveFile(fileName, async, global)`            | Saves the in-memory data for the specified file to disk. Call this to persist changes made via `setVar` . This will also clear the data from the memory (ram) |
| `DiskApi.getVar(fileName, key, fallbackValue, global)` | Retrieves the value associated with `key` from the in-memory file. If the key doesn't exist, returns `fallbackValue`                                          |
| `DiskApi.setVar(fileName, key, value, global)`         | Sets the value of `key` to `value` in the in-memory file. This does not save to disk until `saveFile` is called                                               |

{% hint style="danger" %}
When storing and loading player data, make sure to separate the files for each player. Also, always save the player's file when they leave to prevent memory leaks from accumulating as new players join!
{% endhint %}

***

## Parameters

| Parameter       | Type      | Description                                                                  |
| --------------- | --------- | ---------------------------------------------------------------------------- |
| `fileName`      | `String`  | Name of the file (no extension). Should be unique per player or purpose.     |
| `key`           | `String`  | The variable name to store or retrieve.                                      |
| `value`         | `Any`     | Value to be saved. Will be serialized using `JSON.stringify`.                |
| `fallbackValue` | `Any`     | Value to return if the key does not exist.                                   |
| `async`         | `Boolean` | If `true`, runs the load/save operation in a separate thread.                |
| `global`        | `Boolean` | If `true`, the file is shared across all scripts; otherwise script-specific. |

***

#### Async Explained

Setting `async = true` will cause the file operation to run in a separate thread, **preventing lag or stalling** the main server thread.

However, since file I/O will be **delayed**, you should wait before accessing or modifying data by using:

```js
task.spawn(function(){ /* Your logic here */ })
```

Using `registerSchedule` with the second parameter set to `0` ensures the code runs in a separated thread.

{% hint style="info" %}
If you're using `task.spawn(function() {})` to run your logic off the main thread, you **should set `async = false`** in your DiskApi methods. This avoids double-threading and **ensures data is loaded and available in the same thread**.
{% endhint %}

***

#### Global vs Local Storage

* `global = false`: Data is saved **per script**, useful for isolated storage.
* `global = true`: Data is shared across scripts, use for shared access.

***

{% code title="Example Usage" %}

```js
var ValueName = "destroyedBlocks"

function getFileName(player) {
    return player.getUniqueId() + "_data"
}

registerEvent("org.bukkit.event.player.PlayerJoinEvent", function(event) {
    task.spawn(function() {
        var player = event.getPlayer();
        var fileName = getFileName(player);
        DiskApi.loadFile(fileName, false, false);
        var breakedBlocks = DiskApi.getVar(fileName, ValueName, 0, false);
        player.sendMessage("You destroyed "+breakedBlocks+" blocks!")
    });
})

registerEvent("org.bukkit.event.player.PlayerQuitEvent", function(event) {
    task.spawn(function() {
        var player = event.getPlayer();
        var fileName = getFileName(player);
        log.info("Saving player data...")
        DiskApi.saveFile(fileName, false, false);
        log.info("Data saved!")
    })
})

registerEvent("org.bukkit.event.block.BlockBreakEvent", function(event) {
    var player = event.getPlayer()
    var fileName = getFileName(player);
    var destroyedBlocks = DiskApi.getVar(fileName, ValueName, 0, false) + 1
    DiskApi.setVar(fileName, "destroyedBlocks", destroyedBlocks, false)
    event.getPlayer().sendMessage("You destroyed " + destroyedBlocks + " blocks!");
});
```

{% endcode %}

***

{% hint style="success" %}

#### Tips

* Always load the file before using `getVar()` or `setVar()`
* For frequent access, store `fileName` in a variable to avoid recalculating
* For large data sets or many players, prefer `async = true` and threading logic using `task.spawn()`
* Data that is still in memory will automatically save as soon as the plugin gets disabled/shutdown
  {% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://openjs.wiki.gd/openjs-components/in-build-classes/diskapi.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
