Documentation Index
Fetch the complete documentation index at: https://mintlify.com/FarlandsModdingTeam/TerbinProyect/llms.txt
Use this file to discover all available pages before exploring further.
ServicePlugins is a static handler class that orchestrates the full lifecycle of a mod (plugin) as it relates to a specific game instance. It delegates network and filesystem work to Manager.Plugin, Manager.Instances, and Manager.StoragePlugin. Plugins travel through two distinct layers before they are active in a game: the Plugin Storage (a global archive) and the instance manifest (a per-instance record of what is installed where).
Key Concepts
Id vs IdLocal
Each plugin manifest carries two identifiers:
Id(storage ID) — TheGuidassigned when the plugin archive is first downloaded and stored in the global Plugin Storage. This ID links back to aReferencePluginStoreentry and is stable across instances.IdLocal(local ID) — A freshGuidgenerated at install time byManager.Manifest.HandleAddPlugin. This ID uniquely identifies this installation of the plugin inside this instance, allowing the same plugin (sameId) to be installed multiple times under differentIdLocalvalues.
OutSideIntance
A bool? flag indicating whether the plugin was extracted to a path outside the instance directory root. When true, paths inside DirectoryHandwritten are absolute rather than relative to the instance.
DirectoryHandwritten
Tracks every file and directory created during extraction. This log is read back during uninstallation by NodeUtil.DeleteFromHandwritten to reverse the operation precisely.
Data Models
ManifestPlugin
| Field | Type | Description |
|---|---|---|
Name | string? | Human-readable mod name derived from the archive filename. |
Id | string? | Storage-layer Guid (links to ReferencePluginStore). |
IdLocal | string? | Install-time Guid unique to this instance installation. |
OutSideIntance | bool? | true if installed outside the instance root directory. |
HandWritten | DirectoryHandwritten | Tree of all files and directories extracted during install. |
ManifestPluginDTO (wire format)
| Field | Type | Wire encoding |
|---|---|---|
Name | string? | Length-prefixed UTF-16 char array |
Id | string? | Length-prefixed UTF-16 char array |
IdLocal | string? | Length-prefixed UTF-16 char array |
OutSideIntance | bool? | sbyte via ToSByte() / ToBoolUk() |
Operations
DowloadPlugin — (CodeServices.Dowload, CodeServicesSection.Plugin)
DowloadPlugin — (CodeServices.Dowload, CodeServicesSection.Plugin)
Downloads a plugin archive from a URL and stores it in the global Plugin Storage. The service first calls Action bytes:
NetUtil.GetContentLength to determine the total download size, then calls Manager.Plugin.DowloadOne, which streams the file to a temporary path before moving it to storage and registering a ReferencePluginStore entry.This operation is marked TODO in the source — a future refactor will move it to
ServicePluginStorage, and an existence check before overwriting will be added.(byte)CodeServices.Dowload = 13, (byte)CodeServicesSection.Plugin = 20Request Payload
The full download URL for the plugin archive, encoded as a length-prefixed UTF-16 char array.
Optional. When
true (and the remaining buffer length is ≥ 1), the service sets up a MaxProgressDTO containing the file’s content-length and calls ProgressUtil.CreateProgressAndSetMax to wire progress reporting back to the caller on (CodeServices.Dowload, CodeServicesSection.Plugin).Progress Reporting
WhenuseProgress is true, the client receives two extra IPC messages before the final response:SetMaxProgress(CodeServicesClient.SetMaxProgress) — sent once with the total byte count (long sizePlugin).SetBarProgress(CodeServicesClient.SetBarProgress) — sent repeatedly during download with aTerbinInfoProgrssstruct (Percentage,Current,Finish).
Response
On success the response body is empty.Error Conditions
InternalErrors value | Code | Meaning |
|---|---|---|
PluginNotConect | 201 | NetUtil.GetContentLength returned null — the URL is unreachable or returned no content-length header. |
PluginNotSuchSpace | 203 | Not enough disk space for the download (Manager.Plugin.Status.NotSuchSpace). |
PluginInvalidURL | 204 | The URL is malformed or the host rejected it (Status.InvalidURL). |
PluginOnDowload | 202 | Any other network or I/O failure during the download (Status.ErrorOnDowload). |
Example
InstallPlugin — (CodeServices.Install, CodeServicesSection.Plugin)
InstallPlugin — (CodeServices.Install, CodeServicesSection.Plugin)
Extracts a previously downloaded plugin from storage into a specific path within a named instance. The service resolves the instance path via
Manager.Instances.GetPathFolder, combines it with relativePath, and then calls Manager.Plugin.InstallOne. On success, a ManifestPlugin JSON file is written and a ReferencePlugin is appended to the instance’s ManifestInstance.Action bytes: (byte)CodeServices.Install = 14, (byte)CodeServicesSection.Plugin = 20Request Payload
The name of the target instance, encoded as a length-prefixed UTF-16 char array.
The storage-layer ID (
Guid as string) of the plugin to install. Must match a ReferencePluginStore.Id in the global storage index.The relative path inside the instance directory where the plugin archive will be extracted (e.g.,
BepInEx/plugins/MyMod).Optional. When
true, the service reads the uncompressed size from Manager.StoragePlugin.GetSize(idPlugin) and calls ProgressUtil.CreateProgressAndSetMax to send progress updates on (CodeServices.Dowload, CodeServicesSection.Plugin).Progress Reporting
Identical toDowloadPlugin: a SetMaxProgress message followed by repeated SetBarProgress ticks carrying TerbinInfoProgrss.Response
On success the response body is empty.Error Conditions
InternalErrors value | Code | Meaning |
|---|---|---|
InstanceNotExist | 302 | The named instance was not found in the index. |
PluginGetPath | 207 | Could not resolve the physical path for the plugin archive (Status.ErrorGetPathPlugin). |
PluginGetManifest | 209 | Could not read or create the instance manifest after extraction (Status.ErrorGetManifest). |
PluginOnSave | 208 | Failed to persist the plugin’s ManifestPlugin JSON file (Status.ErrorOnSaveManifest). |
PluginNotExist | 205 | The idPlugin was not found in plugin storage (Status.ErrorGetPlugin or unrecognised status). |
If the operation is cancelled mid-extraction,
Manager.Instances.UnistallPlugin is automatically called on the partial result to clean up any extracted files, and Manager.Manifest.HandleRemovePlugin removes the partially-registered reference.Example
GetAll — (CodeServices.ReadAll, CodeServicesSection.Plugin)
GetAll — (CodeServices.ReadAll, CodeServicesSection.Plugin)
Lists all
ManifestPluginDTO records for every plugin installed in the named instance. The service resolves the instance path, loads the instance manifest, then iterates ManifestInstance.Plugins to deserialize each individual plugin JSON file via Manager.Plugin.GetAll.Action bytes: (byte)CodeServices.ReadAll, (byte)CodeServicesSection.Plugin = 20Request Payload
The name of the instance whose plugins should be listed.
Response Payload
If no plugins are installed the response contains a single zero byte ([0]).Otherwise:Number of installed plugins.
Array of
count consecutive ManifestPluginDTO structs. Each contains Name, Id, IdLocal, and OutSideIntance.Error Conditions
InternalErrors value | Code | Meaning |
|---|---|---|
InstanceNotExist | 302 | Instance not found or path could not be resolved. |
ManifestGet | 903 | The instance’s ManifestInstance JSON file could not be deserialized. |
Example
GetOne — (CodeServices.Read, CodeServicesSection.Plugin)
GetOne — (CodeServices.Read, CodeServicesSection.Plugin)
Fetches the
ManifestPluginDTO for a single plugin installed in an instance, identified by its IdLocal. The service loads the instance manifest and searches ManifestInstance.Plugins for a matching ReferencePlugin.IdLocal, then deserializes the corresponding plugin JSON file.Action bytes: (byte)CodeServices.Read, (byte)CodeServicesSection.Plugin = 20Request Payload
The instance name.
The
IdLocal of the installed plugin (the install-time Guid, not the storage Id).Response Payload
On success the entire body is a serializedManifestPluginDTO:Mod name.
Storage-layer Guid.
Install-time local Guid.
Whether installed outside the instance root.
Error Conditions
InternalErrors value | Code | Meaning |
|---|---|---|
InstanceNotExist | 302 | Instance not found or path could not be resolved. |
ManifestGet | 903 | Instance manifest could not be deserialized. |
PluginGet | 206 | The plugin was not found in the instance manifest, or its individual JSON file could not be read. |
Example
Delete — (CodeServices.Deleted, CodeServicesSection.Plugin)
Delete — (CodeServices.Deleted, CodeServicesSection.Plugin)
Uninstalls a plugin from an instance. The service first resolves the
ManifestPlugin via its IdLocal, then calls Manager.Plugin.UnistallOne which uses DirectoryHandwritten to reverse-delete every file and directory the plugin created, and finally calls Manager.Manifest.HandleRemovePlugin to remove the ReferencePlugin entry from the instance manifest and delete the plugin’s individual JSON file.Action bytes: (byte)CodeServices.Deleted, (byte)CodeServicesSection.Plugin = 20Request Payload
The instance name.
The
IdLocal of the plugin installation to remove.Optional. When
true, the service reads mani.HandWritten.GetSize() (total number of items to delete) and calls ProgressUtil.CreateProgressAndSetMax to send progress ticks on (CodeServices.Deleted, CodeServicesSection.Plugin).Progress Reporting
WhenuseProgress is true, the client receives a SetMaxProgress message with the total file/directory count, followed by SetBarProgress ticks during deletion.Response
On success the response body is empty.Error Conditions
InternalErrors value | Code | Meaning |
|---|---|---|
InstanceNotExist | 302 | Instance not found or path could not be resolved. |
ManifestGet | 903 | Instance manifest could not be deserialized. |
PluginGet | 206 | The plugin IdLocal was not found in the instance manifest. |