Class SaveData<T>

java.lang.Object
org.openpatch.scratch.save.SaveData<T>
Type Parameters:
T - the game's data class

public final class SaveData<T> extends Object
Saves a game's progress as JSON independently of its installation directory. Data classes should have a public no-argument constructor and public fields. Public fields, including inherited fields, primitives, strings, enums, arrays and nested data classes, form the portable save format. Static and transient fields are excluded. Avoid getters, setters, library objects and object cycles in data intended to move between the desktop and browser implementations. Saves live under the operating-system user's data folder, independently of the game installation. Keep the game ID unchanged across releases. Call save at checkpoints, rather than every frame. This helper assumes one running game instance; it does not synchronize writes from multiple instances or implement schema migrations or Steam-account separation.

On Windows, files live in LOCALAPPDATA; on macOS in Library/Application Support; on Linux in XDG_DATA_HOME or .local/share. Each game has a separate saves directory. The browser implementation uses IndexedDB, scoped to the hosting origin and browser profile, with a separate record per game and slot. Browser storage can be cleared by the user or evicted by the browser.

SaveData<Progress> saves = new SaveData<>("org.example.game", "slot1", Progress.class);
Progress progress = saves.loadOrDefault(() -> new Progress());
progress.coins += 10;
saves.save(progress);
  • Constructor Summary

    Constructors
    Constructor
    Description
    SaveData(String gameId, String slot, Class<T> type)
    Selects a game's save slot without creating a file or opening a database.
  • Method Summary

    Modifier and Type
    Method
    Description
    Returns the save's location for diagnostics.
    loadOrDefault(Supplier<? extends T> defaults)
    Returns defaults only when the file is missing.
    Returns the absolute save file path for desktop tools and Steam Auto-Cloud.
    void
    save(T data)
    Serializes before touching the save, flushes a sibling temporary file, and replaces the save through an atomic rename.

    Methods inherited from class Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • SaveData

      public SaveData(String gameId, String slot, Class<T> type)
      Selects a game's save slot without creating a file or opening a database.
      Parameters:
      gameId - a stable identifier, for example org.openpatch.coincatcher
      slot - a slot name, for example slot1, slot2 or slot3
      type - the data class to load
      Throws:
      IllegalArgumentException - if a name is unsafe or the root override is relative
  • Method Details

    • path

      public Path path()
      Returns the absolute save file path for desktop tools and Steam Auto-Cloud.
      Returns:
      the desktop file path
    • getLocation

      public String getLocation()
      Returns the save's location for diagnostics. On desktop this is a file path; in the browser it identifies an IndexedDB record rather than a file.
      Returns:
      a description of the save location
    • loadOrDefault

      public T loadOrDefault(Supplier<? extends T> defaults) throws IOException
      Returns defaults only when the file is missing. Unreadable, incompatible, empty or corrupt files raise IOException and remain untouched. Defaults stay in memory until the game explicitly calls save.
      Parameters:
      defaults - creates initial progress for a missing slot; called only when missing
      Returns:
      loaded progress, or the supplied defaults for a missing slot
      Throws:
      IOException - if existing data cannot be read or decoded
    • save

      public void save(T data) throws IOException
      Serializes before touching the save, flushes a sibling temporary file, and replaces the save through an atomic rename. If the filesystem does not support atomic replacement, saving fails rather than falling back to an unsafe overwrite. Atomic rename is not a backup or an assurance against every possible storage failure. In the browser, the method waits until the IndexedDB transaction commits.
      Parameters:
      data - the progress to save; must not be null
      Throws:
      IOException - if serialization or writing fails