IMPORTANT — Living document
This file is the source of truth for the technical and functional specification of the GLMod project. It MUST be consulted before any modification of the project (new feature, refactor, bug fix, dependency bump, etc.). It MUST be kept up to date whenever the project evolves:
- Addition / removal / rename of a service, entity, enum, or constant.
- Change of the targeted Among Us version, .NET, BepInEx, or any dependency.
- Change of the Good Loss API contract (endpoints, payloads, RPC codes).
- Change of the folder structure or naming conventions.
- Addition or modification of a Harmony patch.
- Any change to the game flow (GameStep, validation steps, RPC).
If a PR introduces a change that is not reflected here, the PR MUST be considered incomplete.
The entire project is written and maintained in English. No exceptions.
This rule applies to:
- Source code: identifiers (classes, methods, fields, properties, variables, parameters), file names, namespaces.
- Comments: single-line (
//), multi-line (/* */), and XML doc comments (///). - Log messages sent via
GLMod.log(...),_logger.LogInfo(...), or any logging facility. - String literals used for diagnostics, errors, and developer-facing messages.
- Commit messages, branch names, PR titles, and PR descriptions.
- Documentation: this
CLAUDE.md,README.md,docs/dev.MD, and any other repository documentation. - Configuration keys in BepInEx config files.
- Auto-generated files:
GLMod/Properties/Resources.Designer.csis regenerated by Visual Studio in the developer's UI culture. Do not hand-edit; if it must be regenerated, do so on a machine configured with English UI.
Any code review MUST reject contributions that introduce non-English identifiers, comments, or developer-facing strings. When updating existing code, opportunistically translate any leftover non-English content you encounter.
- Name: GLMod (Good Loss Mod)
- Current version:
5.4.0(see GLMod/GLMod.csproj and GLMod/GLMod.cs) - BepInEx plugin Id:
glmod - Author: Matux
- License: GNU GPLv3
- Repository: https://github.com/MatuxGG/GLMod
- Remote service: Good Loss — Discord: https://goodloss.fr/discord
GLMod is an open source mod for Among Us that collects match data and uploads it to the Good Loss platform in order to:
- Provide a complete match history per player.
- Compute and display detailed statistics (kills, exiles, votes, tasks, etc.).
- Maintain a ranking system (ranks) per mod.
- Enable third-party integration: other Among Us mods can override GLMod to record their custom roles and actions.
- Game OS: Windows and Linux (via Proton/Wine).
- Platform: Steam only (identification is based on
SteamID). No other platform (Epic, mobile, console) is supported. - Targeted Among Us version: see
<GameVersion>in GLMod/GLMod.csproj (currently2026.3.31). The README documents the downloadable release version (must be synchronized with every release). - Runtime: .NET 6.0 (
net6.0).
- BepInEx (IL2CPP) — Plugin injection framework for Unity IL2CPP.
- HarmonyLib — Runtime patching of Among Us methods.
- Il2CppInterop.Runtime — Managed C# ↔ IL2CPP bridge.
- Steamworks.NET — Reads the local SteamID.
- Hazel — Among Us internal network RPC system.
- UnityEngine — Coroutines, GameObjects, MonoBehaviour.
- System.Text.Json — Serialization / deserialization of API payloads.
The required DLLs are referenced via wildcard in the csproj:
<Reference Include="..\Among Us\BepInEx\core\*.dll" />
<Reference Include="..\Among Us\BepInEx\interop\*.dll" />GLMod follows a service-oriented architecture with:
- Interfaces in
GLMod/Services/Interfaces/(contracts). - Implementations in
GLMod/Services/Implementations/(logic). - Manual dependency injection in
GLMod.Load()(GLMod/GLMod.cs). - Static access from the outside via the static properties of the
GLModclass (e.g.GLMod.AuthService,GLMod.GameStateManager).
BasePlugin.Load()is invoked by BepInEx when the game starts.InitializeConfiguration()— binds the BepInExConfigEntry<string>instances (BepInEx/config/glmod.cfg).InitializeServices()— instantiates the services (order matters, see dependencies below).VerifyStartupServices()— logs the status of each service.ConfigureDefaultSettings()— enables the default services (see §3.3).CoroutineRunner.Init()— creates a persistentDontDestroyOnLoadGameObject to run coroutines from outsideMonoBehaviours.Harmony.PatchAll()— applies all Harmony patches from theGLMod.EventPatchnamespace.
AuthenticationService ← ManualLogSource, ConfigEntry<string> connectionState
ConfigurationService ← ManualLogSource, configPath
GameStateManager ← Logger, AuthService, ConfigService, apiEndpoint, stepRpc
ServiceManager ← (none)
ItemService ← Logger, AuthService, apiEndpoint
RankService ← Logger, AuthService, ConfigService, apiEndpoint
IntegrityService ← Logger, apiEndpoint
MapService ← Logger
- API calls use Unity coroutines (
IEnumerator) to remain compatible with the Unity main thread. - The bridge between
Task-based async work and coroutines is centralized in GLMod/Class/CoroutineHelpers.cs (RunAsync<T>/RunAsync). It encapsulates theTask.Run+ volatiledoneflag +yield return nullpattern. Do not re-implement this pattern elsewhere. - See GLMod/Class/ApiService.cs (
PostFormAsync,PostFormWithErrorHandlingAsync) for typical usage. IIntegrityServiceadditionally exposes async/await variants (*Async) for consumers running outside a Unity context.CoroutineRunner(GLMod/Class/CoroutineRunner.cs) is aMonoBehavioursingleton registered in IL2CPP viaClassInjector.RegisterTypeInIl2Cpp.
Every service is exposed statically via the main GLMod class and has a dedicated interface.
3.1 IAuthenticationService — Interfaces/IAuthenticationService.cs
- Role: handle Steam → Good Loss authentication.
- Endpoint:
POST {API}/user/loginwithsteamId. - HTTP codes:
200→ token returned inresponse.Content.403+ body prefixed"Banned: "→ user is banned, reason follows the prefix.- Others → silent failure.
- Exposed state:
Token,IsLoggedIn,IsBanned,BanReason.
3.2 IServiceManager — Interfaces/IServiceManager.cs
- Role: enable / disable data collectors (see enum
ServiceType). - Services enabled by default at startup (
ConfigureDefaultSettings):StartGame,EndGame,Tasks,TasksMax,Exiled,Kills,BodyReported,Emergencies,Turns,Votes,Roles,Shield.
- A third-party mod can disable a service to override its behaviour (see
docs/dev.MD).
3.3 IGameStateManager — Interfaces/IGameStateManager.cs
- Role: state machine of the match lifecycle + uploads game data to the API.
- Properties:
CurrentGame(GLGame),Step(GameStep),GameCode,GameMap. - Key methods:
StartGame(code, map, ranked)— initializes aGLGame.SetRanked(ranked)— updates the ranked flag on the current game (boolsetter; stored as"0"/"1").AddPlayer(name, role, team, color)— adds a player to the current match.SendGame(onComplete)— uploads the match to the API (coroutine).SyncGameId(onComplete)— broadcasts the match ID to non-hosts via RPC.AddMyPlayer(onComplete)— registers the local player on the server.GetShieldPlayer(onComplete, onError)— returns the player who would have benefited from a T1 shield (retries on HTTP 400).SetWinnerTeams(winners)/AddWinnerPlayer(name)— sets the outcome.EndGame()— closes the match server-side.AddAction(source, target, action)— records an action (kill, vote, sabotage, custom…).ResetGame()— resets the state (Step = Initial).
3.4 IItemService — Interfaces/IItemService.cs
- Role: fetch unlocked items (achievements) and owned Steam DLCs.
- Methods:
ReloadItems(),IsUnlocked(id),ReloadDlcOwnerships(),HasDlc(appId).
3.5 IRankService — Interfaces/IRankService.cs
- Role: fetch a player rank for a given mod.
- Method:
GetRank(modName, onComplete)—modName = null⇒ uses the current mod.
3.6 IIntegrityService — Interfaces/IIntegrityService.cs
- Role: verify DLL integrity via remote checksum.
- Endpoints:
POST {API}/data,POST {API}/checksum. - Methods:
- Coroutines:
GetApiData,GetChecksum,VerifyDll,VerifyGLMod. - Async:
GetApiDataAsync,GetChecksumAsync,VerifyDllAsync,VerifyGLModAsync.
- Coroutines:
3.7 IConfigurationService — Interfaces/IConfigurationService.cs
- Role: determine the host mod name.
- Logic:
FindModName()scansBepInEx/config/*.glmod. If no.glmodfile is found,ModName = "Vanilla". - Manual override:
SetModName(modName)(used by third-party mods in theirLoad()).
3.8 IMapService — Interfaces/IMapService.cs
- Role: resolve the current map name.
- Logic: reads
GameOptionsManager.Instance.currentGameOptions.MapId, maps it viaGameMapType+ special caseDleks → "dlekSehT".
| Class | Role |
|---|---|
GLGame |
Match model: id, code, map, modName, ranked, winner, turns, players, actions. |
GLPlayer |
Player model: login, playerName, role, team, tasks, tasksDead, tasksMax, win, positions, color. |
GLAction |
Collected action: turn, source, target, action, triggerTimeMs. |
GLPosition |
Spatial position (x, y) at a given time for a player, indexed by turn. |
GLItem |
Unlocked item: id, name. |
GLRank |
Rank: id, name, link, percent, error. |
GLData / GLDataList |
Generic key/value wrappers for API responses. |
GLJson |
Static helpers Serialize<T> / Deserialize<T> (System.Text.Json) with try/catch + log. |
Note: every numeric property transiting through the API is encoded as
string(tasks = "0",ranked = "1", etc.). This convention matches the Good Loss API protocol and must not be changed without coordination with the API team.
ServiceType — Enums/ServiceType.cs
StartGame, EndGame, Tasks, TasksMax, Exiled, Kills,
BodyReported, Emergencies, Turns, Votes, Roles, Shield
GameStep — Enums/GameStep.cs
Initial (0) → PlayersAdded (1) → GameSent (2) → GameIdSynced (3)
→ PlayersRecorded (4) → WinnerSet (5)
GameMapType — Enums/GameMapType.cs
Unknown, TheSkeld (0), MiraHQ (1), Polus (2), Airship (4), TheFungle (5)
Special case: Dleks → display "dlekSehT".
SabotageType — Enums/SabotageType.cs
Reactor, Coms, Lights, O2
| Constant | Value |
|---|---|
API_ENDPOINT |
https://goodloss.fr/api |
SUPPORT_ID_CHARS |
A-Za-z1-9 (no 0) |
SUPPORT_ID_LENGTH |
10 |
RPC_SYNC_TIMEOUT |
5.0f seconds |
BACKGROUND_POLLING_INTERVAL |
0.5f seconds |
RPC_POLLING_INTERVAL |
0.1f seconds |
DEFAULT_GAME_CODE |
XXXXXX |
DEFAULT_MAP_NAME |
Unknown |
ACTION_PREFIX_DC_PROCESS |
DC_PROCESS_ (background-detected DC) |
ACTION_PREFIX_DC_INTERNAL |
DC_INTERNAL_ (RPC DisconnectInternal) |
ACTION_PREFIX_DC_HANDLE |
DC_HANDLE_ (RPC HandleDisconnect) |
ACTION_PREFIX_DC_ON |
DC_ON_ (RPC OnDisconnect) |
ACTION_PREFIX_SAB_START |
SAB_START_ (suffixed by sabotage type) |
ACTION_PREFIX_SAB_END |
SAB_END_ (suffixed by sabotage type) |
Patches are applied automatically via Harmony.PatchAll() at the end of Load(). Each file contains classes decorated with [HarmonyPatch(...)].
| File | Main targets |
|---|---|
AmongUsClientPatch.cs |
Hooks on the Among Us network client (host/non-host). |
InnerNetClientPatch.cs |
RPC reception. |
MainMenuManagerPatch.cs |
Post-main-menu initialization. |
PlayerControlPatch.cs |
Player actions (kill, report, vote, tasks…). |
MeetingHudPatch.cs |
Meeting cycle (vote, exile). |
ExileControllerPatch.cs |
Exile animation and turn rollover. |
RPC.cs |
Manages CustomRPC 240 (HandleRpc). Contains GLRPCProcedure.makeRpcCall and handleRpc. |
- Reserved ID:
240(CustomRPC.HandleRpc). - Payload format:
int id,int count, thencount×string value. - Known RPC cases (see
RPC.cs):1: non-hosts receive the matchGameId.2:DisconnectInternal→ builds reasonDC_INTERNAL_<value>.3:HandleDisconnect→ builds reasonDC_HANDLE_<value>.4:OnDisconnect→ builds reasonDC_ON_<value>.- (additional cases must be documented as they are added — update this table).
Any new RPC ID must be reserved here before implementation to prevent collisions.
| File | Role |
|---|---|
HttpHelper.cs |
Shared static HttpClient, proxy disabled. |
ApiService.cs |
PostFormAsync, PostFormWithErrorHandlingAsync, ApiResponse type. |
CoroutineHelpers.cs |
RunAsync / RunAsync<T> — async-task ↔ coroutine bridge. Use these instead of re-implementing the Task.Run + volatile done flag pattern. |
CoroutineRunner.cs |
MonoBehaviour IL2CPP singleton used to run coroutines from static classes. |
ServiceLogger.cs |
Log(logger, serviceName, message) — shared log formatter producing [GLMod][Service] PlayerName: message. Every service must delegate to it. |
BackgroundEvents.cs |
Background loop: watches DCs, hidden sabotages, etc. |
VanillaEvents.cs |
Default implementations (startGameVanilla, endGameVanilla…) used when the matching ServiceType is enabled. |
| Section | Key | Description |
|---|---|---|
GoodLoss |
Connected |
Persisted connection state. |
GoodLoss |
Enabled |
"Yes" / "No" — global mod toggle. |
GoodLoss |
Support Id |
10-character support id, generated once. |
Validation |
steps |
Must be "YES" after a complete match. |
Validation |
RPC |
Must be "YES" (with history) after a complete match. |
A file BepInEx/config/<MODNAME>.glmod (empty) at the root of the config folder serves as a host-mod marker: its name (without extension) becomes ConfigService.ModName.
Base: https://goodloss.fr/api
| Endpoint | Method | Service | Usage |
|---|---|---|---|
/user/login |
POST | AuthService | Steam login. |
/user/steamownerships |
POST | ItemService | Steam DLC ownerships. |
/data |
POST | IntegrityService | Generic data lookup by id. |
/checksum |
POST | IntegrityService | Checksum retrieval. |
/game/start |
POST | GameStateManager | Sends a new match. |
/game/addMyPlayer |
POST | GameStateManager | Registers the local player. |
/game/getShieldPlayer |
POST | GameStateManager | Returns the T1 shield candidate. |
/game/end |
POST | GameStateManager | Finalizes a match. |
/player/challengerItems |
POST | ItemService | Player's unlocked items. |
/player/rank |
POST | RankService | Player rank by mod. |
Keep up to date: every endpoint added to or removed from the project must be reflected in this table.
- Recommended IDE: Visual Studio 2022.
- SDK: .NET 6.0.
dotnet build --configuration Debugat the repo root.dotnet test GLMod.Tests/GLMod.Tests.csproj --configuration Debugto run the unit-test suite.- An
AfterTargets="Build"step copiesGLMod.dlltoAmong Us/BepInEx/plugins/(Debug only) — see GLMod/GLMod.csproj.
- GitHub Actions: .github/workflows/main.yml.
- Trigger: push & PR on
main. - Single job:
dotnet restore+dotnet build --configuration Debug. - Unit tests (xUnit, in GLMod.Tests/) are runnable locally; the CI workflow does not invoke
dotnet testyet.
- Test framework: xUnit (GLMod.Tests/GLMod.Tests.csproj).
- Scope: pure logic — entities (
GLGame,GLPlayer,GLPosition), enums (SabotageType,GameMapType),ServiceManager, andGameConstantsinvariants. Anything that touches IL2CPP / Among Us types stays untestable until further decoupling. - Add new tests for any new pure-logic surface. Refactor toward injectable abstractions before adding tests that would otherwise require IL2CPP mocking.
- Build driven by build.cake (Cake).
- Version is derived from the Git tag (
refs/tags/X.Y.Z) or a CI suffix. - Iterates over
GamePlatform = Steam | Itch(multi-build).
GLMod/ # Repo root
├── .editorconfig # Style rules (IDE0002 disabled).
├── .github/workflows/main.yml # .NET 6 CI pipeline.
├── .gitignore # The "Among Us/" folder is ignored.
├── build.cake # Multi-platform release build script.
├── CLAUDE.md # ← THIS FILE. Living project spec.
├── GLMod.sln # Visual Studio solution.
├── LICENSE # GPLv3.
├── README.md # End-user documentation.
├── docs/
│ └── dev.MD # Integration guide for third-party modders.
├── Among Us/ # (gitignored) Local install used for debugging.
│ └── BepInEx/ # Core + interop DLLs (referenced by csproj).
├── GLMod.Tests/ # xUnit test project for pure-logic types.
│ ├── GLMod.Tests.csproj
│ ├── EntityTests.cs
│ ├── EnumTests.cs
│ ├── GameConstantsTests.cs
│ └── ServiceManagerTests.cs
└── GLMod/ # C# project.
├── GLMod.csproj # Project definition, mod version, targeted Among Us version.
├── GLMod.cs # Plugin entry point + static facade.
├── Class/ # Cross-cutting helpers (non-services).
│ ├── ApiService.cs
│ ├── BackgroundEvents.cs
│ ├── CoroutineHelpers.cs # Async-task ↔ coroutine bridge.
│ ├── CoroutineRunner.cs
│ ├── HttpHelper.cs
│ ├── ServiceLogger.cs # Shared [GLMod][Service] log formatter.
│ └── VanillaEvents.cs
├── Constants/
│ └── GameConstants.cs # Global constants (API, timeouts, defaults).
├── Enums/
│ ├── GameMapType.cs # + GameMapTypeExtensions.
│ ├── GameStep.cs
│ ├── SabotageType.cs # + SabotageTypeExtensions.
│ └── ServiceType.cs
├── EventPatch/ # Harmony patches — one file per patched Among Us target.
│ ├── AmongUsClientPatch.cs
│ ├── ExileControllerPatch.cs
│ ├── InnerNetClientPatch.cs
│ ├── MainMenuManagerPatch.cs
│ ├── MeetingHudPatch.cs
│ ├── PlayerControlPatch.cs
│ └── RPC.cs # CustomRPC + handleRpc dispatcher.
├── GLEntities/ # Domain entities (API DTOs + models).
│ ├── GLAction.cs
│ ├── GLData.cs
│ ├── GLDataList.cs
│ ├── GLGame.cs
│ ├── GLItem.cs
│ ├── GLJson.cs # Serialize / Deserialize helpers.
│ ├── GLPlayer.cs
│ ├── GLPosition.cs
│ └── GLRank.cs
├── Properties/
│ ├── Resources.Designer.cs # Auto-generated by Visual Studio — DO NOT hand-edit.
│ └── Resources.resx
└── Services/ # Service-oriented architecture.
├── Interfaces/ # ONE file per interface, prefixed with "I".
│ ├── IAuthenticationService.cs
│ ├── IConfigurationService.cs
│ ├── IGameStateManager.cs
│ ├── IIntegrityService.cs
│ ├── IItemService.cs
│ ├── IMapService.cs
│ ├── IRankService.cs
│ └── IServiceManager.cs
└── Implementations/ # ONE file per implementation, same name without "I".
├── AuthenticationService.cs
├── ConfigurationService.cs
├── GameStateManager.cs
├── IntegrityService.cs
├── ItemService.cs
├── MapService.cs
├── RankService.cs
└── ServiceManager.cs
- One service = one interface + one implementation, in their respective folders.
- Naming:
- Interfaces:
I<Name>ServiceorI<Name>Manager. - Implementations:
<Name>Service/<Name>Manager(noI). - File = public class name (
PascalCase.cs).
- Interfaces:
- Namespaces:
GLMod— static facade.GLMod.Class— utilities.GLMod.Constants— constants.GLMod.Enums— enumerations (+ extensions in the same file).GLMod.EventPatch— Harmony patches.GLMod.GLEntities— DTOs / models.GLMod.Services.Interfaces— contracts.GLMod.Services.Implementations— logic.
- No business logic in
GLMod.cs— only bootstrap + a static facade over the services. Legacy methods (StartGame,AddPlayer, etc.) are nothing more than wrappers delegating to the services. - No direct access to
HttpClientfrom a service — go throughApiServiceorHttpHelper.Client. - No new
HttpClientinstance — reuse the staticHttpHelperinstance. - Every coroutine must be launched via
CoroutineRunner.Run(...)unless we are already inside an IL2CPPMonoBehaviour. - Every new Harmony patch goes into
GLMod/EventPatch/with one file per patched Among Us class. - Every new enum goes into
GLMod/Enums/, with its<Enum>Extensionsextensions class in the same file when applicable. - Every constant goes into
GLMod/Constants/GameConstants.cs— no magic strings/numbers scattered around. - Every entity serialized to/from the API goes into
GLMod/GLEntities/, withstringproperties (see §4).
- Indentation: 4 spaces (default C# / VS).
- Braces: Allman style (brace on its own line).
var: allowed for obvious types.- XML doc comments (
/// <summary>): mandatory on every public method and property of a service interface. - Logging: inside a service, expose
private void Log(string message) => ServiceLogger.Log(_logger, nameof(<Service>), message);and callLog(...)everywhere. The shared formatter (GLMod/Class/ServiceLogger.cs) produces[GLMod][ServiceName] PlayerName: message. Outside of services, useGLMod.log(...). - Exception handling:
try/catcharound every call into the game / network / parser, log the exception, never silently rethrow in a way that would crash the game. - Language: all identifiers, comments, and developer-facing strings MUST be in English (see §0).
A third-party mod consumes GLMod by:
- Adding
GLMod.dlltoBepInEx/plugins/. - Creating an empty file
BepInEx/config/<MOD_NAME>.glmod. - Calling
GLMod.ConfigService.SetModName("MOD_NAME")in itsLoad(). - (Optional) Disabling the default services it wants to override:
GLMod.ServiceManager.DisableService(ServiceType.StartGame)etc. - (Optional) Overriding the match lifecycle:
GLMod.StartGame(code, map, ranked)GLMod.AddPlayer(name, role, team)for each playerGLMod.SendGame()+GLMod.AddMyPlayer()to validateGLMod.SetWinnerTeams(...)+GLMod.AddWinnerPlayer(...)+GLMod.EndGame()at the end
- Adding custom actions:
GLMod.addAction(source, target, action).
RPC 240 is reserved for GLMod. No third-party mod must use it.
Any change in the collection surface must be reflected both in the README AND in this section.
- State (Started / Finished), Code (disabled in transmission), Map, Start date, Duration, Mod used, Player count.
- Name (PseudoInGame), Good Loss account (if connected), Role, Team (
Crewmate/Impostor/Neutral/ other), Tasks alive, Tasks dead, Tasks max, Win (0/1), Color, Positions.
source,target,action,turn,triggerTimeMs.- Default vanilla actions: kills, exiles, reports, emergencies, votes, shapeshifts, unshapeshifts, tracks, untracks, shields.
- Any new default action must be listed here.
- Identifier: SteamID (only transmitted to
goodloss.frfor authentication). - No password: login = SteamID → Good Loss token.
token.txt,output,serverare gitignored (see.gitignore).- Ban: handled server-side, HTTP 403 response +
"Banned: <reason>". - Integrity:
IntegrityServicecan verify a DLL's SHA against a remote checksum to detect mod tampering.
For every change to the project:
- Read CLAUDE.md first. Identify the affected section.
- Apply the change following the structure in §12.
- Update CLAUDE.md:
- New service → §3 + §12.
- New entity → §4.
- New enum → §5.
- New constant → §6.
- New patch / new RPC → §7 (and table §7.1 for RPCs).
- New API endpoint → §10.
- Version bump (
GLMod,GameVersion, .NET, BepInEx) → §1.1 and §1.3. - New
ServiceTypeenabled by default → §3.2 and §14.
- Update
README.mdif the user-facing surface changes. - Update
docs/dev.MDif the third-party integration surface changes. - Update the version in three places that MUST stay in sync:
<Version>in GLMod/GLMod.csproj.GLMod.Versionconstant in GLMod/GLMod.cs.- The version badge in README.md (
https://img.shields.io/badge/GLMod-vX.Y.Z-blue).
- Make sure the change respects the English-only rule (§0) — code, comments, logs, docs.
- Commit + PR.
GLMod.Versionvs csproj<Version>vs README badge: the three must be identical. Any drift breaks display on the Good Loss side or misleads users about the installed version. The README badge URL ishttps://img.shields.io/badge/GLMod-vX.Y.Z-blue— update theX.Y.Zsegment on every version bump.- csproj
<GameVersion>vs README: must point to the same Among Us version — a build against the wrong Among Us version will crash because of incompatible IL2CPP signatures. PlayerControl.LocalPlayermay benullat startup (pre-menu). Always use?.(see the pattern in everyLog(...)).- IL2CPP: any new
MonoBehaviourmust be registered withClassInjector.RegisterTypeInIl2Cpp<T>()before instantiation. CurrentGamemay benullbetweenEndGame()and the nextStartGame(). Always check before access.- Coroutines & threads: never touch the Unity API from a
Task.Run— only from the main thread (thedoneflag +yield return nullpattern is there for that). - The
Among Us/folder is gitignored — every developer installs their own copy. Never commit this folder. - Auto-generated
Resources.Designer.cs: regenerated by Visual Studio in the developer's UI culture and is the only file allowed to contain non-English content. Do not hand-edit; regenerate from a machine with an English UI if needed.
Last updated: 2026-05-28 — GLMod version 5.4.0. Every change to the project must be accompanied by an update of this file.