SessionZero-Client/docs/design-doc.md
2025-10-16 13:33:02 -05:00

13 KiB

SessionZero Design Document

1. Introduction

1.1 Purpose

SessionZero is a free and open-source TTRPG companion app designed to streamline tabletop role-playing game management. It emphasizes flexibility, modularity, and federation through a system-agnostic datapack format, supporting both offline and self-hostable online play. The goal is to empower players and GMs with full control over their data, rulesets, and session management.

1.2 Scope

The project will begin as a cross-platform desktop application (Windows and Linux), offering tools for creating and managing TTRPG data such as characters, datasets, templates, and sessions. The backend supports user accounts, a database for shared content (SessionZeroDB), and prepares for future federation capabilities. Phase 2 introduces federation, while Phase 3 focuses on mobile support and plugin extensibility.

1.3 Objectives

  • Provide a modular, open-source companion app for any TTRPG system.
  • Implement a JSON-based datapack format for extensible content storage.
  • Support both local use and self-hostable online instances.
  • Create a foundation for future federation and mobile support.

2. System Overview

SessionZero consists of three main layers:

  1. Frontend (Client): Cross-platform desktop application (.NET Avalonia).
  2. Backend (Server): ASP.NET backend managing user accounts, SessionZeroDB, and P2P connections.
  3. Datapack System: A structured archive format for storing and sharing game data.

3. Technology Stack

  • Core: C# / .NET 9.0 (minimal API)
  • Client: Avalonia UI (cross-platform desktop)
  • Database: PostgreSQL (primary data store for shared/online content)
  • Offline/Local: Local file storage, perhaps SQLite for local instances.
  • Networking: WebSockets for real-time session updates; SignalR/gRPC considered for P2P/federation.

4. Core Data Concepts

4.1 Datapack

The top-level container (.szp file), bundling all system-specific data (templates, datasets, assets).

4.2 Template

A reusable definition of a data structure (e.g., a Character Template defining character sheet fields, or a Session Template defining campaign structure).

4.3 Dataset

A structured collection of external data records (e.g., a bestiary, a list of items, or spells).

4.4 Instance

The runtime data created from a Template (e.g., "Aelric's Character Sheet" based on the "Fantasy Character" Template).

4.5 Schema

Formal JSON Schemas used to validate the structure of Datapacks and their contents.

5. Datapack Specification

A datapack is a self-contained archive (.szp) that holds all data and assets for a specific TTRPG system, module, or expansion. It serves as the foundation for SessionZero's extensible content model. Each pack can define datasets, templates, and optionally contain instance data (though instances are usually stored separately as save files). The structure emphasizes modularity, portability, and reliable dependency management between packs.

5.1 Directory Structure

pack-name/
├── szpack.json                 # Pack metadata and manifest
├── media/
│   └── images/                 # Image assets (referenced by objects)
└── objects/
    ├── datasets/               # User-defined structured data (e.g. items, NPCs)
    ├── character-templates/    # Templates defining character structures
    └── session-templates/      # Templates defining session/campaign structures

5.2 Pack Metadata (szpack.json)

Each datapack contains a root metadata file that defines its identity, authorship, dependencies, and compatibility information. This structure aligns with the C# Datapack and DatapackDependency models.

{
  "id": "c9a3f9c8-8b8a-4f1f-9f3b-2d8c7f2c6c62",
  "name": "Example Pack",
  "version": "1.0.0",
  "author": "UserName",
  "license": "CC-BY-SA-4.0",
  "description": "A fantasy setting datapack containing items and NPCs.",
  "createdAt": "2025-10-15T00:00:00Z",
  "sessionZeroVersion": "1.0.0",
  "dependencies": [
    {
      "id": "c2e6d0a4-2a8f-4a51-b36e-9f8f2c7b1d11",
      "name": "Core-Ruleset",
      "version": "1.2.0"
    }
  ]
}

5.3 Common Object Metadata

Objects within the datapack (datasets, templates) inherit from SzObject. The szType field is required to identify the object type. Image paths are relative to the media/images folder.

