Easy Chapter Generator
EnglishEspañol

Implementar cuatro operaciones de clave exacta

IProgressStore define TryRead, Write, Delete y Flush. El Manager proporciona claves completas y opacas. El adaptador no debe interpretarlas, cambiarles el prefijo, enumerarlas ni mezclarlas con las ranuras del sistema de partida.

Una clave ausente devuelve false y un string vacío. Un valor vacío guardado devuelve true. Las claves null producen ArgumentNullException; vacías o con espacios, ArgumentException; Write también rechaza un valor null.

Instalar el proveedor antes del bloqueo

Llama a TrySetProgressStore antes de leer, escribir, restaurar, borrar, confirmar o iniciar la progresión. Success sustituye el proveedor sin copiar ni modificar datos. Un valor null devuelve StoreUnavailable; una llamada tardía, ManagerAlreadyInitialized.

Un proveedor del Inspector debe ser un MonoBehaviour que implemente la interfaz. Si no se asigna se utiliza PlayerPrefs. V1 llama desde el hilo principal y no exige seguridad multihilo.

No ocultar fallos del almacenamiento

  • Write crea o sustituye sin llamar a Flush.
  • Delete indica si existía y tampoco confirma automáticamente.
  • Flush confirma lo pendiente, pero no captura nuevo progreso.
  • Las excepciones se convierten en StoreError.
  • Un esquema más nuevo devuelve UnsupportedSchema.

Si el proveedor real es asíncrono, acumula operaciones limitadas y define una frontera de confirmación compatible, o conserva esa persistencia fuera de este adaptador. No bloquees el hilo principal con red sin límite.

Pruebas del proveedor

  1. 1
    Distingue clave ausente y valor vacío.
  2. 2
    Escribe dos veces y comprueba que sustituye.
  3. 3
    Elimina una clave existente y otra ausente: true y false.
  4. 4
    Comprueba que Write/Delete no llaman a Flush y una sola llamada confirma el conjunto.
  5. 5
    Provoca fallos de cada operación y exige StoreError.
  6. 6
    Ejecuta la prueba de restauración y confirma que no se repiten eventos históricos.

Confirmar el progreso en un punto de guardado

Dónde colocarlo
Añade este método al coordinador de guardado o al controlador de puntos de control del proyecto.
Cuándo llamarlo
Llama a FlushAtSavePoint después de cambios de progreso aceptados o antes de una salida controlada.
Comportamiento
FlushProgress solo confirma el almacén de progresión configurado; no serializa escenas, inventarios ni GameObjects arbitrarios.
using System;
using System.Collections;
using System.Collections.Generic;
using OverFuture.ChapterObjectiveSystem.Chapters;
using OverFuture.ChapterObjectiveSystem.Events;
using OverFuture.ChapterObjectiveSystem.Objectives;
using OverFuture.ChapterObjectiveSystem.Persistence;
using OverFuture.ChapterObjectiveSystem.Progression;
using UnityEngine;

public sealed class FlushProgressExample : MonoBehaviour
{
    public ProgressOperationResult FlushAtSavePoint()
    {
        ChapterManager manager = ChapterManager.Instance;
        return manager != null
            ? manager.FlushProgress()
            : ProgressOperationResult.StoreUnavailable;
    }
}

Implementar un IProgressStore personalizado

Dónde colocarlo
Coloca el almacén en el ensamblado de guardado del proyecto y pasa una instancia a TrySetProgressStore antes de que la inicialización bloquee la configuración.
Cuándo llamarlo
El Manager llama a las operaciones de clave exacta desde el hilo principal de Unity; Flush solo se invoca en puntos explícitos.
Comportamiento
El ejemplo en memoria demuestra el contrato, pero no conserva datos entre sesiones. Sustituye el almacenamiento y Flush por tu sistema sin interpretar ni reescribir las claves opacas.
using System;
using System.Collections;
using System.Collections.Generic;
using OverFuture.ChapterObjectiveSystem.Chapters;
using OverFuture.ChapterObjectiveSystem.Events;
using OverFuture.ChapterObjectiveSystem.Objectives;
using OverFuture.ChapterObjectiveSystem.Persistence;
using OverFuture.ChapterObjectiveSystem.Progression;
using UnityEngine;

public sealed class MemoryProgressStore : IProgressStore
{
    private readonly Dictionary<string, string> values =
        new Dictionary<string, string>(StringComparer.Ordinal);

    public bool TryRead(string key, out string value)
    {
        ValidateKey(key);
        if (values.TryGetValue(key, out value))
        {
            return true;
        }

        value = string.Empty;
        return false;
    }

    public void Write(string key, string value)
    {
        ValidateKey(key);
        values[key] = value ?? throw new ArgumentNullException(nameof(value));
    }

    public bool Delete(string key)
    {
        ValidateKey(key);
        return values.Remove(key);
    }

    public void Flush()
    {
        // Persist pending data in the project-specific backend here.
    }

    private static void ValidateKey(string key)
    {
        if (key == null)
        {
            throw new ArgumentNullException(nameof(key));
        }

        if (string.IsNullOrWhiteSpace(key))
        {
            throw new ArgumentException("A progress key cannot be empty.", nameof(key));
        }
    }
}