From 3a19c311ec17623eed0fe22d8858e2e076a8b0f0 Mon Sep 17 00:00:00 2001 From: Eve <85962933+obvEve@users.noreply.github.com> Date: Wed, 16 Sep 2026 11:31:13 +0200 Subject: [PATCH 1/7] Le harmony update --- SecretAPI.Examples/Patches/ExampleAmmoPatch.cs | 8 +++----- SecretAPI.Examples/SecretAPI.Examples.csproj | 2 +- SecretAPI/SecretAPI.csproj | 12 +++++++----- 3 files changed, 11 insertions(+), 11 deletions(-) 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..09de51d 100644 --- a/SecretAPI.Examples/SecretAPI.Examples.csproj +++ b/SecretAPI.Examples/SecretAPI.Examples.csproj @@ -7,7 +7,7 @@ - + diff --git a/SecretAPI/SecretAPI.csproj b/SecretAPI/SecretAPI.csproj index db3c6ac..c31687d 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 @@ - + + + + From c6faf191f6d559e50cda7ddacd9d9b14d08dfaf9 Mon Sep 17 00:00:00 2001 From: Eve <85962933+obvEve@users.noreply.github.com> Date: Wed, 16 Sep 2026 13:43:05 +0200 Subject: [PATCH 2/7] Lib.Harmony.Thin --- SecretAPI.Examples/SecretAPI.Examples.csproj | 2 +- SecretAPI/SecretAPI.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SecretAPI.Examples/SecretAPI.Examples.csproj b/SecretAPI.Examples/SecretAPI.Examples.csproj index 09de51d..5248071 100644 --- a/SecretAPI.Examples/SecretAPI.Examples.csproj +++ b/SecretAPI.Examples/SecretAPI.Examples.csproj @@ -7,7 +7,7 @@ - + diff --git a/SecretAPI/SecretAPI.csproj b/SecretAPI/SecretAPI.csproj index c31687d..b06bcdb 100644 --- a/SecretAPI/SecretAPI.csproj +++ b/SecretAPI/SecretAPI.csproj @@ -25,7 +25,7 @@ - + From 5ce0662269a0fcecc6ee992e4ebc2d8bf8f409f8 Mon Sep 17 00:00:00 2001 From: Eve <85962933+obvEve@users.noreply.github.com> Date: Wed, 16 Sep 2026 14:29:26 +0200 Subject: [PATCH 3/7] Obsolete --- SecretAPI/Attributes/HarmonyPatchCategory.cs | 4 ++-- SecretAPI/Extensions/HarmonyExtensions.cs | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/SecretAPI/Attributes/HarmonyPatchCategory.cs b/SecretAPI/Attributes/HarmonyPatchCategory.cs index 4257803..9de4637 100644 --- a/SecretAPI/Attributes/HarmonyPatchCategory.cs +++ b/SecretAPI/Attributes/HarmonyPatchCategory.cs @@ -1,4 +1,4 @@ -namespace SecretAPI.Attributes; +/*namespace SecretAPI.Attributes; using System; using SecretAPI.Extensions; @@ -22,4 +22,4 @@ public HarmonyPatchCategory(string category) /// Gets the patch category. /// public string Category { get; } -} \ No newline at end of file +}*/ \ No newline at end of file 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}"); } } } From 754015ce3048ab32d29a45e9218537f1126a2a9d Mon Sep 17 00:00:00 2001 From: Eve <85962933+obvEve@users.noreply.github.com> Date: Wed, 16 Sep 2026 16:00:08 +0200 Subject: [PATCH 4/7] Remove publicize --- SecretAPI.Examples/ExampleEntry.cs | 9 +++++++-- SecretAPI.Examples/SecretAPI.Examples.csproj | 5 +---- SecretAPI/Extensions/CodeMatcherExtensions.cs | 11 ++++------- SecretAPI/Features/UserSettings/CustomSetting.cs | 3 +-- SecretAPI/SecretAPI.csproj | 2 +- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/SecretAPI.Examples/ExampleEntry.cs b/SecretAPI.Examples/ExampleEntry.cs index 1839237..5fd53a0 100644 --- a/SecretAPI.Examples/ExampleEntry.cs +++ b/SecretAPI.Examples/ExampleEntry.cs @@ -1,10 +1,10 @@ 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 +29,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/SecretAPI.Examples.csproj b/SecretAPI.Examples/SecretAPI.Examples.csproj index 5248071..cce57e4 100644 --- a/SecretAPI.Examples/SecretAPI.Examples.csproj +++ b/SecretAPI.Examples/SecretAPI.Examples.csproj @@ -7,10 +7,7 @@ - - + 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/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/SecretAPI.csproj b/SecretAPI/SecretAPI.csproj index b06bcdb..1689e92 100644 --- a/SecretAPI/SecretAPI.csproj +++ b/SecretAPI/SecretAPI.csproj @@ -25,7 +25,7 @@ - + From 28eda5a3f5225fb4373e196dfc84ccb66c072706 Mon Sep 17 00:00:00 2001 From: Eve <85962933+obvEve@users.noreply.github.com> Date: Wed, 16 Sep 2026 16:19:01 +0200 Subject: [PATCH 5/7] Use: HarmonyArgument --- .../Features/Settings/SettingsOriginalDefinitionFix.cs | 8 +++----- .../Patches/Features/Settings/SettingsSyncValidateFix.cs | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) 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 From 9c6e0a7cb21930d1a9d1d6418d9c9f03eb3859c6 Mon Sep 17 00:00:00 2001 From: Eve <85962933+obvEve@users.noreply.github.com> Date: Thu, 17 Sep 2026 11:51:08 +0200 Subject: [PATCH 6/7] Remove breaking change --- SecretAPI.Examples/ExampleEntry.cs | 9 ++++++++- SecretAPI/Attributes/HarmonyPatchCategory.cs | 8 +++++--- SecretAPI/SecretApi.cs | 9 ++++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/SecretAPI.Examples/ExampleEntry.cs b/SecretAPI.Examples/ExampleEntry.cs index 5fd53a0..58f82bc 100644 --- a/SecretAPI.Examples/ExampleEntry.cs +++ b/SecretAPI.Examples/ExampleEntry.cs @@ -1,4 +1,11 @@ -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; diff --git a/SecretAPI/Attributes/HarmonyPatchCategory.cs b/SecretAPI/Attributes/HarmonyPatchCategory.cs index 9de4637..00026d9 100644 --- a/SecretAPI/Attributes/HarmonyPatchCategory.cs +++ b/SecretAPI/Attributes/HarmonyPatchCategory.cs @@ -1,4 +1,4 @@ -/*namespace SecretAPI.Attributes; +namespace SecretAPI.Attributes; using System; using SecretAPI.Extensions; @@ -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; } @@ -22,4 +24,4 @@ public HarmonyPatchCategory(string category) /// Gets the patch category. /// public string Category { get; } -}*/ \ No newline at end of file +} \ No newline at end of file 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; From a50eb468dc7cdf87741e6cabaafbf3299114ca4e Mon Sep 17 00:00:00 2001 From: Eve <85962933+obvEve@users.noreply.github.com> Date: Thu, 24 Sep 2026 18:12:10 +0200 Subject: [PATCH 7/7] 3.5.0-beta1 bump --- .github/README.md | 26 +++++++++++++++++++------- Directory.Build.props | 2 +- 2 files changed, 20 insertions(+), 8 deletions(-) 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