SessionZero-Client/.hidden/docs/design-doc.md

355 lines
13 KiB
Markdown

# **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**
```text
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.
```json
{
"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.**
```json
{
"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.
```json
{
"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.
```json
{
"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.
```json
{
"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.
```json
{
"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.