{
  "id": "core-items",
  "name": "Core Items",
  "szType": "dataset",
  "description": "A collection of basic weapons and armor.",
  "icon": "core-items.png",
  "version": "1.0.0",
  "schemaVersion": "1.0.0"
}

Note: The system resolves the icon field path (e.g., "core-items.png") to datapack/media/images/core-items.png.

5.4 Dataset Objects

Datasets are structured collections of data entries. The entry structure includes TopLevelFields and optional Groups of fields, aligning with the DatasetEntry C# model.

{
  "id": "core-items",
  "szType": "dataset",
  "datasetType": "items",
  "name": "Core Items",
  "description": "Weapons, armor, and consumables for the base ruleset.",
  "version": "1.0.0",
  "schemaVersion": "1.0.0",
  "entries": {
    "sword": {
      "id": "sword",
      "name": "Sword",
      "description": "A basic weapon.",
      "icon": "weapons/sword.png",
      "topLevelFields": {
        "damage": { "type": "Number", "value": 10 },
        "weight": { "type": "Number", "value": 3 }
      },
      "groups": [
        {
          "id": "stats",
          "name": "Stats",
          "fields": {
            "rarity": { "type": "Text", "value": "Common" }
          }
        }
      ]
    },
    "potion": {
      "id": "potion",
      "name": "Healing Potion",
      "description": "Restores a small amount of HP.",
      "icon": "consumables/potion.png",
      "topLevelFields": {
        "healAmount": { "type": "Number", "value": 20 },
        "consumable": { "type": "Boolean", "value": true }
      }
    }
  }
}

Note: The field retrieval path is expected to be EntryName.FieldName or EntryName.GroupName.FieldName, matching the logic in Dataset.cs.

5.5 Character Templates

Character templates define the fields and structure for characters. Note the use of the specific DatasetLink object for list fields, requiring a Datapack ID, Dataset ID, and Version.

{
  "id": "default-character",
  "szType": "character-template",
  "name": "Generic Character",
  "description": "A base character layout usable across multiple systems.",
  "icon": "character.png",
  "version": "1.0.0",
  "schemaVersion": "1.0.0",
  "sections": [
    {
      "id": "core",
      "name": "Core Stats",
      "groups": [
        {
          "id": "attributes",
          "name": "Attributes",
          "fields": [
            { "id": "strength", "name": "Strength", "type": "Number", "defaultValue": 10 },
            { "id": "dexterity", "name": "Dexterity", "type": "Number", "defaultValue": 10 },
            { "id": "intelligence", "name": "Intelligence", "type": "Number", "defaultValue": 10 }
          ]
        },
        {
          "id": "inventory",
          "name": "Inventory",
          "fields": [
            {
              "id": "equipment",
              "name": "Equipment",
              "type": "List",
              "datasetLink": {
                "datapackId": "c9a3f9c8-8b8a-4f1f-9f3b-2d8c7f2c6c62",
                "datasetId": "core-items",
                "version": "1.0.0"
              }
            }
          ]
        }
      ]
    }
  ]
}

5.6 Session Templates

Session templates are blueprints for setting up a campaign. This example uses CharacterTemplateLink and a list of DatasetLink objects for RequiredDatasets as defined in SessionTemplate.cs.

{
  "id": "basic-session",
  "szType": "session-template",
  "name": "Basic Fantasy Campaign",
  "description": "A classic campaign setup with standard fantasy rules.",
  "icon": "session.png",
  "version": "1.0.0",
  "schemaVersion": "1.0.0",
  "characterTemplateLink": {
    "datapackId": "c9a3f9c8-8b8a-4f1f-9f3b-2d8c7f2c6c62",
    "templateId": "default-character",
    "version": "1.0.0"
  },
  "requiredDatasets": [
    {
      "datapackId": "c9a3f9c8-8b8a-4f1f-9f3b-2d8c7f2c6c62",
      "datasetId": "core-items",
      "version": "1.0.0"
    }
  ],
  "sections": [
    {
      "id": "session-info",
      "name": "Session Info",
      "groups": [
        {
          "id": "details",
          "name": "Details",
          "fields": [
            { "id": "setting", "name": "Setting", "type": "Text", "defaultValue": "Thalindra" },
            { "id": "gmNotes", "name": "GM Notes", "type": "MultiText" }
          ]
        }
      ]
    }
  ]
}

