Skip to main content

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.

ServicePluginStorage is a static handler class that exposes read and delete operations against the global plugin storage registry — the centralized catalog of every plugin archive that has been downloaded to the local machine. Unlike ServicePlugins, which operates within the scope of a specific game instance, this service is concerned only with the storage layer: the .zip archives on disk and their corresponding ReferencePluginStore index entries.

Storage vs Instance Layer

Understanding how these two layers relate is important when building clients:
ConceptClassScopeKey ID
Plugin StorageReferencePluginStoreGlobal — one entry per downloaded archiveId (Guid, assigned at download)
Installed PluginManifestPlugin + ReferencePluginPer-instance — one entry per installationIdLocal (Guid, assigned at install)
A single ReferencePluginStore entry (with a given Id) can be installed into multiple instances, each installation generating a different IdLocal. When you delete a storage entry, you remove the physical .zip archive and its registry entry — any instance that previously installed from that archive retains its extracted files but loses the ability to reinstall from the cached archive.
The storage index is persisted in a hidden JSON file (ManifestIndexStorage) inside the configured rute_plugins directory. The manifest is managed exclusively by Manager.StoragePlugin.

Data Models

ReferencePluginStore

The canonical on-disk and in-index model for a stored plugin archive.
FieldTypeDescription
Namestring?Human-readable name extracted from the archive filename by Manager.Node.GetNameByFile.
Idstring?Unique Guid (N-format) assigned at download time.
FileNamestring?The filename of the stored archive (e.g., MyMod-1.2.3.zip).
UrlWebstring?Original download URL (may be null if the archive was imported manually).
Versionstring?Version string extracted from the filename by PluginUtil.ExtratVersion.

ReferencePluginStoreDTO (wire format)

The serialized transport struct used in all responses from this service.
FieldTypeWire encoding
Namestring?Length-prefixed UTF-16 char array
Idstring?Length-prefixed UTF-16 char array
FileNamestring?Length-prefixed UTF-16 char array
UrlWebstring?Length-prefixed UTF-16 char array
Versionstring?Length-prefixed UTF-16 char array

ManifestIndexStorage

The root object of the on-disk storage index (not transmitted directly over IPC — clients receive ReferencePluginStoreDTO structs).
FieldTypeDescription
NameGamestring?Name of the target game (always "Farlands" for default init).
KeySteamint?Steam App ID used to identify the game.
ReferencesList<ReferencePluginStore>The list of all stored plugins.

Operations

Returns all entries in the global plugin storage registry by calling Manager.StoragePlugin.GetAll(), which deserializes the ManifestIndexStorage JSON file and returns its References list.
Despite the method being named GetOne in the source file (ServicePluginStorage.cs), it is decorated with [TerbinExecutable((byte)CodeServices.ReadAll, ...)] and behaves as a full list operation.
Action bytes: (byte)CodeServices.ReadAll, (byte)CodeServicesSection.PluginStorage = 21

Request Payload

None required. Any bytes sent are ignored.

Response Payload

If no plugins are stored, the response contains a single zero byte ([0]).Otherwise:
count
ThreeQuartersInt
Number of entries in the storage registry.
plugins[]
ReferencePluginStoreDTO[]
Array of count consecutive ReferencePluginStoreDTO structs. Each contains Name, Id, FileName, UrlWeb, and Version.

Example

var response = await client.Communicate(
    (byte)CodeServices.ReadAll,
    (byte)CodeServicesSection.PluginStorage,
    Array.Empty<byte>()
);

if (response.Status == CodeStatus.Succes && response.Payload.Length > 1)
{
    ReadOnlySpan<byte> reader = response.Payload;
    int count = reader.Read<ThreeQuartersInt>();
    for (int i = 0; i < count; i++)
    {
        ReferencePluginStoreDTO dto = reader.ReadStruct<ReferencePluginStoreDTO>();
        Console.WriteLine($"[{dto.Id}] {dto.Name} v{dto.Version}{dto.FileName}");
    }
}
Fetches a single storage entry by its Id (Guid) by calling Manager.StoragePlugin.Get(id), which iterates the storage index and returns the matching ReferencePluginStore.
The method is named GetAll in the source file, but it is decorated with [TerbinExecutable((byte)CodeServices.Read, ...)] and accepts a single id to return one entry.
Action bytes: (byte)CodeServices.Read, (byte)CodeServicesSection.PluginStorage = 21

Request Payload

id
char[]
required
The Id (Guid in N-format, no hyphens) of the plugin storage entry to retrieve, encoded as a length-prefixed UTF-16 char array.

Response Payload

On success the entire body is a serialized ReferencePluginStoreDTO:
Name
string
Human-readable plugin name.
Id
string
Storage Guid in N-format.
FileName
string
Archive filename on disk.
UrlWeb
string
Original download URL (may be empty).
Version
string
Version string extracted from the filename.

Error Conditions

InternalErrors valueCodeMeaning
PluginNotExist205No entry with the given Id was found in the storage registry.

Example

string pluginId = "a1b2c3d4e5f647a8b9c0d1e2f3a4b5c6"; // Guid N-format

Serialineitor s = new();
s.AddArray<char>(pluginId.ToCharArray());

var response = await client.Communicate(
    (byte)CodeServices.Read,
    (byte)CodeServicesSection.PluginStorage,
    s.Serialize()
);

if (response.Status == CodeStatus.Succes)
{
    ReferencePluginStoreDTO dto = new();
    dto.ReadFrom(response.Payload);
    Console.WriteLine($"{dto.Name}{dto.FileName}");
}
Permanently deletes a plugin from the global storage registry. Internally the service calls Manager.Plugin.DeletedOne(id, token), which in turn calls Manager.StoragePlugin.Eliminate(id). Eliminate physically deletes the archive file from disk and removes the ReferencePluginStore entry from the ManifestIndexStorage JSON.Action bytes: (byte)CodeServices.Deleted, (byte)CodeServicesSection.PluginStorage = 21

Request Payload

id
char[]
required
The Id (Guid N-format) of the plugin storage entry to delete.

Response

On success the response body is empty.On failure the response body contains the InternalErrors code serialized as a ushort (2 bytes, little-endian).

Error Conditions

InternalErrors valueCodeMeaning
PluginNotExist205The Id was not found in the storage registry (Eliminate returned null).
PluginOnRemove211The archive file existed but could not be deleted, or the index update failed (Eliminate returned false).
Deleting a storage entry only removes the cached archive. Any instance that previously installed this plugin retains its extracted files. However, reinstallation from the InstallPlugin endpoint will fail for that Id until the plugin is downloaded again.

Example

string pluginId = "a1b2c3d4e5f647a8b9c0d1e2f3a4b5c6";

Serialineitor s = new();
s.AddArray<char>(pluginId.ToCharArray());

var response = await client.Communicate(
    (byte)CodeServices.Deleted,
    (byte)CodeServicesSection.PluginStorage,
    s.Serialize()
);

if (response.Status == CodeStatus.Succes)
{
    Console.WriteLine("Plugin archive removed from storage.");
}
else
{
    // Decode the ushort error code from the response body
    ushort errorCode = Serialineitor.Deserialize<ushort>(response.Payload);
    Console.WriteLine($"Error: {(InternalErrors)errorCode}");
}

Build docs developers (and LLMs) love