# Infinite Save Scripting

## Step 1: Create a Script

Create a script or multiple scripts that will handle all save menu functionality.

For this example, we will create a single script called `InfiniteSavesExample.cs`.

Start the script by adding the member variables that can be set from the inspector.

```csharp
public class InfiniteSavesExample : MonoBehaviour
{
    [SerializeField]
    private Button saveSlotPrefab;
    
    [SerializeField]
    private Button saveSlotCreator;
    
    [SerializeField]
    private Transform content;
    
    [SerializeField]
    private Text timeElapsedText;
    
    [SerializeField]
    private Toggle modeToggle;
}
```

Remember to add a GameObject to the scene and add this script to it. At this point, we should have everything to populate the inspector properties.

<figure><img src="/files/420lh9ff2wiqnTuSdKwR" alt=""><figcaption></figcaption></figure>

### Properties

**Save Slot Prefab:** the save slot button prefab.

**Save Slot Creator:** the button that will create a new save.

**Content:** the scroll view's content object.

**Time Elapsed Text:** the text object that will display the time elapsed.

**Mode Toggle:** the toggle that will toggle the mode between load and save mode.

## Step 2: Other Script Members

We will create other members that won't be visible in the inspector.

```csharp
public class InfiniteSavesExample : MonoBehaviour
{
        private const string timeElapsedKey = "TimeElapsed";

        [SerializeField]
        private Button saveSlotPrefab;
        
        [SerializeField]
        private Button saveSlotCreator;
        
        [SerializeField]
        private Transform content;
        
        [SerializeField]
        private Text timeElapsedText;
        
        [SerializeField]
        private Toggle modeToggle;

        private List<Button> slots = new();

        private float timeElapsed;

        private bool loadMode { get => modeToggle.isOn; }
}
```

**timeElapsedKey:** the key (or ID) of the time elapsed for saving purposes.

**slots:** a list of buttons that will store all of the instantiated save slots.

**timeElapsed:** the time elapsed as a float.

**loadMode:** the isOn value of the toggle.

If load mode is true, we will make the save slots load a save. If it's false (save mode), we will make the save slots overwrite a save.

## Step 3: Instantiate Existing Saves

When we enter play mode, we need to first load any existing saves that the player may have made in a previous session.

We can do this using the Start method.

```csharp
private void Start()
{
    // Instantiate slots for existing saves
    foreach (var save in SaveStorage.instance.saves.Values) 
    {
        CreateNewSaveSlot(save);
    }
}
```

## Step 4: Increment Time

In the Update method, we will increment the time elapsed. This will be the only data that will be saved and loaded for this example.

```csharp
private void Update()
{
    // Increment time per frame
    timeElapsed += Time.deltaTime;
    timeElapsedText.text = $"Time Elapsed: {timeElapsed}";
}
```

## Step 5: Saving and Loading Data

We will create 3 methods for saving and loading. The first one will load the data from a save file.

```csharp
/// <summary>
/// Loads a save.
/// </summary>
/// <param name="saveFile">The save file.</param>
public void LoadSave(SaveFile saveFile)
{
    timeElapsed = saveFile.GetData<float>(timeElapsedKey);
}
```

The second one will save (or overwrite) the data in the save file.

```csharp
/// <summary>
/// Overwrites a save.
/// </summary>
/// <param name="saveFile">The save file.</param>
public void OverwriteSave(SaveFile saveFile)
{
    // Save the time elapsed
    saveFile.AddOrUpdateData(timeElapsedKey, timeElapsed);
    saveFile.Save();
}
```

The third one will be used by the save slots and will load or overwrite the data depending on the mode.

```csharp
/// <summary>
/// Loads or overwrites the save based on the active mode.
/// </summary>
/// <param name="saveFile">The save file.</param>
public void LoadOrOverwriteSave(SaveFile saveFile)
{
    if (loadMode)
    {
        LoadSave(saveFile);
    }
    else
    {
        OverwriteSave(saveFile);
    }
}
```

## Step 6: Create New Save

We have methods that require a save file, but no save file is being created yet. A save file should be created when the 'Create New Save' button is pressed, along with a save slot.

So, let's create some methods for this. The first method will create a new save file.

```csharp
/// <summary>
/// Creates a new save.
/// </summary>
public void CreateNewSave()
{
    // Create the save file data
    SaveFileSetupData saveFileSetupData = new()
    {
        fileName = $"InfiniteExampleSave{SaveStorage.instance.saveCount}",
        saveLocation = SaveLocation.DataPath,
        filePath = "StylishEsper/ESave/Examples/Any RP Examples",
        fileType = FileType.Json,
        encryptionMethod = EncryptionMethod.None,
        addToStorage = true
    };

    SaveFile saveFile = new SaveFile(saveFileSetupData);

    // Save the time elapsed
    // Techincally, nothing is being overwitten at this stage since it is an empty save file
    OverwriteSave(saveFile);

    // Create ths save slot for this data
    CreateNewSaveSlot(saveFile);
}
```

At the end, CreateNewSaveSlot is called. This has not been created yet.  The CreateNewSaveSlot method will instantiate a new save slot, edit the save slot's text, and give the save slot an on-click event that will call LoadOrOverwriteSave.

```csharp
/// <summary>
/// Creates a save slot for a save file.
/// </summary>
/// <param name="saveFile">The save file.</param>
public void CreateNewSaveSlot(SaveFile saveFile)
{
    // Instantiate the save slot
    var slot = Instantiate(saveSlotPrefab, content);
    var slotText = slot.transform.GetChild(0).GetComponent<Text>();
    slotText.text = $"Save Slot {slots.Count}";

    // Move save creator to the bottom
    saveSlotCreator.transform.SetAsLastSibling();

    // Add on-click event for loading
    slot.onClick.AddListener(() => LoadOrOverwriteSave(saveFile));

    slots.Add(slot);
}
```

We still need the save slot creator button to have an on-click event that creates a new save. This can be done by updating our Start method.

```csharp
private void Start()
{
    // Instantiate slots for existing saves
    foreach (var save in SaveStorage.instance.saves.Values) 
    {
        CreateNewSaveSlot(save);
    }

    // Save slot creator on-click event
    saveSlotCreator.onClick.AddListener(CreateNewSave);
}
```

Done! You can now test it in play mode.


---

# 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://espergames.gitbook.io/esave/scripting/runtime-save-creation/infinite-saves/infinite-save-scripting.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.
