diff --git a/BepisModSettings/BepisModSettings.csproj b/BepisModSettings/BepisModSettings.csproj index b10dd63..57c0a30 100644 --- a/BepisModSettings/BepisModSettings.csproj +++ b/BepisModSettings/BepisModSettings.csproj @@ -1,19 +1,19 @@  - 1.2.0 + 1.3.0 ResoniteModding net9.0 Bepis Mod Settings https://github.com/ResoniteModding/$(AssemblyName) ResoniteModding.$(AssemblyName) false - false + true true $(ResonitePath)/ $(MSBuildProgramFiles32)\Steam\steamapps\common\Resonite\ $(HOME)/.steam/steam/steamapps/common/Resonite/ - $(GamePath)BepInEx\plugins\$(AssemblyName) + $(GamePath)BepInEx\plugins\$(Authors)-$(AssemblyName)\$(AssemblyName) $(AssemblyName) https://nuget-modding.resonite.net/v3/index.json; diff --git a/BepisModSettings/DataFeeds/BepisConfigsPage.cs b/BepisModSettings/DataFeeds/BepisConfigsPage.cs new file mode 100644 index 0000000..661046c --- /dev/null +++ b/BepisModSettings/DataFeeds/BepisConfigsPage.cs @@ -0,0 +1,460 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using BepInEx; +using BepInEx.Configuration; +using BepInEx.NET.Common; +using BepInExResoniteShim; +using BepisLocaleLoader; +using BepisModSettings.ConfigAttributes; +using Elements.Core; +using FrooxEngine; +using FrooxEngine.UIX; +using ProtoFlux.Runtimes.Execution.Nodes.FrooxEngine.Variables; + +namespace BepisModSettings.DataFeeds; + +public static class BepisConfigsPage +{ + internal static readonly Dictionary, IAsyncEnumerable>> CategoryHandlers = new Dictionary, IAsyncEnumerable>>(); + + public static event Func, IAsyncEnumerable> CustomPluginConfigsPages; + + internal static async IAsyncEnumerable Enumerate(IReadOnlyList path) + { + await Task.CompletedTask; + + string pluginId = path[1]; + + if (!DataFeedHelpers.DoesPluginExist(pluginId)) + { + if (CustomPluginConfigsPages != null) + { + foreach (Delegate del in CustomPluginConfigsPages.GetInvocationList()) + { + if (del is not Func, IAsyncEnumerable> handler) continue; + + await foreach (DataFeedItem item in handler(path)) + { + yield return item; + } + } + } + + yield break; + } + + if (!DataFeedHelpers.TryGetPluginData(pluginId, out ConfigFile configFile, out ModMeta metadata)) yield break; + + if (string.IsNullOrWhiteSpace(metadata.Name)) + metadata.Name = "Unknown"; + if (string.IsNullOrWhiteSpace(metadata.Version)) + metadata.Version = "Unknown"; + if (string.IsNullOrWhiteSpace(metadata.ID)) + metadata.ID = "Unknown"; + + if (DataFeedHelpers.IsEmpty(configFile)) + { + DataFeedLabel noConfigs = new DataFeedLabel(); + noConfigs.InitBase("NoConfigs", path, null, "Settings.BepInEx.Plugins.NoConfigs".AsLocaleKey()); + yield return noConfigs; + } + else + { + IAsyncEnumerable configs = EnumerateConfigs(configFile, metadata, path); + await foreach (DataFeedItem item in configs) + { + yield return item; + } + } + + // Metadata + DataFeedGroup modGroup = new DataFeedGroup(); + modGroup.InitBase("Metadata", path, null, "Settings.BepInEx.Plugins.Metadata".AsLocaleKey()); + yield return modGroup; + + string[] metadataGroup = ["Metadata"]; + + DataFeedIndicator idIndicator = new DataFeedIndicator(); + idIndicator.InitBase("Id", path, metadataGroup, "Settings.BepInEx.Plugins.Guid".AsLocaleKey()); + idIndicator.InitSetupValue(field => field.Value = metadata.ID); + yield return idIndicator; + + if (!string.IsNullOrWhiteSpace(metadata.Author)) + { + DataFeedIndicator authorsIndicator = new DataFeedIndicator(); + authorsIndicator.InitBase("Author", path, metadataGroup, "Settings.BepInEx.Plugins.Author".AsLocaleKey()); + authorsIndicator.InitSetupValue(field => field.Value = metadata.Author); + yield return authorsIndicator; + } + + DataFeedIndicator versionIndicator = new DataFeedIndicator(); + versionIndicator.InitBase("Version", path, metadataGroup, "Settings.BepInEx.Plugins.Version".AsLocaleKey()); + versionIndicator.InitSetupValue(field => field.Value = metadata.Version); + yield return versionIndicator; + + if (!string.IsNullOrWhiteSpace(metadata.Link) && Uri.TryCreate(metadata.Link, UriKind.Absolute, out Uri uri)) + { + DataFeedAction modHyperlink = new DataFeedAction(); + modHyperlink.InitBase("Link", path, metadataGroup, "Settings.BepInEx.Plugins.ModPage".AsLocaleKey(), metadata.Link); + modHyperlink.InitAction(syncDelegate => + { + Slot slot = syncDelegate?.Slot; + if (slot == null) return; + + slot.AttachComponent().URL.Value = uri; + }); + yield return modHyperlink; + } + } + + private static async IAsyncEnumerable EnumerateConfigs(ConfigFile configFile, ModMeta metaData, IReadOnlyList path) + { + CategoryHandlers.Clear(); + + List> groupedConfigs = configFile.Values.Where(config => Plugin.ShowHidden.Value || !HiddenConfig.IsHidden(config)).GroupBy(config => config.Definition.Section).ToList(); + foreach (IGrouping sectionGroup in groupedConfigs) + { + string section = sectionGroup.Key; + + if (!sectionGroup.Any()) continue; + + DataFeedResettableGroup configs = new DataFeedResettableGroup(); + configs.InitBase(section, path, null, section); + configs.InitResetAction(a => + { + Button but = a.Slot.GetComponentInChildren