presets v1

This commit is contained in:
XtraCube committed 2025-03-23 13:44:40 -04:00
1 parent 5b608f5b3a
commit 38f72c42a3
17 files changed
+275 -142

No files matched your search

+7
View File
@@ -83,4 +83,11 @@ public interface IModdedOption
/// </summary>
/// <param name="data">>The byte array representing the network data.</param>
void HandleNetData(byte[] data);
/// <summary>
/// Saves the option to a preset configuration file.
/// </summary>
/// <param name="presetConfig">The ConfigFile representing the preset configuration.</param>
/// <param name="saveDefault">Indicates whether to save the default value instead of the current value.</param>
void SaveToPreset(ConfigFile presetConfig, bool saveDefault = false);
}
+6 -4
View File
@@ -42,7 +42,7 @@ public static class ModdedOptionsManager
Groups.Add(group);
TypeToGroup.Add(type, group);
pluginInfo.OptionGroups.Add(group);
pluginInfo.InternalOptionGroups.Add(group);
typeof(OptionGroupSingleton<>).MakeGenericType(type)
.GetField("_instance", BindingFlags.Static | BindingFlags.NonPublic)!
@@ -119,7 +119,7 @@ public static class ModdedOptionsManager
option.ConfigDefinition = new ConfigDefinition(groupName, propertyName);
option.ParentMod = pluginInfo.MiraPlugin;
pluginInfo.Options.Add(option);
pluginInfo.InternalOptions.Add(option);
ModdedOptions.Add(option.Id, option);
group.Options.Add(option);
}
@@ -140,7 +140,7 @@ public static class ModdedOptionsManager
// we dont know how other plugins handle their configs
// this way, all the options are saved at once, instead of one by one
var oldConfigSetting = new Dictionary<MiraPluginInfo, bool>();
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins())
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins)
{
oldConfigSetting.Add(plugin, plugin.PluginConfig.SaveOnConfigSet);
plugin.PluginConfig.SaveOnConfigSet = false;
@@ -156,7 +156,7 @@ public static class ModdedOptionsManager
option.HandleNetData(netData.Data);
}
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins())
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins)
{
plugin.PluginConfig.Save();
plugin.PluginConfig.SaveOnConfigSet = oldConfigSetting[plugin];
@@ -173,6 +173,7 @@ public static class ModdedOptionsManager
/// </summary>
/// <param name="__originalMethod">The original setter method.</param>
/// <param name="value">The new object value.</param>
// ReSharper disable once InconsistentNaming
public static void PropertySetterPatch(MethodBase __originalMethod, object value)
{
var attribute = OptionAttributes.First(pair => pair.Key.GetSetMethod() == __originalMethod).Value;
@@ -185,6 +186,7 @@ public static class ModdedOptionsManager
/// <param name="__originalMethod">The original getter method.</param>
/// <param name="__result">The result of the property getter.</param>
/// <returns>False so the original getter gets skipped.</returns>
// ReSharper disable InconsistentNaming
public static bool PropertyGetterPatch(MethodBase __originalMethod, ref object __result)
{
var attribute = OptionAttributes.First(pair => pair.Key.GetGetMethod() == __originalMethod).Value;
@@ -4,6 +4,7 @@ using MiraAPI.Networking;
using MiraAPI.PluginLoading;
using Reactor.Localization.Utilities;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.GameOptions.OptionTypes;
@@ -127,6 +128,24 @@ public abstract class ModdedOption<T> : IModdedOption
OnValueChanged(newValue);
}
/// <inheritdoc />
public void SaveToPreset(ConfigFile presetConfig, bool saveDefault=false)
{
if (ConfigDefinition is null)
{
Logger<MiraApiPlugin>.Error($"Attempted to save {Title} to preset, but ConfigDefinition is null.");
return;
}
var value = saveDefault ? DefaultValue : Value;
if (!presetConfig.ContainsKey(ConfigDefinition))
{
presetConfig.Bind(ConfigDefinition, DefaultValue);
}
presetConfig[ConfigDefinition].BoxedValue = value;
}
/// <inheritdoc />
public abstract float GetFloatData();
+1 -1
View File
@@ -29,7 +29,7 @@ public static class CustomButtonManager
}
CustomButtons.Add(button);
pluginInfo.Buttons.Add(button);
pluginInfo.InternalButtons.Add(button);
typeof(CustomButtonSingleton<>).MakeGenericType(buttonType)
.GetField("_instance", BindingFlags.Static | BindingFlags.NonPublic)!
.SetValue(null, button);
+2 -2
View File
@@ -38,8 +38,8 @@ public abstract class BaseModifier : IOptionable
/// Gets the parent mod of the modifier.
/// </summary>
public MiraPluginInfo ParentMod => Array.Find(
MiraPluginManager.Instance.RegisteredPlugins(),
x => x.Modifiers.Exists(y => y.TypeId == TypeId)
MiraPluginManager.Instance.RegisteredPlugins,
x => x.InternalModifiers.Exists(y => y.TypeId == TypeId)
) ?? throw new InvalidOperationException("Modifier is not registered.");
/// <summary>
+1 -1
View File
@@ -75,7 +75,7 @@ public static class ModifierManager
modifier = (BaseModifier)FormatterServices.GetUninitializedObject(modifierType);
}
info.Modifiers.Add(modifier);
info.InternalModifiers.Add(modifier);
if (modifier is not GameModifier gameModifier)
{
+7 -7
View File
@@ -67,9 +67,9 @@ internal static class TaskAdderPatches
modifiersFolder.FolderName = "Modifiers";
modifiersFolder.name = "ModifiersFolder";
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins())
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins)
{
if (plugin.CustomRoles.Any(x => x.Value is ICustomRole { Configuration.ShowInFreeplay: true }))
if (plugin.InternalRoles.Any(x => x.Value is ICustomRole { Configuration.ShowInFreeplay: true }))
{
var newFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner);
newFolder.name = plugin.PluginId+":Roles";
@@ -78,7 +78,7 @@ internal static class TaskAdderPatches
rolesFolder.SubFolders.Add(newFolder);
}
if (plugin.Modifiers.Exists(x => x.ShowInFreeplay))
if (plugin.InternalModifiers.Exists(x => x.ShowInFreeplay))
{
var newFolder = Object.Instantiate(__instance.RootFolderPrefab, _scroller.Inner);
newFolder.name = plugin.PluginId+":Modifiers";
@@ -317,9 +317,9 @@ internal static class TaskAdderPatches
ref float num2,
ref float num3)
{
for (var m = 0; m < plugin.Modifiers.Count; m++)
for (var m = 0; m < plugin.InternalModifiers.Count; m++)
{
var modifier = plugin.Modifiers[m];
var modifier = plugin.InternalModifiers[m];
if (!modifier.ShowInFreeplay)
{
continue;
@@ -368,9 +368,9 @@ internal static class TaskAdderPatches
private static void PluginRoles(TaskAdderGame instance, MiraPluginInfo plugin, ref float num, ref float num2, ref float num3)
{
for (var m = 0; m < plugin.CustomRoles.Count; m++)
for (var m = 0; m < plugin.InternalRoles.Count; m++)
{
var roleBehaviour = plugin.CustomRoles.ElementAt(m).Value;
var roleBehaviour = plugin.InternalRoles.ElementAt(m).Value;
if (roleBehaviour.Role == RoleTypes.ImpostorGhost || roleBehaviour.Role == RoleTypes.CrewmateGhost ||
roleBehaviour is ICustomRole { Configuration.ShowInFreeplay: false })
{
@@ -14,18 +14,12 @@ using Object = UnityEngine.Object;
namespace MiraAPI.Patches.Options;
/// <summary>
/// Patches the GameOptionsMenu to add custom options.
/// </summary>
[HarmonyPatch(typeof(GameOptionsMenu))]
public static class GameOptionsMenuPatch
internal static class GameOptionsMenuPatch
{
/// <summary>
/// Update patch for the GameOptionsMenu.
/// </summary>
/// <param name="__instance">The GameOptionsMenu instance.</param>
[HarmonyPostfix]
[HarmonyPatch(nameof(GameOptionsMenu.Update))]
// ReSharper disable once InconsistentNaming
public static void UpdatePatch(GameOptionsMenu __instance)
{
if (GameSettingMenuPatches.SelectedModIdx == 0)
@@ -41,7 +35,7 @@ public static class GameOptionsMenuPatch
else
{
var filteredGroups =
GameSettingMenuPatches.SelectedMod?.OptionGroups
GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x => x.OptionableType == null && !x.ShowInModifiersMenu) ?? [];
foreach (var group in filteredGroups)
@@ -107,7 +101,7 @@ public static class GameOptionsMenuPatch
private static void ModifiersUpdate(ref float num)
{
var groups = GameSettingMenuPatches.SelectedMod?.OptionGroups
var groups = GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x => x.ShowInModifiersMenu || x.OptionableType?.IsAssignableTo(typeof(BaseModifier))==true) ?? [];
foreach (var modGroup in groups)
@@ -118,7 +112,7 @@ public static class GameOptionsMenuPatch
private static void ModifiersCreate(GameOptionsMenu menu)
{
var groups = GameSettingMenuPatches.SelectedMod?.OptionGroups
var groups = GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x => x.ShowInModifiersMenu || x.OptionableType?.IsAssignableTo(typeof(BaseModifier))==true) ?? [];
foreach (var group in groups)
{
@@ -128,6 +122,7 @@ public static class GameOptionsMenuPatch
[HarmonyPrefix]
[HarmonyPatch(nameof(GameOptionsMenu.CreateSettings))]
// ReSharper disable once InconsistentNaming
public static bool SettingsPatch(GameOptionsMenu __instance)
{
if (GameSettingMenuPatches.SelectedModIdx == 0)
@@ -143,7 +138,7 @@ public static class GameOptionsMenuPatch
return false;
}
var filteredGroups = GameSettingMenuPatches.SelectedMod?.OptionGroups
var filteredGroups = GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x => x.OptionableType == null && !x.ShowInModifiersMenu) ?? [];
foreach (var group in filteredGroups)
@@ -156,6 +151,7 @@ public static class GameOptionsMenuPatch
[HarmonyPrefix]
[HarmonyPatch(nameof(GameOptionsMenu.Initialize))]
// ReSharper disable once InconsistentNaming
public static bool InitPatch(GameOptionsMenu __instance)
{
if (__instance.Children != null && __instance.Children.Count != 0)
@@ -1,26 +1,101 @@
using System.Linq;
using HarmonyLib;
using MiraAPI.Presets;
using MiraAPI.PluginLoading;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace MiraAPI.Patches.Options;
internal static class GamePresetsTabPatches
{
[HarmonyPatch(typeof(GamePresetsTab), nameof(GamePresetsTab.OpenMenu))]
public static class GamePresetsTabOnEnablePatch
[HarmonyPatch(typeof(GamePresetsTab), nameof(GamePresetsTab.Start))]
public static class GamePresetsTabStartPatch
{
// ReSharper disable once InconsistentNaming
public static void Postfix(GamePresetsTab __instance)
{
if (GameSettingMenuPatches.SelectedModIdx == 0)
var prefab = GameSettingMenu.Instance.GameSettingsButton;
if (prefab == null)
{
Logger<MiraApiPlugin>.Error("GameSettingsButton prefab is null");
return;
}
__instance.StandardPresetButton.gameObject.SetActive(false);
__instance.SecondPresetButton.gameObject.SetActive(false);
var holder = new GameObject("PresetHolder");
holder.transform.SetParent(__instance.transform, false);
holder.transform.localPosition = new Vector3(-1.7f, 1.7f, 0);
var arrange = holder.AddComponent<GridArrange>();
foreach (var preset in PresetManager.Presets.Where(x=>x.Plugin==GameSettingMenuPatches.SelectedMod))
foreach (var preset in MiraPluginManager.Instance.RegisteredPlugins.SelectMany(x=>x.Presets))
{
var button = Object.Instantiate(prefab, holder.transform);
button.buttonText.text = preset.Name;
if (button.buttonText.TryGetComponent<TextTranslatorTMP>(out var tmp))
{
tmp.DestroyImmediate();
}
button.OnClick = new Button.ButtonClickedEvent();
button.OnClick.AddListener(
(UnityAction)(() =>
{
Logger<MiraApiPlugin>.Error($"Loading preset {preset.Name}");
preset.LoadPreset();
}));
button.gameObject.SetActive(false);
preset.PresetButton = button.gameObject;
}
arrange.Alignment = GridArrange.StartAlign.Right;
arrange.CellSize = new Vector2(2.5f, -.55f);
arrange.Start();
arrange.ArrangeChilds();
}
}
[HarmonyPatch(typeof(GamePresetsTab), nameof(GamePresetsTab.OnEnable))]
public static class GamePresetsOnEnablePatch
{
// ReSharper disable once InconsistentNaming
public static void Postfix(GamePresetsTab __instance)
{
Logger<MiraApiPlugin>.Error("OnEnable called");
__instance.StandardPresetButton.gameObject.SetActive(GameSettingMenuPatches.SelectedModIdx == 0);
__instance.SecondPresetButton.gameObject.SetActive(GameSettingMenuPatches.SelectedModIdx == 0);
foreach (var mod in MiraPluginManager.Instance.RegisteredPlugins)
{
foreach (var button in mod.Presets.Select(x=>x.PresetButton))
{
if (button != null)
{
button.SetActive(mod == GameSettingMenuPatches.SelectedMod);
}
}
}
}
}
[HarmonyPatch(typeof(GamePresetsTab), nameof(GamePresetsTab.OnDisable))]
public static class GamePresetsOnDisablePatch
{
// ReSharper disable once InconsistentNaming
public static void Postfix()
{
Logger<MiraApiPlugin>.Error("OnDisable called");
foreach (var mod in MiraPluginManager.Instance.RegisteredPlugins)
{
foreach (var button in mod.Presets.Select(x=>x.PresetButton))
{
if (button != null)
{
button.SetActive(false);
}
}
}
}
}
@@ -4,7 +4,6 @@ using HarmonyLib;
using MiraAPI.Modifiers;
using MiraAPI.PluginLoading;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
@@ -33,6 +32,7 @@ internal static class GameSettingMenuPatches
[HarmonyPostfix]
[HarmonyPatch(nameof(GameSettingMenu.ChangeTab))]
// ReSharper disable once InconsistentNaming
public static void ChangeTabPostfix(GameSettingMenu __instance, int tabNum, bool previewOnly)
{
if ((previewOnly && Controller.currentTouchType == Controller.TouchType.Joystick) || !previewOnly)
@@ -79,6 +79,7 @@ internal static class GameSettingMenuPatches
/// <param name="__instance">The GameSettingMenu instance.</param>
[HarmonyPrefix]
[HarmonyPatch(nameof(GameSettingMenu.Start))]
// ReSharper disable once InconsistentNaming
public static void StartPrefix(GameSettingMenu __instance)
{
_roleBtnOgPos = __instance.RoleSettingsButton.transform.localPosition;
@@ -112,7 +113,7 @@ internal static class GameSettingMenuPatches
(UnityAction)(() =>
{
SelectedModIdx += 1;
if (SelectedModIdx > MiraPluginManager.Instance.RegisteredPlugins().Length)
if (SelectedModIdx > MiraPluginManager.Instance.RegisteredPlugins.Length)
{
SelectedModIdx = 0;
}
@@ -132,7 +133,7 @@ internal static class GameSettingMenuPatches
SelectedModIdx -= 1;
if (SelectedModIdx < 0)
{
SelectedModIdx = MiraPluginManager.Instance.RegisteredPlugins().Length;
SelectedModIdx = MiraPluginManager.Instance.RegisteredPlugins.Length;
}
UpdateText(__instance, __instance.GameSettingsTab, __instance.RoleSettingsTab);
@@ -212,37 +213,37 @@ internal static class GameSettingMenuPatches
UpdateText(__instance, __instance.GameSettingsTab, __instance.RoleSettingsTab);
}
private static void ChangeRoleSettingButton(bool replace, GameSettingMenu __instance)
private static void ChangeRoleSettingButton(bool replace, GameSettingMenu menu)
{
__instance.RoleSettingsButton.OnClick = new ButtonClickedEvent();
__instance.RoleSettingsButton.OnMouseOver = new UnityEvent();
menu.RoleSettingsButton.OnClick = new ButtonClickedEvent();
menu.RoleSettingsButton.OnMouseOver = new UnityEvent();
if (replace)
{
__instance.RoleSettingsButton.buttonText.text = "Modifiers Settings";
__instance.RoleSettingsButton.OnClick.AddListener(
menu.RoleSettingsButton.buttonText.text = "Modifiers Settings";
menu.RoleSettingsButton.OnClick.AddListener(
(UnityAction)(() =>
{
__instance.ChangeTab(3, false);
menu.ChangeTab(3, false);
}));
__instance.RoleSettingsButton.OnMouseOver.AddListener(
menu.RoleSettingsButton.OnMouseOver.AddListener(
(UnityAction)(() =>
{
__instance.ChangeTab(3, true);
menu.ChangeTab(3, true);
}));
}
else
{
__instance.RoleSettingsButton.buttonText.text = "Roles Settings";
__instance.RoleSettingsButton.OnClick.AddListener(
menu.RoleSettingsButton.buttonText.text = "Roles Settings";
menu.RoleSettingsButton.OnClick.AddListener(
(UnityAction)(() =>
{
__instance.ChangeTab(2, false);
menu.ChangeTab(2, false);
}));
__instance.RoleSettingsButton.OnMouseOver.AddListener(
menu.RoleSettingsButton.OnMouseOver.AddListener(
(UnityAction)(() =>
{
__instance.ChangeTab(2, true);
menu.ChangeTab(2, true);
}));
}
}
@@ -256,7 +257,7 @@ internal static class GameSettingMenuPatches
else if (_text is not null)
{
_text.fontSizeMax = 2.3f;
SelectedMod = MiraPluginManager.Instance.RegisteredPlugins()[SelectedModIdx - 1];
SelectedMod = MiraPluginManager.Instance.RegisteredPlugins[SelectedModIdx - 1];
var name = SelectedMod.MiraPlugin.OptionsTitleText;
_text.text = name[..Math.Min(name.Length, 25)];
@@ -269,9 +270,9 @@ internal static class GameSettingMenuPatches
if (SelectedModIdx != 0)
{
var modHasRoles = SelectedMod!.CustomRoles.Count != 0;
var modHasModifiers = SelectedMod.OptionGroups.Exists(x => x.ShowInModifiersMenu || x.OptionableType?.IsAssignableTo(typeof(BaseModifier)) == true);
var modHasOptions = SelectedMod.OptionGroups.Exists(x => x.OptionableType == null && !x.ShowInModifiersMenu);
var modHasRoles = SelectedMod!.InternalRoles.Count != 0;
var modHasModifiers = SelectedMod.InternalOptionGroups.Exists(x => x.ShowInModifiersMenu || x.OptionableType?.IsAssignableTo(typeof(BaseModifier)) == true);
var modHasOptions = SelectedMod.InternalOptionGroups.Exists(x => x.OptionableType == null && !x.ShowInModifiersMenu);
_modifiersButton.gameObject.SetActive(true);
_smallRolesButton.gameObject.SetActive(true);
@@ -367,6 +368,11 @@ internal static class GameSettingMenuPatches
ChangeRoleSettingButton(replaceWithModifiers, menu);
}
if (menu.PresetsTab.gameObject.active)
{
menu.ChangeTab(0, false);
}
CleanupTab(settings, roles);
}
@@ -385,6 +391,34 @@ internal static class GameSettingMenuPatches
private static void CleanupTab(GameOptionsMenu settings, RolesSettingsMenu roles)
{
if (roles.roleChances != null && SelectedMod?.InternalRoles.Count > 0)
{
CleanupRoleSettings(roles);
}
if (settings.Children != null && SelectedMod?.InternalOptionGroups.Count > 0)
{
CleanupSettings(settings);
}
if (_modifiersTab?.Children?.Count > 0)
{
CleanupSettings(_modifiersTab);
}
void CleanupSettings(GameOptionsMenu gameOptMenu)
{
ClearOptions(gameOptMenu.Children);
gameOptMenu.Children = null;
gameOptMenu.settingsContainer
.GetComponentsInChildren<CategoryHeaderMasked>()
.ToList()
.ForEach(header => header.gameObject.DestroyImmediate());
gameOptMenu.Initialize();
gameOptMenu.scrollBar.ScrollToTop();
}
void CleanupRoleSettings(RolesSettingsMenu rolesMenu)
{
if (rolesMenu.advancedSettingChildren != null)
@@ -410,34 +444,5 @@ internal static class GameSettingMenuPatches
rolesMenu.SetQuotaTab();
rolesMenu.scrollBar.ScrollToTop();
}
void CleanupSettings(GameOptionsMenu gameOptMenu)
{
ClearOptions(gameOptMenu.Children);
gameOptMenu.Children = null;
gameOptMenu.settingsContainer
.GetComponentsInChildren<CategoryHeaderMasked>()
.ToList()
.ForEach(header => header.gameObject.DestroyImmediate());
gameOptMenu.Initialize();
gameOptMenu.scrollBar.ScrollToTop();
}
if (roles.roleChances != null && SelectedMod?.CustomRoles.Count > 0)
{
CleanupRoleSettings(roles);
}
if (settings.Children != null && SelectedMod?.OptionGroups.Count > 0)
{
CleanupSettings(settings);
}
if (_modifiersTab?.Children?.Count > 0)
{
CleanupSettings(_modifiersTab);
}
}
}
@@ -24,7 +24,7 @@ public static class LobbyViewPanePatches
private static MiraPluginInfo? SelectedMod => SelectedModIdx == 0
? null
: MiraPluginManager.Instance.RegisteredPlugins()[SelectedModIdx - 1];
: MiraPluginManager.Instance.RegisteredPlugins[SelectedModIdx - 1];
private static PassiveButton? ModifiersTabButton { get; set; }
@@ -74,7 +74,7 @@ public static class LobbyViewPanePatches
(UnityAction)(() =>
{
SelectedModIdx += 1;
if (SelectedModIdx > MiraPluginManager.Instance.RegisteredPlugins().Length)
if (SelectedModIdx > MiraPluginManager.Instance.RegisteredPlugins.Length)
{
SelectedModIdx = 0;
}
@@ -98,7 +98,7 @@ public static class LobbyViewPanePatches
SelectedModIdx -= 1;
if (SelectedModIdx < 0)
{
SelectedModIdx = MiraPluginManager.Instance.RegisteredPlugins().Length;
SelectedModIdx = MiraPluginManager.Instance.RegisteredPlugins.Length;
}
Refresh(__instance);
@@ -127,7 +127,7 @@ public static class LobbyViewPanePatches
__instance.rolesTabButton.SelectButton(false);
ModifiersTabButton?.SelectButton(true);
var filteredGroups = SelectedMod.OptionGroups
var filteredGroups = SelectedMod.InternalOptionGroups
.Where(x => x.GroupVisible() && (x.ShowInModifiersMenu || x.OptionableType?.IsAssignableTo(typeof(BaseModifier))==true));
DrawOptions(__instance, filteredGroups);
return false;
@@ -142,7 +142,7 @@ public static class LobbyViewPanePatches
return true;
}
var filteredGroups = SelectedMod.OptionGroups
var filteredGroups = SelectedMod.InternalOptionGroups
.Where(x => x.OptionableType == null && x.GroupVisible.Invoke());
DrawOptions(__instance, filteredGroups);
return false;
@@ -250,7 +250,7 @@ public static class LobbyViewPanePatches
var list = new List<Type>();
var roleGroups = GameSettingMenuPatches.SelectedMod?.CustomRoles.Values.OfType<ICustomRole>()
var roleGroups = GameSettingMenuPatches.SelectedMod?.InternalRoles.Values.OfType<ICustomRole>()
.ToLookup(x => x.RoleOptionsGroup);
if (roleGroups is null)
@@ -315,7 +315,7 @@ public static class LobbyViewPanePatches
viewSettingsInfoPanelRoleVariant.transform.localScale = Vector3.one;
viewSettingsInfoPanelRoleVariant.transform.localPosition = new Vector3(num2, num, -2f);
var advancedRoleOptions = SelectedMod.OptionGroups
var advancedRoleOptions = SelectedMod.InternalOptionGroups
.Where(x => x.OptionableType == customRole.GetType())
.SelectMany(x => x.Options)
.ToList();
@@ -402,7 +402,7 @@ public static class LobbyViewPanePatches
return 0;
}
var role = SelectedMod.CustomRoles.Values.FirstOrDefault(x => x.GetType() == roleType);
var role = SelectedMod.InternalRoles.Values.FirstOrDefault(x => x.GetType() == roleType);
if (role == null)
{
@@ -425,7 +425,7 @@ public static class LobbyViewPanePatches
var num = viewPanel.yPosStart;
var num2 = 1.08f;
var filteredOptions = SelectedMod.OptionGroups
var filteredOptions = SelectedMod.InternalOptionGroups
.Where(x => x.OptionableType == roleType)
.SelectMany(x=>x.Options)
.ToList();
@@ -67,7 +67,7 @@ public static class RoleSettingMenuPatches
var num3 = 0;
var roleGroups = GameSettingMenuPatches.SelectedMod?.CustomRoles.Values.OfType<ICustomRole>()
var roleGroups = GameSettingMenuPatches.SelectedMod?.InternalRoles.Values.OfType<ICustomRole>()
.ToLookup(x => x.RoleOptionsGroup);
if (roleGroups is null)
@@ -310,7 +310,7 @@ public static class RoleSettingMenuPatches
var num = hasImage ? -0.872f : -1;
// TODO: create sub groups under the role settings.
var filteredOptions = GameSettingMenuPatches.SelectedMod?.OptionGroups
var filteredOptions = GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x=> x.OptionableType == role.GetType())
.SelectMany(x=>x.Options)
.ToList() ?? [];
@@ -474,7 +474,7 @@ public static class RoleSettingMenuPatches
roleOptionSetting.titleText.horizontalAlignment = HorizontalAlignmentOptions.Left;
if (GameSettingMenuPatches.SelectedMod is null ||
GameSettingMenuPatches.SelectedMod.OptionGroups
GameSettingMenuPatches.SelectedMod.InternalOptionGroups
.Exists(x => x.OptionableType == role.GetType()))
{
var newButton = Object.Instantiate(roleOptionSetting.buttons[0], roleOptionSetting.transform);
@@ -506,7 +506,7 @@ public static class RoleSettingMenuPatches
roleOptionSetting.ChancePlusBtn.gameObject.SetActive(false);
}
if (index < GameSettingMenuPatches.SelectedMod?.CustomRoles.Count - 1)
if (index < GameSettingMenuPatches.SelectedMod?.InternalRoles.Count - 1)
{
ScrollerNum -= 0.43f;
}
+30 -31
View File
@@ -6,7 +6,9 @@ using MiraAPI.GameModes;
using MiraAPI.GameOptions;
using MiraAPI.Hud;
using MiraAPI.Modifiers;
using MiraAPI.Presets;
// ReSharper disable UnusedAutoPropertyAccessor.Global
namespace MiraAPI.PluginLoading;
/// <summary>
@@ -23,61 +25,58 @@ public class MiraPluginInfo
}
/// <summary>
/// Get a read only collection of this plugin's modifiers. This is probably not safe because they are uninitialized.
/// Gets a read only collection of this plugin's modifiers. This is not safe for modifiers with constructors.
/// </summary>
/// <returns>Readonly collection of modifiers.</returns>
public IReadOnlyCollection<BaseModifier> GetModifiers()
{
return Modifiers.AsReadOnly();
}
public IReadOnlyCollection<BaseModifier> Modifiers { get; private set; } = null!;
/// <summary>
/// Get a read only collection of this plugin's Option Groups.
/// Gets a read only collection of this plugin's Option Groups.
/// </summary>
/// <returns>Readonly collection of option groups.</returns>
public IReadOnlyCollection<AbstractOptionGroup> GetOptionGroups()
{
return OptionGroups.AsReadOnly();
}
public IReadOnlyCollection<AbstractOptionGroup> OptionGroups { get; private set; } = null!;
/// <summary>
/// Gets a read only collection of this plugin's options.
/// </summary>
/// <returns>Read only collection of options.</returns>
public IReadOnlyCollection<IModdedOption> GetOptions()
{
return Options.AsReadOnly();
}
public IReadOnlyCollection<IModdedOption> Options { get; private set; } = null!;
/// <summary>
/// Gets a read only dictionary of Role IDs and the RoleBehaviour object they are associated with.
/// </summary>
/// <returns>Read only dictionary of IDs and Roles.</returns>
public ReadOnlyDictionary<ushort, RoleBehaviour> GetRoles()
{
return new ReadOnlyDictionary<ushort, RoleBehaviour>(CustomRoles);
}
public ReadOnlyDictionary<ushort, RoleBehaviour> Roles { get; private set; } = null!;
/// <summary>
/// Gets a read only collection of this plugin's custom buttons.
/// </summary>
/// <returns>Read only collection of buttons.</returns>
public IReadOnlyCollection<CustomActionButton> GetButtons()
public IReadOnlyCollection<CustomActionButton> Buttons { get; private set; } = null!;
/// <summary>
/// Gets a read only dictionary of this plugin's custom game modes.
/// </summary>
public IReadOnlyCollection<OptionPreset> Presets { get; internal set; } = null!;
internal void SavePublicCollections()
{
return Buttons.AsReadOnly();
Presets = [..InternalPresets];
Modifiers = [..InternalModifiers];
OptionGroups = [..InternalOptionGroups];
Options = [..InternalOptions];
Roles = new ReadOnlyDictionary<ushort, RoleBehaviour>(InternalRoles);
Buttons = [..InternalButtons];
}
internal List<AbstractOptionGroup> OptionGroups { get; } = [];
internal List<OptionPreset> InternalPresets { get; } = [];
internal List<IModdedOption> Options { get; } = [];
internal List<AbstractOptionGroup> InternalOptionGroups { get; } = [];
internal List<BaseModifier> Modifiers { get; } = [];
internal List<IModdedOption> InternalOptions { get; } = [];
internal Dictionary<ushort, RoleBehaviour> CustomRoles { get; } = [];
internal List<BaseModifier> InternalModifiers { get; } = [];
internal Dictionary<int, CustomGameMode> GameModes { get; } = [];
internal Dictionary<ushort, RoleBehaviour> InternalRoles { get; } = [];
internal List<CustomActionButton> Buttons { get; } = [];
internal Dictionary<int, CustomGameMode> InternalGameModes { get; } = [];
internal List<CustomActionButton> InternalButtons { get; } = [];
/// <summary>
/// Gets the plugin's ID, as defined in the plugin's BepInEx metadata.
+13 -3
View File
@@ -12,6 +12,7 @@ using MiraAPI.GameOptions;
using MiraAPI.GameOptions.Attributes;
using MiraAPI.Hud;
using MiraAPI.Modifiers;
using MiraAPI.Presets;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using Reactor.Networking;
@@ -26,8 +27,9 @@ public sealed class MiraPluginManager
{
private readonly Dictionary<Assembly, MiraPluginInfo> _registeredPlugins = [];
internal MiraPluginInfo[] RegisteredPlugins() => [.. _registeredPlugins.Values];
internal Dictionary<MiraPluginInfo, List<Type>> QueuedRoleRegistrations { get; } = new();
internal MiraPluginInfo[] RegisteredPlugins { get; private set; } = null!;
internal Dictionary<MiraPluginInfo, List<Type>> QueuedRoleRegistrations { get; } = [];
internal static MiraPluginManager Instance { get; private set; } = new();
internal void Initialize()
@@ -96,17 +98,25 @@ public sealed class MiraPluginManager
RegisterColorClasses(type);
}
info.OptionGroups.Sort((x, y) => x.GroupPriority.CompareTo(y.GroupPriority));
info.InternalOptionGroups.Sort((x, y) => x.GroupPriority.CompareTo(y.GroupPriority));
QueuedRoleRegistrations.Add(info, roles);
_registeredPlugins.Add(assembly, info);
info.SavePublicCollections();
PresetManager.CreateDefaultPreset(info);
PresetManager.LoadPresets(info);
Logger<MiraApiPlugin>.Info($"Registering mod {pluginInfo.Metadata.GUID} with Mira API.");
};
IL2CPPChainloader.Instance.Finished += PaletteManager.RegisterAllColors;
IL2CPPChainloader.Instance.Finished += MiraEventManager.SortAllHandlers;
IL2CPPChainloader.Instance.Finished += () =>
{
// Save all buttons into a read-only collection for easy access
CustomButtonManager.Buttons = new ReadOnlyCollection<CustomActionButton>(CustomButtonManager.CustomButtons);
// Cache all the registered plugins into an array for easy access
RegisteredPlugins = [.._registeredPlugins.Values];
};
}
+6
View File
@@ -1,6 +1,7 @@
using System.Linq;
using BepInEx.Configuration;
using MiraAPI.PluginLoading;
using UnityEngine;
namespace MiraAPI.Presets;
@@ -29,6 +30,11 @@ public class OptionPreset
/// </summary>
public ConfigFile PresetConfig { get; }
/// <summary>
/// Gets or sets the button associated with the preset in the UI.
/// </summary>
public GameObject? PresetButton { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="OptionPreset"/> class with the specified name and configuration file.
/// </summary>
+22 -8
View File
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.IO;
using System.Linq;
using BepInEx.Configuration;
using MiraAPI.PluginLoading;
using UnityEngine;
@@ -16,10 +16,23 @@ public static class PresetManager
/// </summary>
public static string PresetDirectory { get; } = Path.Join(Application.persistentDataPath, "mira_presets");
/// <summary>
/// Gets the list of available presets for the game options.
/// </summary>
public static List<OptionPreset> Presets { get; } = [];
internal static void CreateDefaultPreset(MiraPluginInfo plugin)
{
var presetPath = Path.Join(PresetManager.PresetDirectory, plugin.PluginId);
if (!Directory.Exists(presetPath))
{
Directory.CreateDirectory(presetPath);
}
var presetConfig = new ConfigFile(Path.Join(presetPath, "Default.cfg"), true);
foreach (var option in plugin.InternalOptions.Where(x => x.IncludeInPreset))
{
option.SaveToPreset(presetConfig, true);
}
presetConfig.Save();
}
/// <summary>
/// Loads the presets for the specified plugin by reading the configuration files from the preset directory.
@@ -27,7 +40,7 @@ public static class PresetManager
/// <param name="plugin">>The plugin for which the presets should be loaded.</param>
public static void LoadPresets(MiraPluginInfo plugin)
{
Presets.Clear();
plugin.InternalPresets.Clear();
if (!Directory.Exists(PresetDirectory))
{
Directory.CreateDirectory(PresetDirectory);
@@ -43,7 +56,8 @@ public static class PresetManager
{
var presetName = Path.GetFileNameWithoutExtension(file);
var presetConfig = new ConfigFile(file, true);
Presets.Add(new OptionPreset(presetName, plugin, presetConfig));
plugin.InternalPresets.Add(new OptionPreset(presetName, plugin, presetConfig));
}
plugin.Presets = [.. plugin.InternalPresets];
}
}
+4 -4
View File
@@ -70,7 +70,7 @@ public static class CustomRoleManager
continue;
}
pluginInfo.CustomRoles.Add((ushort)role.Role, role);
pluginInfo.InternalRoles.Add((ushort)role.Role, role);
}
}
@@ -156,7 +156,7 @@ public static class CustomRoleManager
/// <returns>A MiraPluginInfo object representing the parent mod of the role.</returns>
public static MiraPluginInfo FindParentMod(ICustomRole role)
{
return MiraPluginManager.Instance.RegisteredPlugins().First(plugin => plugin.CustomRoles.ContainsValue(role as RoleBehaviour ?? throw new InvalidOperationException()));
return MiraPluginManager.Instance.RegisteredPlugins.First(plugin => plugin.InternalRoles.ContainsValue(role as RoleBehaviour ?? throw new InvalidOperationException()));
}
/// <summary>
@@ -231,7 +231,7 @@ public static class CustomRoleManager
// we dont know how other plugins handle their configs
// this way, all the options are saved at once, instead of one by one
var oldConfigSetting = new Dictionary<MiraPluginInfo, bool>();
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins())
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins)
{
oldConfigSetting.Add(plugin, plugin.PluginConfig.SaveOnConfigSet);
plugin.PluginConfig.SaveOnConfigSet = false;
@@ -266,7 +266,7 @@ public static class CustomRoleManager
}
}
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins())
foreach (var plugin in MiraPluginManager.Instance.RegisteredPlugins)
{
plugin.PluginConfig.Save();
plugin.PluginConfig.SaveOnConfigSet = oldConfigSetting[plugin];