diff --git a/docs/framework/greg-hooks-and-events.md b/docs/framework/greg-hooks-and-events.md new file mode 100644 index 0000000..273e684 --- /dev/null +++ b/docs/framework/greg-hooks-and-events.md @@ -0,0 +1,53 @@ +--- +title: Greg hooks & event runtime +sidebar_label: Greg hooks & events +description: greg.* hook registry, GregEventDispatcher, Rust FFI event ids, and how they relate to legacy FFM strings. +--- + +# Greg hooks & event runtime + +The **FrikaModdingFramework** assembly (`gregCore/FrikaMF.csproj`, output **`FrikaModdingFramework.dll`**) combines Harmony patches, C# mod events, and the Rust/native bridge. Mod and plugin authors should understand **three related surfaces**: + +| Surface | Purpose | Typical entry | +|--------|---------|----------------| +| **`greg.*` string hooks** | Canonical hook names for new work; registry drives codegen and docs. | `GregEventDispatcher.On("greg....", handler, modId)` in **`gregFramework.Core`** | +| **Legacy `FFM.*` strings** | Numeric Rust/game pipeline still resolves through **`HookNames`** constants today. | [`FrikaMF/HookNames.cs`](https://github.com/mleem97/gregFramework/blob/main/gregCore/FrikaMF/HookNames.cs), [`EventIds.cs`](https://github.com/mleem97/gregFramework/blob/main/gregCore/FrikaMF/EventIds.cs) | +| **In-process mod messages** | Cross-mod C# notifications (not the same as `greg.*`). | `AssetExporter.ModFramework` / **`ModFramework.Events`** | + +Naming policy for **new** public identifiers remains **`FMF..*`** — see [FMF hook naming](/wiki/reference/fmf-hook-naming). The **`greg.*`** registry is generated from the Il2Cpp unpack and is the **runtime source of truth** for Harmony bridge patches in **`gregFramework.Hooks`** (auto-generated types under `gregCore/Hooks/`). + +## `greg_hooks.json` (version 2) + +- **Repo paths:** `gregCore/gregFramework/greg_hooks.json` (and a mirrored copy under `gregCore/framework/gregFramework/` for some builds). +- **Meaning:** canonical list of `greg..` hooks with patch targets, strategies, and payload hints. +- **Regenerate:** `gregCore/scripts/Generate-GregHooksFromIl2CppDump.ps1` when `gregReferences/` Il2Cpp unpack or merged interop changes. +- **Runtime compat:** **`GregCompatBridge`** (`gregFramework.Core`) can load **`greg_hooks.json`** next to the framework DLL to map legacy spellings. + +## `GregEventDispatcher` + +Implemented in **`gregCore/Core/GregEventDispatcher.cs`** (`namespace gregFramework.Core`). Use **`On` / `Once` / `Off` / `Emit`** (and cancelable overloads where exposed) for string-keyed hooks with optional **`modId`** for diagnostics. + +## Rust FFI and numeric events + +Rust mods receive **numeric** event ids; C# maps them via **`EventDispatcher`** / **`GregHookIntegration`** in the **`FrikaMF`** tree so that game and bridge traffic can still surface as **`greg.*`** where integrated. Standalone bridge documentation: `gregCore/bridges/gregSta.RustBridge/README.md`. + +## MelonLoader entry points (same DLL) + +Two **`MelonMod`** types ship in one assembly for different scenarios (check `MelonInfo` / `MelonGame` attributes in source): + +- **`DataCenterModLoader.Core`** — primary Data Center + Rust load path (`FrikaMF/Core.cs`). +- **`AssetExporter.Main`** — broader tooling / dev entry (`Main.cs`), also participates in framework bootstrap paths. + +Exact responsibilities evolve in **`gregCore`**; treat this split as **“two hosts, one framework DLL”** when debugging load order. + +## Tooling & assistants + +- **MCP:** `greg_hook_registry`, `greg_hook_search`, `greg_hook_stats` read **`greg_hooks.json`** when `dataRoot` points at **`gregCore/`** — see [MCP server](/wiki/reference/mcp-server). +- **Legacy catalog page:** [FMF hooks catalog](/wiki/reference/fmf-hooks-catalog) is generated from **`FrikaMF/HookNames.cs`** and **`FrikaMF/EventIds.cs`** (`tools/Generate-FmfHookCatalog.ps1`). +- **Declarative doc stub:** [FMF Hook Reference](/wiki/framework/fmf-hooks) (from `fmf_hooks.json` / scanner, may lag core). + +## See also + +- [Repository architecture](/wiki/framework/architecture) +- [FFI, hooks & Lua (hub)](/wiki/topics/ffi-and-hooks/overview) +- [Getting started](/wiki/getting-started) diff --git a/docs/getting-started/documentation-layout.md b/docs/getting-started/documentation-layout.md index 7896964..a8b64ec 100644 --- a/docs/getting-started/documentation-layout.md +++ b/docs/getting-started/documentation-layout.md @@ -22,7 +22,7 @@ This folder is the **single source of truth** for the public Docusaurus site. Th | **Tools** | [`tools/`](../tools/workshop-uploader.md) | Workshop uploader and related. | | **Guides** | [`guides/`](../guides/players/overview.md) | Role-based paths (players, mod developers, contributors, sponsors). | | **Releases** | [`releases/`](../releases/index.mdx) | Per-artifact release notes. | -| **Reference** | [`reference/`](../reference/wiki-mapping.md) | Naming, catalogs, MCP, release channels. | +| **Reference** | [`reference/`](../reference/wiki-mapping.md) | Naming, catalogs, [`greg_hooks` registry](../reference/greg-hooks-registry.md), MCP, release channels. | | **Contributors** | [`contributors/`](../contributors/repo-inventory.md) | Repo inventory, Docusaurus workflow, design system. | | **Roadmap** | [`roadmap/`](../roadmap/unified-roadmap.md) | Planning docs. | | **Topics hub** | [`topics/`](../topics/index.md) | Cross-cutting overviews (assets, multiplayer, security, …). | diff --git a/docs/guides/mod-developers/greg-hooks-showcase.md b/docs/guides/mod-developers/greg-hooks-showcase.md index 91a935c..13d257f 100644 --- a/docs/guides/mod-developers/greg-hooks-showcase.md +++ b/docs/guides/mod-developers/greg-hooks-showcase.md @@ -1,41 +1,77 @@ --- title: Greg hooks showcase (sample mod) sidebar_label: Greg hooks showcase -description: How to subscribe to greg.* hooks via GregShowcaseMod and gregFramework.Core APIs. +description: Subscribe to greg.* hooks via GregShowcaseMod, GregEventDispatcher, GregPayload, and optional OnCancelable veto. --- # Greg hooks showcase -The repository includes **GregShowcaseMod** (`mods/GregShowcaseMod/` in **gregFramework**): a minimal MelonLoader mod that logs one representative event per **GregDomain**, using only public APIs: +The **gregFramework** repo ships **GregShowcaseMod** at `mods/GregShowcaseMod/`. It demonstrates the public API only: -- `GregEventDispatcher.On` / `UnregisterAll` +- `GregEventDispatcher.On` / `Once` / `OnCancelable` / `UnregisterAll` - `GregHookName.Create(GregDomain.*, "Action")` -- `GregPayload.Get` / `GregPayload.Dump` for anonymous payloads +- `GregPayload.Get` / `GregPayload.Dump` for anonymous payloads ## Canonical hook strings -Runtime hook names look like `greg..`, e.g. `greg.PLAYER.MoneyChanged`. Build the string with `GregHookName.Create` — do not concatenate raw strings in mods. +Runtime names look like `greg..`. Always build them with `GregHookName.Create` — do not concatenate raw strings in mods. -## Registry file +## Registry -`greg_hooks.json` (shipped beside `FrikaModdingFramework.dll`) is generated from `MergedCode.md` by: +**`greg_hooks.json`** at the **gregFramework** repository root is the canonical catalog (`description`, `payloadSchema`, `strategy`, optional `legacy`). A copy is emitted next to **`FrikaModdingFramework.dll`** for `GregCompatBridge` legacy resolution. -```bash -pwsh gregCore/scripts/Generate-GregHooksFromMergedCode.ps1 +Authoritative documentation: [greg hooks registry (IL2CPP)](/wiki/reference/greg-hooks-registry) — regeneration script, whitelist, and Harmony deduplication rules. + +## FFI bridge and greg.* emission + +`DataCenterModLoader.EventDispatcher` emits **`greg.*`** events through **`GregHookIntegration`** for the same gameplay moments as the Rust FFI event ids (money, cables, customers, save/load, etc.), even when the FFI bridge is not connected. + +## Payload access patterns + +**Pattern A — dynamic (anonymous types from compiler):** + +```csharp +private static void OnMoneyChanged(object payload) +{ + dynamic p = payload; + float delta = (float)p.coinChangeAmount; + float balance = (float)p.newBalance; + MelonLogger.Msg($"Δ={delta} → {balance}"); +} ``` -Options are passed through to `parse_merged_code.py` (e.g. `--no-hot-loops` to omit `Update`/`FixedUpdate` from the catalog). The dump is large; regeneration can take several minutes. +**Pattern B — `GregPayload` (reflection, case-insensitive property names):** -## Sample subscriptions +```csharp +private static void OnReputationChanged(object payload) +{ + var amount = GregPayload.Get(payload, "amount"); + var rep = GregPayload.Get(payload, "reputation"); + MelonLogger.Msg($"Reputation: {amount} → {rep}"); +} +``` -See `mods/GregShowcaseMod/Handlers/*.cs` — each file registers one hook for its domain (except **POWER**, where `GregPowerHooks` is still empty until Il2Cpp types are classified). +**Pattern C — typed record (when you define a shared contract in your mod or core):** + +```csharp +// public record PlayerMoneyPayload(float CoinChangeAmount, float NewBalance, bool WithoutSound, bool Accepted); +// if (payload is PlayerMoneyPayload p) { ... } +``` + +Use **`GregPayload.Dump(payload)`** for one-line debug strings. + +## Prefix hooks and cancellation + +Hooks that run **before** the original method (Harmony Prefix) can call **`GregEventDispatcher.InvokeCancelable(hookName, payload)`**. Mods register **`GregEventDispatcher.OnCancelable(hookName, p => bool, modId)`**; if any handler returns `false`, the integration can skip the original (e.g. `Player.UpdateCoin`). + +Showcase: enable `blockNegativeTransactions` in `content/modconfig.json` to register a veto on large negative `coinChangeAmount` values. ## Configuration -Copy `mods/GregShowcaseMod/modconfig.example.json` to `{Game}/Mods/GregShowcaseMod/modconfig.json` to toggle per-domain logging. +Edit **`content/modconfig.json`** next to the built DLL (defaults are copied from the repo). Keys include `logPlayerEvents`, `logNetworkEvents`, `blockNegativeTransactions`, `reputationWarningThreshold`. ## See also - [Mod developers (hub)](./overview) - [System architecture principles](/wiki/meta/system-architecture-principles) -- [Framework](/wiki/mods/framework) — runtime overview +- [Framework](/wiki/mods/framework) diff --git a/docs/guides/mod-developers/overview.md b/docs/guides/mod-developers/overview.md index ea946c4..8542ee2 100644 --- a/docs/guides/mod-developers/overview.md +++ b/docs/guides/mod-developers/overview.md @@ -9,6 +9,7 @@ description: Getting started, mod config, debugging — curated docs for FMF mod **Mod authors** — build your own mods (hooks, configuration, debugging). Role overview: [By audience](/wiki/guides/players/audiences-overview). - [Greg hooks showcase](/wiki/guides/mod-developers/greg-hooks-showcase) — sample mod (`GregShowcaseMod`) and `GregPayload` usage +- [greg hooks registry (IL2CPP)](/wiki/reference/greg-hooks-registry) — `greg_hooks.json`, regeneration, overlap with `HarmonyPatches` - [System architecture & documentation principles](/wiki/meta/system-architecture-principles) — layer model **ModManager → Framework → Plugins → Mods**, priorities, wiki rules - [By audience — intermediates](/wiki/audiences/intermediates) and [professionals](/wiki/audiences/professionals) - [Framework overview](/wiki/mods/framework) — runtime capabilities and repo layout diff --git a/docs/mods/framework.md b/docs/mods/framework.md index b10256d..607d502 100644 --- a/docs/mods/framework.md +++ b/docs/mods/framework.md @@ -19,4 +19,5 @@ The core `FrikaMF` runtime provides: - [FMF hooks (generated)](/wiki/framework/fmf-hooks) — hook surface and categories - [FMF hook naming](/wiki/reference/fmf-hook-naming) — `FMF.*` vs legacy `FFM.*` - [FMF hooks catalog](/wiki/reference/fmf-hooks-catalog) — strings from core `HookNames.cs` +- [greg hooks registry (IL2CPP)](/wiki/reference/greg-hooks-registry) — `greg.*` Harmony hooks and `greg_hooks.json` - [Framework architecture](/wiki/framework/architecture) — runtime layout and bridges diff --git a/docs/reference/fmf-hook-naming.md b/docs/reference/fmf-hook-naming.md index 971c427..f53769e 100644 --- a/docs/reference/fmf-hook-naming.md +++ b/docs/reference/fmf-hook-naming.md @@ -40,6 +40,10 @@ Domains are **closed by default**. Add a new domain only via changelog + maintai | `SAVE` | Save/load lifecycle | | `FRAMEWORK` | Loader, bridge, diagnostics | +## Runtime IL2CPP (MelonLoader): `greg.*` + +Harmony patches in **gregFramework** emit stable **`greg..`** strings via `GregHookName` / `GregEventDispatcher`. That surface is documented in **[greg hooks registry (IL2CPP)](/wiki/reference/greg-hooks-registry)** (`greg_hooks.json`, regeneration, overlap with hand-written `HarmonyPatches`). It is separate from the `FMF.*` / `FFM.*` documentation constants below. + ## Legacy: `FFM.*` strings in code The runtime currently maps numeric event IDs to **`FFM.*`** string constants in [`FrikaMF/HookNames.cs`](https://github.com/mleem97/gregFramework/blob/master/FrikaMF/HookNames.cs) (e.g. `FFM.Economy.Balance.OnChanged`). That is **legacy naming** (four segments after `FFM`). diff --git a/docs/reference/fmf-hooks-catalog.md b/docs/reference/fmf-hooks-catalog.md index ac62bb4..4c7766d 100644 --- a/docs/reference/fmf-hooks-catalog.md +++ b/docs/reference/fmf-hooks-catalog.md @@ -9,101 +9,103 @@ description: Auto-generated catalog of hook strings and event id mappings from F # FMF hooks catalog -This page is **generated** from `framework/FrikaMF/HookNames.cs` and `framework/FrikaMF/EventIds.cs`. +This page is **generated** from `gregCore/FrikaMF/HookNames.cs` and `gregCore/FrikaMF/EventIds.cs`. +Regenerate after hook changes: `./tools/Generate-FmfHookCatalog.ps1` -**Generated:** 2026-04-06 14:26:09 UTC +**Generated:** 2026-04-10 01:36:21 UTC ## Hook string constants | C# field | Hook string | |----------|-------------| -| ``CustomerContractOnSigned`` | ``FFM.Customer.Contract.OnSigned`` | -| ``CustomerReputationOnChanged`` | ``FFM.Customer.Reputation.OnChanged`` | -| ``CustomerSlaOnBreached`` | ``FFM.Customer.SLA.OnBreached`` | -| ``CustomerSlaOnRestored`` | ``FFM.Customer.SLA.OnRestored`` | -| ``EconomyBalanceOnChanged`` | ``FFM.Economy.Balance.OnChanged`` | -| ``EmployeesStaffOnHiredCustom`` | ``FFM.Employees.Staff.OnHired`` | -| ``EmployeesStaffOnTerminatedCustom`` | ``FFM.Employees.Staff.OnTerminated`` | -| ``FrameworkHooksOnBridgeInstalled`` | ``FFM.Framework.Hooks.OnBridgeInstalled`` | -| ``FrameworkHooksOnBridgeTriggered`` | ``FFM.Framework.Hooks.OnBridgeTriggered`` | -| ``GameLoadOnCompleted`` | ``FFM.Game.Load.OnCompleted`` | -| ``GameSaveOnCompleted`` | ``FFM.Game.Save.OnCompleted`` | -| ``GameSaveOnRequested`` | ``FFM.Game.Save.OnRequested`` | -| ``GameTimeOnDayChanged`` | ``FFM.Game.Time.OnDayChanged`` | -| ``GameTimeOnMonthChanged`` | ``FFM.Game.Time.OnMonthChanged`` | -| ``GameXpOnGained`` | ``FFM.Game.XP.OnGained`` | -| ``NetworkCableOnConnected`` | ``FFM.Network.Cable.OnConnected`` | -| ``NetworkCableOnConnectedSuppress`` | ``FFM.Network.Cable.OnConnected.Suppress`` | -| ``NetworkCableOnDisconnected`` | ``FFM.Network.Cable.OnDisconnected`` | -| ``NetworkCableOnDisconnectedSuppress`` | ``FFM.Network.Cable.OnDisconnected.Suppress`` | -| ``NetworkCableOnLinkDown`` | ``FFM.Network.Cable.OnLinkDown`` | -| ``NetworkCableOnLinkUp`` | ``FFM.Network.Cable.OnLinkUp`` | -| ``NetworkTrafficOnThresholdExceeded`` | ``FFM.Network.Traffic.OnThresholdExceeded`` | -| ``ObjectsDeviceOnDegraded`` | ``FFM.Objects.Device.OnDegraded`` | -| ``ObjectsDeviceOnEOL`` | ``FFM.Objects.Device.OnEOL`` | -| ``ObjectsDeviceOnPoweredOff`` | ``FFM.Objects.Device.OnPoweredOff`` | -| ``ObjectsDeviceOnPoweredOn`` | ``FFM.Objects.Device.OnPoweredOn`` | -| ``ObjectsDeviceOnRepaired`` | ``FFM.Objects.Device.OnRepaired`` | -| ``ObjectsRackOnDevicePlaced`` | ``FFM.Objects.Rack.OnDevicePlaced`` | -| ``ObjectsRackOnRemoved`` | ``FFM.Objects.Rack.OnRemoved`` | -| ``ObjectsServerOnClientAssigned`` | ``FFM.Objects.Server.OnClientAssigned`` | -| ``ObjectsServerOnClientUnassigned`` | ``FFM.Objects.Server.OnClientUnassigned`` | -| ``StoreCartOnCheckedOutCleared`` | ``FFM.Store.Cart.OnCheckedOut`` | -| ``StoreCartOnItemAdded`` | ``FFM.Store.Cart.OnItemAdded`` | -| ``StoreCartOnItemRemoved`` | ``FFM.Store.Cart.OnItemRemoved`` | -| ``WorldRoomOnExpanded`` | ``FFM.World.Room.OnExpanded`` | +| ``CustomerContractOnSigned`` | ``greg.Customer.Contract.OnSigned`` | +| ``CustomerReputationOnChanged`` | ``greg.Customer.Reputation.OnChanged`` | +| ``CustomerSlaOnBreached`` | ``greg.Customer.SLA.OnBreached`` | +| ``CustomerSlaOnRestored`` | ``greg.Customer.SLA.OnRestored`` | +| ``EconomyBalanceOnChanged`` | ``greg.Economy.Balance.OnChanged`` | +| ``EmployeesStaffOnHired`` | ``greg.Employees.Staff.OnHired`` | +| ``EmployeesStaffOnTerminatedCustom`` | ``greg.Employees.Staff.OnTerminated`` | +| ``FrameworkHooksOnBridgeInstalled`` | ``greg.Framework.Hooks.OnBridgeInstalled`` | +| ``FrameworkHooksOnBridgeTriggered`` | ``greg.Framework.Hooks.OnBridgeTriggered`` | +| ``GameLoadOnCompleted`` | ``greg.Game.Load.OnCompleted`` | +| ``GameSaveOnCompleted`` | ``greg.Game.Save.OnCompleted`` | +| ``GameSaveOnRequested`` | ``greg.Game.Save.OnRequested`` | +| ``GameTimeOnDayChanged`` | ``greg.Game.Time.OnDayChanged`` | +| ``GameTimeOnMonthChanged`` | ``greg.Game.Time.OnMonthChanged`` | +| ``GameXpOnGained`` | ``greg.Game.XP.OnGained`` | +| ``NetworkCableOnConnected`` | ``greg.Network.Cable.OnConnected`` | +| ``NetworkCableOnConnectedSuppress`` | ``greg.Network.Cable.OnConnected.Suppress`` | +| ``NetworkCableOnDisconnected`` | ``greg.Network.Cable.OnDisconnected`` | +| ``NetworkCableOnDisconnectedSuppress`` | ``greg.Network.Cable.OnDisconnected.Suppress`` | +| ``NetworkCableOnLinkDown`` | ``greg.Network.Cable.OnLinkDown`` | +| ``NetworkCableOnLinkUp`` | ``greg.Network.Cable.OnLinkUp`` | +| ``NetworkTrafficOnThresholdExceeded`` | ``greg.Network.Traffic.OnThresholdExceeded`` | +| ``ObjectsDeviceOnDegraded`` | ``greg.Objects.Device.OnDegraded`` | +| ``ObjectsDeviceOnEOL`` | ``greg.Objects.Device.OnEOL`` | +| ``ObjectsDeviceOnPoweredOff`` | ``greg.Objects.Device.OnPoweredOff`` | +| ``ObjectsDeviceOnPoweredOn`` | ``greg.Objects.Device.OnPoweredOn`` | +| ``ObjectsDeviceOnRepaired`` | ``greg.Objects.Device.OnRepaired`` | +| ``ObjectsRackOnDevicePlaced`` | ``greg.Objects.Rack.OnDevicePlaced`` | +| ``ObjectsRackOnRemoved`` | ``greg.Objects.Rack.OnRemoved`` | +| ``ObjectsServerOnClientAssigned`` | ``greg.Objects.Server.OnClientAssigned`` | +| ``ObjectsServerOnClientUnassigned`` | ``greg.Objects.Server.OnClientUnassigned`` | +| ``StoreCartOnCheckedOut`` | ``greg.Store.Cart.OnCheckedOut`` | +| ``StoreCartOnItemAdded`` | ``greg.Store.Cart.OnItemAdded`` | +| ``StoreCartOnItemRemoved`` | ``greg.Store.Cart.OnItemRemoved`` | +| ``WorldRoomOnExpanded`` | ``greg.World.Room.OnExpanded`` | ## Event id to hook mapping | Event id (uint) | EventIds name | Resolves to field | Hook string | |-----------------|---------------|---------------------|-------------| -| 213 | `CableCleared` | `StoreCartOnCheckedOutCleared` | `FFM.Store.Cart.OnCheckedOut` | -| 204 | `CableConnected` | `NetworkCableOnConnected` | `FFM.Network.Cable.OnConnected` | -| 211 | `CableCreated` | `NetworkCableOnConnected` | `FFM.Network.Cable.OnConnected` | -| 205 | `CableDisconnected` | `NetworkCableOnDisconnected` | `FFM.Network.Cable.OnDisconnected` | -| 212 | `CableRemoved` | `NetworkCableOnDisconnected` | `FFM.Network.Cable.OnDisconnected` | -| 215 | `CableSfpInserted` | `NetworkCableOnConnected` | `FFM.Network.Cable.OnConnected` | -| 216 | `CableSfpRemoved` | `NetworkCableOnDisconnected` | `FFM.Network.Cable.OnDisconnected` | -| 214 | `CableSpeedChanged` | `NetworkTrafficOnThresholdExceeded` | `FFM.Network.Traffic.OnThresholdExceeded` | -| 1001 | `CustomEmployeeFired` | `EmployeesStaffOnTerminatedCustom` | `FFM.Employees.Staff.OnTerminated` | -| 1000 | `CustomEmployeeHired` | `EmployeesStaffOnHiredCustom` | `FFM.Employees.Staff.OnHired` | -| 400 | `CustomerAccepted` | `CustomerContractOnSigned` | `FFM.Customer.Contract.OnSigned` | -| 401 | `CustomerSatisfied` | `CustomerSlaOnRestored` | `FFM.Customer.SLA.OnRestored` | -| 402 | `CustomerUnsatisfied` | `CustomerSlaOnBreached` | `FFM.Customer.SLA.OnBreached` | -| 300 | `DayEnded` | `GameTimeOnDayChanged` | `FFM.Game.Time.OnDayChanged` | -| 601 | `EmployeeFired` | `EmployeesStaffOnTerminated` | `FFM.Employees.Staff.OnTerminated` | -| 600 | `EmployeeHired` | `EmployeesStaffOnHired` | `FFM.Employees.Staff.OnHired` | -| 702 | `GameAutoSaved` | `GameSaveOnRequested` | `FFM.Game.Save.OnRequested` | -| 701 | `GameLoaded` | `GameLoadOnCompleted` | `FFM.Game.Load.OnCompleted` | -| 700 | `GameSaved` | `GameSaveOnCompleted` | `FFM.Game.Save.OnCompleted` | -| 1100 | `HookBridgeInstalled` | `FrameworkHooksOnBridgeInstalled` | `FFM.Framework.Hooks.OnBridgeInstalled` | -| 1101 | `HookBridgeTriggered` | `FrameworkHooksOnBridgeTriggered` | `FFM.Framework.Hooks.OnBridgeTriggered` | -| 100 | `MoneyChanged` | `EconomyBalanceOnChanged` | `FFM.Economy.Balance.OnChanged` | -| 301 | `MonthEnded` | `GameTimeOnMonthChanged` | `FFM.Game.Time.OnMonthChanged` | -| 900 | `NetWatchDispatched` | `NetworkTrafficOnThresholdExceeded` | `FFM.Network.Traffic.OnThresholdExceeded` | -| 208 | `RackUnmounted` | `ObjectsRackOnRemoved` | `FFM.Objects.Rack.OnRemoved` | -| 102 | `ReputationChanged` | `CustomerReputationOnChanged` | `FFM.Customer.Reputation.OnChanged` | -| 207 | `ServerAppChanged` | `ObjectsServerOnClientUnassigned` | `FFM.Objects.Server.OnClientUnassigned` | -| 201 | `ServerBroken` | `ObjectsDeviceOnDegraded` | `FFM.Objects.Device.OnDegraded` | -| 206 | `ServerCustomerChanged` | `ObjectsServerOnClientAssigned` | `FFM.Objects.Server.OnClientAssigned` | -| 203 | `ServerInstalled` | `ObjectsRackOnDevicePlaced` | `FFM.Objects.Rack.OnDevicePlaced` | -| 200 | `ServerPowered` | `ObjectsDeviceOnPoweredOn` | `FFM.Objects.Device.OnPoweredOn` | -| 202 | `ServerRepaired` | `ObjectsDeviceOnRepaired` | `FFM.Objects.Device.OnRepaired` | -| 502 | `ShopCartCleared` | `StoreCartOnCheckedOutCleared` | `FFM.Store.Cart.OnCheckedOut` | -| 500 | `ShopCheckout` | `StoreCartOnCheckedOut` | `FFM.Store.Cart.OnCheckedOut` | -| 501 | `ShopItemAdded` | `StoreCartOnItemAdded` | `FFM.Store.Cart.OnItemAdded` | -| 503 | `ShopItemRemoved` | `StoreCartOnItemRemoved` | `FFM.Store.Cart.OnItemRemoved` | -| 209 | `SwitchBroken` | `NetworkCableOnLinkDown` | `FFM.Network.Cable.OnLinkDown` | -| 210 | `SwitchRepaired` | `NetworkCableOnLinkUp` | `FFM.Network.Cable.OnLinkUp` | -| 800 | `WallPurchased` | `WorldRoomOnExpanded` | `FFM.World.Room.OnExpanded` | -| 101 | `XPChanged` | `GameXpOnGained` | `FFM.Game.XP.OnGained` | +| 213 | `CableCleared` | `StoreCartOnCheckedOutCleared` | `greg.Store.Cart.OnCheckedOut` | +| 204 | `CableConnected` | `NetworkCableOnConnected` | `greg.Network.Cable.OnConnected` | +| 211 | `CableCreated` | `NetworkCableOnConnected` | `greg.Network.Cable.OnConnected` | +| 205 | `CableDisconnected` | `NetworkCableOnDisconnected` | `greg.Network.Cable.OnDisconnected` | +| 212 | `CableRemoved` | `NetworkCableOnDisconnected` | `greg.Network.Cable.OnDisconnected` | +| 215 | `CableSfpInserted` | `NetworkCableOnConnected` | `greg.Network.Cable.OnConnected` | +| 216 | `CableSfpRemoved` | `NetworkCableOnDisconnected` | `greg.Network.Cable.OnDisconnected` | +| 214 | `CableSpeedChanged` | `NetworkTrafficOnThresholdExceeded` | `greg.Network.Traffic.OnThresholdExceeded` | +| 1001 | `CustomEmployeeFired` | `EmployeesStaffOnTerminatedCustom` | `greg.Employees.Staff.OnTerminated` | +| 1000 | `CustomEmployeeHired` | `EmployeesStaffOnHiredCustom` | `greg.Employees.Staff.OnHired` | +| 400 | `CustomerAccepted` | `CustomerContractOnSigned` | `greg.Customer.Contract.OnSigned` | +| 401 | `CustomerSatisfied` | `CustomerSlaOnRestored` | `greg.Customer.SLA.OnRestored` | +| 402 | `CustomerUnsatisfied` | `CustomerSlaOnBreached` | `greg.Customer.SLA.OnBreached` | +| 300 | `DayEnded` | `GameTimeOnDayChanged` | `greg.Game.Time.OnDayChanged` | +| 601 | `EmployeeFired` | `EmployeesStaffOnTerminated` | `greg.Employees.Staff.OnTerminated` | +| 600 | `EmployeeHired` | `EmployeesStaffOnHired` | `greg.Employees.Staff.OnHired` | +| 702 | `GameAutoSaved` | `GameSaveOnRequested` | `greg.Game.Save.OnRequested` | +| 701 | `GameLoaded` | `GameLoadOnCompleted` | `greg.Game.Load.OnCompleted` | +| 700 | `GameSaved` | `GameSaveOnCompleted` | `greg.Game.Save.OnCompleted` | +| 1100 | `HookBridgeInstalled` | `FrameworkHooksOnBridgeInstalled` | `greg.Framework.Hooks.OnBridgeInstalled` | +| 1101 | `HookBridgeTriggered` | `FrameworkHooksOnBridgeTriggered` | `greg.Framework.Hooks.OnBridgeTriggered` | +| 100 | `MoneyChanged` | `EconomyBalanceOnChanged` | `greg.Economy.Balance.OnChanged` | +| 301 | `MonthEnded` | `GameTimeOnMonthChanged` | `greg.Game.Time.OnMonthChanged` | +| 900 | `NetWatchDispatched` | `NetworkTrafficOnThresholdExceeded` | `greg.Network.Traffic.OnThresholdExceeded` | +| 208 | `RackUnmounted` | `ObjectsRackOnRemoved` | `greg.Objects.Rack.OnRemoved` | +| 102 | `ReputationChanged` | `CustomerReputationOnChanged` | `greg.Customer.Reputation.OnChanged` | +| 207 | `ServerAppChanged` | `ObjectsServerOnClientUnassigned` | `greg.Objects.Server.OnClientUnassigned` | +| 201 | `ServerBroken` | `ObjectsDeviceOnDegraded` | `greg.Objects.Device.OnDegraded` | +| 206 | `ServerCustomerChanged` | `ObjectsServerOnClientAssigned` | `greg.Objects.Server.OnClientAssigned` | +| 203 | `ServerInstalled` | `ObjectsRackOnDevicePlaced` | `greg.Objects.Rack.OnDevicePlaced` | +| 200 | `ServerPowered` | `ObjectsDeviceOnPoweredOn` | `greg.Objects.Device.OnPoweredOn` | +| 202 | `ServerRepaired` | `ObjectsDeviceOnRepaired` | `greg.Objects.Device.OnRepaired` | +| 502 | `ShopCartCleared` | `StoreCartOnCheckedOutCleared` | `greg.Store.Cart.OnCheckedOut` | +| 500 | `ShopCheckout` | `StoreCartOnCheckedOut` | `greg.Store.Cart.OnCheckedOut` | +| 501 | `ShopItemAdded` | `StoreCartOnItemAdded` | `greg.Store.Cart.OnItemAdded` | +| 503 | `ShopItemRemoved` | `StoreCartOnItemRemoved` | `greg.Store.Cart.OnItemRemoved` | +| 209 | `SwitchBroken` | `NetworkCableOnLinkDown` | `greg.Network.Cable.OnLinkDown` | +| 210 | `SwitchRepaired` | `NetworkCableOnLinkUp` | `greg.Network.Cable.OnLinkUp` | +| 800 | `WallPurchased` | `WorldRoomOnExpanded` | `greg.World.Room.OnExpanded` | +| 101 | `XPChanged` | `GameXpOnGained` | `greg.Game.XP.OnGained` | ## Fallback -Unknown event ids resolve to ``FFM.Framework.Unknown.OnEvent`` in `HookNames.Resolve`. +Unknown event ids resolve to ``greg.Framework.Unknown.OnEvent`` in `HookNames.Resolve`. ## See also - [FMF hook naming](./fmf-hook-naming.md) -- [EventIds source](https://github.com/mleem97/gregFramework/blob/master/framework/FrikaMF/EventIds.cs) -- [HookNames source](https://github.com/mleem97/gregFramework/blob/master/framework/FrikaMF/HookNames.cs) +- [EventIds source](https://github.com/mleem97/gregFramework/blob/main/gregCore/FrikaMF/EventIds.cs) +- [HookNames source](https://github.com/mleem97/gregFramework/blob/main/gregCore/FrikaMF/HookNames.cs) +- [Greg hooks & event runtime](/wiki/framework/greg-hooks-and-events) diff --git a/docs/reference/greg-hooks-registry.md b/docs/reference/greg-hooks-registry.md new file mode 100644 index 0000000..6ab265f --- /dev/null +++ b/docs/reference/greg-hooks-registry.md @@ -0,0 +1,80 @@ +--- +id: greg-hooks-registry +title: greg.* hooks registry (IL2CPP) +slug: /reference/greg-hooks-registry +description: greg_hooks.json, Harmony hook sources under gregCore, regeneration from Il2Cpp unpack, and overlap with Rust bridge patches. +--- + +# greg.* hooks registry (IL2CPP) + +This page documents the **canonical C# / MelonLoader hook surface** for *Data Center* IL2CPP interop: stable string ids, JSON registry, generated Harmony patches, and how they coexist with the existing Rust FFI bridge. + +## Canonical hook ids + +Runtime identifiers follow: + +```text +greg.. +``` + +- **`greg`** — fixed prefix (never `FMF`, `FFM`, or product-specific spellings in new APIs). +- **``** — uppercase segment from `GregDomain` (`PLAYER`, `EMPLOYEE`, `NETWORK`, `UI`, `SYSTEM`, …). Same logical areas as the framework domain model; see `GregHookName` in **gregFramework** sources. +- **``** — `PascalCase` verb or noun phrase (`MoneyChanged`, `Hired`, `ComponentInitialized`, …). + +Always build ids with `GregHookName.Create(GregDomain.*, "Action")` in mods — do not concatenate raw strings. + +## Registry file: `greg_hooks.json` + +| Location | Role | +|----------|------| +| **Repo root** `greg_hooks.json` | Source of truth checked into **gregFramework**; documents every emitted hook (`name`, `patchTarget`, `strategy`, `payloadSchema`, optional `legacy`). | +| **Next to `FrikaModdingFramework.dll`** (build output) | Copy via `FrikaMF.csproj` (`gregCore/framework/gregFramework/greg_hooks.json`) so `GregCompatBridge` can resolve legacy ids at runtime. | + +The file is **generated**; edit the generator or whitelist (see below), then re-run the script — do not hand-edit hundreds of entries unless you are fixing metadata only. + +## Code layout (gregFramework repo) + +| Path | Purpose | +|------|---------| +| `gregCore/Core/` | `GregDomain`, `GregHookName`, `GregEventDispatcher`, `GregCompatBridge`, `GregPayload` | +| `gregCore/Hooks/` | `GregPlayerHooks`, `GregEmployeeHooks`, … — Harmony postfix patches compiled into the MelonLoader plugin | +| `gregCore/scripts/Generate-GregHooksFromIl2CppDump.ps1` | Regenerates `greg_hooks.json` and all `Greg*Hooks.cs` files | + +The main plugin project (`gregCore/framework/FrikaMF.csproj`) references `..\Core\**\*.cs` and `..\Hooks\**\*.cs`. Harmony discovers any type in that assembly marked with `[HarmonyPatch]` (see `Core.ApplyHarmonyPatchesWithDiagnostics`). + +## Regeneration pipeline + +1. **Source of truth for patchable signatures** — Il2CppInterop C# under `gregReferences/il2cpp-unpack/Assembly-CSharp/Il2Cpp/*.cs` (stand-in when a single-file `MergedCode.md` dump is not in the repo). +2. Run from repo root (PowerShell): + + ```powershell + pwsh -NoProfile -File gregCore/scripts/Generate-GregHooksFromIl2CppDump.ps1 + ``` + +3. Rebuild **FrikaMF** so hooks and copied JSON match. + +### Generator behaviour (summary) + +- Emits **postfix** Harmony stubs with `GregEventDispatcher.Emit` and try/catch around each emit. +- Skips high-frequency Unity loops (`Update`, `FixedUpdate`, `LateUpdate`, `OnUpdate`), coroutine `IEnumerator` entrypoints, property accessors, and obvious IL2CPP noise (`codegen`, `MethodInternalStatic`, …). +- Skips **ECS-heavy** signatures unless Unity.Entities (and related) references are added to the project (`Entity`, `EntityCommandBuffer`, `SystemState`, `BlobArray`, …). +- Skips additional interop-only types where the project lacks references (e.g. some `Unity.InputSystem`, UI event types) — extend `Test-SkipInteropSignature` or add references when you need those patches. +- **Overload policy:** only the **first** overload per `Type|MethodName` per file is emitted (Harmony `nameof` ambiguity otherwise). +- **Whitelist (`gameHookClasses`)** — keeps the **FrikaMF** build green without pulling the entire game surface into scope; expand the list in the script when you add assembly references for more types. +- **Harmony exclusion set** — parses `gregCore/framework/FrikaMF/HarmonyPatches.cs` for `HarmonyPatch(typeof(...), nameof(...))` / string method names so **Rust bridge patches are not duplicated** by generated `Greg*Hooks` (e.g. `Player.UpdateCoin` stays owned by the hand-written patch that already forwards to `GregEventDispatcher`). + +## Mod author entry points + +- [Greg hooks showcase](/wiki/guides/mod-developers/greg-hooks-showcase) — subscribe to `greg.*`, use `GregPayload`, optional cancelable flows where the bridge exposes them. +- [FMF hook naming](/wiki/reference/fmf-hook-naming) — older **`FMF.*` / `FFM.*`** string catalog and domain policy for *documentation* constants; runtime IL2CPP Harmony surface is **`greg.*`** as above. +- [FMF hooks catalog](/wiki/reference/fmf-hooks-catalog) — generated table from legacy `HookNames` / `EventIds` sources (distinct from `greg_hooks.json`). + +## Legacy hook ids + +`GregCompatBridge` loads optional `legacy` → `name` mappings from `greg_hooks.json` next to the assembly. Populate `legacy` only when you intentionally support old spellings; keep new public API strictly on **`greg.*`**. + +## See also + +- [FFI, hooks & Lua](/wiki/topics/ffi-and-hooks/overview) +- [Framework architecture](/wiki/framework/architecture) +- [Reference & technical hub](/wiki/topics/reference/overview) diff --git a/docs/reference/reference-data-files.md b/docs/reference/reference-data-files.md index 7a241aa..296a31d 100644 --- a/docs/reference/reference-data-files.md +++ b/docs/reference/reference-data-files.md @@ -31,6 +31,16 @@ $gzip.CopyTo($out) $gzip.Dispose(); $out.Dispose(); $in.Dispose() ``` +## JSON hook registry (gregFramework) + +The **gregFramework** repo also ships a **structured** hook list for IL2CPP Harmony patches: + +- **Path:** `greg_hooks.json` at repo root (and a build-staged copy under `gregCore/framework/gregFramework/`). +- **Purpose:** canonical `greg..` ids, `patchTarget`, `payloadSchema`, and optional `legacy` aliases for `GregCompatBridge`. +- **Docs:** [greg hooks registry (IL2CPP)](/wiki/reference/greg-hooks-registry). + +This file is **generated** from Il2CppInterop sources; it is not one of the gzip archives above. + ## Pipeline usage - Prefer reading `.gz` directly from scripts when possible. diff --git a/docs/topics/ffi-and-hooks/overview.md b/docs/topics/ffi-and-hooks/overview.md index c8f6f25..62d25a9 100644 --- a/docs/topics/ffi-and-hooks/overview.md +++ b/docs/topics/ffi-and-hooks/overview.md @@ -11,5 +11,6 @@ The framework is intended to act as a **hook proxy**: Unity / IL2CPP events are - [FMF hooks](/wiki/framework/fmf-hooks) — generated hook surface - [FMF hooks catalog](/wiki/reference/fmf-hooks-catalog) — strings from core sources - [FMF hook naming](/wiki/reference/fmf-hook-naming) — `FMF.*` vs legacy `FFM.*` +- [greg hooks registry (IL2CPP)](/wiki/reference/greg-hooks-registry) — `greg_hooks.json`, `Greg*Hooks` Harmony emitters, regeneration script - [Framework architecture](/wiki/framework/architecture) — bridges (including Rust) and runtime layout - [Modding language requirement](/wiki/reference/modding-language-requirement) — C# policy for mods/plugins diff --git a/docs/topics/index.md b/docs/topics/index.md index 0867524..8e500c4 100644 --- a/docs/topics/index.md +++ b/docs/topics/index.md @@ -16,7 +16,7 @@ Documentation is **curated** in this repository: guides, framework articles, ref |------|------------| | **Roles** | [By audience](/wiki/guides/players/audiences-overview) — [End users](/wiki/guides/players/overview), [Mod developers](/wiki/guides/mod-developers/overview), [Contributors (workflow)](/wiki/guides/contributors/topics-overview), [Sponsors](/wiki/guides/sponsors/overview) | | **Experience paths** | [Newbies](/wiki/audiences/newbies) · [Intermediates](/wiki/audiences/intermediates) · [Professionals](/wiki/audiences/professionals) | -| **Technical reference** | [Reference & technical](/wiki/topics/reference/overview) | +| **Technical reference** | [Reference & technical](/wiki/topics/reference/overview) — includes [greg IL2CPP hook registry](/wiki/reference/greg-hooks-registry) | | **Ship planning** | [Roadmap & planning](/wiki/topics/roadmap/overview) | | **Repository inventory** | [Repo inventory](/wiki/contributors/repo-inventory) | | **Steam, betas, backlog, game paths** | [Meta & operations](/wiki/topics/meta/overview) — [Game folder layout](/wiki/topics/meta/game-folder-layout) | diff --git a/docs/topics/reference/overview.md b/docs/topics/reference/overview.md index 2348daf..2c7723e 100644 --- a/docs/topics/reference/overview.md +++ b/docs/topics/reference/overview.md @@ -13,6 +13,7 @@ Authoritative reference material for the framework and documentation site. - [Modding language (C# only)](/wiki/reference/modding-language-requirement) — mods, plugins, extensions: **C#** only. - [FMF hook naming](/wiki/reference/fmf-hook-naming) — conventions for hook identifiers. - [FMF hooks catalog](/wiki/reference/fmf-hooks-catalog) — generated listing from framework sources. +- [greg hooks registry (IL2CPP)](/wiki/reference/greg-hooks-registry) — `greg.*` Harmony hooks, `greg_hooks.json`, codegen from Il2Cpp unpack. - [Release channels](/wiki/reference/release-channels) — how builds are staged. See also [FFI, hooks & Lua](/wiki/topics/ffi-and-hooks/overview) for imported deep dives from the legacy wiki. diff --git a/sidebars.js b/sidebars.js index eb0e836..4f310dd 100644 --- a/sidebars.js +++ b/sidebars.js @@ -27,7 +27,12 @@ const sidebars = { { type: 'category', label: 'Framework', - items: ['framework/architecture', 'framework/fmf-hooks', 'framework/hexmod'], + items: [ + 'framework/architecture', + 'framework/greg-hooks-and-events', + 'framework/fmf-hooks', + 'framework/hexmod', + ], }, { type: 'category', @@ -141,6 +146,7 @@ const sidebars = { 'reference/wiki-mapping', 'reference/mod-store-vision', 'reference/fmf-hook-naming', + 'reference/greg-hooks-registry', 'reference/fmf-hooks-catalog', 'reference/mcp-server', 'reference/reference-data-files',