diff --git a/.hidden/.gitignore b/.hidden/.gitignore deleted file mode 100644 index 8afdcb6..0000000 --- a/.hidden/.gitignore +++ /dev/null @@ -1,454 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# Tye -.tye/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -## -## Visual studio for Mac -## - - -# globs -Makefile.in -*.userprefs -*.usertasks -config.make -config.status -aclocal.m4 -install-sh -autom4te.cache/ -*.tar.gz -tarballs/ -test-results/ - -# Mac bundle stuff -*.dmg -*.app - -# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore -# Windows thumbnail cache files -Thumbs.db -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# JetBrains Rider -.idea/ -*.sln.iml - -## -## Visual Studio Code -## -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json diff --git a/.hidden/SessionZero.sln b/.hidden/SessionZero.sln deleted file mode 100644 index d56de21..0000000 --- a/.hidden/SessionZero.sln +++ /dev/null @@ -1,34 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SessionZero.Shared", "src\SessionZero.Shared\SessionZero.Shared.csproj", "{86CD0D66-D47D-41DA-B857-F8371AC6E6A9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SessionZero.Client", "src\SessionZero.Client\SessionZero.Client.csproj", "{A6455219-BBF2-4A67-B13C-449249083703}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SessionZero.Server", "src\SessionZero.Server\SessionZero.Server.csproj", "{54824F5A-0499-4BC9-AC8E-88E943C66256}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "szpack", "tools\szpack\szpack.csproj", "{70FDB950-CAE6-4C38-A476-3FC10BFCF6E6}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {86CD0D66-D47D-41DA-B857-F8371AC6E6A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86CD0D66-D47D-41DA-B857-F8371AC6E6A9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86CD0D66-D47D-41DA-B857-F8371AC6E6A9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86CD0D66-D47D-41DA-B857-F8371AC6E6A9}.Release|Any CPU.Build.0 = Release|Any CPU - {A6455219-BBF2-4A67-B13C-449249083703}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A6455219-BBF2-4A67-B13C-449249083703}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A6455219-BBF2-4A67-B13C-449249083703}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A6455219-BBF2-4A67-B13C-449249083703}.Release|Any CPU.Build.0 = Release|Any CPU - {54824F5A-0499-4BC9-AC8E-88E943C66256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {54824F5A-0499-4BC9-AC8E-88E943C66256}.Debug|Any CPU.Build.0 = Debug|Any CPU - {54824F5A-0499-4BC9-AC8E-88E943C66256}.Release|Any CPU.ActiveCfg = Release|Any CPU - {54824F5A-0499-4BC9-AC8E-88E943C66256}.Release|Any CPU.Build.0 = Release|Any CPU - {70FDB950-CAE6-4C38-A476-3FC10BFCF6E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {70FDB950-CAE6-4C38-A476-3FC10BFCF6E6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {70FDB950-CAE6-4C38-A476-3FC10BFCF6E6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {70FDB950-CAE6-4C38-A476-3FC10BFCF6E6}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/.hidden/docs/design-doc.md b/.hidden/docs/design-doc.md deleted file mode 100644 index 4f5ef71..0000000 --- a/.hidden/docs/design-doc.md +++ /dev/null @@ -1,354 +0,0 @@ -# **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. diff --git a/.hidden/docs/rambling.md b/.hidden/docs/rambling.md deleted file mode 100644 index e69de29..0000000 diff --git a/.hidden/samples/samples.txt b/.hidden/samples/samples.txt deleted file mode 100644 index bf4847c..0000000 --- a/.hidden/samples/samples.txt +++ /dev/null @@ -1,2 +0,0 @@ -Samples: -- This folder will include sample datapacks diff --git a/.hidden/src/SessionZero.Client/App.axaml b/.hidden/src/SessionZero.Client/App.axaml deleted file mode 100644 index 99d86a9..0000000 --- a/.hidden/src/SessionZero.Client/App.axaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.hidden/src/SessionZero.Client/App.axaml.cs b/.hidden/src/SessionZero.Client/App.axaml.cs deleted file mode 100644 index 415fbb3..0000000 --- a/.hidden/src/SessionZero.Client/App.axaml.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Avalonia; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Data.Core; -using Avalonia.Data.Core.Plugins; -using System.Linq; -using Avalonia.Markup.Xaml; -using SessionZero.Client.ViewModels; -using SessionZero.Client.Views; - -namespace SessionZero.Client; - -public partial class App : Application -{ - public override void Initialize() - { - AvaloniaXamlLoader.Load(this); - } - - public override void OnFrameworkInitializationCompleted() - { - if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - // Avoid duplicate validations from both Avalonia and the CommunityToolkit. - // More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins - DisableAvaloniaDataAnnotationValidation(); - desktop.MainWindow = new MainWindow - { - DataContext = new MainWindowViewModel(), - }; - } - - base.OnFrameworkInitializationCompleted(); - } - - private void DisableAvaloniaDataAnnotationValidation() - { - // Get an array of plugins to remove - var dataValidationPluginsToRemove = - BindingPlugins.DataValidators.OfType().ToArray(); - - // remove each entry found - foreach (var plugin in dataValidationPluginsToRemove) - { - BindingPlugins.DataValidators.Remove(plugin); - } - } -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Client/Assets/avalonia-logo.ico b/.hidden/src/SessionZero.Client/Assets/avalonia-logo.ico deleted file mode 100644 index f7da8bb..0000000 Binary files a/.hidden/src/SessionZero.Client/Assets/avalonia-logo.ico and /dev/null differ diff --git a/.hidden/src/SessionZero.Client/Program.cs b/.hidden/src/SessionZero.Client/Program.cs deleted file mode 100644 index 0addfe3..0000000 --- a/.hidden/src/SessionZero.Client/Program.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Avalonia; -using System; - -namespace SessionZero.Client; - -sealed class Program -{ - // Initialization code. Don't use any Avalonia, third-party APIs or any - // SynchronizationContext-reliant code before AppMain is called: things aren't initialized - // yet and stuff might break. - [STAThread] - public static void Main(string[] args) => BuildAvaloniaApp() - .StartWithClassicDesktopLifetime(args); - - // Avalonia configuration, don't remove; also used by visual designer. - public static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure() - .UsePlatformDetect() - .WithInterFont() - .LogToTrace(); -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Client/SessionZero.Client.csproj b/.hidden/src/SessionZero.Client/SessionZero.Client.csproj deleted file mode 100644 index 939b4e4..0000000 --- a/.hidden/src/SessionZero.Client/SessionZero.Client.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - WinExe - net9.0 - enable - true - app.manifest - true - - - - - - - - - - - - - - - None - All - - - - - - - - diff --git a/.hidden/src/SessionZero.Client/ViewLocator.cs b/.hidden/src/SessionZero.Client/ViewLocator.cs deleted file mode 100644 index d59f1cb..0000000 --- a/.hidden/src/SessionZero.Client/ViewLocator.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Avalonia.Controls; -using Avalonia.Controls.Templates; -using SessionZero.Client.ViewModels; - -namespace SessionZero.Client; - -public class ViewLocator : IDataTemplate -{ - public Control? Build(object? param) - { - if (param is null) - return null; - - var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); - var type = Type.GetType(name); - - if (type != null) - { - return (Control)Activator.CreateInstance(type)!; - } - - return new TextBlock { Text = "Not Found: " + name }; - } - - public bool Match(object? data) - { - return data is ViewModelBase; - } -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Client/ViewModels/MainWindowViewModel.cs b/.hidden/src/SessionZero.Client/ViewModels/MainWindowViewModel.cs deleted file mode 100644 index 799c449..0000000 --- a/.hidden/src/SessionZero.Client/ViewModels/MainWindowViewModel.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SessionZero.Client.ViewModels; - -public partial class MainWindowViewModel : ViewModelBase -{ - public string Greeting { get; } = "Welcome to Avalonia!"; -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Client/ViewModels/ViewModelBase.cs b/.hidden/src/SessionZero.Client/ViewModels/ViewModelBase.cs deleted file mode 100644 index 3873adc..0000000 --- a/.hidden/src/SessionZero.Client/ViewModels/ViewModelBase.cs +++ /dev/null @@ -1,7 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; - -namespace SessionZero.Client.ViewModels; - -public class ViewModelBase : ObservableObject -{ -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Client/Views/MainWindow.axaml b/.hidden/src/SessionZero.Client/Views/MainWindow.axaml deleted file mode 100644 index 81ce6f2..0000000 --- a/.hidden/src/SessionZero.Client/Views/MainWindow.axaml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - diff --git a/.hidden/src/SessionZero.Client/Views/MainWindow.axaml.cs b/.hidden/src/SessionZero.Client/Views/MainWindow.axaml.cs deleted file mode 100644 index 44ac4e8..0000000 --- a/.hidden/src/SessionZero.Client/Views/MainWindow.axaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Avalonia.Controls; - -namespace SessionZero.Client.Views; - -public partial class MainWindow : Window -{ - public MainWindow() - { - InitializeComponent(); - } -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Client/app.manifest b/.hidden/src/SessionZero.Client/app.manifest deleted file mode 100644 index eb09286..0000000 --- a/.hidden/src/SessionZero.Client/app.manifest +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - diff --git a/.hidden/src/SessionZero.Server/Program.cs b/.hidden/src/SessionZero.Server/Program.cs deleted file mode 100644 index d5e0ef3..0000000 --- a/.hidden/src/SessionZero.Server/Program.cs +++ /dev/null @@ -1,41 +0,0 @@ -var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. -// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi -builder.Services.AddOpenApi(); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.MapOpenApi(); -} - -app.UseHttpsRedirection(); - -var summaries = new[] -{ - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" -}; - -app.MapGet("/weatherforecast", () => - { - var forecast = Enumerable.Range(1, 5).Select(index => - new WeatherForecast - ( - DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - Random.Shared.Next(-20, 55), - summaries[Random.Shared.Next(summaries.Length)] - )) - .ToArray(); - return forecast; - }) - .WithName("GetWeatherForecast"); - -app.Run(); - -record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) -{ - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Server/Properties/launchSettings.json b/.hidden/src/SessionZero.Server/Properties/launchSettings.json deleted file mode 100644 index def5fae..0000000 --- a/.hidden/src/SessionZero.Server/Properties/launchSettings.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": false, - "applicationUrl": "http://localhost:5227", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": false, - "applicationUrl": "https://localhost:7090;http://localhost:5227", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/.hidden/src/SessionZero.Server/SessionZero.Server.csproj b/.hidden/src/SessionZero.Server/SessionZero.Server.csproj deleted file mode 100644 index 63257cb..0000000 --- a/.hidden/src/SessionZero.Server/SessionZero.Server.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net9.0 - enable - enable - - - - - - - diff --git a/.hidden/src/SessionZero.Server/SessionZero.Server.http b/.hidden/src/SessionZero.Server/SessionZero.Server.http deleted file mode 100644 index 57ddf6a..0000000 --- a/.hidden/src/SessionZero.Server/SessionZero.Server.http +++ /dev/null @@ -1,6 +0,0 @@ -@SessionZero.Server_HostAddress = http://localhost:5227 - -GET {{SessionZero.Server_HostAddress}}/weatherforecast/ -Accept: application/json - -### diff --git a/.hidden/src/SessionZero.Server/appsettings.Development.json b/.hidden/src/SessionZero.Server/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/.hidden/src/SessionZero.Server/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/.hidden/src/SessionZero.Server/appsettings.json b/.hidden/src/SessionZero.Server/appsettings.json deleted file mode 100644 index 10f68b8..0000000 --- a/.hidden/src/SessionZero.Server/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/.hidden/src/SessionZero.Shared/Models/CharacterTemplate.cs b/.hidden/src/SessionZero.Shared/Models/CharacterTemplate.cs deleted file mode 100644 index 33dcd12..0000000 --- a/.hidden/src/SessionZero.Shared/Models/CharacterTemplate.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SessionZero.Shared.Models; - -public class CharacterTemplate : TemplateBase -{ - -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Shared/Models/Datapack.cs b/.hidden/src/SessionZero.Shared/Models/Datapack.cs deleted file mode 100644 index d7f98d8..0000000 --- a/.hidden/src/SessionZero.Shared/Models/Datapack.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace SessionZero.Shared.Models; - -/// -/// The model for a datapack (used for the szpack.json file). -/// -public class Datapack -{ - public required Guid Id { get; set; } - public required string Name { get; set; } - public required string Version { get; set; } - public required string Author { get; set; } - public required string License { get; set; } - public string Description { get; set; } = string.Empty; - public required DateTime CreatedAt { get; set; } - public required string SessionZeroVersion { get; set; } - - public List Dependencies { get; set; } = new(); -} - -/// -/// Represents a dependency of a datapack. -/// -public class DatapackDependency -{ - public required Guid Id { get; set; } - public required string Name { get; set; } - public required string Version { get; set; } -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Shared/Models/Dataset.cs b/.hidden/src/SessionZero.Shared/Models/Dataset.cs deleted file mode 100644 index c9e6d87..0000000 --- a/.hidden/src/SessionZero.Shared/Models/Dataset.cs +++ /dev/null @@ -1,80 +0,0 @@ -using SessionZero.Shared.Schema; - -namespace SessionZero.Shared.Models; - -public class Dataset : SzObject -{ - /// - /// Arbitrary string used to identify the dataset type (e.g. "items", "quests", "npcs", etc.). - /// - public required string DatasetType { get; set; } - - /// - /// The entries in the dataset. - /// - public required Dictionary Entries { get; set; } = new(); - - /// - /// Retrieves a FieldValue from the dataset using a dot-separated path. - /// Format: [EntryName].[FieldName] or [EntryName].[GroupName].[FieldName] - /// - /// The dot-separated path to the field. - /// The FieldValue if found, otherwise null. - public FieldValue? GetField(string fieldName) - { - var split = fieldName.Split('.'); - - // Path must contain at least EntryName.FieldName (length 2) - if (split.Length < 2 || split.Length > 3) - { - return null; - } - - var entryName = split[0]; - if (!Entries.TryGetValue(entryName, out var entry)) - { - return null; - } - - if (split.Length == 2) - { - // Format: EntryName.FieldName (Top-level field) - var fName = split[1]; - - if (entry.TopLevelFields is null) return null; - - return entry.TopLevelFields.TryGetValue(fName, out var value) ? value : null; - } - else - { - // Format: EntryName.GroupName.FieldName - var groupName = split[1]; - var fName = split[2]; - - if (entry.Groups is null) return null; - - var dataGroup = entry.Groups.FirstOrDefault(g => g.Name == groupName); - - if (dataGroup is null || dataGroup.Fields is null) - { - return null; - } - - return dataGroup.Fields.TryGetValue(fName, out var value) ? value : null; - } - } - - /// - /// Sets a FieldValue in the dataset using a dot-separated path. - /// Format: [EntryName].[FieldName] or [EntryName].[GroupName].[FieldName] - /// - /// The dot-separated path to the field. - /// The value to set. - /// True if the value was set, false otherwise - public static bool SetField(string fieldName, FieldValue value) - { - // TODO: Implementation for SetField - return false; - } -} - diff --git a/.hidden/src/SessionZero.Shared/Models/SessionTemplate.cs b/.hidden/src/SessionZero.Shared/Models/SessionTemplate.cs deleted file mode 100644 index 4ab3277..0000000 --- a/.hidden/src/SessionZero.Shared/Models/SessionTemplate.cs +++ /dev/null @@ -1,17 +0,0 @@ -using SessionZero.Shared.Schema; - -namespace SessionZero.Shared.Models; - -public class SessionTemplate : TemplateBase -{ - /// - /// Reference to the required Character Template for character creation in this session. - /// - public required CharacterTemplateLink CharacterTemplateLink { get; set; } - - /// - /// List of required Datasets that this session template depends on - /// (datapack ids must be present in the DatapackDependency list in the datapack object) - /// - public required List RequiredDatasets { get; set; } = new(); -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Shared/Models/SzObject.cs b/.hidden/src/SessionZero.Shared/Models/SzObject.cs deleted file mode 100644 index 6002bbb..0000000 --- a/.hidden/src/SessionZero.Shared/Models/SzObject.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace SessionZero.Shared.Models; - -public class SzObject -{ - public required string Id { get; set; } - public required string Name { get; set; } - public required string SzType { get; set; } - public string Description { get; set; } = string.Empty; - public string Icon { get; set; } = string.Empty; - public required string Version { get; set; } - public required string SchemaVersion { get; set; } -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Shared/Models/TemplateBase.cs b/.hidden/src/SessionZero.Shared/Models/TemplateBase.cs deleted file mode 100644 index fa32fb5..0000000 --- a/.hidden/src/SessionZero.Shared/Models/TemplateBase.cs +++ /dev/null @@ -1,11 +0,0 @@ -using SessionZero.Shared.Schema; - -namespace SessionZero.Shared.Models; - -/// -/// Base class for templates. -/// -public class TemplateBase : SzObject -{ - public required List Sections { get; set; } = new(); -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Shared/Schema/Schema.cs b/.hidden/src/SessionZero.Shared/Schema/Schema.cs deleted file mode 100644 index 24921d2..0000000 --- a/.hidden/src/SessionZero.Shared/Schema/Schema.cs +++ /dev/null @@ -1,120 +0,0 @@ -namespace SessionZero.Shared.Schema; - -/// -/// Valid types for fields. -/// -public enum FieldType -{ - Text, - MultiText, - Number, - Boolean, - Formula, - List -} - -/// -/// Represents a list of allowed values for a field with type List. -/// -public class SzListType -{ - // NOTE: Only one of these lists should be allowed - public List? AllowedDatasetTypes { get; set; } - public List? AllowedDatasetIds { get; set; } - public string? CustomValues { get; set; } -} - -/// -/// Represents a formula field. -/// -public class SzFormulaType -{ - // TODO: Implement a way to parse formulas - public string? Formula { get; set; } -} - -/// -/// Used to link a dataset in other data or template objects. -/// -public class DatasetLink -{ - public required Guid DatapackId { get; set; } - public required string DatasetId { get; set; } - public required string Version { get; set; } -} - -/// -/// Used to link a character template in other template objects. -/// -public class CharacterTemplateLink -{ - public required Guid DatapackId { get; set; } - public required string TemplateId { get; set; } - public required string Version { get; set; } -} - -/// -/// Represents a field value. -/// -public class FieldValue -{ - public required FieldType Type { get; set; } - public required object Value { get; set; } -} - -/// -/// Represents a group of fields in a dataset. -/// -public class DataGroup -{ - public required string Id { get; set; } - public required string Name { get; set; } - public required Dictionary Fields { get; set; } = new(); -} - -/// -/// Represents a dataset entry used in datasets. -/// -public class DatasetEntry -{ - public required string Id { get; set; } - public required string Name { get; set; } - public string Description { get; set; } = string.Empty; - public string Icon { get; set; } = string.Empty; - - public Dictionary? TopLevelFields { get; set; } = new(); - public List? Groups { get; set; } = new(); -} - -/// -/// Represents a section in a template that houses multiple groups. -/// -public class TemplateSection -{ - public required string Id { get; set; } - public required string Name { get; set; } - public required List Groups { get; set; } = new(); -} - -/// -/// Represents a group of fields in a template. -/// -public class TemplateGroup -{ - public required string Id { get; set; } - public required string Name { get; set; } - public required List? Fields { get; set; } = new(); -} - -/// -/// Represents a field definition in a template -/// (Does not hold actual field values as templates are meant to be filled in upon instance creation). -/// -public class TemplateFieldDefinition -{ - public required string Id { get; set; } - public required string Name { get; set; } - public required FieldType Type { get; set; } - public object? DefaultValue { get; set; } - public DatasetLink? DatasetLink { get; set; } -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Shared/Services/DatapackService.cs b/.hidden/src/SessionZero.Shared/Services/DatapackService.cs deleted file mode 100644 index b657d63..0000000 --- a/.hidden/src/SessionZero.Shared/Services/DatapackService.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System.Text.Json; -using SessionZero.Shared.Models; -using System.IO; -using System.Threading.Tasks; -using System; -using System.Collections.Generic; -using System.IO.Compression; - -namespace SessionZero.Shared.Services; - -public static class DatapackService -{ - private static readonly JsonSerializerOptions JsonOptions = new() - { - WriteIndented = true, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - - /// - /// Creates a new Datapack model with required metadata. - /// - /// The display name of the datapack. - /// The initial version string (e.g., "1.0.0"). - /// The pack creator's name. - /// The license (e.g., "CC-BY-SA-4.0"). - /// A fully initialized Datapack model. - public static Datapack CreateEmptyDatapack(string name, string version, string author, string license) - { - return new Datapack - { - Id = Guid.NewGuid(), - Name = name, - Version = version, - Author = author, - License = license, - Description = String.Empty, - CreatedAt = DateTime.UtcNow, - SessionZeroVersion = "0.0.1", - Dependencies = new() - }; - } - - /// - /// Serializes a Datapack model and saves it to a file named 'szpack.json' - /// inside a new subdirectory named after the datapack's slug. - /// - /// The Datapack object to save. - /// The directory where the new datapack folder will be created. - /// The full path to the created szpack.json file. - public static async Task SaveDatapackMetadataAsync(Datapack datapack, string parentDirectoryPath) - { - var packDirectoryName = datapack.Name.ToLower().Replace(' ', '-').Trim(); - var packRootDirectory = Path.Combine(parentDirectoryPath, packDirectoryName); - - Directory.CreateDirectory(packRootDirectory); - - var filePath = Path.Combine(packRootDirectory, "szpack.json"); - - var jsonString = JsonSerializer.Serialize(datapack, JsonOptions); - await File.WriteAllTextAsync(filePath, jsonString); - - return filePath; - } - - /// - /// Serializes an SzObject (Dataset, Template, etc.) and saves it to a file. - /// - /// The type of the object, must inherit from SzObject. - /// The object to save. - /// The specific subdirectory (e.g., 'datasets') within the datapack root. - /// The full path to the created JSON file. - public static async Task SaveSzObjectAsync(T szObject, string directoryPath) where T : SzObject - { - Directory.CreateDirectory(directoryPath); - - var fileName = $"{szObject.Id}.json"; - var filePath = Path.Combine(directoryPath, fileName); - var jsonString = JsonSerializer.Serialize(szObject, JsonOptions); - await File.WriteAllTextAsync(filePath, jsonString); - - return filePath; - } - - /// - /// Defines and creates the standard directory structure for a SessionZero datapack. - /// - /// The root directory path of the new datapack. - /// A dictionary containing the standard folder names and their absolute paths. - public static Dictionary CreateDatapackDirectoryStructure(string rootPath) - { - var structure = new Dictionary - { - { "datasets", Path.Combine(rootPath, "datasets") }, - { "character_templates", Path.Combine(rootPath, "characters") }, - { "session_templates", Path.Combine(rootPath, "sessions") }, - { "media", Path.Combine(rootPath, "media") }, - { "images", Path.Combine(rootPath, "media", "images") } - }; - - foreach (var path in structure.Values) - { - Directory.CreateDirectory(path); - } - - return structure; - } - - /// - /// Compresses a datapack directory into a .szpack zip archive. - /// - /// The path to the datapack's root directory. - /// The full path and filename for the output .szpack file. - public static void PackDatapack(string sourceDirectoryPath, string outputFilePath) - { - if (!Directory.Exists(sourceDirectoryPath)) - { - throw new DirectoryNotFoundException($"Source directory not found: {sourceDirectoryPath}"); - } - - if (File.Exists(outputFilePath)) - { - File.Delete(outputFilePath); - } - - ZipFile.CreateFromDirectory(sourceDirectoryPath, outputFilePath); - } - - /// - /// Extracts a .szpack zip archive into a target directory. - /// - /// The path to the .szpack file. - /// The directory where the contents will be extracted. - public static void UnpackDatapack(string sourceFilePath, string destinationDirectoryPath) - { - if (!File.Exists(sourceFilePath)) - { - throw new FileNotFoundException($"Datapack file not found: {sourceFilePath}"); - } - - Directory.CreateDirectory(destinationDirectoryPath); - - ZipFile.ExtractToDirectory(sourceFilePath, destinationDirectoryPath, overwriteFiles: true); - } - - /// - /// Deserializes and loads the core Datapack metadata (szpack.json) from a directory. - /// - /// The path to the datapack's root directory. - /// A Datapack model containing the metadata. - /// Thrown if szpack.json is not found. - /// Thrown if deserialization fails. - public static async Task LoadDatapackMetadataAsync(string datapackRootPath) - { - var filePath = Path.Combine(datapackRootPath, "szpack.json"); - - if (!File.Exists(filePath)) - { - throw new FileNotFoundException($"The required metadata file 'szpack.json' was not found in: {datapackRootPath}", filePath); - } - - var jsonString = await File.ReadAllTextAsync(filePath); - - var datapack = JsonSerializer.Deserialize(jsonString, JsonOptions); - - if (datapack is null) - { - throw new JsonException($"Failed to deserialize szpack.json from {filePath}. The file may be corrupt or invalid."); - } - - return datapack; - } -} \ No newline at end of file diff --git a/.hidden/src/SessionZero.Shared/SessionZero.Shared.csproj b/.hidden/src/SessionZero.Shared/SessionZero.Shared.csproj deleted file mode 100644 index 17b910f..0000000 --- a/.hidden/src/SessionZero.Shared/SessionZero.Shared.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - net9.0 - enable - enable - - - diff --git a/.hidden/src/SessionZero.Shared/Validation/DatapackValidator.cs b/.hidden/src/SessionZero.Shared/Validation/DatapackValidator.cs deleted file mode 100644 index 828e9b2..0000000 --- a/.hidden/src/SessionZero.Shared/Validation/DatapackValidator.cs +++ /dev/null @@ -1,45 +0,0 @@ -using SessionZero.Shared.Models; - -namespace SessionZero.Shared.Validation; - -public static class DatapackValidator -{ - public static List ValidateDatapack(Datapack datapack) - { - var errors = new List(); - - if (datapack.Id == Guid.Empty) errors.Add("Datapack 'Id' is required and must not be an empty GUID."); - - ValidateRequiredString(errors, datapack.Name, nameof(datapack.Name)); - ValidateRequiredString(errors, datapack.Version, nameof(datapack.Version)); - ValidateRequiredString(errors, datapack.Author, nameof(datapack.Author)); - ValidateRequiredString(errors, datapack.License, nameof(datapack.License)); - ValidateRequiredString(errors, datapack.SessionZeroVersion, nameof(datapack.SessionZeroVersion)); - - if (datapack.CreatedAt == DateTime.MinValue) errors.Add("Datapack 'CreatedAt' is required and must not be an empty DateTime."); - - return errors; - } - - public static List ValidateSzObject(SzObject szObject) - { - var errors = new List(); - var objectName = szObject.Id; - - ValidateRequiredString(errors, szObject.Id, $"{objectName}'s Id"); - ValidateRequiredString(errors, szObject.Name, $"{objectName}'s Name"); - ValidateRequiredString(errors, szObject.SzType, $"{objectName}'s SzType"); - ValidateRequiredString(errors, szObject.Version, $"{objectName}'s Version"); - ValidateRequiredString(errors, szObject.SchemaVersion, $"{objectName}'s SchemaVersion"); - - // 2. Validate Icon path format (optional/future: e.g., only allows alphanumeric + slashes + extension) - // For now, we'll only check if it's not null, which is done by the property definition in SzObject. - - return errors; - } - - private static void ValidateRequiredString(List errors, string? value, string fieldName) - { - if (string.IsNullOrWhiteSpace(value)) errors.Add($"'{fieldName}' is required and must not be empty."); - } -} \ No newline at end of file diff --git a/.hidden/tools/szpack/CreateCommand.cs b/.hidden/tools/szpack/CreateCommand.cs deleted file mode 100644 index 6a1fd25..0000000 --- a/.hidden/tools/szpack/CreateCommand.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* - * WARNING: - * This tool was created by an LLM based on the SessionZero shared lib project, therefore it is subject to errors and does not reflect the architecture of the SessionZero project. - * It was created to be used as a quick and dirty validation tool for the szpack format. -*/ - -using SessionZero.Shared.Models; -using SessionZero.Shared.Services; -using Spectre.Console; -using Spectre.Console.Cli; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; - -namespace SessionZero.Tools.Packer; - -// Settings class defines the command-line arguments -public class CreateSettings : CommandSettings -{ - [CommandArgument(0, "")] - [Description("The display name of the datapack (e.g., 'My Fantasy Spells').")] - public required string Name { get; init; } - - [CommandArgument(1, "[author]")] - [Description("The author's name.")] - [DefaultValue("Test Author")] - public string Author { get; init; } = "Test Author"; - - [CommandOption("-o|--output")] - [Description("The parent directory where the new pack folder will be created.")] - [DefaultValue(".")] - public string Output { get; init; } = Environment.CurrentDirectory; -} - -public class CreateCommand : AsyncCommand -{ - public override async Task ExecuteAsync([NotNull] CommandContext context, [NotNull] CreateSettings settings, CancellationToken cancellationToken) - { - AnsiConsole.MarkupLine($"\n[bold white on blue] --- Creating Datapack: '{settings.Name}' --- [/]"); - - try - { - // 1. Create the top-level model and save szpack.json - var newPack = DatapackService.CreateEmptyDatapack(settings.Name, "1.0.0", settings.Author, "MIT"); - var szpackPath = await DatapackService.SaveDatapackMetadataAsync(newPack, settings.Output); - var packRootDirectory = Path.GetDirectoryName(szpackPath)!; - - AnsiConsole.MarkupLine($"[green]✅ Created metadata file at: {szpackPath}[/]"); - - // 2. Create the standard directory structure - var structure = DatapackService.CreateDatapackDirectoryStructure(packRootDirectory); - AnsiConsole.MarkupLine($"[green]✅ Created standard directories at: {packRootDirectory}[/]"); - - // 3. Create and save test objects - await CreateTestObjects(packRootDirectory, structure); - - AnsiConsole.MarkupLine("\n[bold]Creation Complete![/] Use 'szpack pack' to compress it."); - return 0; - } - catch (Exception ex) - { - AnsiConsole.MarkupLine($"\n[bold white on red]❌ ERROR:[/] Failed to create datapack. Details: {ex.Message}"); - return 1; - } - } - - // Helper method for creating test objects (copied from previous Program.cs) - private static async Task CreateTestObjects(string rootPath, Dictionary structure) - { - // ... (Test object creation logic remains the same, ensure you have the necessary usings in this file) - - // --- Test object creation logic (omitted for brevity, assume the previous logic is here) --- - var testDataset = new Dataset { /* ... test data ... */ Id = "basic-attributes", Name = "Basic Character Attributes", SzType = "Dataset", Version = "1.0.0", SchemaVersion = "1.0.0", DatasetType = "Attribute", Entries = new() }; - var dsPath = await DatapackService.SaveSzObjectAsync(testDataset, structure["datasets"]); - AnsiConsole.MarkupLine($" -> Saved Test Dataset: [yellow]{Path.GetFileName(dsPath)}[/]"); - - var testCharTemplate = new CharacterTemplate { /* ... test data ... */ Id = "default-char-sheet", Name = "Default Character Template", SzType = "Template", Version = "1.0.0", SchemaVersion = "1.0.0", Sections = new() }; - var charPath = await DatapackService.SaveSzObjectAsync(testCharTemplate, structure["character_templates"]); - AnsiConsole.MarkupLine($" -> Saved Test Character Template: [yellow]{Path.GetFileName(charPath)}[/]"); - - var testSessionTemplate = new SessionTemplate - { - /* ... test data ... */ Id = "basic-encounter", - Name = "Basic Encounter Template", - SzType = "Template", - Version = "1.0.0", - SchemaVersion = "1.0.0", - CharacterTemplateLink = new() - { - DatapackId = Guid.Empty, - TemplateId = testCharTemplate.Id, - Version = testCharTemplate.Version - }, - RequiredDatasets = new() - { - new() - { - DatapackId = Guid.Empty, - DatasetId = testDataset.Id, - Version = testDataset.Version - } - }, - Sections = new() - }; - var sessionPath = await DatapackService.SaveSzObjectAsync(testSessionTemplate, structure["session_templates"]); - AnsiConsole.MarkupLine($" -> Saved Test Session Template: [yellow]{Path.GetFileName(sessionPath)}[/]"); - } -} \ No newline at end of file diff --git a/.hidden/tools/szpack/PackCommand.cs b/.hidden/tools/szpack/PackCommand.cs deleted file mode 100644 index 7e6c411..0000000 --- a/.hidden/tools/szpack/PackCommand.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * WARNING: - * This tool was created by an LLM based on the SessionZero shared lib project, therefore it is subject to errors and does not reflect the architecture of the SessionZero project. - * It was created to be used as a quick and dirty validation tool for the szpack format. -*/ - -using SessionZero.Shared.Services; -using Spectre.Console; -using Spectre.Console.Cli; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; - -namespace SessionZero.Tools.Packer; - -public class PackSettings : CommandSettings -{ - [CommandArgument(0, "")] - [Description("The root directory of the datapack to pack.")] - public required string Input { get; init; } -} - -public class PackCommand : Command -{ - public override int Execute([NotNull] CommandContext context, [NotNull] PackSettings settings, CancellationToken cancellationToken) - { - AnsiConsole.MarkupLine($"\n[bold white on blue] --- Packing Datapack: {settings.Input} --- [/]"); - try - { - var packDirectoryName = new DirectoryInfo(settings.Input).Name; - var outputFilePath = Path.Combine(Path.GetDirectoryName(settings.Input) ?? Environment.CurrentDirectory, $"{packDirectoryName}.szpack"); - - DatapackService.PackDatapack(settings.Input, outputFilePath); - - AnsiConsole.MarkupLine($"[green]✅ Successfully created archive: {outputFilePath}[/]"); - return 0; - } - catch (Exception ex) - { - AnsiConsole.MarkupLine($"\n[bold white on red]❌ ERROR:[/] Failed to pack datapack. Details: {ex.Message}"); - return 1; - } - } -} \ No newline at end of file diff --git a/.hidden/tools/szpack/Program.cs b/.hidden/tools/szpack/Program.cs deleted file mode 100644 index eb8b3ee..0000000 --- a/.hidden/tools/szpack/Program.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * WARNING: - * This tool was created by an LLM based on the SessionZero shared lib project, therefore it is subject to errors and does not reflect the architecture of the SessionZero project. - * It was created to be used as a quick and dirty validation tool for the szpack format. -*/ - -using Spectre.Console.Cli; - -namespace SessionZero.Tools.Packer; - -internal class Program -{ - static int Main(string[] args) - { - var app = new CommandApp(); - - app.Configure(config => - { - config.SetApplicationName("szpack"); - - config.AddCommand("create") - .WithDescription("Creates a new datapack directory with test objects."); - - config.AddCommand("pack") - .WithDescription("Compresses a datapack directory into a .szpack file."); - - config.AddCommand("unpack") - .WithDescription("Extracts a .szpack file and displays its metadata."); - - // Optional: Set a default command if no command is specified - // config.SetDefaultCommand(); - }); - - return app.Run(args); - } -} \ No newline at end of file diff --git a/.hidden/tools/szpack/UnpackCommand.cs b/.hidden/tools/szpack/UnpackCommand.cs deleted file mode 100644 index 6509b2d..0000000 --- a/.hidden/tools/szpack/UnpackCommand.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * WARNING: - * This tool was created by an LLM based on the SessionZero shared lib project, therefore it is subject to errors and does not reflect the architecture of the SessionZero project. - * It was created to be used as a quick and dirty validation tool for the szpack format. -*/ - -using SessionZero.Shared.Services; -using Spectre.Console; -using Spectre.Console.Cli; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; - -namespace SessionZero.Tools.Packer; - -public class UnpackSettings : CommandSettings -{ - [CommandArgument(0, "")] - [Description("The path to the .szpack file.")] - public required string Input { get; init; } - - [CommandOption("-o|--output")] - [Description("The directory where the pack will be extracted.")] - [DefaultValue("unpacked")] - public string Output { get; init; } = "unpacked"; -} - -public class UnpackCommand : AsyncCommand -{ - public override async Task ExecuteAsync([NotNull] CommandContext context, [NotNull] UnpackSettings settings, CancellationToken cancellationToken) - { - AnsiConsole.MarkupLine($"\n[bold white on blue] --- Unpacking Datapack: {settings.Input} --- [/]"); - try - { - // Unpack the archive - DatapackService.UnpackDatapack(settings.Input, settings.Output); - AnsiConsole.MarkupLine($"[green]✅ Successfully unpacked archive to: {settings.Output}[/]"); - - // Load and display the core data - var datapack = await DatapackService.LoadDatapackMetadataAsync(settings.Output); - - AnsiConsole.MarkupLine("\n[bold]--- Datapack Info (szpack.json) ---[/]"); - AnsiConsole.MarkupLine($"[yellow]ID:[/]\t\t{datapack.Id}"); - AnsiConsole.MarkupLine($"[yellow]Name:[/]\t{datapack.Name}"); - AnsiConsole.MarkupLine($"[yellow]Version:[/]\t{datapack.Version}"); - AnsiConsole.MarkupLine($"[yellow]Author:[/]\t{datapack.Author}"); - - return 0; - } - catch (Exception ex) - { - AnsiConsole.MarkupLine($"\n[bold white on red]❌ ERROR:[/] Failed to unpack or load datapack. Details: {ex.Message}"); - return 1; - } - } -} \ No newline at end of file diff --git a/.hidden/tools/szpack/readme.md b/.hidden/tools/szpack/readme.md deleted file mode 100644 index 4575808..0000000 --- a/.hidden/tools/szpack/readme.md +++ /dev/null @@ -1,10 +0,0 @@ -# SZPACK CLI Tool - -## ***WARNING:*** -This tool was created by an LLM based on the SessionZero shared lib project, therefore it is subject to errors and does not reflect the architecture of the SessionZero project. -It was created to be used as a quick and dirty validation tool for the szpack format. - -## Usage -* `szpack create `: Creates a sample datapack directory with a given name -* `szpack pack `: Packs a datapack directory into a szpack file (must be a valid datapack) -* `szpack unpack `: Unpacks a .szpack file into a datapack directory and displays some metadata \ No newline at end of file diff --git a/.hidden/tools/szpack/szpack.csproj b/.hidden/tools/szpack/szpack.csproj deleted file mode 100644 index 2437a23..0000000 --- a/.hidden/tools/szpack/szpack.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net9.0 - enable - enable - - - - - - - - - - - - diff --git a/.hidden/tools/tools.txt b/.hidden/tools/tools.txt deleted file mode 100644 index 94beeaa..0000000 --- a/.hidden/tools/tools.txt +++ /dev/null @@ -1,2 +0,0 @@ -Planned tools: -- szpack: a cli tool for validating and packing szpack archives