Skip to content

Commit

Permalink
Added: Basic Documentation for Internal Libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
Sewer56 committed Jul 31, 2022
1 parent df1ce0f commit 982297f
Show file tree
Hide file tree
Showing 12 changed files with 397 additions and 80 deletions.
57 changes: 57 additions & 0 deletions docs/InternalLibrariesCommunity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Community Index Library

!!! info

API for [Reloaded II's Community Index](https://github.com/Reloaded-Project/Reloaded.Community) which provides compatibility and user suggestions for games.
[[NuGet Package]](https://www.nuget.org/packages/Reloaded.Mod.Loader.Community)

## Index API

!!! info

Shows how to fetch data from the community index.

```csharp
// Can specify optional parameter to fetch index from alternative URL or from filesystem.
// Get the Index
var indexApi = new IndexApi();
var index = await indexApi.GetIndexAsync();
```

### Get Application in Index

!!! info

Shows how to find an application within the index.

```csharp
// exeLocation contains the absolute file path to an EXE.
await using var fileStream = new FileStream(exeLocation, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 524288);
var hash = Hashing.ToString(await Hashing.FromStreamAsync(fileStream));

// index variable taken from previous example.
// appId is the name of the EXE, in lower case, e.g. tsonic_win.exe [Path.GetFileName(filePath).ToLower()]
var applications = index.FindApplication(hash, appId, out bool hashMatches);

if (applications.Count == 1 && hashMatches)
{
if (hashMatches)
{
// Guaranteed match! Get the application info.
var application = await indexApi.GetApplicationAsync(applications[0]);

// use TryGetError to validate game data against possible incompatibilities.
}
else
{
// Hash does not match.
// Either wrong game, or EXE was modified by user.
// Must be resolved by user.
}
}
else if (applications.Count > 1)
{
// Multiple matches, must be resolved by user.
// Rare!
}
```
93 changes: 93 additions & 0 deletions docs/InternalLibrariesIO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# I/O Library

!!! info

The [I/O library](https://www.nuget.org/packages/Reloaded.Mod.Loader.IO) is used for discovery, monitoring changes and parsing of Reloaded-II's configuration files.

## Read/Write Loader Configuration

!!! info

Shows how to read and write to the mod loader configuration.

Read:
```csharp
var config = IConfig<LoaderConfig>.FromPathOrDefault(Paths.LoaderConfigPath);
```

Write:
```csharp
IConfig<LoaderConfig>.ToPath(config, Paths.LoaderConfigPath);
```

The `IConfig` API can be used with all structures inside the `Reloaded.Mod.Loader.IO.Config` namespace, as such you can also use this API to read app or mod configurations.

## Monitor Available Configurations

!!! info

Shows how to use create services which keep track of all currently available configurations.

These services actively monitor the FileSystem and update their contents whenever a user deletes a mod, modifies a mod or creates a new mod.

Mods:
```csharp
// Read Loader Config
var config = IConfig<LoaderConfig>.FromPathOrDefault(Paths.LoaderConfigPath);

// Monitor Mods
var modConfigService = new ModConfigService(config);

// modConfigService.ItemsByFolder | A dictionary of all Folders -> Configurations
// modConfigService.ItemsByPath | A dictionary of all Config File Paths -> Configurations
// modConfigService.ItemsById | A dictionary of all ModIds -> Configurations
```

The following services are also available:

| Service | Contents |
|--------------------------|--------------------------------------------------------------------------------|
| ApplicationConfigService | All Application/Game Configurations. |
| ModUserConfigService | All User Specified Overrides for Mods, e.g. 'Allow Updating to Beta Versions'. |

## Batch Read Configurations

!!! info

Shows how to read multiple configurations at once.

The `ConfigReader<T>` class can be used for the batch reading of configurations.

```csharp
// Read all mod configurations.
var configs = ConfigReader<ModConfig>.ReadConfigurations(loaderConfig.GetModConfigDirectory(), ModConfig.ConfigFileName, token, 2, 2);
```

## Useful Utility Methods

!!! info

This section lists some static commonly used utility methods.

| Method | Purpose |
|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| ModConfig.GetAllMods | Reads all available mod configurations. |
| ModConfig.SortMods | Sorts a list of mods taking into account their individual dependencies. i.e. Ensures that Mod A is loaded before Mod B if Mod B depends on Mod A. |
| ModConfig.GetDependencies | Returns a list of all dependencies' mod configurations for a given mod. |
| ModUserConfig.GetAllUserConfigs | Retrieves all user configurations that override mod properties. |
| ModUserConfig.GetUserConfigPathForMod | Retrieves the path of a user configuration for a given mod. |
| ModUserConfig.GetUserConfigFolderForMod | Retrieves the path where mod configuration files are stored. |
| ApplicationConfig.GetAllApplications | Retrieves a list of all application configurations. |
| ApplicationConfig.GetAllMods | Retrieves a list of all mods for a given application. |

## Other Utilities

A list of other utilities that may be helpful.

| Class | Purpose |
|------------------------------|---------------------------------------------------------------------------------------------|
| Paths | Used to get the file paths of various Reloaded components, such as logs and configurations. |
| IOEx | Various utility methods for I/O operations. |
| FileSystemWatcherFactory | Factory method(s) for creating functions that monitor FileSystem events. |
| NtQueryDirectoryFileSearcher | [Windows Only] Very, very fast directory and file searcher. |
| BasicPeParser | Basic fast parser for Windows PE files [EXE, DLL] with limited functionality. |
18 changes: 18 additions & 0 deletions docs/InternalLibrariesIntro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Internal Libraries

!!! warning

Some of following libraries are considered 'internal' to Reloaded.

While most are relatively 'stable' in terms of API surface, it is still possible that some internal implementation details might change; meaning you might need to update your packages from one Reloaded release to another.

The following pages here will provide an 'Introduction' to each library; showing common use cases; they do not document the entire available API.

If you need alternative overloads, etc. consider contributing to Reloaded.

!!! note

These pages are based on the current development version of Reloaded.
Some APIs may not be available in current NuGet packages, they will release soon.

With that in mind, please enjoy.
35 changes: 35 additions & 0 deletions docs/InternalLibrariesPackaging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Packaging Library

!!! info

Library for creating downloadable packages and updates for Reloaded II mods.
[[NuGet Package]](https://www.nuget.org/packages/Reloaded.Mod.Loader.Update.Packaging)

## Create Packages

!!! info

Shows how to create an update package.

```csharp
// Use the Publisher.PublishAsync API
await Publisher.PublishAsync(new PublishArgs()
{
ModTuple = new PathTuple<ModConfig>(configPath, config),
OutputFolder = options.OutputFolder,
IncludeRegexes = options.IncludeRegexes.ToList(),
IgnoreRegexes = options.IgnoreRegexes.ToList(),
OlderVersionFolders = options.OlderVersionFolders.ToList(),
AutomaticDelta = options.AutomaticDelta,
CompressionLevel = options.CompressionLevel,
CompressionMethod = options.CompressionMethod,
Progress = progressBar.AsProgress<double>(),
PackageName = options.PackageName,
PublishTarget = options.PublishTarget,
ChangelogPath = options.ChangelogPath,
MetadataFileName = config.ReleaseMetadataFileName
});
```

The parameters are functionally identical to those in the `Reloaded.Publisher` CLI tool.
Refer to parameters' documentation for definitions.
47 changes: 47 additions & 0 deletions docs/InternalLibrariesServer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Server Library

!!! info

Library for communicating with 'Reloaded II Server' mod (formerly part of mod loader).
Allows for remote querying of information as well as mod manipulation (e.g. load/unload mods) in real time.
[[NuGet Package]](https://www.nuget.org/packages/Reloaded.Mod.Loader.Server)

## Connect to Server

!!! info

Connects to the server for remote control.

```csharp
// Create a new client. will automatically asynchronously connect.
// Can specify remote IP address, but user must enable 'Allow External Connections' in 'Reloaded II Server' Mod.
// ... and port forward
Client = new LiteNetLibClient(IPAddress.Loopback, "", _port, true);

// If the server restarts, e.g. user unloaded and reloaded the mod,
// you should probably try to get the server's new port number (in case it changed).
Client.OnTryReconnect += (peer) => TryGetPort(out _port); // see below how to get new port
Client.OverrideDetailsOnReconnect += () => (null, _port); // overrides port in reconnect attempt
// Report back exceptions.
Client.OnReceiveException += ClientOnReceiveException;

// Useful:
// Client.OnConnected | When client connects to host.
// Client.IsConnected | If client is connected.
```

If the server is hosted on the same machine, you can get the port number programmatically:
```csharp
ServerUtility.GetPort(processId);
```

## Check if Reloaded is Present

!!! info

Checks if Reloaded has been loaded into a process with a given ID.

```csharp
ReloadedMappedFile.Exists(processId);
```
127 changes: 127 additions & 0 deletions docs/InternalLibrariesUpdate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Update Library

!!! info

Library for resolving dependencies, searching and downloading Reloaded II mod updates.
[[NuGet Package]](https://www.nuget.org/packages/Reloaded.Mod.Loader.Update)

## Check & Apply Mod Updates

!!! info

Checks and applies updates for Reloaded mods.

```csharp
// modConfigService: See IO Library
// modUserConfigService: See IO Library
var updater = new Updater(modConfigService, modUserConfigService, updaterData);
var updateDetails = await updater.GetUpdateDetailsAsync();

if (updateDetails.HasUpdates())
{
// Warning: Consider checking if files are in use.
// Otherwise might be stuck waiting for a very long time, there is no timeout.
await Updater.Update(Summary);
}
```

Alternative lower level API: `PackageResolverFactory`.

## Search for Mods

!!! info

Shows how to search for mods (NuGet, GameBanana, other supported providers).

```csharp
// May return null if none are available.
// appConfig represents ApplicationConfig from IO.
var aggregateProvider = PackageProviderFactory.GetProvider(appConfig);

// Search for 'Cool Mod' return, 20 entries, skip 0.
var results = await aggregateProvider.SearchAsync("Cool Mod", 0, 20);
```

To search for NuGet packages, you will need to manually create `NuGetPackageProvider`:

```csharp
// loaderConfig is Mod Loader config
var nuGetRepository = new AggregateNugetRepository(loaderConfig.NuGetFeeds);
var nuGetProvider = new NuGetPackageProvider(nuGetRepository);
```

You can use `AggregatePackageProvider` to combine multiple providers:

```csharp
// Extract from existing provider.
var provider = new AggregatePackageProvider(new IDownloadablePackageProvider[] { nuGetProvider, aggregateProvider }, "NuGet");
```

## Resolve Missing Dependencies For Mod

!!! info

Shows how to check and download missing dependencies for mods.

Download dependencies for a mod:
```csharp
// nuGetRepository is AggregateNugetRepository
// mod is ModConfig
var resolver = DependencyResolverFactory.GetInstance(nuGetRepository);
var result = await resolver.ResolveAsync(mod.ModId, mod.PluginData);
```

For multiple mods:
```csharp
// The loop is used to resolve nested dependencies (dependencies of dependencies).
// Non-NuGet sources usually do not have the ability to resolve those.
ModDependencyResolveResult resolveResult = null!;

do
{
var missingDeps = modConfigService.GetMissingDependencies();
var resolver = DependencyResolverFactory.GetInstance(nuGetRepository);

var results = new List<Task<ModDependencyResolveResult>>();
foreach (var dependencyItem in missingDeps.Items)
foreach (var dependency in dependencyItem.Dependencies)
results.Add(resolver.ResolveAsync(dependency, dependencyItem.Mod.PluginData, token));

await Task.WhenAll(results); // wait for completion
resolveResult = ModDependencyResolveResult.Combine(results.Select(x => x.Result)); // merge results
// Download dependencies here using resolveResult.FoundDependencies
// so on next loop, will find less dependencies.
}
while (resolveResult.FoundDependencies.Count > 0);
```

## Write Dependency Metadata

!!! info

Modifies mod configurations to insert data required for resolving dependencies.

e.g. If Mod A depends on Mod B, which receives updates from GitHub, Mod A's config will be modified to include Mod B's update configuration. This will allow people to download Mod B if they have Mod A.

```csharp
// modConfigService is ModConfigService
await DependencyMetadataWriterFactory.ExecuteAllAsync(modConfigService);
```

## Check Reloaded Dependencies

!!! info

Shows how to check if all runtimes required to run Reloaded are available.

```csharp
// loaderConfig is LoaderConfig from IO library.
var deps = new DependencyChecker(loaderConfig, IntPtr.Size == 8); // 64-bit check
if (deps.AllAvailable)
return;

// In deps array you can get install urls for any missing runtimes via the interface.
```

Grabs loader path from the loader config. This is used to check for missing dependencies on boot in cases where e.g. user installed 64-bit runtime but not 32-bit after ignoring the installer.
Loading

0 comments on commit 982297f

Please sign in to comment.