Developer Best Practices
The rules that keep multi-mod setups stable. (Oxide equivalent: “Plugin Guidelines” + “Best Practices” + “Permissions”.)
1. Dependencies, not assumptions
Section titled “1. Dependencies, not assumptions”greg.mods.list() -- {{id, name, version}}greg.mods.is_loaded("other_mod") -- -> boolgreg.mods.version("other_mod") -- -> stringgreg.mods.declare({{mod = "other_mod", min_version = "1.0.0", required = true}})local ok, detail = greg.mods.ensure({mod = "other_mod", min_version = "1.0.0"})greg.mods.check() -- {{owner, mod, detail}}; empty = okC#: [GregDependsOn("gregCore", "1.2.3")] + GregModDeps.Declare / EnsureLoaded / CheckAll. Report missing deps in the log + Hub instead of throwing. There is no Oxide-style permission/group system — gating is per-mod via these declarations and your own settings.
2. Performance
Section titled “2. Performance”- No per-frame reflection or
FindObjectsOfType; cache + throttle (0.1 s / 1 s / 2 s / 30 s). - No per-frame logging; batch notifications (
greg.ui.notify). - Prefer event-state over polling; prefer automation engines over reimplemented loops.
- Full rules: Developer Harmony IL2CPP, Developer Timers Coroutines.
3. Saves and identity
Section titled “3. Saves and identity”- Settings → config, state → save/sidecar, bulk →
data/sandbox (Developer Data Storage). - Address devices via inventory UIDs, never display names (Developer Hardware IDs Inventory).
- Never reuse IDs/GUIDs; one bad entry must never abort a load; test save→load→uninstall→load-vanilla.
4. UI honesty
Section titled “4. UI honesty”- Every Hub entry needs a truthful Open/Close affordance (
HasOpener/HasCloser); every HUD row maps to a real hotkey (Developer UI Panels HUD). - Lock input only while open; restore cursor/movement after; ignore toggles during Pause/Escape/Options.
5. Co-op + sandbox discipline
Section titled “5. Co-op + sandbox discipline”- Local-only; no second transport (Developer Native Coop).
- Lua: no world spawning, no cable ops, no keyboard capture, no escapes from
<modId>/data/— move those to C#. requireonly your folder +@shared; no circular requires.
6. Diagnostics before release
Section titled “6. Diagnostics before release”GregDoctorclean;[DynamicPatcher]shows your patches applied; no[gregCore][HwId]error spam.scripts/validate_contracts.pyfor hook coverage claims;python3 scripts/validate_version.py <VERSION>;dotnet testgreen..codacy/local scan (lizard,opengrep,pylint,trivy) before the PR — no duplicate CI run exists.- Ship with: unique mod ID,
min_framework_version, README (events you emit, settings, co-op scope), CHANGELOG entry.