diff --git a/.github/README.md b/.github/README.md index d353b21..1f11f0e 100644 --- a/.github/README.md +++ b/.github/README.md @@ -1,14 +1,26 @@ # SecretAPI ![Downloads](https://img.shields.io/github/downloads/Misfiy/SecretAPI/total) * SecretAPI is a plugin that extends [LabAPI](https://github.com/northwood-studios/LabAPI) by providing extra features to help devs. +# Dependencies +- SecretAPI relies on Harmony to implement features + - You can find the latest version [here](https://github.com/pardeike/Harmony/releases/latest) + - You should download Harmony-Fat and put the **0harmony.dll** (found in /net48) into your dependencies folder! + # Features -- CollectionExtensions: Extensions to provide utility for collections like lists and arrays. -- RoomExtensions: Extensions to help with room specific tasks, like checking if a room is safe to teleport to. -- HarmonyExtensions: Extensions to provide more utility to Harmony patching, like adding some updated Harmony features which can't be utilised, i.e. patching by category. -- CustomPlayerEffect: Create custom status effects using the base-game system. -- IRegister: Handle auto registering certain plugin features inheriting this interface and then running `IRegister.RegisterAll(Assembly)` in your plugin's initialise method. -- CallOnLoadAttribute: Allows calling static initialize methods on enable via ``CallOnLoadAttribute.Load(Assembly)`` -- CustomSetting: Server Specific Settings without the management hassle, control everything for 1 setting in 1 class, including permissions. A better setting system overall. +- **CustomPlayerEffect**: Create custom status effects using the base-game system. + - BlastResistance: Grants 0.5% resistance to explosion damage + - Depleted: Disables stamina and its regen + - Energized: Disables stamina usage +- **IRegister**: Handle auto registering certain plugin features inheriting this interface and then running `IRegister.RegisterAll(Assembly)` in your plugin's initialize method. +- **CallOnLoadAttribute**: Allows calling static initialize methods on enable via ``CallOnLoadAttribute.Load(Assembly)`` +- **CustomSetting**: Server Specific Settings without the management hassle, control everything for 1 setting in 1 class, including permissions. A better setting system overall. +- **PrefabStore** and **PrefabManager**: Designed to help access prefabs in a clean way +- Extensions: + - CodeMatcherExtensions: Extensions related to ``HarmonyLib.CodeMatcher``. + - CollectionExtensions: Extensions to provide utility for collections like lists and arrays. + - MirrorExtensions: Extensions providing help with fake-syncing ``SyncVar``, ``SyncList`` and ``Rpc`` + - ReflectionExtensions: Extensions related to C# Reflection + - RoomExtensions: Extensions to help with room specific tasks, like checking if a room is safe to teleport to. # Examples You can find examples inside the `SecretAPI.Examples` folder above, this contains some example settings, patches using categories and some more. diff --git a/Directory.Build.props b/Directory.Build.props index 24401c1..52706c7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@  enable - 3.4.0 + 3.5.0-beta1 diff --git a/SecretAPI.Examples/ExampleEntry.cs b/SecretAPI.Examples/ExampleEntry.cs index 1839237..58f82bc 100644 --- a/SecretAPI.Examples/ExampleEntry.cs +++ b/SecretAPI.Examples/ExampleEntry.cs @@ -1,10 +1,17 @@ -namespace SecretAPI.Examples; +/* + Temp until 4.0 +*/ +#pragma warning disable SA1200 +global using HarmonyPatchCategoryAttribute = HarmonyLib.HarmonyPatchCategory; +#pragma warning restore SA1200 + +namespace SecretAPI.Examples; using System; +using System.Reflection; using HarmonyLib; using LabApi.Loader.Features.Plugins; using SecretAPI.Examples.Settings; -using SecretAPI.Extensions; using SecretAPI.Features.UserSettings; /// @@ -29,11 +36,16 @@ public class ExampleEntry : Plugin /// public override Version RequiredApiVersion { get; } = new(LabApi.Features.LabApiProperties.CompiledVersion); + /// + /// Gets the of SecretAPI.Examples. + /// + internal Assembly Assembly { get; } = typeof(ExampleEntry).Assembly; + /// public override void Enable() { CustomSetting.Register(new ExampleKeybindSetting(), new ExampleDropdownSetting(), new ExampleButtonSetting(), new ExampleFakeSyncButton()); - harmony.PatchCategory(nameof(ExampleFakeSyncButton)); + harmony.PatchCategory(Assembly, nameof(ExampleFakeSyncButton)); } /// diff --git a/SecretAPI.Examples/Patches/ExampleAmmoPatch.cs b/SecretAPI.Examples/Patches/ExampleAmmoPatch.cs index 46467c6..e119515 100644 --- a/SecretAPI.Examples/Patches/ExampleAmmoPatch.cs +++ b/SecretAPI.Examples/Patches/ExampleAmmoPatch.cs @@ -20,15 +20,13 @@ private static void Prefix() // gets called after the original method is called // We grab the method params of ammoType and player, the names must be correct - // ref __result will become a reference to the return value -#pragma warning disable SA1313 - private static void Postfix(ItemType ammoType, ReferenceHub player, ref ushort __result) -#pragma warning restore SA1313 + // ref result will become a reference to the return value + private static void Postfix(ItemType ammoType, ReferenceHub player, [HarmonyArgument("__result")] ref ushort result) { // make sure we don't modify the max ammo if its not the correct ammo type or the player hasn't been fake synced if (ammoType != ExampleFakeSyncButton.AmmoFakeSync || !ExampleFakeSyncButton.FakeSyncs.TryGetValue(player, out ushort sync)) return; - __result = sync; + result = sync; } } \ No newline at end of file diff --git a/SecretAPI.Examples/SecretAPI.Examples.csproj b/SecretAPI.Examples/SecretAPI.Examples.csproj index 7dbfccb..cce57e4 100644 --- a/SecretAPI.Examples/SecretAPI.Examples.csproj +++ b/SecretAPI.Examples/SecretAPI.Examples.csproj @@ -7,10 +7,7 @@ - - + diff --git a/SecretAPI/Attributes/HarmonyPatchCategory.cs b/SecretAPI/Attributes/HarmonyPatchCategory.cs index 4257803..00026d9 100644 --- a/SecretAPI/Attributes/HarmonyPatchCategory.cs +++ b/SecretAPI/Attributes/HarmonyPatchCategory.cs @@ -7,13 +7,15 @@ /// Category handling for . /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -public class HarmonyPatchCategory : Attribute +[Obsolete("Please use HarmonyLib.HarmonyPatchCategoryAttribute - This will be removed in 4.0")] +public class HarmonyPatchCategory : HarmonyLib.HarmonyPatchCategory { /// /// Initializes a new instance of the class. /// /// The category of the patch. public HarmonyPatchCategory(string category) + : base(category) { Category = category; } diff --git a/SecretAPI/Extensions/CodeMatcherExtensions.cs b/SecretAPI/Extensions/CodeMatcherExtensions.cs index 6bfd06a..a2b849e 100644 --- a/SecretAPI/Extensions/CodeMatcherExtensions.cs +++ b/SecretAPI/Extensions/CodeMatcherExtensions.cs @@ -25,11 +25,8 @@ public static class CodeMatcherExtensions /// The of the local to declare. /// The declared. /// The current . - public CodeMatcher DeclareLocal(Type localType, out LocalBuilder localBuilder) - { - localBuilder = matcher.generator.DeclareLocal(localType); - return matcher; - } + [Obsolete("Use CodeMatcher::DeclareLocal(Type, out LocalBuilder)")] + public CodeMatcher DeclareLocal(Type localType, out LocalBuilder localBuilder) => matcher.DeclareLocal(localType, out localBuilder); /// /// Declares a local to be used of a certain . @@ -39,7 +36,7 @@ public CodeMatcher DeclareLocal(Type localType, out LocalBuilder localBuilder) /// The current . public CodeMatcher DeclareLocal(Type localType, out int localIndex) { - DeclareLocal(matcher, localType, out LocalBuilder builder); + matcher.DeclareLocal(localType, out LocalBuilder builder); localIndex = builder.LocalIndex; return matcher; } @@ -63,7 +60,7 @@ public CodeMatcher GetFirstLabel(out Label label) /// The current . public CodeMatcher GetFirstLabelAt(int position, out Label label) { - label = matcher.codes[position].labels.FirstOrDefault(); + label = matcher.Instructions()[position].labels.FirstOrDefault(); return matcher; } } diff --git a/SecretAPI/Extensions/HarmonyExtensions.cs b/SecretAPI/Extensions/HarmonyExtensions.cs index 1eee37b..d44831f 100644 --- a/SecretAPI/Extensions/HarmonyExtensions.cs +++ b/SecretAPI/Extensions/HarmonyExtensions.cs @@ -21,32 +21,36 @@ public static class HarmonyExtensions /// /// The category to patch. /// The assembly to find patches in. + [Obsolete("Use Harmony::PatchCategory(Assembly, string)")] public void PatchCategory(string category, Assembly? assembly = null) { assembly ??= Assembly.GetCallingAssembly(); + harmony.PatchCategory(assembly, category); - assembly.GetTypes().Where(type => + /*assembly.GetTypes().Where(type => { IEnumerable categories = type.GetCustomAttributes(); - return categories.Any(c => c.Category == category); + return categories.Any(c => c.info.category == category); }) - .Do(type => SafePatch(harmony, type)); + .Do(type => SafePatch(harmony, type));*/ } /// /// Patches all patches that don't have a . /// /// The assembly to look for patches. + [Obsolete("Use Harmony::PatchAllUncategorized(Assembly)")] public void PatchAllNoCategory(Assembly? assembly = null) { assembly ??= Assembly.GetCallingAssembly(); + harmony.PatchAllUncategorized(assembly); - assembly.GetTypes().Where(type => + /*assembly.GetTypes().Where(type => { IEnumerable categories = type.GetCustomAttributes(); return !categories.Any(); }) - .Do(type => SafePatch(harmony, type)); + .Do(type => SafePatch(harmony, type));*/ } /// @@ -61,7 +65,7 @@ public void SafePatch(Type type) } catch (Exception ex) { - Logger.Error($"[HarmonyExtensions] failed to safely patch {harmony.Id} ({type.FullName}): {ex}"); + Logger.Error($"[HarmonyExtensions] Failed to safely patch {harmony.Id} ({type.FullName}): {ex}"); } } } diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 5715e44..2b5fc03 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -12,7 +12,6 @@ using LabApi.Features.Wrappers; using Mirror; using NorthwoodLib.Pools; -using SecretAPI.Extensions; /// /// Wraps . @@ -23,7 +22,7 @@ public abstract class CustomSetting : ISetting static CustomSetting() { - SecretApi.Harmony.PatchCategory(nameof(CustomSetting), SecretApi.Assembly); + SecretApi.Harmony.PatchCategory(SecretApi.Assembly, nameof(CustomSetting)); ServerSpecificSettingsSync.SendOnJoinFilter = null; ServerSpecificSettingsSync.DefinedSettings ??= []; // fix null ref diff --git a/SecretAPI/Patches/Features/Settings/SettingsOriginalDefinitionFix.cs b/SecretAPI/Patches/Features/Settings/SettingsOriginalDefinitionFix.cs index c3f0a7f..77cb9aa 100644 --- a/SecretAPI/Patches/Features/Settings/SettingsOriginalDefinitionFix.cs +++ b/SecretAPI/Patches/Features/Settings/SettingsOriginalDefinitionFix.cs @@ -12,14 +12,12 @@ [HarmonyPatch(typeof(ServerSpecificSettingBase), nameof(ServerSpecificSettingBase.OriginalDefinition), MethodType.Getter)] internal static class SettingsOriginalDefinitionFix { -#pragma warning disable SA1313 // Parameter '__result' should begin with lower-case letter - private static void Postfix(ServerSpecificSettingBase __instance, ref ServerSpecificSettingBase __result) -#pragma warning restore SA1313 + private static void Postfix([HarmonyArgument("__instance")] ServerSpecificSettingBase instance, [HarmonyArgument("__result")] ref ServerSpecificSettingBase result) { // Prevent handling non SecretAPI settings. - if (__result != null) + if (result != null) return; - __result = CustomSetting.Get(__instance.GetType(), __instance.SettingId)?.Base ?? null!; + result = CustomSetting.Get(instance.GetType(), instance.SettingId)?.Base ?? null!; } } \ No newline at end of file diff --git a/SecretAPI/Patches/Features/Settings/SettingsSyncValidateFix.cs b/SecretAPI/Patches/Features/Settings/SettingsSyncValidateFix.cs index 31cb578..51d29b7 100644 --- a/SecretAPI/Patches/Features/Settings/SettingsSyncValidateFix.cs +++ b/SecretAPI/Patches/Features/Settings/SettingsSyncValidateFix.cs @@ -12,14 +12,12 @@ [HarmonyPatch(typeof(ServerSpecificSettingsSync), nameof(ServerSpecificSettingsSync.ServerPrevalidateClientResponse))] internal static class SettingsSyncValidateFix { -#pragma warning disable SA1313 // Parameter '__result' should begin with lower-case letter - private static void Postfix(SSSClientResponse msg, ref bool __result) -#pragma warning restore SA1313 + private static void Postfix(SSSClientResponse msg, [HarmonyArgument("__result")] ref bool result) { // prevent overriding already validated settings - if (__result) + if (result) return; - __result = CustomSetting.Get(msg.SettingType, msg.Id) != null; + result = CustomSetting.Get(msg.SettingType, msg.Id) != null; } } \ No newline at end of file diff --git a/SecretAPI/SecretAPI.csproj b/SecretAPI/SecretAPI.csproj index db3c6ac..1689e92 100644 --- a/SecretAPI/SecretAPI.csproj +++ b/SecretAPI/SecretAPI.csproj @@ -4,6 +4,8 @@ net48 latest true + true + false @@ -23,10 +25,7 @@ - - + @@ -40,11 +39,14 @@ - + + + + diff --git a/SecretAPI/SecretApi.cs b/SecretAPI/SecretApi.cs index 2268034..d1b14a6 100644 --- a/SecretAPI/SecretApi.cs +++ b/SecretAPI/SecretApi.cs @@ -1,4 +1,11 @@ -namespace SecretAPI; +/* + Temp until 4.0 +*/ +#pragma warning disable SA1200 +global using HarmonyPatchCategoryAttribute = HarmonyLib.HarmonyPatchCategory; +#pragma warning restore SA1200 + +namespace SecretAPI; using System; using System.IO;