# API

**Assembly:** `Spark.Save` **Interface:** `ISaveDataPlugin` **Implementation:** `SaveDataPlugin`

## Interface

```csharp
public interface ISaveDataPlugin
{
    // Type registration
    void RegisterSaveDataType<T>();

    // Data access
    T GetSaveData<T>(string key = null);
    void SetSaveData<T>(T data, string key = null);
    bool HasSaveData<T>(string key = null);
    string[] GetRegisteredTypeNames();

    // Persistence
    Task<bool> SaveAsync();
    Task<bool> LoadAsync();
    void ClearAllData();

    // Storage providers
    void RegisterStorageProvider(ISaveDataProvider provider);
    void SetActiveStorageProvider(string providerId);

    // Slot management
    SaveSlotManager GetSlotManager();
    Task<SaveSlotMetadata> CreateNewSlot(string displayName);
    Task<bool> LoadSlot(string slotId);
    Task<bool> DeleteSlot(string slotId);
    Task<List<SaveSlotMetadata>> GetAllSlots();
    Task<SaveSlotMetadata> GetCurrentSlotMetadata();
    Task<bool> SaveAndUpdateMetadata();

    // Version management
    Task<SaveVersionMetadata> CreateManualVersion(string displayName,
        long totalPlaytimeSeconds);
    Task<List<SaveVersionMetadata>> GetAllVersions();
    Task<bool> LoadVersion(string versionId);
    Task<bool> DeleteVersion(string versionId);
    bool IsLoadingVersion();
}
```

## SaveDataEntry

Abstract base class for all save data types.

| Field          | Type   | Description                    |
| -------------- | ------ | ------------------------------ |
| `saveKey`      | string | Storage key identifier         |
| `lastModified` | long   | Timestamp of last modification |

**Virtual Methods:**

```csharp
void OnBeforeSave()       // Called before serialization
void OnAfterLoad()        // Called after deserialization
void InitializeDefaults() // Sets default values for new data
void ValidateData()       // Validates data integrity after load
```

## SaveSlotMetadata

Represents a save slot.

| Field                   | Type   | Description                     |
| ----------------------- | ------ | ------------------------------- |
| `slotId`                | string | Unique slot identifier          |
| `displayName`           | string | Player-facing name              |
| `creationTimestamp`     | long   | When the slot was created       |
| `lastModifiedTimestamp` | long   | When last saved                 |
| `activeVersionId`       | string | Current version within the slot |

**Methods:**

```csharp
string GetFormattedCreationDate()
string GetFormattedLastModified()
void UpdateTimestamp()
```

## SaveVersionMetadata

Represents a versioned snapshot within a slot.

| Field                  | Type            | Description                         |
| ---------------------- | --------------- | ----------------------------------- |
| `versionId`            | string          | Unique version identifier           |
| `displayName`          | string          | Player-facing name                  |
| `creationTimestamp`    | long            | When created                        |
| `versionType`          | SaveVersionType | Initial, Auto, Manual, or QuickSave |
| `fileName`             | string          | Storage file name                   |
| `savedTimestamp`       | long            | When saved                          |
| `fileSizeBytes`        | long            | File size                           |
| `totalPlaytimeSeconds` | long            | Playtime at save                    |

```csharp
public enum SaveVersionType
{
    Initial,
    Auto,
    Manual,
    QuickSave
}
```

**Methods:**

```csharp
string GetFormattedCreationDate()
string GetFormattedSaveDate()
string GetFormattedFileSize()
string GetFormattedPlaytime()
```

## SaveDataContainer

Internal JSON serialization wrapper.

| Field             | Type                      | Description                  |
| ----------------- | ------------------------- | ---------------------------- |
| `saveDataEntries` | List\<TypedSaveDataEntry> | Type-keyed data              |
| `keyedSaveData`   | List\<KeyedSaveDataEntry> | String-keyed data            |
| `saveTimestamp`   | long                      | When the container was saved |
| `sparkVersion`    | string                    | Spark version at save time   |

## Commands

| Command                | Description                                           |
| ---------------------- | ----------------------------------------------------- |
| `SaveDataCommand`      | Triggers async save with optional completion callback |
| `LoadDataCommand`      | Triggers async load with optional completion callback |
| `ClearSaveDataCommand` | Clears all in-memory data with optional callback      |

## Storage Providers

The Save plugin supports pluggable storage backends through `ISaveDataProvider`:

| Provider                         | Description                              |
| -------------------------------- | ---------------------------------------- |
| `LocalFileSaveProvider`          | Writes to local JSON files               |
| `SlotAwareLocalFileSaveProvider` | Multi-slot local storage with versioning |

Custom providers implement `ISaveDataProvider` and register via `RegisterStorageProvider()`.

## Usage

```csharp
var savePlugin = Spark.GetPlugin<ISaveDataPlugin>();
if (savePlugin != null)
{
    // Register a custom save data type
    savePlugin.RegisterSaveDataType<MyCustomSaveData>();

    // Store data
    var data = new MyCustomSaveData();
    data.score = 1000;
    savePlugin.SetSaveData(data);

    // Retrieve data
    var loaded = savePlugin.GetSaveData<MyCustomSaveData>();
    Debug.Log($"Score: {loaded.score}");

    // Save to disk
    bool success = await savePlugin.SaveAsync();

    // Slot management
    var slot = await savePlugin.CreateNewSlot("Adventure 1");
    var allSlots = await savePlugin.GetAllSlots();
    await savePlugin.LoadSlot(slot.slotId);

    // Version snapshots
    var version = await savePlugin.CreateManualVersion("Before Boss", 3600);
    await savePlugin.LoadVersion(version.versionId);
}
```

## Creating Custom Save Data

```csharp
[System.Serializable]
public class MyCustomSaveData : SaveDataEntry
{
    public int score;
    public List<string> unlockedItems = new List<string>();

    public override void InitializeDefaults()
    {
        score = 0;
        unlockedItems.Clear();
    }

    public override void ValidateData()
    {
        if (score < 0) score = 0;
    }
}
```

Register the type during your plugin's initialization:

```csharp
Spark.GetPlugin<ISaveDataPlugin>()?.RegisterSaveDataType<MyCustomSaveData>();
```


---

# 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://docs.sparkframework.dev/documentation/developer-guide/core-systems/save/api.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.
