chore(workspace): flat gregFramework layout (gregFramework/{repo}/) and path/doc updates

Made-with: Cursor
This commit is contained in:
Marvin
2026-04-10 01:52:35 +02:00
parent 0bad959708
commit 28a75eeb1c
23 changed files with 233 additions and 166 deletions

View File

@@ -15,21 +15,22 @@ These folders typically sit **next to each other** in a developer workspace (see
| Area | Path (on disk) | Role | | Area | Path (on disk) | Role |
|------|----------------|------| |------|----------------|------|
| **Framework core** | `gregCore/` | Platform **framework core**: translations, hooks, Harmony/event runtime, MelonLoader hosting, bridges; plugins under `plugins/`; templates under `Templates/` | | **Framework core** | `gregCore/` | Runtime, hooks, Harmony, bridge — main project `gregCore/framework/FrikaMF.csproj`; templates under `gregCore/Templates/` |
| **Mods** | `gregMod.<Name>/` (direkt unter `gregFramework/`) | Standalone gameplay mods (`FMF.*`) as individual repositories | | **Mods (split repos)** | `gregMod.<Name>/` (directly under `gregFramework/`) | Standalone gameplay mods (`FMF.*` assemblies); **not** nested under a `gregMods/` umbrella |
| **Extensions** | `gregExt.<Name>/` (direkt unter `gregFramework/`) | Extension modules (e.g. player models) | | **Extensions / framework plugins (split repos)** | `gregExt.<Name>/` (directly under `gregFramework/`) | FFM framework plugins (`FFM.Plugin.*`); **not** under legacy `StandaloneMods/` paths |
| **Documentation** | `gregWiki/` ([`mleem97/gregWiki`](https://github.com/mleem97/gregWiki)) | **This site**: Docusaurus app at repo root, all authored pages under `docs/` | | **Documentation** | `gregWiki/` ([`mleem97/gregWiki`](https://github.com/mleem97/gregWiki)) | **This site**: Docusaurus app at repo root, all authored pages under `docs/` |
| **Legacy / staging exporter** | `gregDataCenterExporter/` | Historical monolith layout; some tools and HexMod assets may still live here during migration | | **Tools** | `gregModmanager/` (WorkshopManager), `gregDataCenterExporter/`, etc. | Supporting apps and templates |
| **Other tools** | `gregIPAM/` (DHCP + IPAM; assembly `DHCPSwitches`), `gregStore/` (**Gregweb**, private repo), `gregReferences/`, `gregInternalDocs/`, `gregMeta/` | Supporting repos and internal notes | | **Other** | `gregIPAM/`, `gregReferences/`, … | Side projects and references |
## Canonical code locations (split repos) ## Canonical code locations (split repos)
| Concern | Where to look | | Concern | Where to look |
|---------|----------------| |---------|----------------|
| Framework `.csproj` | `gregCore/framework/FrikaMF.csproj` | | Framework `.csproj` | `gregCore/framework/FrikaMF.csproj` |
| Plugins (`FFM.Plugin.*`) | `gregCore/plugins/` | | Plugins (`FFM.Plugin.*`) — authoring | `gregExt.<Name>/` (e.g. `gregExt.AssetExporter/`) |
| Mod sources | `gregMod.*/` and templates under `gregCore/Templates/` | | Plugins — optional mirrors | `gregCore/plugins/FFM.Plugin.*` |
| MCP server | `gregCore/mcp-server/` (and parallel copies in other repos as wired locally) | | Mod sources (`FMF.*`) | `gregMod.<Name>/` |
| Templates | `gregCore/Templates/` |
| Wiki content | `gregWiki/docs/` | | Wiki content | `gregWiki/docs/` |
## Wiki import (legacy) ## Wiki import (legacy)
@@ -38,24 +39,19 @@ Long-form pages mirrored from the GitHub Wiki live under [`docs/legacy/wiki-impo
## .NET projects on disk (`*.csproj`) ## .NET projects on disk (`*.csproj`)
Paths below are relative to **`gregCore/`** (framework repo root). Individual mods may live under **`gregMod.*/`** with their own `.csproj` names. - **Framework:** `gregCore/framework/FrikaMF.csproj` (solution `gregCore/FrikaMF.sln` when present).
- **Plugins:** primary checkouts **`gregExt.<Name>/`** (assembly `FFM.Plugin.*.dll`); duplicates under `gregCore/plugins/` for all-in-one builds.
| Project | Location | In `FrikaMF.sln`? | - **Mods:** **`gregMod.<Name>/`** at workspace root (`FMF.*.csproj` names vary).
|---------|----------|-------------------| - **WorkshopManager:** `gregModmanager/WorkshopUploader.csproj` (separate from the MelonLoader framework solution).
| FrikaMF | `framework/FrikaMF.csproj` | Yes |
| WorkshopUploader | `tools/steam-workshop-upload/` or legacy `workshopuploader/` (varies by branch) | Usually separate solution |
| FFM.Plugin.* | `plugins/FFM.Plugin.*/` | Yes when included in `FrikaMF.sln` |
| FMF.* mods | `gregMod.*/` (clone layout, under `gregFramework/`) | Per-repo / optional |
| Templates | `Templates/FMF.*`, `Templates/StandaloneModTemplate/` | No |
## Build status (framework project) ## Build status (framework project)
- `framework/FrikaMF.csproj` explicitly **excludes** `workshopuploader/**` from compile (that app builds only via `workshopuploader/WorkshopUploader.csproj` / `WorkshopUploader.sln` in that folder). - `gregCore/framework/FrikaMF.csproj` does not compile the WorkshopManager app; that builds from `gregModmanager/WorkshopUploader.csproj`.
- `dotnet build FrikaMF.sln` builds framework and plugin projects under `plugins\`**not** the MAUI Workshop app (MelonLoader/game refs still required locally unless `CI=true`). - `dotnet build` on the framework solution (when present under `gregCore/`) builds core + optional `gregCore/plugins/*`**not** split-repo `gregExt.*` / `gregMod.*` folders unless you add them to the solution.
## `FrikaMF.sln` drift (action items) ## `FrikaMF.sln` drift (action items)
1. **Mods not in solution**: Standalone mod projects under `mods/` are intentionally omitted from the solution to keep the graph small; add them if you want `dotnet build` for every module in one shot. 1. **Mods outside solution**: Standalone mod projects under `gregMod.*` are usually **not** in `FrikaMF.sln`; build them per repo or add them if you want one `dotnet build` for everything.
2. **Templates in `framework/FrikaMF.csproj`**: Template sources under `Templates/` may fail `dotnet build framework/FrikaMF.csproj` with `CS0122` if `Core` visibility does not match template expectations — treat templates as **samples** until the project graph is cleaned up. 2. **Templates in `framework/FrikaMF.csproj`**: Template sources under `Templates/` may fail `dotnet build framework/FrikaMF.csproj` with `CS0122` if `Core` visibility does not match template expectations — treat templates as **samples** until the project graph is cleaned up.
@@ -69,19 +65,18 @@ Paths below are relative to **`gregCore/`** (framework repo root). Individual mo
## Hook / event sources of truth (code) ## Hook / event sources of truth (code)
- String constants: [`framework/FrikaMF/HookNames.cs`](https://github.com/mleem97/gregFramework/blob/master/framework/FrikaMF/HookNames.cs) (`FFM.*` hook IDs today). - String constants: [`gregCore/framework/FrikaMF/HookNames.cs`](https://github.com/mleem97/gregFramework/blob/main/gregCore/framework/FrikaMF/HookNames.cs) (`FFM.*` hook IDs today).
- Numeric IDs: [`framework/FrikaMF/EventIds.cs`](https://github.com/mleem97/gregFramework/blob/master/framework/FrikaMF/EventIds.cs). - Numeric IDs: [`gregCore/framework/FrikaMF/EventIds.cs`](https://github.com/mleem97/gregFramework/blob/main/gregCore/framework/FrikaMF/EventIds.cs).
- Generated wiki mirror: run [`tools/Generate-FmfHookCatalog.ps1`](https://github.com/mleem97/gregFramework/blob/master/tools/Generate-FmfHookCatalog.ps1) → [`fmf-hooks-catalog`](../reference/fmf-hooks-catalog.md). - Generated wiki mirror: run [`tools/Generate-FmfHookCatalog.ps1`](https://github.com/mleem97/gregFramework/blob/main/tools/Generate-FmfHookCatalog.ps1) → [`fmf-hooks-catalog`](../reference/fmf-hooks-catalog.md).
## Debugging (MelonLoader, IL2CPP, Unity) ## Debugging (MelonLoader, IL2CPP, Unity)
- **Build first:** `dotnet build FrikaMF.sln -c Debug` (requires MelonLoader + IL2CPP interop under `MelonLoader/` for your game install, or `lib/references/MelonLoader` — see `tools/refresh_refs.py`). - **Build first:** `dotnet build gregCore/FrikaMF.sln -c Debug` (requires MelonLoader + IL2CPP interop under `MelonLoader/` for your game install, or `lib/references/MelonLoader` — see `tools/refresh_refs.py`).
- **Attach:** Run **Data Center** with MelonLoader, then attach your IDEs **.NET / CoreCLR** debugger to the game process (process name usually matches the game executable). Breakpoints hit in **Debug** builds of mods/plugins copied into `Mods/`. - **Attach:** Run **Data Center** with MelonLoader, then attach your IDEs **.NET / CoreCLR** debugger to the game process (process name usually matches the game executable). Breakpoints hit in **Debug** builds of mods/plugins copied into `Mods/`.
- **`FFM.Plugin.AssetExporter`:** The project links `framework/Main.cs` (and related files) **and** references `FrikaMF.csproj`, which would normally produce **CS0436** duplicate-type warnings. Those are **suppressed** in the plugin `.csproj` (`NoWarn`); do not remove the project reference without linking the rest of the `FrikaMF` sources. - **`FFM.Plugin.AssetExporter`:** The project links `framework/Main.cs` (and related files) **and** references `FrikaMF.csproj`, which would normally produce **CS0436** duplicate-type warnings. Those are **suppressed** in the plugin `.csproj` (`NoWarn`); do not remove the project reference without linking the rest of the `FrikaMF` sources.
## Related ## Related
- [Monorepo target layout](/wiki/contributors/monorepo-target-layout) — phased folder goals - [Monorepo target layout](/wiki/contributors/monorepo-target-layout) — phased folder goals
- [Modding language (C# only)](/wiki/reference/modding-language-requirement) — mandatory C# for mod/plugin/extension logic
- [FMF hook naming](/wiki/reference/fmf-hook-naming) — naming convention - [FMF hook naming](/wiki/reference/fmf-hook-naming) — naming convention
- [Release channels](/wiki/reference/release-channels) — Steam vs GitHub beta - [Release channels](/wiki/reference/release-channels) — Steam vs GitHub beta

View File

@@ -25,6 +25,6 @@ The **Hex Label** mod adds in-world hex color labels for cable spinners and rack
## Source & layout ## Source & layout
- **Build sources:** [`mods/FMF.Mod.HexLabelMod`](https://github.com/mleem97/gregFramework/tree/master/mods/FMF.Mod.HexLabelMod) - **Build sources:** [`gregMod.HexLabelMod`](https://github.com/mleem97/gregFramework/tree/main/gregMod.HexLabelMod) (assembly `FMF.HexLabelMod.dll`)
See also the detailed wiki article [FMF.HexLabelMod](/wiki/mods/fmf-hex-label-mod). See also the detailed wiki article [FMF.HexLabelMod](/wiki/mods/fmf-hex-label-mod).

View File

@@ -17,8 +17,8 @@ This folder is the **single source of truth** for the public Docusaurus site. Th
| **Getting started** | [`getting-started.md`](../getting-started.md) | Onboarding (`getting-started`) + this layout page. | | **Getting started** | [`getting-started.md`](../getting-started.md) | Onboarding (`getting-started`) + this layout page. |
| **Workspace** | [`workspace/`](../workspace/index.mdx) | Map of `gregFramework/` repos on disk. | | **Workspace** | [`workspace/`](../workspace/index.mdx) | Map of `gregFramework/` repos on disk. |
| **Framework** | [`framework/`](../framework/architecture.md) | Architecture, hooks, Hexmod. | | **Framework** | [`framework/`](../framework/architecture.md) | Architecture, hooks, Hexmod. |
| **Plugins** | [`plugins/`](../plugins/index.md) | `FFM.Plugin.*` wiki pages. | | **Plugins** | [`plugins/`](../plugins/index.md) | `FFM.Plugin.*` assemblies; repos `gregExt.*` on disk. |
| **Mods** | [`mods/`](../mods/index.md) | Gameplay mods (`FMF.*`) + framework overview. | | **Mods** | [`mods/`](../mods/index.md) | Gameplay mods (`FMF.*`); repos `gregMod.*` on disk. |
| **Tools** | [`tools/`](../tools/workshop-uploader.md) | Workshop uploader and related. | | **Tools** | [`tools/`](../tools/workshop-uploader.md) | Workshop uploader and related. |
| **Guides** | [`guides/`](../guides/players/overview.md) | Role-based paths (players, mod developers, contributors, sponsors). | | **Guides** | [`guides/`](../guides/players/overview.md) | Role-based paths (players, mod developers, contributors, sponsors). |
| **Releases** | [`releases/`](../releases/index.mdx) | Per-artifact release notes. | | **Releases** | [`releases/`](../releases/index.mdx) | Per-artifact release notes. |

View File

@@ -22,36 +22,38 @@ This guide covers the development workflow for the WorkshopManager and how to pu
## Repository structure ## Repository structure
Paths are relative to the **`gregFramework/`** workspace root (split repos cloned side by side).
| Path | Purpose | | Path | Purpose |
|------|---------| |------|---------|
| `framework/FrikaMF.csproj` | Core MelonLoader framework DLL | | `gregCore/framework/FrikaMF.csproj` | Core MelonLoader framework DLL |
| `plugins/FFM.Plugin.*/` | FMF extension plugins (5 projects) | | `gregExt.*/` | FFM framework plugins (`FFM.Plugin.*` assemblies — one repo per plugin) |
| `mods/FMF.*/` | Standalone mods (4 projects) | | `gregMod.*/` | Standalone gameplay mods (`FMF.*` assemblies) |
| `WorkshopUploader/` | WorkshopManager MAUI app | | `gregModmanager/WorkshopUploader.csproj` | WorkshopManager MAUI app |
| `scripts/Deploy-Release-ToWorkshop.ps1` | Package all builds into Workshop folders | | `gregFramework/scripts/Deploy-Release-ToWorkshop.ps1` | Package all builds into Workshop folders (when present in your clone) |
| `scripts/Deploy-Release-ToDataCenter.ps1` | Deploy to game for local testing | | `gregFramework/scripts/Deploy-Release-ToDataCenter.ps1` | Deploy to game for local testing |
## Building ## Building
### Build everything (solution) ### Build everything (solution)
```bash ```bash
dotnet build FrikaMF.sln -c Release dotnet build gregCore/FrikaMF.sln -c Release
``` ```
### Build standalone mods (not in solution) ### Build standalone mods (per split repo)
```bash ```bash
dotnet build mods/FMF.ConsoleInputGuard/FMF.ConsoleInputGuard.csproj -c Release dotnet build gregMod.ConsoleInputGuard/FMF.ConsoleInputGuard.csproj -c Release
dotnet build mods/FMF.Mod.GregifyEmployees/FMF.GregifyEmployees.csproj -c Release dotnet build gregMod.GregifyEmployees/FMF.GregifyEmployees.csproj -c Release
dotnet build mods/FMF.Mod.HexLabelMod/FMF.HexLabelMod.csproj -c Release dotnet build gregMod.HexLabelMod/FMF.HexLabelMod.csproj -c Release
dotnet build mods/FMF.Plugin.LangCompatBridge/FMF.JoniMLCompatMod.csproj -c Release dotnet build gregMod.LangCompatBridge/FMF.JoniMLCompatMod.csproj -c Release
``` ```
### Build WorkshopManager only ### Build WorkshopManager only
```bash ```bash
dotnet build WorkshopUploader/WorkshopUploader.csproj -c Release dotnet build gregModmanager/WorkshopUploader.csproj -c Release
``` ```
## Workshop project structure ## Workshop project structure
@@ -130,7 +132,7 @@ The `SteamWorkshopService` in `WorkshopUploader/Services/SteamWorkshopService.cs
## Adding a new mod to the release ## Adding a new mod to the release
1. Create the mod project under `mods/`. 1. Create the mod as a split repo folder `gregMod.<Name>/` under the gregFramework workspace (or clone an existing `gregMod.*` repo).
2. Add it to the `$mods` array in `Deploy-Release-ToWorkshop.ps1`. 2. Add it to the `$mods` array in `Deploy-Release-ToWorkshop.ps1`.
3. Run the deploy script. 3. Run the deploy script.
4. Open the new workshop project in the WorkshopManager and publish. 4. Open the new workshop project in the WorkshopManager and publish.

View File

@@ -22,8 +22,8 @@ This documentation describes the **current split layout**: a local `gregFramewor
- [Workspace map](./workspace/index.mdx) — how folders map to repos - [Workspace map](./workspace/index.mdx) — how folders map to repos
- Core: `gregCore/FrikaMF-StandaloneRepo/` - Core: `gregCore/FrikaMF-StandaloneRepo/`
- Mods: `gregMods/` (repos `gregMod.<Name>`) - Mods: `gregMod.<Name>/` (split repos, directly under `gregFramework/`)
- Extensions: `gregExtensions/` (repos `gregExt.<Name>`) - Extensions (FFM plugins): `gregExt.<Name>/` (split repos, directly under `gregFramework/`)
- Wiki: `gregWiki/` (this site) - Wiki: `gregWiki/` (this site)
## Hooks and releases ## Hooks and releases

View File

@@ -12,8 +12,8 @@
"workshopContentPath": "content/Mods/", "workshopContentPath": "content/Mods/",
"workshopUrl": "", "workshopUrl": "",
"githubReleaseUrl": "", "githubReleaseUrl": "",
"wikiPath": "/wiki/hexmod", "wikiPath": "/wiki/mods/fmf-hex-label-mod",
"sourcePath": "mods/FMF.Mod.HexLabelMod" "sourcePath": "gregMod.HexLabelMod"
}, },
{ {
"id": "console-input-guard", "id": "console-input-guard",
@@ -25,8 +25,8 @@
"workshopContentPath": "content/Mods/", "workshopContentPath": "content/Mods/",
"workshopUrl": "", "workshopUrl": "",
"githubReleaseUrl": "", "githubReleaseUrl": "",
"wikiPath": "/wiki/mods/mods/fmf-console-input-guard", "wikiPath": "/wiki/mods/fmf-console-input-guard",
"sourcePath": "mods/FMF.ConsoleInputGuard" "sourcePath": "gregMod.ConsoleInputGuard"
}, },
{ {
"id": "gregify-employees", "id": "gregify-employees",
@@ -38,8 +38,8 @@
"workshopContentPath": "content/Mods/", "workshopContentPath": "content/Mods/",
"workshopUrl": "", "workshopUrl": "",
"githubReleaseUrl": "", "githubReleaseUrl": "",
"wikiPath": "/wiki/mods/mods/fmf-gregify-employees", "wikiPath": "/wiki/mods/fmf-gregify-employees",
"sourcePath": "mods/FMF.Mod.GregifyEmployees" "sourcePath": "gregMod.GregifyEmployees"
}, },
{ {
"id": "lang-compat-bridge", "id": "lang-compat-bridge",
@@ -51,8 +51,8 @@
"workshopContentPath": "content/Mods/", "workshopContentPath": "content/Mods/",
"workshopUrl": "", "workshopUrl": "",
"githubReleaseUrl": "", "githubReleaseUrl": "",
"wikiPath": "/wiki/mods/extensions/fmf-lang-compat-bridge", "wikiPath": "/wiki/mods/fmf-lang-compat-bridge",
"sourcePath": "mods/FMF.Plugin.LangCompatBridge" "sourcePath": "gregMod.LangCompatBridge"
} }
] ]
} }

View File

@@ -24,7 +24,7 @@ Provides guardrails around console input handling and accidental interactions.
- Category: Mod - Category: Mod
- Primary Language: C# - Primary Language: C#
- Project Path: `mods/FMF.ConsoleInputGuard` - Project Path: `gregMod.ConsoleInputGuard/`
## Installation ## Installation

View File

@@ -24,7 +24,7 @@ Applies themed employee customization to hiring-related gameplay flows.
- Category: Mod - Category: Mod
- Primary Language: C# - Primary Language: C#
- Project Path: `mods/FMF.Mod.GregifyEmployees` - Project Path: `gregMod.GregifyEmployees/`
## Installation ## Installation

View File

@@ -5,7 +5,7 @@ sidebar_label: FMF.HexLabelMod
<!-- markdownlint-disable MD060 --> <!-- markdownlint-disable MD060 -->
`mods/FMF.Mod.HexLabelMod` `gregMod.HexLabelMod/` (assembly `FMF.HexLabelMod.dll`)
## Purpose ## Purpose
@@ -78,7 +78,7 @@ Pressing **Ctrl+F1** toggles live config reload (6-second interval), allowing yo
## Build ## Build
```powershell ```powershell
dotnet build .\mods\FMF.Mod.HexLabelMod\FMF.HexLabelMod.csproj dotnet build .\gregMod.HexLabelMod\FMF.HexLabelMod.csproj
``` ```
Output lands in the standard MelonLoader `Mods/` folder as configured in the `.csproj`. Output lands in the standard MelonLoader `Mods/` folder as configured in the `.csproj`.
@@ -94,11 +94,11 @@ Output lands in the standard MelonLoader `Mods/` folder as configured in the `.c
## Notes ## Notes
- Original gameplay behavior is unaffected. - Original gameplay behavior is unaffected.
- This mod runs from `mods/FMF.Mod.HexLabelMod` and no longer from the repository root. - This mod is developed in `gregMod.HexLabelMod/` (workspace root), not under a legacy `mods/` tree.
- The config file is fully rewritten if any expected keys are missing (for example, after an update adds new keys). - The config file is fully rewritten if any expected keys are missing (for example, after an update adds new keys).
- FMF assembly presence is no longer required as a startup gate. - FMF assembly presence is no longer required as a startup gate.
## Sources ## Sources
- Module path: `mods/FMF.Mod.HexLabelMod` - Module path: `gregMod.HexLabelMod/`
- Relatedocs: [`Standalone Mods`](/wiki/legacy/wiki-import/StandaloneMods) - Relatedocs: [`Standalone Mods`](/wiki/legacy/wiki-import/StandaloneMods)

View File

@@ -24,7 +24,7 @@ Provides language/localization compatibility bridging for mixed mod stacks.
- Category: Mod - Category: Mod
- Primary Language: C# - Primary Language: C#
- Project Path: `mods/FMF.Plugin.LangCompatBridge` - Project Path: `gregMod.LangCompatBridge/` (assembly `FMF.JoniMLCompatMod.dll`)
## Installation ## Installation

View File

@@ -10,10 +10,10 @@ Legacy standalone UI replacement module page kept for compatibility.
## Project Status ## Project Status
- Status: Legacy documentation entry - Status: Legacy documentation entry
- Note: No active `csproj` module was detected under `mods/` for this page. - Note: No active split-repo folder (e.g. `gregMod.*`) was found under the gregFramework workspace for this entry.
## Source ## Source
- Previous mixed wiki path: `mods/standalone/fmf-ui-replacement-mod` - Previous mixed wiki path: `mods/standalone/fmf-ui-replacement-mod` (legacy layout; not mirrored as `gregMod.*` today)
- [Open Release Page](/wiki/releases/mods/fmf-ui-replacement-mod-release) - [Open Release Page](/wiki/releases/mods/fmf-ui-replacement-mod-release)

View File

@@ -6,7 +6,7 @@ description: Standalone MelonLoader gameplay mods (FMF.*) — separate from FFM
# Gameplay mods # Gameplay mods
These pages document **gameplay mods** (`FMF.*` assemblies), hosted under `gregMods/` in the workspace. They are **not** the same as [FFM plugins](../plugins/index.md), which extend the framework inside the game process. These pages document **gameplay mods** (`FMF.*` assemblies). **Source of truth** on disk: split-repo folders **`gregMod.<Name>/`** directly under the gregFramework workspace root (not under a legacy `gregMods/` umbrella). They are **not** the same as [FFM plugins](../plugins/index.md), which extend the framework inside the game process.
## Mods ## Mods

View File

@@ -3,7 +3,7 @@ title: FFM.Plugin.AssetExporter
sidebar_label: FFM.Plugin.AssetExporter sidebar_label: FFM.Plugin.AssetExporter
--- ---
`StandaloneMods/FFM.Plugin.AssetExporter` `gregExt.AssetExporter/` (assembly `FFM.Plugin.AssetExporter.dll`)
## Purpose ## Purpose
@@ -11,5 +11,5 @@ Provides export-focused tooling for asset-related workflows.
## Sources ## Sources
- Module path: `StandaloneMods/FFM.Plugin.AssetExporter` - Module path: `gregExt.AssetExporter/`
- Overview: [`Standalone Mods`](/wiki/legacy/wiki-import/StandaloneMods) - Overview: [`Standalone Mods`](/wiki/legacy/wiki-import/StandaloneMods)

View File

@@ -3,7 +3,7 @@ title: FFM.Plugin.Multiplayer
sidebar_label: FFM.Plugin.Multiplayer sidebar_label: FFM.Plugin.Multiplayer
--- ---
`StandaloneMods/FFM.Plugin.Multiplayer` `gregExt.Multiplayer/` (assembly `FFM.Plugin.Multiplayer.dll`)
## Purpose ## Purpose
@@ -11,5 +11,5 @@ Contains **multiplayer / networking** runtime (bridge, sync). **Not** the same a
## Sources ## Sources
- Module path: `StandaloneMods/FFM.Plugin.Multiplayer` - Module path: `gregExt.Multiplayer/`
- Roadmap context: [`Steamworks P2P Multiplayer Roadmap`](/wiki/legacy/wiki-import/Steamworks-P2P-Multiplayer-Roadmap) - Roadmap context: [`Steamworks P2P Multiplayer Roadmap`](/wiki/legacy/wiki-import/Steamworks-P2P-Multiplayer-Roadmap)

View File

@@ -3,7 +3,7 @@ title: FFM.Plugin.PlayerModels
sidebar_label: FFM.Plugin.PlayerModels sidebar_label: FFM.Plugin.PlayerModels
--- ---
`StandaloneMods/FFM.Plugin.PlayerModels` `gregExt.PlayerModels/` (assembly `FFM.Plugin.PlayerModels.dll`)
## Purpose ## Purpose
@@ -11,5 +11,5 @@ Hosts standalone player-model specific behavior and integration.
## Sources ## Sources
- Module path: `StandaloneMods/FFM.Plugin.PlayerModels` - Module path: `gregExt.PlayerModels/`
- Debug docs: [`Mod Developer Debug`](/wiki/legacy/wiki-import/Mod-Developer-Debug) - Debug docs: [`Mod Developer Debug`](/wiki/legacy/wiki-import/Mod-Developer-Debug)

View File

@@ -3,7 +3,7 @@ title: FFM.Plugin.Sysadmin
sidebar_label: FFM.Plugin.Sysadmin sidebar_label: FFM.Plugin.Sysadmin
--- ---
`StandaloneMods/FFM.Plugin.Sysadmin` `gregExt.Sysadmin/` (assembly `FFM.Plugin.Sysadmin.dll`)
## Purpose ## Purpose
@@ -11,5 +11,5 @@ Contains **sysadmin-oriented UI** features (Unity UI modernization, mod settings
## Sources ## Sources
- Module path: `StandaloneMods/FFM.Plugin.Sysadmin` - Module path: `gregExt.Sysadmin/`
- Framework context: [`Framework Features & Use Cases`](/wiki/legacy/wiki-import/Framework-Features-Use-Cases) - Framework context: [`Framework Features & Use Cases`](/wiki/legacy/wiki-import/Framework-Features-Use-Cases)

View File

@@ -3,7 +3,7 @@ title: FFM.Plugin.WebUIBridge
sidebar_label: FFM.Plugin.WebUIBridge sidebar_label: FFM.Plugin.WebUIBridge
--- ---
`StandaloneMods/FFM.Plugin.WebUIBridge` `gregExt.WebUIBridge/` (assembly `FFM.Plugin.WebUIBridge.dll`)
## Purpose ## Purpose
@@ -11,5 +11,5 @@ Focuses on standalone web UI bridge integration flows.
## Sources ## Sources
- Module path: `StandaloneMods/FFM.Plugin.WebUIBridge` - Module path: `gregExt.WebUIBridge/`
- Reference: [`Web UI Bridge (DC2WEB)`](/wiki/legacy/wiki-import/Web-UI-Bridge) - Reference: [`Web UI Bridge (DC2WEB)`](/wiki/legacy/wiki-import/Web-UI-Bridge)

View File

@@ -6,7 +6,7 @@ description: FFM.Plugin.* modules that extend the framework runtime — distinct
# Framework plugins (`FFM.Plugin.*`) # Framework plugins (`FFM.Plugin.*`)
These **plugins** ship as `FFM.Plugin.*` assemblies and extend the **framework runtime**. They are deployed under the games FMF plugin path (see [Game folder layout](/wiki/topics/meta/game-folder-layout)). These **plugins** ship as `FFM.Plugin.*` assemblies and extend the **framework runtime**. **Source of truth** on disk: one split-repo folder per plugin under the workspace root, named **`gregExt.<Name>/`** (for example `gregExt.AssetExporter/`). Mirrored copies may also exist under `gregCore/plugins/` for solution builds. Deploy built DLLs under the games FMF plugin path (see [Game folder layout](/wiki/topics/meta/game-folder-layout)).
Gameplay mods (`FMF.*`) are documented under **[Mods](../mods/index.md)** — not here. Gameplay mods (`FMF.*`) are documented under **[Mods](../mods/index.md)** — not here.

View File

@@ -11,6 +11,7 @@ description: Windows desktop app for managing Steam Workshop content, browsing m
## Features ## Features
### Author tools (Projects / Editor / My Uploads) ### Author tools (Projects / Editor / My Uploads)
- Create workshop projects from templates (vanilla assets, MelonLoader mods, FMF plugins). - Create workshop projects from templates (vanilla assets, MelonLoader mods, FMF plugins).
- Edit **title**, **description** (with BBCode toolbar), **visibility**, **tags**, and **preview image**; stored in `metadata.json`. - Edit **title**, **description** (with BBCode toolbar), **visibility**, **tags**, and **preview image**; stored in `metadata.json`.
- **BBCode formatting toolbar** — insert Steam-compatible formatting (bold, italic, headings, URL, image, list, code, quote, spoiler, horizontal rule, table) directly in the description editor. - **BBCode formatting toolbar** — insert Steam-compatible formatting (bold, italic, headings, URL, image, list, code, quote, spoiler, horizontal rule, table) directly in the description editor.
@@ -25,6 +26,7 @@ description: Windows desktop app for managing Steam Workshop content, browsing m
- **Per-item stats** — subscriptions, votes, score, size. - **Per-item stats** — subscriptions, votes, score, size.
### Mod Store (integrated in Mod Manager) ### Mod Store (integrated in Mod Manager)
- **Browse** all Workshop items for Data Center with tag filtering and sort options (last updated, newest, top rated, trending, most subscribed, title A-Z). - **Browse** all Workshop items for Data Center with tag filtering and sort options (last updated, newest, top rated, trending, most subscribed, title A-Z).
- **Search** mods by text. - **Search** mods by text.
- **Subscribe / Unsubscribe** to mods directly from the store. - **Subscribe / Unsubscribe** to mods directly from the store.
@@ -33,17 +35,20 @@ description: Windows desktop app for managing Steam Workshop content, browsing m
- **Item detail view** — full statistics, description, tags, gallery images, action buttons, and links to changelog/comments. - **Item detail view** — full statistics, description, tags, gallery images, action buttons, and links to changelog/comments.
### Mod Manager / Health ### Mod Manager / Health
- **Dependency health** checks: game installed, MelonLoader, Il2Cpp assemblies, FMF core, FMF plugins directory, ModCfg directory. - **Dependency health** checks: game installed, MelonLoader, Il2Cpp assemblies, FMF core, FMF plugins directory, ModCfg directory.
- **MelonLoader** download page link and game folder access. - **MelonLoader** download page link and game folder access.
- **FMF Plugin channels** — stable (local scan) and beta (server, TODO). - **FMF Plugin channels** — stable (local scan) and beta (server, TODO).
### Settings ### Settings
- **Workspace path** — change where projects are stored (defaults to `<GameRoot>/workshop`). - **Workspace path** — change where projects are stored (defaults to `<GameRoot>/workshop`).
- **Language** — switch between EN, DE, RU, ES, IT, JP, PL, CN (defaults to system language). Restart button applies the change instantly. - **Language** — switch between EN, DE, RU, ES, IT, JP, PL, CN (defaults to system language). Restart button applies the change instantly.
- **Mod Store toggle** — enable/disable the Mod Store tab (disabled by default). Restart button included. - **Mod Store toggle** — enable/disable the Mod Store tab (disabled by default). Restart button included.
- **Community links** — quick access to Discord, Modding Channel, and GregFramework.eu. - **Community links** — quick access to Discord, Modding Channel, and GregFramework.eu.
### FMF dependency notice ### FMF dependency notice
- Projects can be marked as **"Needs FrikaModFramework"** in the editor. When uploading, a notice is automatically appended to the Steam description telling users to install FMF. - Projects can be marked as **"Needs FrikaModFramework"** in the editor. When uploading, a notice is automatically appended to the Steam description telling users to install FMF.
## Requirements ## Requirements
@@ -51,7 +56,7 @@ description: Windows desktop app for managing Steam Workshop content, browsing m
- **Windows 10** (version 1809+). - **Windows 10** (version 1809+).
- **Steam** with a signed-in account that **owns Data Center** (App ID **4170200**). - **Steam** with a signed-in account that **owns Data Center** (App ID **4170200**).
- **No additional dependencies** — the release is fully self-contained (includes .NET runtime and Windows App SDK). - **No additional dependencies** — the release is fully self-contained (includes .NET runtime and Windows App SDK).
- `steam_appid.txt` must be next to the executable (included in the release build). The app loads **`steam_api64.dll`** from **`Data Center_Data/Plugins/x86_64/`** in the Data Center install when possible; otherwise it uses the copy shipped next to the uploader. - `steam_appid.txt` must be next to the executable (included in the release build). The app loads `**steam_api64.dll`** from `**Data Center_Data/Plugins/x86_64/**` in the Data Center install when possible; otherwise it uses the copy shipped next to the uploader.
## Paths and directories {#paths} ## Paths and directories {#paths}
@@ -109,11 +114,11 @@ Data Center has a **built-in mod system** (`ModLoader`) that loads mods from `co
The game's `ModLoader` (a Unity `MonoBehaviour`) runs the following on startup: The game's `ModLoader` (a Unity `MonoBehaviour`) runs the following on startup:
1. **`SyncWorkshopThenLoadAll()`** — a coroutine that: 1. `**SyncWorkshopThenLoadAll()`** — a coroutine that:
- Queries all subscribed Steam Workshop items (`PublishedFileId_t[]`) - Queries all subscribed Steam Workshop items (`PublishedFileId_t[]`)
- Waits for downloads to complete (with timeout) - Waits for downloads to complete (with timeout)
- Copies each Workshop item folder into `StreamingAssets/Mods/workshop_<ID>` via `CopyDirectory()` - Copies each Workshop item folder into `StreamingAssets/Mods/workshop_<ID>` via `CopyDirectory()`
2. **`LoadAllMods()`** — scans all subdirectories in the mods path: 2. `**LoadAllMods()**` — scans all subdirectories in the mods path:
- Calls `LoadModPack(folderPath)` for each mod folder - Calls `LoadModPack(folderPath)` for each mod folder
- Reads `config.json`, then for each entry calls: - Reads `config.json`, then for each entry calls:
- `LoadShopItem()``CreateShopTemplate()` + `CreateShopButton()` for purchasable items - `LoadShopItem()``CreateShopTemplate()` + `CreateShopButton()` for purchasable items
@@ -124,6 +129,7 @@ The `LoadDll()` method exists in the `ModLoader` but **object assets (shopItems,
::: :::
Internal state tracked by `ModLoader`: Internal state tracked by `ModLoader`:
- `modTemplates``Dictionary<int, GameObject>` of loaded shop item prefabs by mod ID - `modTemplates``Dictionary<int, GameObject>` of loaded shop item prefabs by mod ID
- `modTemplatesByFolder``Dictionary<string, GameObject>` of prefabs by folder name - `modTemplatesByFolder``Dictionary<string, GameObject>` of prefabs by folder name
- `staticInstances``List<GameObject>` of instantiated static decorations - `staticInstances``List<GameObject>` of instantiated static decorations
@@ -196,17 +202,20 @@ The `workshop_` prefix distinguishes Workshop-downloaded mods from manually inst
### config.json fields ### config.json fields
| Field | Description | | Field | Description |
|-------|-------------| | --------------- | ------------------------------------------------------------------------- |
| `modName` | Display name of the mod | | `modName` | Display name of the mod |
| `shopItems[]` | Purchasable objects that appear in the in-game shop | | `shopItems[]` | Purchasable objects that appear in the in-game shop |
| `staticItems[]` | Decorations placed at fixed world positions | | `staticItems[]` | Decorations placed at fixed world positions |
| `dlls[]` | Native plugin DLLs (see [DLL mods without MelonLoader](#native-dll-mods)) | | `dlls[]` | Native plugin DLLs (see [DLL mods without MelonLoader](#native-dll-mods)) |
### shopItems fields ### shopItems fields
| Field | Type | Description | | Field | Type | Description |
|-------|------|-------------| | ---------------- | ----------- | --------------------------------------------------------- |
| `itemName` | `string` | Display name in the shop | | `itemName` | `string` | Display name in the shop |
| `price` | `int` | Purchase price | | `price` | `int` | Purchase price |
| `xpToUnlock` | `int` | XP threshold to unlock (0 = immediately available) | | `xpToUnlock` | `int` | XP threshold to unlock (0 = immediately available) |
@@ -220,12 +229,14 @@ The `workshop_` prefix distinguishes Workshop-downloaded mods from manually inst
| `iconFile` | `string` | Path to `.png` shop icon (loaded via `LoadIcon`) | | `iconFile` | `string` | Path to `.png` shop icon (loaded via `LoadIcon`) |
| `objectType` | `int` | `0` = passive object | | `objectType` | `int` | `0` = passive object |
The `ModShopItem` UI component displays each shop item with `itemIcon`, `txtName`, and `txtPrice`. Purchasing calls `ButtonBuyItem()`. The `ModShopItem` UI component displays each shop item with `itemIcon`, `txtName`, and `txtPrice`. Purchasing calls `ButtonBuyItem()`.
### staticItems fields ### staticItems fields
| Field | Type | Description | | Field | Type | Description |
|-------|------|-------------| | ---------------- | ----------- | --------------------------- |
| `itemName` | `string` | Display name | | `itemName` | `string` | Display name |
| `modelFile` | `string` | Path to `.obj` model file | | `modelFile` | `string` | Path to `.obj` model file |
| `textureFile` | `string` | Path to `.png` texture file | | `textureFile` | `string` | Path to `.png` texture file |
@@ -235,15 +246,18 @@ The `ModShopItem` UI component displays each shop item with `itemIcon`, `txtName
| `position` | `[x, y, z]` | World position | | `position` | `[x, y, z]` | World position |
| `rotation` | `[x, y, z]` | Euler rotation in degrees | | `rotation` | `[x, y, z]` | Euler rotation in degrees |
### Asset loading pipeline ### Asset loading pipeline
| Method | Input | Output | | Method | Input | Output |
|--------|-------|--------| | ----------------------------------------- | ----------- | ----------------- |
| `LoadMesh(folderPath, modelFile)` | `.obj` file | Unity `Mesh` | | `LoadMesh(folderPath, modelFile)` | `.obj` file | Unity `Mesh` |
| `CreateMaterial(folderPath, textureFile)` | `.png` file | Unity `Material` | | `CreateMaterial(folderPath, textureFile)` | `.png` file | Unity `Material` |
| `LoadIcon(folderPath, iconFile)` | `.png` file | Unity `Sprite` | | `LoadIcon(folderPath, iconFile)` | `.png` file | Unity `Sprite` |
| `LoadTexture(path)` | `.png` file | Unity `Texture2D` | | `LoadTexture(path)` | `.png` file | Unity `Texture2D` |
- **3D models**: Wavefront OBJ format (`.obj`) - **3D models**: Wavefront OBJ format (`.obj`)
- **Textures**: PNG format (`.png`) - **Textures**: PNG format (`.png`)
- **Icons**: PNG format (`.png`) — shown in the shop UI - **Icons**: PNG format (`.png`) — shown in the shop UI
@@ -268,8 +282,9 @@ The game's `ModLoader` has **built-in DLL loading** — no MelonLoader required.
``` ```
**How it works internally:** **How it works internally:**
1. `ModLoader.LoadDll(folderPath, DllEntry)` loads the DLL from the mod folder 1. `ModLoader.LoadDll(folderPath, DllEntry)` loads the DLL from the mod folder
2. The `entryClass` must reference a class that implements the **`IModPlugin`** interface 2. The `entryClass` must reference a class that implements the `**IModPlugin`** interface
3. Loaded plugins are stored in `ModLoader.loadedPlugins` (`List<IModPlugin>`) 3. Loaded plugins are stored in `ModLoader.loadedPlugins` (`List<IModPlugin>`)
:::warning Loading timing :::warning Loading timing
@@ -278,21 +293,25 @@ Unlike asset objects (`shopItems`, `staticItems`) which are loaded at game start
**DLL entry requirements:** **DLL entry requirements:**
| Field | Description | | Field | Description |
|-------|-------------| | ------------ | ------------------------------------------------------------------------------------- |
| `fileName` | The `.dll` file in the mod folder | | `fileName` | The `.dll` file in the mod folder |
| `entryClass` | Fully qualified class name (e.g. `MyNamespace.MyPlugin`) that implements `IModPlugin` | | `entryClass` | Fully qualified class name (e.g. `MyNamespace.MyPlugin`) that implements `IModPlugin` |
:::caution Experimental feature :::caution Experimental feature
The developer has marked DLL loading as **untested**. The `LoadDll` method and `IModPlugin` interface exist in the game code, but stability is not guaranteed. A mod that uses only `shopItems` and `staticItems` (asset-only) is the safest approach. The developer has marked DLL loading as **untested**. The `LoadDll` method and `IModPlugin` interface exist in the game code, but stability is not guaranteed. A mod that uses only `shopItems` and `staticItems` (asset-only) is the safest approach.
::: :::
**Advantages over MelonLoader:** **Advantages over MelonLoader:**
- No external framework needed — works with the vanilla game - No external framework needed — works with the vanilla game
- Distributed via Workshop like any other mod (just include the DLL in the mod folder) - Distributed via Workshop like any other mod (just include the DLL in the mod folder)
- The game manages loading/unloading through its own lifecycle - The game manages loading/unloading through its own lifecycle
**Limitations:** **Limitations:**
- The `IModPlugin` interface contract is not publicly documented — you need to reference the game's IL2CPP assemblies to implement it - The `IModPlugin` interface contract is not publicly documented — you need to reference the game's IL2CPP assemblies to implement it
- Less flexibility than MelonLoader's Harmony patching - Less flexibility than MelonLoader's Harmony patching
- Only the entry class specified in `entryClass` is instantiated - Only the entry class specified in `entryClass` is instantiated
@@ -308,13 +327,15 @@ For now, only **passive objects** are supported for shop items (`objectType: 0`)
The game loads native mods from `Data Center_Data\StreamingAssets\Mods\`. Workshop items are copied into subfolders named `workshop_<PublishedFileId>` under that path (see [Steam install path](#steam-install-path)). The game loads native mods from `Data Center_Data\StreamingAssets\Mods\`. Workshop items are copied into subfolders named `workshop_<PublishedFileId>` under that path (see [Steam install path](#steam-install-path)).
**ModPathRedirector** is a **MelonLoader plugin** (not a MelonMod): install the DLL under **`{GameRoot}/Plugins/`**. It does **not** change native mod paths. It calls **`steam_api64.dll`** directly (Steam flat API: `SteamAPI_ISteamUGC_*`). The game ships this DLL under **`Data Center_Data/Plugins/x86_64/`**; the plugin loads it from there first, then falls back next to the executable. After the Il2Cpp assembly step (see MelonLoader log: `Il2CppAssemblyGenerator`), **`OnPreModsLoaded`** blocks loading MelonMods until each subscribed Workshop item reports installed in Steam and a matching **`Data Center_Data/StreamingAssets/Mods/workshop_<ID>/`** folder exists (per-item **`DownloadItem`**, **`SteamAPI_RunCallbacks`**, timeouts). If the game has not copied Workshop content into `StreamingAssets/Mods` yet, the plugin continues after a short grace period and logs a warning — restart once if mods are missing. **ModPathRedirector** is a **MelonLoader plugin** (not a MelonMod): install the DLL under `**{GameRoot}/Plugins/`**. It does **not** change native mod paths. It calls `**steam_api64.dll`** directly (Steam flat API: `SteamAPI_ISteamUGC_*`). The game ships this DLL under `**Data Center_Data/Plugins/x86_64/**`; the plugin loads it from there first, then falls back next to the executable. After the Il2Cpp assembly step (see MelonLoader log: `Il2CppAssemblyGenerator`), `**OnPreModsLoaded**` blocks loading MelonMods until each subscribed Workshop item reports installed in Steam and a matching `**Data Center_Data/StreamingAssets/Mods/workshop_<ID>/**` folder exists (per-item `**DownloadItem**`, `**SteamAPI_RunCallbacks**`, timeouts). If the game has not copied Workshop content into `StreamingAssets/Mods` yet, the plugin continues after a short grace period and logs a warning — restart once if mods are missing.
**What it does:** **What it does:**
- On each frame (from `OnApplicationStarted`), waits for `SteamAPI_IsSteamRunning` and resolves `SteamAPI_SteamUGC_v0xx``ISteamUGC*`, then calls the native UGC APIs (no Il2Cpp Steamworks wrapper)
- On each frame (from `OnApplicationStarted`), waits for `SteamAPI_IsSteamRunning` and resolves `SteamAPI_SteamUGC_v0xx``ISteamUGC`*, then calls the native UGC APIs (no Il2Cpp Steamworks wrapper)
- Leaves `ModLoader.LoadAllMods` / `CopyDirectory` unchanged — Workshop sync still uses `Data Center_Data/StreamingAssets/Mods/workshop_<ID>/` - Leaves `ModLoader.LoadAllMods` / `CopyDirectory` unchanged — Workshop sync still uses `Data Center_Data/StreamingAssets/Mods/workshop_<ID>/`
**Installation:** **Installation:**
1. Copy `FMF.ModPathRedirector.dll` into `<GameRoot>/Plugins/` (MelonLoader **Plugins** folder next to the executable) 1. Copy `FMF.ModPathRedirector.dll` into `<GameRoot>/Plugins/` (MelonLoader **Plugins** folder next to the executable)
2. Start the game — subscribed Workshop content is requested early; manual native mods still go under `Data Center_Data/StreamingAssets/Mods/<folder>/` (each folder with a `config.json`) 2. Start the game — subscribed Workshop content is requested early; manual native mods still go under `Data Center_Data/StreamingAssets/Mods/<folder>/` (each folder with a `config.json`)
@@ -391,8 +412,9 @@ workshop/
### metadata.json schema ### metadata.json schema
| Field | Type | Description | | Field | Type | Description |
|-------|------|-------------| | -------------------------- | ---------- | -------------------------------------------------------------- |
| `publishedFileId` | `number` | Steam file ID (0 if unpublished) | | `publishedFileId` | `number` | Steam file ID (0 if unpublished) |
| `title` | `string` | Workshop item title (max 128 chars) | | `title` | `string` | Workshop item title (max 128 chars) |
| `description` | `string` | Description, supports [Steam BBCode](#bbcode) (max 8000 chars) | | `description` | `string` | Description, supports [Steam BBCode](#bbcode) (max 8000 chars) |
@@ -402,17 +424,20 @@ workshop/
| `needsFmf` | `boolean` | Appends FMF dependency notice on upload | | `needsFmf` | `boolean` | Appends FMF dependency notice on upload |
| `additionalPreviews` | `string[]` | Relative paths to gallery screenshot images | | `additionalPreviews` | `string[]` | Relative paths to gallery screenshot images |
## Using the app ## Using the app
### Tabs ### Tabs
| Tab | Purpose | | Tab | Purpose |
|-----|---------| | -------------- | ------------------------------------------------- |
| **Projects** | Local workshop projects; search, open editor | | **Projects** | Local workshop projects; search, open editor |
| **New** | Create from template (vanilla, MelonLoader, FMF) | | **New** | Create from template (vanilla, MelonLoader, FMF) |
| **My Uploads** | Paginated list of your published items with stats | | **My Uploads** | Paginated list of your published items with stats |
| **Mod Store** | Browse, search, subscribe, vote, and manage mods | | **Mod Store** | Browse, search, subscribe, vote, and manage mods |
### Publish workflow ### Publish workflow
1. Open a project from the **Projects** tab. 1. Open a project from the **Projects** tab.
@@ -441,6 +466,7 @@ WorkshopUploader.exe --mode publish --path <project-folder>
``` ```
Optional flags: Optional flags:
- `--autocommit` — writes a status JSON for external tools. - `--autocommit` — writes a status JSON for external tools.
## Steam BBCode reference {#bbcode} ## Steam BBCode reference {#bbcode}
@@ -551,8 +577,9 @@ Subscribe to this Workshop item — the game loads it automatically.
Before uploading, the editor runs automated checks: Before uploading, the editor runs automated checks:
| Check | Error condition | Warning condition | | Check | Error condition | Warning condition |
|-------|----------------|-------------------| | ------------------ | --------------------------- | ------------------- |
| **Content folder** | `content/` missing or empty | — | | **Content folder** | `content/` missing or empty | — |
| **Title** | Empty or > 128 characters | — | | **Title** | Empty or > 128 characters | — |
| **Description** | > 8000 characters | Empty (recommended) | | **Description** | > 8000 characters | Empty (recommended) |
@@ -562,17 +589,20 @@ Before uploading, the editor runs automated checks:
| **Content size** | — | > 100 MB | | **Content size** | — | > 100 MB |
| **Changelog** | Empty on first publish | Empty on update | | **Changelog** | Empty on first publish | Empty on update |
Items with **errors** cannot be uploaded. **Warnings** are informational — upload is still possible. Items with **errors** cannot be uploaded. **Warnings** are informational — upload is still possible.
## Preview images {#preview-images} ## Preview images {#preview-images}
### Main preview image ### Main preview image
- Supports **PNG**, **JPG**, **JPEG**, **GIF**, and **WebP**. - Supports **PNG**, **JPG**, **JPEG**, **GIF**, and **WebP**.
- Auto-detected by filename: `preview.png`, `preview.jpg`, etc. - Auto-detected by filename: `preview.png`, `preview.jpg`, etc.
- Recommended size: under **1 MB**. - Recommended size: under **1 MB**.
- The app auto-detects the format from the file's magic bytes when syncing from Steam. - The app auto-detects the format from the file's magic bytes when syncing from Steam.
### Gallery screenshots ### Gallery screenshots
- Up to **9** additional images per item. - Up to **9** additional images per item.
- Stored in `screenshots/` under the project root. - Stored in `screenshots/` under the project root.
- Uploaded in a separate pass after the main content publish. - Uploaded in a separate pass after the main content publish.
@@ -635,6 +665,7 @@ Yes. Use **My Uploads** → select the item → **Import**. The app downloads ev
**Q: Why can't I upload? The button is greyed out / shows errors.** **Q: Why can't I upload? The button is greyed out / shows errors.**
The upload readiness checker found issues. Common blockers: The upload readiness checker found issues. Common blockers:
- `content/` folder is missing or empty. - `content/` folder is missing or empty.
- Title is empty. - Title is empty.
- No changelog provided on first publish. - No changelog provided on first publish.
@@ -644,6 +675,7 @@ Check the readiness panel at the bottom of the editor for details.
Yes for the **first publish** (error if empty). For updates it's recommended but not enforced (warning only). Yes for the **first publish** (error if empty). For updates it's recommended but not enforced (warning only).
**Q: What happens after I click "Save and upload to Steam"?** **Q: What happens after I click "Save and upload to Steam"?**
1. Metadata is saved locally. 1. Metadata is saved locally.
2. Content and preview are uploaded to Steam. 2. Content and preview are uploaded to Steam.
3. Gallery screenshots are uploaded (if any). 3. Gallery screenshots are uploaded (if any).
@@ -690,18 +722,21 @@ Yes. After publishing and during import, gallery screenshots are downloaded from
**Q: How does the game load Workshop mods?** **Q: How does the game load Workshop mods?**
At startup, the game's `ModLoader.SyncWorkshopThenLoadAll()` queries all subscribed items from Steam, waits for downloads to complete, and copies each into `Data Center_Data/StreamingAssets/Mods/workshop_<ID>/`. Then `LoadAllMods()` scans that folder. Asset objects (shopItems, staticItems) load immediately; DLL mods load later at SaveLoad time. The content structure determines what kind of mod it is: At startup, the game's `ModLoader.SyncWorkshopThenLoadAll()` queries all subscribed items from Steam, waits for downloads to complete, and copies each into `Data Center_Data/StreamingAssets/Mods/workshop_<ID>/`. Then `LoadAllMods()` scans that folder. Asset objects (shopItems, staticItems) load immediately; DLL mods load later at SaveLoad time. The content structure determines what kind of mod it is:
- **Native mods** (vanilla): `config.json` + OBJ/PNG assets directly in `content/` — no extra tools needed. - **Native mods** (vanilla): `config.json` + OBJ/PNG assets directly in `content/` — no extra tools needed.
- **MelonLoader mods**: `content/Mods/` with `.dll` files — requires MelonLoader. - **MelonLoader mods**: `content/Mods/` with `.dll` files — requires MelonLoader.
- **FMF plugins**: `content/FMF/Plugins/` with `.dll` files — requires MelonLoader + FMF. - **FMF plugins**: `content/FMF/Plugins/` with `.dll` files — requires MelonLoader + FMF.
**Q: What are the three mod types?** **Q: What are the three mod types?**
| Type | Requirements | Content structure | Use case | | Type | Requirements | Content structure | Use case |
|------|-------------|-------------------|----------| | -------------------- | ----------------- | ------------------------------- | --------------------------------------- |
| **Vanilla (native)** | None | `config.json` + `.obj` + `.png` | Custom objects, decorations, shop items | | **Vanilla (native)** | None | `config.json` + `.obj` + `.png` | Custom objects, decorations, shop items |
| **MelonLoader** | MelonLoader | `Mods/*.dll` | Code mods (IL2CPP) | | **MelonLoader** | MelonLoader | `Mods/*.dll` | Code mods (IL2CPP) |
| **FMF plugin** | MelonLoader + FMF | `FMF/Plugins/*.dll` | FrikaModFramework plugins | | **FMF plugin** | MelonLoader + FMF | `FMF/Plugins/*.dll` | FrikaModFramework plugins |
**Q: What model format does the native mod system use?** **Q: What model format does the native mod system use?**
Wavefront OBJ (`.obj`) for 3D models and PNG (`.png`) for textures and icons. Wavefront OBJ (`.obj`) for 3D models and PNG (`.png`) for textures and icons.
@@ -728,28 +763,33 @@ Yes. Browse or search for mods, then click **Subscribe**. Steam will download th
### Troubleshooting ### Troubleshooting
**Q: The app won't start / crashes on launch.** **Q: The app won't start / crashes on launch.**
- Ensure `steam_appid.txt` is next to the executable; `steam_api64.dll` should resolve from the Data Center install (`Data Center_Data/Plugins/x86_64/`) or from the uploader folder. - Ensure `steam_appid.txt` is next to the executable; `steam_api64.dll` should resolve from the Data Center install (`Data Center_Data/Plugins/x86_64/`) or from the uploader folder.
- Steam must be running and logged in. - Steam must be running and logged in.
- Check the Windows Event Viewer (Application log) for .NET crash details. - Check the Windows Event Viewer (Application log) for .NET crash details.
- On Windows 10 < 1809, the app may not work due to WinUI requirements. - On Windows 10 < 1809, the app may not work due to WinUI requirements.
**Q: "Steam init failed" error in the app.** **Q: "Steam init failed" error in the app.**
- Make sure Steam is running and you are logged in. - Make sure Steam is running and you are logged in.
- Verify you own Data Center (App ID 4170200). - Verify you own Data Center (App ID 4170200).
- Check that `steam_appid.txt` contains `4170200`. - Check that `steam_appid.txt` contains `4170200`.
**Q: My content doesn't show up after subscribing.** **Q: My content doesn't show up after subscribing.**
- Restart the game — Workshop content is loaded at startup. - Restart the game — Workshop content is loaded at startup.
- Check `steamapps/workshop/content/4170200/` to verify the download exists. - Check `steamapps/workshop/content/4170200/` to verify the download exists.
- If the folder is empty, try unsubscribing and re-subscribing. - If the folder is empty, try unsubscribing and re-subscribing.
**Q: The preview image doesn't load in the Mod Store.** **Q: The preview image doesn't load in the Mod Store.**
- The image is loaded from Steam's CDN. Check your internet connection. - The image is loaded from Steam's CDN. Check your internet connection.
- Very large images may take a moment to appear. - Very large images may take a moment to appear.
## See also ## See also
- Repository README: [`WorkshopUploader/README.md`](https://github.com/mleem97/gregFramework/blob/master/WorkshopUploader/README.md) - Repository README: `[WorkshopUploader/README.md](https://github.com/mleem97/gregFramework/blob/master/WorkshopUploader/README.md)`
- [End-User Guide](/wiki/guides/players/enduser-workshop) - [End-User Guide](/wiki/guides/players/enduser-workshop)
- [Contributor Guide](/wiki/guides/contributors/contributor-workshop) - [Contributor Guide](/wiki/guides/contributors/contributor-workshop)
- [Release](/wiki/guides/contributors/release) - [Release](/wiki/guides/contributors/release)

View File

@@ -22,8 +22,8 @@ Diese Dokumentation beschreibt den **aktuellen Split-Stand**: `gregFramework/` a
- [Workspace-Karte](/wiki/workspace/) — Ordner → Repos - [Workspace-Karte](/wiki/workspace/) — Ordner → Repos
- Core: `gregCore/FrikaMF-StandaloneRepo/` - Core: `gregCore/FrikaMF-StandaloneRepo/`
- Mods: `gregMods/` (Repos `gregMod.<Name>`) - Mods: `gregMod.<Name>/` (Split-Repos, direkt unter `gregFramework/`)
- Extensions: `gregExtensions/` (Repos `gregExt.<Name>`) - Extensions (FFM-Plugins): `gregExt.<Name>/` (Split-Repos, direkt unter `gregFramework/`)
- Wiki: `gregWiki/` - Wiki: `gregWiki/`
## Hooks und Releases ## Hooks und Releases

View File

@@ -3,6 +3,8 @@ export type ModuleType = 'plugin' | 'mod';
export type ModuleEntry = { export type ModuleEntry = {
id: string; id: string;
name: string; name: string;
/** Folder under gregFramework/ (split repo), e.g. gregExt.AssetExporter */
repoFolder: string | null;
type: ModuleType; type: ModuleType;
description: string; description: string;
version: string; version: string;
@@ -19,6 +21,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'ffm-plugin-asset-exporter', id: 'ffm-plugin-asset-exporter',
name: 'FFM.Plugin.AssetExporter', name: 'FFM.Plugin.AssetExporter',
repoFolder: 'gregExt.AssetExporter',
type: 'plugin', type: 'plugin',
description: 'Export-focused asset tooling for Data Center workflows.', description: 'Export-focused asset tooling for Data Center workflows.',
version: 'NotReleasedYet', version: 'NotReleasedYet',
@@ -33,6 +36,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'ffm-plugin-multiplayer', id: 'ffm-plugin-multiplayer',
name: 'FFM.Plugin.Multiplayer', name: 'FFM.Plugin.Multiplayer',
repoFolder: 'gregExt.Multiplayer',
type: 'plugin', type: 'plugin',
description: 'Multiplayer-oriented plugin surface for gregFramework ecosystems.', description: 'Multiplayer-oriented plugin surface for gregFramework ecosystems.',
version: 'NotReleasedYet', version: 'NotReleasedYet',
@@ -47,6 +51,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'ffm-plugin-player-models', id: 'ffm-plugin-player-models',
name: 'FFM.Plugin.PlayerModels', name: 'FFM.Plugin.PlayerModels',
repoFolder: 'gregExt.PlayerModels',
type: 'plugin', type: 'plugin',
description: 'Player model extension plugin for runtime and presentation logic.', description: 'Player model extension plugin for runtime and presentation logic.',
version: 'NotReleasedYet', version: 'NotReleasedYet',
@@ -75,6 +80,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'ffm-plugin-web-ui-bridge', id: 'ffm-plugin-web-ui-bridge',
name: 'FFM.Plugin.WebUIBridge', name: 'FFM.Plugin.WebUIBridge',
repoFolder: 'gregExt.WebUIBridge',
type: 'plugin', type: 'plugin',
description: 'Bridge plugin between game runtime data and web UI overlays.', description: 'Bridge plugin between game runtime data and web UI overlays.',
version: 'NotReleasedYet', version: 'NotReleasedYet',
@@ -89,6 +95,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'fmf-modpathredirector', id: 'fmf-modpathredirector',
name: 'FMF.ModPathRedirector', name: 'FMF.ModPathRedirector',
repoFolder: 'gregMod.PathRedirector',
type: 'plugin', type: 'plugin',
description: 'MelonLoader plugin: waits for each subscribed Workshop item (Steam + StreamingAssets/Mods/workshop_*) before MelonMods load.', description: 'MelonLoader plugin: waits for each subscribed Workshop item (Steam + StreamingAssets/Mods/workshop_*) before MelonMods load.',
version: '1.5.0', version: '1.5.0',
@@ -103,6 +110,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'fmf-console-input-guard', id: 'fmf-console-input-guard',
name: 'FMF.ConsoleInputGuard', name: 'FMF.ConsoleInputGuard',
repoFolder: 'gregMod.ConsoleInputGuard',
type: 'mod', type: 'mod',
description: 'Console interaction guardrails for safer gameplay input handling.', description: 'Console interaction guardrails for safer gameplay input handling.',
version: 'NotReleasedYet', version: 'NotReleasedYet',
@@ -117,6 +125,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'fmf-gregify-employees', id: 'fmf-gregify-employees',
name: 'FMF.GregifyEmployees', name: 'FMF.GregifyEmployees',
repoFolder: 'gregMod.GregifyEmployees',
type: 'mod', type: 'mod',
description: 'Gameplay mod for employee theming and behavior customization.', description: 'Gameplay mod for employee theming and behavior customization.',
version: 'NotReleasedYet', version: 'NotReleasedYet',
@@ -131,6 +140,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'fmf-hex-label-mod', id: 'fmf-hex-label-mod',
name: 'FMF.HexLabelMod', name: 'FMF.HexLabelMod',
repoFolder: 'gregMod.HexLabelMod',
type: 'mod', type: 'mod',
description: 'In-world hex color labels for cable spinners and racks.', description: 'In-world hex color labels for cable spinners and racks.',
version: 'NotReleasedYet', version: 'NotReleasedYet',
@@ -145,6 +155,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'fmf-lang-compat-bridge', id: 'fmf-lang-compat-bridge',
name: 'FMF.LangCompatBridge', name: 'FMF.LangCompatBridge',
repoFolder: 'gregMod.LangCompatBridge',
type: 'mod', type: 'mod',
description: 'Localization compatibility bridge for mixed mod stacks.', description: 'Localization compatibility bridge for mixed mod stacks.',
version: 'NotReleasedYet', version: 'NotReleasedYet',
@@ -159,6 +170,7 @@ export const moduleCatalog: ModuleEntry[] = [
{ {
id: 'fmf-ui-replacement-mod', id: 'fmf-ui-replacement-mod',
name: 'FMF.UIReplacementMod', name: 'FMF.UIReplacementMod',
repoFolder: null,
type: 'mod', type: 'mod',
description: 'Replaces and modernizes selected in-game UI layers.', description: 'Replaces and modernizes selected in-game UI layers.',
version: 'NotReleasedYet', version: 'NotReleasedYet',

View File

@@ -9,6 +9,8 @@ export type ModsPageStrings = {
release: string; release: string;
download: string; download: string;
notReleased: string; notReleased: string;
repoFolder: string;
legacyNoSplitRepo: string;
}; };
const byLocale: Record<LocaleKey, ModsPageStrings> = { const byLocale: Record<LocaleKey, ModsPageStrings> = {
@@ -22,6 +24,8 @@ const byLocale: Record<LocaleKey, ModsPageStrings> = {
release: 'Release', release: 'Release',
download: 'Download DLL', download: 'Download DLL',
notReleased: 'Not released yet', notReleased: 'Not released yet',
repoFolder: 'gregFramework folder',
legacyNoSplitRepo: 'Legacy — no split repo in workspace',
}, },
de: { de: {
title: 'Mods- & Plugin-Katalog', title: 'Mods- & Plugin-Katalog',
@@ -33,6 +37,8 @@ const byLocale: Record<LocaleKey, ModsPageStrings> = {
release: 'Release', release: 'Release',
download: 'DLL laden', download: 'DLL laden',
notReleased: 'Noch nicht veröffentlicht', notReleased: 'Noch nicht veröffentlicht',
repoFolder: 'Ordner unter gregFramework',
legacyNoSplitRepo: 'Legacy — kein Split-Repo im Workspace',
}, },
}; };

View File

@@ -52,6 +52,12 @@ export default function ModsCatalogPage(): JSX.Element {
</h3> </h3>
<p className="mb-4 text-sm text-on-surface-variant">{entry.description}</p> <p className="mb-4 text-sm text-on-surface-variant">{entry.description}</p>
<p className="mb-1 text-xs text-on-surface-variant">Version: {entry.version}</p> <p className="mb-1 text-xs text-on-surface-variant">Version: {entry.version}</p>
<p className="mb-1 text-xs text-on-surface-variant">
{m.repoFolder}:{' '}
<span className="font-mono text-on-surface">
{entry.repoFolder ?? m.legacyNoSplitRepo}
</span>
</p>
<p className="mb-4 text-xs text-on-surface-variant"> <p className="mb-4 text-xs text-on-surface-variant">
Languages: {entry.languages.join(', ')} Languages: {entry.languages.join(', ')}
</p> </p>
@@ -98,6 +104,12 @@ export default function ModsCatalogPage(): JSX.Element {
</h3> </h3>
<p className="mb-4 text-sm text-on-surface-variant">{entry.description}</p> <p className="mb-4 text-sm text-on-surface-variant">{entry.description}</p>
<p className="mb-1 text-xs text-on-surface-variant">Version: {entry.version}</p> <p className="mb-1 text-xs text-on-surface-variant">Version: {entry.version}</p>
<p className="mb-1 text-xs text-on-surface-variant">
{m.repoFolder}:{' '}
<span className="font-mono text-on-surface">
{entry.repoFolder ?? m.legacyNoSplitRepo}
</span>
</p>
<p className="mb-4 text-xs text-on-surface-variant"> <p className="mb-4 text-xs text-on-surface-variant">
Dependencies: {entry.dependencies.join(', ')} Dependencies: {entry.dependencies.join(', ')}
</p> </p>