-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add IL2CPP version for BepInEx6 nightly builds (#78)
Code was refactored to use a shared project. Based on source from HC.BepInEx.ConfigurationManager.Il2Cpp.CoreCLR-18.0_beta2_20230821
- Loading branch information
1 parent
77ac031
commit e3b754d
Showing
21 changed files
with
727 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using System.Reflection; | ||
using System.Runtime.InteropServices; | ||
|
||
// General Information about an assembly is controlled through the following | ||
// set of attributes. Change these attribute values to modify the information | ||
// associated with an assembly. | ||
[assembly: AssemblyTitle("BepInEx.KeyboardShortcut")] | ||
[assembly: AssemblyDescription("")] | ||
[assembly: AssemblyConfiguration("")] | ||
[assembly: AssemblyCompany("")] | ||
[assembly: AssemblyProduct("BepInEx.KeyboardShortcut")] | ||
[assembly: AssemblyCopyright("Copyright © Bepis 2022")] | ||
[assembly: AssemblyTrademark("")] | ||
[assembly: AssemblyCulture("")] | ||
|
||
// Setting ComVisible to false makes the types in this assembly not visible | ||
// to COM components. If you need to access a type in this assembly from | ||
// COM, set the ComVisible attribute to true on that type. | ||
[assembly: ComVisible(false)] | ||
|
||
// The following GUID is for the ID of the typelib if this project is exposed to COM | ||
[assembly: Guid("29e2f128-9187-41a9-b834-537d3721cd3a")] | ||
|
||
// Version information for an assembly consists of the following four values: | ||
// | ||
// Major Version | ||
// Minor Version | ||
// Build Number | ||
// Revision | ||
// | ||
// You can specify all the values or you can default the Build and Revision Numbers | ||
// by using the '*' as shown below: | ||
// [assembly: AssemblyVersion("1.0.*")] | ||
[assembly: AssemblyVersion("6.0.0.0")] | ||
[assembly: AssemblyFileVersion("6.0.0.0")] | ||
[assembly: AssemblyInformationalVersion("6.0.0-be.672")] |
20 changes: 20 additions & 0 deletions
20
BepInEx.KeyboardShortcut/BepInEx.KeyboardShortcut.IL2CPP.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>disable</Nullable> | ||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo> | ||
<RootNamespace>BepInEx.KeyboardShortcut</RootNamespace> | ||
<AssemblyName>BepInEx.KeyboardShortcut</AssemblyName> | ||
<DebugType>embedded</DebugType> | ||
<GenerateDocumentationFile>True</GenerateDocumentationFile> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.664" /> | ||
<PackageReference Include="IllusionLibs.HoneyCome.Il2Cppmscorlib" Version="2023.16.10" /> | ||
<PackageReference Include="IllusionLibs.HoneyCome.UnityEngine" Version="2021.3.14.2" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
// This is copied from BepInEx 5 and modified to work with BepInEx 6 nightlies where this type is missing | ||
// This is a temporary fix until this struct is added to BepInEx 6 proper | ||
using BepInEx.Logging; | ||
using System.Reflection; | ||
using UnityEngine; | ||
using Logger = BepInEx.Logging.Logger; | ||
|
||
namespace BepInEx.Configuration | ||
{ | ||
/// <summary> | ||
/// A keyboard shortcut that can be used in Update method to check if user presses a key combo. The shortcut is only | ||
/// triggered when the user presses the exact combination. For example, <c>F + LeftCtrl</c> will trigger only if user | ||
/// presses and holds only LeftCtrl, and then presses F. If any other keys are pressed, the shortcut will not trigger. | ||
/// | ||
/// Can be used as a value of a setting in <see cref="ConfigFile.Bind{T}(ConfigDefinition,T,ConfigDescription)"/> | ||
/// to allow user to change this shortcut and have the changes saved. | ||
/// | ||
/// How to use: Use <see cref="IsDown"/> in this class instead of <see cref="Input.GetKeyDown(KeyCode)"/> in the Update loop. | ||
/// </summary> | ||
public struct KeyboardShortcut | ||
{ | ||
static KeyboardShortcut() | ||
{ | ||
TomlTypeConverter.AddConverter( | ||
typeof(KeyboardShortcut), | ||
new TypeConverter | ||
{ | ||
ConvertToString = (o, type) => ((KeyboardShortcut)o).Serialize(), | ||
ConvertToObject = (s, type) => Deserialize(s) | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Shortcut that never triggers. | ||
/// </summary> | ||
public static readonly KeyboardShortcut Empty = new KeyboardShortcut(); | ||
|
||
/// <summary> | ||
/// All KeyCode values that can be used in a keyboard shortcut. | ||
/// </summary> | ||
public static readonly IEnumerable<KeyCode> AllKeyCodes = Enum.GetValues(typeof(KeyCode)) as KeyCode[]; | ||
|
||
// Don't block hotkeys if mouse is being pressed, e.g. when shooting and trying to strafe | ||
public static readonly KeyCode[] ModifierBlockKeyCodes = AllKeyCodes.Except(new KeyCode[] { | ||
KeyCode.Mouse0, KeyCode.Mouse1, KeyCode.Mouse2, KeyCode.Mouse3, | ||
KeyCode.Mouse4, KeyCode.Mouse5, KeyCode.Mouse6, KeyCode.None }).ToArray(); | ||
|
||
private readonly KeyCode[] _allKeys; | ||
|
||
#if true | ||
private static MethodInfo logMethod = typeof(Logger).GetMethod( | ||
"Log", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, | ||
new Type[] { typeof(LogLevel), typeof(object) }, null); | ||
|
||
#endif | ||
/// <summary> | ||
/// Create a new keyboard shortcut. | ||
/// </summary> | ||
/// <param name="mainKey">Main key to press</param> | ||
/// <param name="modifiers">Keys that should be held down before main key is registered</param> | ||
public KeyboardShortcut(KeyCode mainKey, params KeyCode[] modifiers) : this(new[] { mainKey }.Concat(modifiers).ToArray()) | ||
{ | ||
if (mainKey == KeyCode.None && modifiers.Any()) | ||
throw new ArgumentException($"Can't set {nameof(mainKey)} to KeyCode.None if there are any {nameof(modifiers)}"); | ||
} | ||
|
||
private KeyboardShortcut(KeyCode[] keys) | ||
{ | ||
_allKeys = SanitizeKeys(keys); | ||
} | ||
|
||
private static KeyCode[] SanitizeKeys(params KeyCode[] keys) | ||
{ | ||
return keys != null && keys.Length != 0 && keys[0] != KeyCode.None | ||
? new KeyCode[] { keys[0] }.Concat(keys.Skip(1).Distinct().Where(x => x != keys[0]).OrderBy(x => (int)x)).ToArray() | ||
: new KeyCode[] { KeyCode.None }; | ||
} | ||
|
||
/// <summary> | ||
/// Main key of the key combination. It has to be pressed / let go last for the combination to be triggered. | ||
/// If the combination is empty, <see cref="KeyCode.None"/> is returned. | ||
/// </summary> | ||
public KeyCode MainKey => _allKeys != null && _allKeys.Length > 0 ? _allKeys[0] : KeyCode.None; | ||
|
||
/// <summary> | ||
/// Modifiers of the key combination, if any. | ||
/// </summary> | ||
public IEnumerable<KeyCode> Modifiers => _allKeys?.Skip(1) ?? Enumerable.Empty<KeyCode>(); | ||
|
||
/// <summary> | ||
/// Attempt to deserialize key combination from the string. | ||
/// </summary> | ||
public static KeyboardShortcut Deserialize(string str) | ||
{ | ||
try | ||
{ | ||
KeyCode[] parts = str.Split(new[] { ' ', '+', ',', ';', '|' }, StringSplitOptions.RemoveEmptyEntries) | ||
.Select(x => (KeyCode)Enum.Parse(typeof(KeyCode), x)).ToArray(); | ||
return new KeyboardShortcut(parts); | ||
} | ||
catch (SystemException ex) | ||
{ | ||
#if false | ||
Logger.Log(LogLevel.Error, "Failed to read keybind from settings: " + ex.Message); | ||
#else | ||
logMethod?.Invoke(null, new object[] { LogLevel.Error, "Failed to read keybind from settings: " + ex.Message }); | ||
#endif | ||
} | ||
return Empty; | ||
} | ||
|
||
/// <summary> | ||
/// Serialize the key combination into a user readable string. | ||
/// </summary> | ||
public string Serialize() | ||
{ | ||
return _allKeys != null | ||
? string.Join(" + ", _allKeys.Select(x => x.ToString()).ToArray()) | ||
: string.Empty; | ||
} | ||
|
||
/// <summary> | ||
/// Check if the main key was just pressed (Input.GetKeyDown), and specified modifier keys are all pressed | ||
/// </summary> | ||
public bool IsDown() | ||
{ | ||
KeyCode mainKey = MainKey; | ||
return mainKey != KeyCode.None && Input.GetKeyDown(mainKey) && ModifierKeyTest(); | ||
} | ||
|
||
/// <summary> | ||
/// Check if the main key is currently held down (Input.GetKey), and specified modifier keys are all pressed | ||
/// </summary> | ||
public bool IsPressed() | ||
{ | ||
KeyCode mainKey = MainKey; | ||
return mainKey != KeyCode.None && Input.GetKey(mainKey) && ModifierKeyTest(); | ||
} | ||
|
||
/// <summary> | ||
/// Check if the main key was just lifted (Input.GetKeyUp), and specified modifier keys are all pressed. | ||
/// </summary> | ||
public bool IsUp() | ||
{ | ||
KeyCode mainKey = MainKey; | ||
return mainKey != KeyCode.None && Input.GetKeyUp(mainKey) && ModifierKeyTest(); | ||
} | ||
|
||
private bool ModifierKeyTest() | ||
{ | ||
KeyCode mainKey = MainKey; | ||
return | ||
_allKeys.All(key => key == mainKey || Input.GetKey(key)) && | ||
ModifierBlockKeyCodes.Except(_allKeys).All(key => !Input.GetKey(key)); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override string ToString() | ||
{ | ||
return MainKey != KeyCode.None | ||
? string.Join(" + ", _allKeys.Select(key => key.ToString()).ToArray()) | ||
: "Not set"; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override bool Equals(object obj) | ||
{ | ||
return obj is KeyboardShortcut shortcut && MainKey == shortcut.MainKey && Modifiers.SequenceEqual(shortcut.Modifiers); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override int GetHashCode() | ||
{ | ||
return MainKey != KeyCode.None | ||
? _allKeys.Aggregate(_allKeys.Length, (current, item) => unchecked(current * 31 + (int)item)) | ||
: 0; | ||
} | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
ConfigurationManager.IL2CPP/ConfigurationManager.IL2CPP.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<ImplicitUsings>disable</ImplicitUsings> | ||
<Nullable>disable</Nullable> | ||
<GenerateAssemblyInfo>False</GenerateAssemblyInfo> | ||
<RootNamespace>ConfigurationManager</RootNamespace> | ||
<AssemblyName>ConfigurationManager</AssemblyName> | ||
|
||
<OutputPath>D:\SVN\BepInEx.ConfigurationManager\bin\IL2CPP</OutputPath> | ||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> | ||
<GenerateDocumentationFile>True</GenerateDocumentationFile> | ||
|
||
<DebugType>embedded</DebugType> | ||
<DefineConstants>$(DefineConstants);IL2CPP</DefineConstants> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.664" /> | ||
<PackageReference Include="IllusionLibs.HoneyCome.Il2Cppmscorlib" Version="2023.16.10" /> | ||
<PackageReference Include="IllusionLibs.HoneyCome.UnityEngine" Version="2021.3.14.2" /> | ||
<PackageReference Include="IllusionLibs.HoneyCome.UnityEngine.UI" Version="2021.3.14.2" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\BepInEx.KeyboardShortcut\BepInEx.KeyboardShortcut.IL2CPP.csproj" /> | ||
</ItemGroup> | ||
|
||
<Import Project="..\ConfigurationManager.Shared\ConfigurationManager.Shared.projitems" Label="Shared" /> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using BepInEx; | ||
using BepInEx.Configuration; | ||
using BepInEx.Unity.IL2CPP; | ||
using System.ComponentModel; | ||
using System.Linq; | ||
using System.Reflection; | ||
using UnityEngine; | ||
|
||
namespace ConfigurationManager | ||
{ | ||
internal static class SettingSearcher | ||
{ | ||
private static readonly ICollection<string> _updateMethodNames = new[] | ||
{ | ||
"Update", | ||
"FixedUpdate", | ||
"LateUpdate", | ||
"OnGUI" | ||
}; | ||
|
||
// Search for instances of BaseUnityPlugin to also find dynamically loaded plugins. Doing this makes checking Chainloader.PluginInfos redundant. | ||
// Have to use FindObjectsOfType(Type) instead of FindObjectsOfType<T> because the latter is not available in some older unity versions. | ||
public static IReadOnlyList<PluginInfo> FindPlugins() => IL2CPPChainloader.Instance.Plugins.Values.Where(x => x.Instance is BasePlugin).ToList(); | ||
|
||
public static void CollectSettings(out IEnumerable<SettingEntryBase> results, out List<string> modsWithoutSettings, bool showDebug) | ||
{ | ||
modsWithoutSettings = new List<string>(); | ||
try | ||
{ | ||
results = GetBepInExCoreConfig(); | ||
} | ||
catch (Exception ex) | ||
{ | ||
results = Enumerable.Empty<SettingEntryBase>(); | ||
ConfigurationManager.Logger.LogError(ex); | ||
} | ||
|
||
foreach (var plugin in FindPlugins()) | ||
{ | ||
var type = plugin.Instance.GetType(); | ||
|
||
bool advanced = false; | ||
if (type.GetCustomAttributes(typeof(BrowsableAttribute), false).Cast<BrowsableAttribute>() | ||
.Any(x => !x.Browsable)) | ||
{ | ||
var metadata = plugin.Metadata; | ||
|
||
if (metadata.GUID != ConfigurationManager.GUID) | ||
{ | ||
modsWithoutSettings.Add(metadata.Name); | ||
continue; | ||
} | ||
advanced = true; | ||
} | ||
|
||
var detected = GetPluginConfig(plugin).Cast<SettingEntryBase>().ToList(); | ||
|
||
detected.RemoveAll(x => x.Browsable == false); | ||
|
||
if (detected.Count == 0 || advanced) | ||
detected.ForEach(x => x.IsAdvanced = true); | ||
|
||
// Allow to enable/disable plugin if it uses any update methods ------ | ||
if (showDebug) | ||
{ | ||
var pluginAssembly = type.Assembly; | ||
var behaviours = UnityEngine.Object.FindObjectsOfType<MonoBehaviour>() | ||
.Where(behaviour => behaviour.GetType().Assembly == pluginAssembly); | ||
foreach (var behaviour in behaviours) | ||
{ | ||
var behaviourType = behaviour.GetType(); | ||
if (!behaviourType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(m => _updateMethodNames.Contains(m.Name))) | ||
continue; | ||
PropertyInfo property = behaviourType.GetProperty(nameof(MonoBehaviour.enabled)); | ||
PropertySettingEntry enabledSetting = new PropertySettingEntry(behaviour, property, plugin); | ||
enabledSetting.DispName = "!Allow plugin to run on every frame"; | ||
enabledSetting.Description = "Disabling this will disable some or all of the plugin's functionality.\nHooks and event-based functionality will not be disabled.\nThis setting will be lost after game restart."; | ||
enabledSetting.IsAdvanced = true; | ||
detected.Add(enabledSetting); | ||
break; | ||
} | ||
} | ||
|
||
if (detected.Count > 0) | ||
results = results.Concat(detected); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Get entries for all core BepInEx settings | ||
/// </summary> | ||
private static IEnumerable<SettingEntryBase> GetBepInExCoreConfig() | ||
{ | ||
var bepinMeta = new BepInPlugin(nameof(BepInEx), nameof(BepInEx), BepInEx.Paths.BepInExVersion.ToString().Split('+')[0]); | ||
|
||
return ConfigFile.CoreConfig.Select(kvp => (SettingEntryBase)new ConfigSettingEntry(kvp.Value, null) { IsAdvanced = true, PluginInfo = bepinMeta }); | ||
} | ||
|
||
/// <summary> | ||
/// Get entries for all settings of a plugin | ||
/// </summary> | ||
private static IEnumerable<ConfigSettingEntry> GetPluginConfig(PluginInfo plugin) | ||
{ | ||
var basePlugin = plugin.Instance as BasePlugin; | ||
return basePlugin != null | ||
? basePlugin.Config.Select(kvp => new ConfigSettingEntry(kvp.Value, plugin)) | ||
: Enumerable.Empty<ConfigSettingEntry>(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.