Introduce ModManager and IModFactory

This commit is contained in:
Yoshi Askharoun
2024-05-21 20:54:02 -05:00
parent 5e78ca81aa
commit 44d033786d
9 changed files with 108 additions and 60 deletions
+26
View File
@@ -0,0 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
using System;
namespace ZuneModCore;
public interface IModFactory<out T> where T : Mod
{
ModMetadata Metadata { get; }
T Create(IServiceProvider services);
}
/// <summary>
/// A base class that implements <see cref="IModFactory{T}"/> with
/// <see cref="Create(IServiceProvider)"/> using dependency injection.
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class DIModFactoryBase<T> : IModFactory<T> where T : Mod
{
public abstract ModMetadata Metadata { get; }
public virtual T Create(IServiceProvider services)
{
return ActivatorUtilities.CreateInstance<T>(services, Metadata);
}
}
+4 -36
View File
@@ -1,51 +1,19 @@
using Microsoft.Extensions.DependencyInjection;
using OwlCore.AbstractUI.Models;
using OwlCore.AbstractUI.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ZuneModCore.Mods;
namespace ZuneModCore;
public abstract class Mod
public abstract class Mod(ModMetadata metadata)
{
/// <summary>
/// A list of all available mods
/// </summary>
public static readonly IReadOnlyList<Type> AvailableModTypes = new List<Type>
{
typeof(FeaturesOverrideMod),
typeof(VideoSyncMod),
typeof(WebservicesMod),
typeof(BackgroundImageMod),
typeof(MbidLocatorMod),
}.AsReadOnly();
public static string DefaultZuneInstallDir { get; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Zune");
public ModMetadata Metadata { get; } = metadata;
public string ZuneInstallDir { get; set; } = DefaultZuneInstallDir;
private static List<Mod>? _mods;
public static IReadOnlyList<Mod> GetAvailableMods()
{
if (_mods is null)
{
_mods = new(AvailableModTypes.Count);
var services = CommunityToolkit.Mvvm.DependencyInjection.Ioc.Default;
foreach (var modType in AvailableModTypes)
{
var instance = ActivatorUtilities.CreateInstance(services, modType);
if (instance is Mod mod)
_mods.Add(mod);
}
}
return _mods;
}
public abstract ModMetadata Metadata { get; }
public virtual AbstractUICollection? GetDefaultOptionsUI() => null;
public abstract Task<string?> Apply();
+37
View File
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using ZuneModCore.Mods;
namespace ZuneModCore;
public class ModManager
{
/// <summary>
/// Factories for all available mods.
/// </summary>
public static readonly IReadOnlyList<IModFactory<Mod>> ModFactories = new List<IModFactory<Mod>>
{
new FeaturesOverrideModFactory(),
new VideoSyncModFactory(),
new WebservicesModFactory(),
new BackgroundImageModFactory(),
new MbidLocatorModFactory(),
}.AsReadOnly();
private static List<Mod>? _mods;
public static IReadOnlyList<Mod> GetAvailableMods()
{
if (_mods is null)
{
_mods = new(ModFactories.Count);
var services = CommunityToolkit.Mvvm.DependencyInjection.Ioc.Default;
foreach (var modType in ModFactories)
{
var mod = modType.Create(services);
_mods.Add(mod);
}
}
return _mods;
}
}
+4 -1
View File
@@ -9,7 +9,7 @@ using ZuneModCore.Win32;
namespace ZuneModCore.Mods;
public class BackgroundImageMod : Mod
public class BackgroundImageModFactory : DIModFactoryBase<BackgroundImageMod>
{
private const string Description = "Replaces the \"Zero\" background with an image of your choice.";
@@ -17,7 +17,10 @@ public class BackgroundImageMod : Mod
public override ModMetadata Metadata => new(nameof(BackgroundImageMod), "Background Image",
Description, Author, new(1, 0));
}
public class BackgroundImageMod(ModMetadata metadata) : Mod(metadata)
{
public override AbstractUICollection? GetDefaultOptionsUI()
{
AbstractUICollection optionsUi = new(nameof(BackgroundImageMod))
+6 -2
View File
@@ -8,9 +8,8 @@ using ZuneModCore.Win32;
namespace ZuneModCore.Mods;
public class FeaturesOverrideMod : Mod, IAsyncInit
public class FeaturesOverrideModFactory : DIModFactoryBase<FeaturesOverrideMod>
{
private const string ZUNE_FEATURESOVERRIDE_REGKEY = RegEdit.ZUNE_REG_PATH + "FeaturesOverride";
private const string Description = "Re-enables access to some features disabled by Microsoft, such as the Social and Marketplace tabs.\r\n" +
"Does not restore functionality of those features, but shows them in the software.";
@@ -19,6 +18,11 @@ public class FeaturesOverrideMod : Mod, IAsyncInit
public override ModMetadata Metadata => new(nameof(FeaturesOverrideMod), "Features Override",
Description, Author, new(1, 0));
}
public class FeaturesOverrideMod(ModMetadata metadata) : Mod(metadata), IAsyncInit
{
private const string ZUNE_FEATURESOVERRIDE_REGKEY = RegEdit.ZUNE_REG_PATH + "FeaturesOverride";
public override AbstractUICollection? GetDefaultOptionsUI()
{
+11 -8
View File
@@ -7,15 +7,8 @@ using System.Threading.Tasks;
namespace ZuneModCore.Mods;
public class MbidLocatorMod : Mod
public class MbidLocatorModFactory : DIModFactoryBase<MbidLocatorMod>
{
public const string ZUNE_ALBUM_ARTIST_MEDIA_ID_NAME = "ZuneAlbumArtistMediaID";
public const string ZUNE_ALBUM_MEDIA_ID_NAME = "ZuneAlbumMediaID";
public const string ZUNE_MEDIA_ID_NAME = "ZuneMediaID";
public const string ZUNE_COLLECTION_ID_NAME = "ZuneCollectionID";
private static readonly string[] KNOWN_EXTS = [".mp3", ".mp4", ".m4a", ".wav"];
private const string Description = "Puts MusicBrainz IDs added by MusicBrainz Picard where the Zune " +
"software can use it to show additional information provided by Community Webservices.\r\n" +
"Note that this will only have an effect if you have used MusicBrainz Picard on your music library.";
@@ -24,6 +17,16 @@ public class MbidLocatorMod : Mod
public override ModMetadata Metadata => new(nameof(MbidLocatorMod), "MusicBrainz ID Locator",
Description, Author, new(1, 0));
}
public class MbidLocatorMod(ModMetadata metadata) : Mod(metadata)
{
public const string ZUNE_ALBUM_ARTIST_MEDIA_ID_NAME = "ZuneAlbumArtistMediaID";
public const string ZUNE_ALBUM_MEDIA_ID_NAME = "ZuneAlbumMediaID";
public const string ZUNE_MEDIA_ID_NAME = "ZuneMediaID";
public const string ZUNE_COLLECTION_ID_NAME = "ZuneCollectionID";
private static readonly string[] KNOWN_EXTS = [".mp3", ".mp4", ".m4a", ".wav"];
public override AbstractUICollection? GetDefaultOptionsUI()
{
+6 -3
View File
@@ -6,10 +6,8 @@ using System.Threading.Tasks;
namespace ZuneModCore.Mods;
public class VideoSyncMod : Mod
public class VideoSyncModFactory : DIModFactoryBase<VideoSyncMod>
{
private const int ZUNEENCENG_WMVCORA_OFFSET = 0x161E;
private const string Description =
"Resolves \"Error C00D11CD\" when attempting to sync video to a Zune device using Windows 10 1607 (Anniversary Update) or newer";
@@ -17,6 +15,11 @@ public class VideoSyncMod : Mod
public override ModMetadata Metadata => new(nameof(VideoSyncMod), "Fix Video Sync",
Description, Author, new(2, 0));
}
public class VideoSyncMod(ModMetadata metadata) : Mod(metadata)
{
private const int ZUNEENCENG_WMVCORA_OFFSET = 0x161E;
public override async Task<string?> Apply()
{
+13 -9
View File
@@ -10,7 +10,19 @@ using static ZuneModCore.Mods.FeaturesOverrideMod;
namespace ZuneModCore.Mods;
public class WebservicesMod : Mod, IAsyncInit
public class WebservicesModFactory : DIModFactoryBase<WebservicesMod>
{
private const string Description = "Partially restores online features such as the Marketplace by patching the Zune desktop software " +
"to use the community's recreation of Microsoft's Zune servers at zunes.me (instead of zune.net).";
private const string Author = "Joshua \"Yoshi\" Askharoun";
public override ModMetadata Metadata => new(nameof(WebservicesMod), "Community Webservices",
Description, Author, new(1, 1));
}
public class WebservicesMod(ModMetadata metadata) : Mod(metadata), IAsyncInit
{
private const int ZUNESERVICES_ENDPOINTS_BLOCK_OFFSET = 0x14D60;
private const int ZUNESERVICES_ENDPOINTS_BLOCK_LENGTH = 0x884;
@@ -34,14 +46,6 @@ public class WebservicesMod : Mod, IAsyncInit
private HttpClient _client;
private CancellationTokenSource _cts = new();
private const string Description = "Partially restores online features such as the Marketplace by patching the Zune desktop software " +
"to use the community's recreation of Microsoft's Zune servers at zunes.me (instead of zune.net).";
private const string Author = "Joshua \"Yoshi\" Askharoun";
public override ModMetadata Metadata => new(nameof(WebservicesMod), "Community Webservices",
Description, Author, new(1, 1));
public override AbstractUICollection? GetDefaultOptionsUI()
{
AbstractUICollection optionsUi = new(nameof(FeaturesOverrideMod))