-
-
Notifications
You must be signed in to change notification settings - Fork 6
API and customizations
PATCH can use different downloaders. If you own the [BASIC]
version, you have access to the default FileDownloader
. If you own the [PRO]
version of PATCH, you will find additional downloaders: SmartDownloader
and DropboxDownloader
.
You can switch between downloaders just by injecting it into the Updater/Repairer/PatcherUpdater/UpdatingContext, based on your needs.
Downloaders can be mixed: you can use SmartDownloader
for Repairer
and FileDownloader
for Updater
, for example.
It is the default downloader for PATCH, the only one included in the [BASIC]
version. It is a sequential, single-threaded downloader. It downloads files one after another and follows a retry-based strategy if a download fails.
It does not need to be injected, it is used by default.
It is an high performance downloader that targets on downloading a lot of files in a reduced amount of time. Very useful for the first time downloading, when the whole application needs to be fully downloaded.
The downloading strategy it uses is the following:
- files to download are ordered starting from the smallest one
-
X
downloading threads are started (whereX
is yourprocessors count - 1
) - downloading threads use a work-stealing strategy to download files
This downloader also follows a retry-based strategy if a download fails.
You can inject it in this way:
_updater = new Updater(_context);
_updater.Downloader = new SmartDownloader();
_updater.Downloader.DownloadComplete += DownloadComplete;
_updater.Downloader.ProgressChanged += DownloadProgressChanged;
It is the same as the SmartDownloader
, with same strategies, but for Dropbox.
You can inject it in this way:
_updater = new Updater(_context);
_updater.Downloader = new DropboxDownloader()
{
Credentials = new NetworkCredential(string.Empty, "your_dropbox_api_key")
};
_updater.Downloader.DownloadComplete += DownloadComplete;
_updater.Downloader.ProgressChanged += DownloadProgressChanged;
In both [BASIC]
and [PRO]
versions you can also implement your own downloaders for your Launcher, if needed. Just implement IDownloader
interface in your own class as following:
public sealed class MyDownloader : MHLab.Patch.Core.Client.IO.IDownloader
{
// The code to implement IDownloader
}
then inject it into the Updater/Repairer/PatcherUpdater/UpdatingContext:
// This is taken from Launcher.cs, Initialize method.
_updater = new Updater(_context);
_updater.Downloader = new MyDownloader();
_updater.Downloader.DownloadComplete += DownloadComplete;
_updater.Downloader.ProgressChanged += DownloadProgressChanged;
You can implement your own logger for your Launcher, if needed. Just implement ILogger
interface in your own class as following:
public sealed class MyLogger : MHLab.Patch.Core.Loggers.ILogger
{
// The code to implement ILogger
}
then inject it into the UpdatingContext:
// This is taken from Launcher.cs, Initialize method.
_context = new UpdatingContext(settings, progress);
_context.Logger = new MyLogger();
Normally the Launcher sample script automatically starts the updating process, but for your convenience (and for customization purposes) some methods are exposed.
var repairer = new Repairer(_context);
repairer.IsRepairNeeded();
// It will return true if a repair is needed
var updater = new Updater(_context);
updater.IsUpdateAvailable();
// It will return true if a patch is available
Also, the UpdatingContext
has the IsDirty
property: you can check if it is set on true. If it is, a restart is recommended.
If you call those methods before the UpdatingContext's
Initialize
call, you will get an exception.
You may be interested in knowing some information from the updating context, so you can show additional information or monitor what is happening under the hood.
_context.CurrentVersion; // It contains the current local version. Useful if you want to display the current version.
_context.PatchesPath; // It contains the shortest path for patches that needs to be applied to pull the latest version.
_context.BuildsIndex; // It contains the metadata for builds on your server.
_context.PatchesIndex; // It contains the metadata for patches on your server.
_context.ExistingFiles; // It contains the metadata of all local tracked files.
_context.CurrentBuildDefinition; // It contains the metadata of the current version.
_context.CurrentUpdaterDefinition; // It contains the metadata of the updater.
If you inspect those properties before the UpdatingContext's
Initialize
call, you will get wrong/empty data.
You can queue your custom update steps in the PATCH's updating pipeline. The UpdatingContext
exposes the RegisterUpdateStep
method. It accepts an IUpdater
(PatchUpdater
, Repairer
and Updater
are all IUpdater
and are all queued in the updating pipeline).
public sealed class MyUpdaterStep : IUpdater
{
// The code to implement IUpdater
}
_context.RegisterUpdaterStep(new MyUpdaterStep());
You can find the sample usage in Launcher.cs
and LauncherUpdater.cs
, in Initialize
method.
Remember that the order matters when you register an IUpdater: it is the same order they will execute. All steps are executed when you call _context.Update()
.
You can also register to the PerformedStep
event on _context.Runner.PerformedStep
. It is executed every time a step in the pipeline completes.
You can expand the settings you can override with the Settings Overriding functionality. You just need to create a class and inherit from SettingsOverride
, then you can add your own properties. Then you just need to change the generic parameter passed to the UpdatingContext.OverrideSettings<TSettings>(Action<ILauncherSettings, TSettings> overrider)
method in your Launcher initialization. An example will explain it better!
/* I create this new MySettingsOverride.cs */
public class MySettingsOverride : SettingsOverride
{
public bool EnableMyCoolOption { get; set; }
}
/* MainWindow.xaml.cs@86 in Initialize() method, but if you are in Unity you can find it in Launcher.cs@19 and LauncherUpdater.cs@21 */
_context.OverrideSettings<MySettingsOverride>((originalSettings, settingsOverride) =>
{
originalSettings.DebugMode = settingsOverride.DebugMode;
originalSettings.PatcherUpdaterSafeMode = settingsOverride.PatcherUpdaterSafeMode;
// Here you can access your EnableMyCoolOption property and do whatever you want with it.
if (settingsOverride.EnableMyCoolOption)
{
// Do stuff...
}
});