5.7 Instances (Stored Separately)

Instances, such as a specific character or a running campaign's state, are typically stored outside of the core, reusable datapacks but follow a similar structure, referencing a template.

{
  "szType": "character-instance",
  "templateId": "default-character",
  "name": "Aelric Stormhand",
  "fields": {
    "strength": 14,
    "dexterity": 11,
    "inventory": ["sword", "potion"]
  }
}

5.8 Validation and Schema Versioning

Formal, versioned JSON Schemas define the structure of szpack.json and core object types.

  • Each object declares a schemaVersion (global versioning per SessionZero release).
  • Validation tools confirm compliance before import/export.
  • Internal references (DatasetLink, CharacterTemplateLink, etc.) are resolved within the pack automatically.
  • External references are verified via dependencies in szpack.json.

Session Datapack vs Templates:

  • Session Template: A reusable blueprint for campaign/session setup. Lives under objects/session-templates/.
  • Session Datapack: The persisted, evolving state of an ongoing campaign. It is stored as a special pack and does not appear alongside normal content packs in the UI. Snapshots are versioned with timestamps. Export/import uses the same .szp format with a distinct type flag in szpack.json.

6. Networking & Synchronization

6.1 Session Model

A "Session" is a single game instance, hosted by a GM. It uses a centralized, shared document model (SessionZeroDB/PostgreSQL) with real-time updates pushed via WebSockets.

6.2 Data Flow

  1. GM Action: GM updates an NPC in their local client.
  2. Client: Pushes the update to the server via API/WebSockets.
  3. Server: Validates, commits to DB, and broadcasts the change to all connected players (including the GM).
  4. Players: Receive the update and apply it to their local model.

6.3 Offline Mode

The application supports full offline functionality, using local storage. When connectivity is restored, the system uses conflict-resolution logic (timestamp-based or operational transformation) to reconcile changes with the SessionZeroDB.

7. Federation

7.1 Concept

Federation allows different SessionZero instances (e.g., self-hosted servers) to share and discover content (Datapacks, public Datasets, Templates). This requires standardized APIs for content retrieval and identity verification.

7.2 Identity

  • Users have a unique global identifier (UID).
  • Datapacks are identified by their UUID (id).

7.3 Data Sharing

Publicly shared Datapacks are discoverable through a federation layer, allowing users to import content from other trusted servers.

8. Licensing

8.1 Source Code License

  • AGPL-3.0 (Affero General Public License): Ensures open-source continuity and attribution, prevents uncredited commercial rebranding.

8.2 User Content License

  • Creative Commons BY-SA 4.0: Allows sharing and adaptation with attribution.

9. Development Phases

Phase 1: Core Platform (MVP)

  • Client (UI, datapack editing, session management)
  • Backend (accounts, SessionZeroDB, P2P prep)
  • JSON datapack format implementation

Phase 2: Federation

  • Cross-server communication
  • Access controls and search indexing

Phase 3: Mobile and Plugins

  • Cross-platform mobile apps
  • Plugin and API extensibility

10. Testing & Quality

  • Unit Tests: Core services (DataPackService, StorageService, NetworkingService) with fixtures for characters/datasets/templates.
  • Schema Validation: CI job validates sample packs against JSON Schemas (see section 5.8) and rejects PRs with invalid packs.
  • Integration Tests: Import/export round-trips, dependency resolution, and session snapshot/recovery.
  • Compatibility Matrix: Validate on Windows and Linux for net9.0; browser target smoke tests where applicable.

11. Accessibility & Internationalization

  • Accessibility: Keyboard navigation across all primary views, sufficient color contrast, focus indicators, and screen-reader-friendly labels.
  • Internationalization: Resource-based localization for UI strings; UTF-8 throughout; prepare for RTL support; date/number formatting via invariant + locale-aware overlays.