From c02cd134c2c9ce9ef7ea6695de125c5695ace8bf Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Sun, 15 Jun 2025 19:56:48 +0200 Subject: [PATCH 01/12] begin implementation --- SecretAPI/Features/UserSettings/CustomSetting.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 8785c7e..35ae051 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -183,17 +183,20 @@ public static void SendSettingsToPlayer(Player player, int? version = null) version ??= ServerSpecificSettingsSync.Version; IEnumerable hasAccess = CustomSettings.Where(s => s.CanView(player)); + List playerSettings = []; + foreach (CustomSetting setting in hasAccess) + { + CustomSetting playerSpecific = EnsurePlayerSpecificSetting(player, setting); + playerSettings.Add(playerSpecific); + } + List ordered = []; - foreach (IGrouping grouping in hasAccess.GroupBy(setting => setting.Header)) + foreach (IGrouping grouping in playerSettings.GroupBy(setting => setting.Header)) { ordered.Add(grouping.Key.Base); ordered.AddRange(grouping.Select(setting => setting.Base)); } - // force update stuff like CustomTextAreaSetting to be in PlayerSettings - foreach (CustomSetting setting in hasAccess) - EnsurePlayerSpecificSetting(player, setting); - if (ServerSpecificSettingsSync.DefinedSettings != null) ordered.AddRange(ServerSpecificSettingsSync.DefinedSettings); From ed7ae60abc5d4c7fe60f74f05bc64e42227cdce6 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Sun, 15 Jun 2025 20:35:16 +0200 Subject: [PATCH 02/12] More player specific --- .../Settings/ExampleDropdownSetting.cs | 9 +++--- .../Settings/ExampleKeybindSetting.cs | 6 ++-- .../Features/UserSettings/CustomSetting.cs | 32 +++++++++++++++---- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs index 51eaaab..506392d 100644 --- a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs +++ b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs @@ -14,8 +14,9 @@ public class ExampleDropdownSetting : CustomDropdownSetting /// /// Initializes a new instance of the class. /// - public ExampleDropdownSetting() - : base(901, "Example dropdown", exampleOptions) + /// The array of settings to use. + public ExampleDropdownSetting(string[]? settings = null) + : base(901, "Example dropdown", settings ?? exampleOptions) { } @@ -23,10 +24,10 @@ public ExampleDropdownSetting() public override CustomHeader Header { get; } = CustomHeader.Examples; /// - protected override CustomSetting CreateDuplicate() => new ExampleDropdownSetting(); + protected override CustomSetting CreatePlayerSetting(Player player) => new ExampleDropdownSetting(); /// - protected override void HandleSettingUpdate(Player player) + protected override void HandleSettingUpdate() { Logger.Info(SelectedOption); } diff --git a/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs b/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs index 53d6d1e..7367023 100644 --- a/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs +++ b/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs @@ -22,15 +22,15 @@ public ExampleKeybindSetting() public override CustomHeader Header { get; } = CustomHeader.Examples; /// - protected override CustomSetting CreateDuplicate() => new ExampleKeybindSetting(); + protected override CustomSetting CreatePlayerSetting(Player player) => new ExampleKeybindSetting(); /// - protected override void HandleSettingUpdate(Player player) + protected override void HandleSettingUpdate() { if (!IsPressed) return; - player.Kill(); + KnownOwner?.Kill(); } } } \ No newline at end of file diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index df45036..211e666 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -35,7 +35,8 @@ static CustomSetting() /// Initializes a new instance of the class. /// /// The setting to use for custom setting. - protected CustomSetting(ServerSpecificSettingBase setting) + /*/// The owner of the custom setting.*/ + protected CustomSetting(ServerSpecificSettingBase setting/*, Player? owner*/) { Base = setting; } @@ -53,6 +54,12 @@ protected CustomSetting(ServerSpecificSettingBase setting) /// public ServerSpecificSettingBase Base { get; } + /// + /// Gets the known owner. + /// + /// This is null on the original object . + public Player? KnownOwner { get; internal set; } + /// /// Gets the of the setting. /// @@ -154,7 +161,9 @@ public static bool TryGetPlayerSetting(Player player, [NotNullWhen(tru /// The setting class to check for. /// The found matching the params, otherwise null. public static T? GetPlayerSetting(int id, Player player) - where T : CustomSetting => PlayerSettings.TryGetValue(player, out List settings) ? settings.FirstOrDefault(s => s.Base.SettingId == id && s.GetType() == typeof(T)) as T : null; + where T : CustomSetting => PlayerSettings.TryGetValue(player, out List settings) + ? settings.FirstOrDefault(s => s.Base.SettingId == id && s.GetType() == typeof(T)) as T + : null; /// /// Updates the settings of a player based on . @@ -171,6 +180,7 @@ public static void SendSettingsToPlayer(Player player, int? version = null) foreach (CustomSetting setting in hasAccess) { CustomSetting playerSpecific = EnsurePlayerSpecificSetting(player, setting); + playerSpecific.UpdatePlayerSetting(); playerSettings.Add(playerSpecific); } @@ -197,14 +207,21 @@ public static void SendSettingsToPlayer(Player player, int? version = null) /// /// Creates a duplicate of the current setting. Used to properly sync values and implement . /// + /// The player who's setting is being created. /// The duplicate setting created. - protected abstract CustomSetting CreateDuplicate(); + protected abstract CustomSetting CreatePlayerSetting(Player player); + + /// + /// Called before setting is re-sent to a player. Should be used to create player specific args. + /// + protected virtual void UpdatePlayerSetting() + { + } /// /// Handles the updating of a setting. /// - /// The player to update. - protected abstract void HandleSettingUpdate(Player player); + protected abstract void HandleSettingUpdate(); private static void RemoveStoredPlayer(Player player) => ReceivedPlayerSettings.Remove(player); @@ -227,7 +244,7 @@ private static void OnSettingsUpdated(ReferenceHub hub, ServerSpecificSettingBas settingBase.SerializeValue(valueWriter); newSettingPlayer.Base.DeserializeEntry(new NetworkReader(entryWriter.buffer)); newSettingPlayer.Base.DeserializeValue(new NetworkReader(valueWriter.buffer)); - newSettingPlayer.HandleSettingUpdate(player); + newSettingPlayer.HandleSettingUpdate(); } private static CustomSetting EnsurePlayerSpecificSetting(Player player, CustomSetting toMatch) @@ -236,7 +253,8 @@ private static CustomSetting EnsurePlayerSpecificSetting(Player player, CustomSe CustomSetting? currentSetting = settings.FirstOrDefault(s => s.Id == toMatch.Id); if (currentSetting == null) { - currentSetting = toMatch.CreateDuplicate(); + currentSetting = toMatch.CreatePlayerSetting(player); + currentSetting.KnownOwner = player; settings.Add(currentSetting); } From f37018ea15e86a6e0633c86ad1170dfc4bf1312a Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Sun, 15 Jun 2025 20:39:38 +0200 Subject: [PATCH 03/12] Update docs and remove Player arg --- SecretAPI/Features/UserSettings/CustomSetting.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 211e666..5d1c0bd 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -207,19 +207,18 @@ public static void SendSettingsToPlayer(Player player, int? version = null) /// /// Creates a duplicate of the current setting. Used to properly sync values and implement . /// - /// The player who's setting is being created. /// The duplicate setting created. - protected abstract CustomSetting CreatePlayerSetting(Player player); + protected abstract CustomSetting CreatePlayerSetting(); /// - /// Called before setting is re-sent to a player. Should be used to create player specific args. + /// Called before setting is sent to a player. Should be used to create player specific options. /// protected virtual void UpdatePlayerSetting() { } /// - /// Handles the updating of a setting. + /// Called when client sends a new value on the setting. /// protected abstract void HandleSettingUpdate(); @@ -253,7 +252,7 @@ private static CustomSetting EnsurePlayerSpecificSetting(Player player, CustomSe CustomSetting? currentSetting = settings.FirstOrDefault(s => s.Id == toMatch.Id); if (currentSetting == null) { - currentSetting = toMatch.CreatePlayerSetting(player); + currentSetting = toMatch.CreatePlayerSetting(); currentSetting.KnownOwner = player; settings.Add(currentSetting); } From a94675af3318df1cdf1edf0042856509ace05185 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Sun, 15 Jun 2025 20:40:56 +0200 Subject: [PATCH 04/12] Update examples --- SecretAPI.Examples/Settings/ExampleDropdownSetting.cs | 7 +++---- SecretAPI.Examples/Settings/ExampleKeybindSetting.cs | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs index 506392d..02190f6 100644 --- a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs +++ b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs @@ -14,9 +14,8 @@ public class ExampleDropdownSetting : CustomDropdownSetting /// /// Initializes a new instance of the class. /// - /// The array of settings to use. - public ExampleDropdownSetting(string[]? settings = null) - : base(901, "Example dropdown", settings ?? exampleOptions) + public ExampleDropdownSetting() + : base(901, "Example dropdown", exampleOptions) { } @@ -24,7 +23,7 @@ public ExampleDropdownSetting(string[]? settings = null) public override CustomHeader Header { get; } = CustomHeader.Examples; /// - protected override CustomSetting CreatePlayerSetting(Player player) => new ExampleDropdownSetting(); + protected override CustomSetting CreatePlayerSetting() => new ExampleDropdownSetting(); /// protected override void HandleSettingUpdate() diff --git a/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs b/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs index 7367023..207aec4 100644 --- a/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs +++ b/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs @@ -22,7 +22,7 @@ public ExampleKeybindSetting() public override CustomHeader Header { get; } = CustomHeader.Examples; /// - protected override CustomSetting CreatePlayerSetting(Player player) => new ExampleKeybindSetting(); + protected override CustomSetting CreatePlayerSetting() => new ExampleKeybindSetting(); /// protected override void HandleSettingUpdate() From 07f505f22cc1c7f881b70a2ddb590faf409b16d2 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Sun, 15 Jun 2025 20:50:40 +0200 Subject: [PATCH 05/12] Rename back to CreateDuplicate --- SecretAPI.Examples/Settings/ExampleDropdownSetting.cs | 2 +- SecretAPI.Examples/Settings/ExampleKeybindSetting.cs | 2 +- SecretAPI/Features/UserSettings/CustomSetting.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs index 02190f6..b2c8c63 100644 --- a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs +++ b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs @@ -23,7 +23,7 @@ public ExampleDropdownSetting() public override CustomHeader Header { get; } = CustomHeader.Examples; /// - protected override CustomSetting CreatePlayerSetting() => new ExampleDropdownSetting(); + protected override CustomSetting CreateDuplicate() => new ExampleDropdownSetting(); /// protected override void HandleSettingUpdate() diff --git a/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs b/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs index 207aec4..ed09fe3 100644 --- a/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs +++ b/SecretAPI.Examples/Settings/ExampleKeybindSetting.cs @@ -22,7 +22,7 @@ public ExampleKeybindSetting() public override CustomHeader Header { get; } = CustomHeader.Examples; /// - protected override CustomSetting CreatePlayerSetting() => new ExampleKeybindSetting(); + protected override CustomSetting CreateDuplicate() => new ExampleKeybindSetting(); /// protected override void HandleSettingUpdate() diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 5d1c0bd..7aeea17 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -208,7 +208,7 @@ public static void SendSettingsToPlayer(Player player, int? version = null) /// Creates a duplicate of the current setting. Used to properly sync values and implement . /// /// The duplicate setting created. - protected abstract CustomSetting CreatePlayerSetting(); + protected abstract CustomSetting CreateDuplicate(); /// /// Called before setting is sent to a player. Should be used to create player specific options. @@ -252,7 +252,7 @@ private static CustomSetting EnsurePlayerSpecificSetting(Player player, CustomSe CustomSetting? currentSetting = settings.FirstOrDefault(s => s.Id == toMatch.Id); if (currentSetting == null) { - currentSetting = toMatch.CreatePlayerSetting(); + currentSetting = toMatch.CreateDuplicate(); currentSetting.KnownOwner = player; settings.Add(currentSetting); } From 7c793e0a591b6ea6461e285d8d4afba15037e962 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:05:07 +0200 Subject: [PATCH 06/12] ExampleDropdownSetting | Supporter example --- .../Settings/ExampleDropdownSetting.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs index b2c8c63..05e97c4 100644 --- a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs +++ b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs @@ -1,7 +1,7 @@ namespace SecretAPI.Examples.Settings { using LabApi.Features.Console; - using LabApi.Features.Wrappers; + using LabApi.Features.Permissions; using SecretAPI.Features.UserSettings; /// @@ -10,6 +10,7 @@ public class ExampleDropdownSetting : CustomDropdownSetting { private static string[] exampleOptions = ["hi", "test", "yum", "fish", "nugget"]; + private static string[] exampleSupporterOptions = ["bucket", "lava", "wanted", "globe"]; /// /// Initializes a new instance of the class. @@ -25,6 +26,15 @@ public ExampleDropdownSetting() /// protected override CustomSetting CreateDuplicate() => new ExampleDropdownSetting(); + /// + protected override void UpdatePlayerSetting() + { + if (KnownOwner == null || !KnownOwner.HasAnyPermission("example.supporter")) + return; + + Base.Options = exampleSupporterOptions; + } + /// protected override void HandleSettingUpdate() { From 89644087e7376d107803beae7beb4cbb15344c73 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Thu, 19 Jun 2025 13:18:01 +0200 Subject: [PATCH 07/12] New setting stuff --- .../UserSettings/CustomDropdownSetting.cs | 9 ++- .../UserSettings/CustomKeybindSetting.cs | 19 ------- .../Features/UserSettings/CustomSetting.cs | 55 +++++++++++++------ .../UserSettings/CustomSliderSetting.cs | 27 +++++++-- 4 files changed, 66 insertions(+), 44 deletions(-) diff --git a/SecretAPI/Features/UserSettings/CustomDropdownSetting.cs b/SecretAPI/Features/UserSettings/CustomDropdownSetting.cs index ec2f146..09dacf8 100644 --- a/SecretAPI/Features/UserSettings/CustomDropdownSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomDropdownSetting.cs @@ -47,13 +47,16 @@ protected CustomDropdownSetting( public string[] Options { get => Base.Options; - [Obsolete("Setting this value is not currently supported.")] - set => Base.Options = value; + set + { + Base.Options = value; + ResyncToOwner(); + } } /// /// Gets the selected option as string. /// - public string SelectedOption => Base.SyncSelectionText; + public string SelectedOption => Options[Base.SyncSelectionIndexRaw]; } } \ No newline at end of file diff --git a/SecretAPI/Features/UserSettings/CustomKeybindSetting.cs b/SecretAPI/Features/UserSettings/CustomKeybindSetting.cs index 5554329..27c4108 100644 --- a/SecretAPI/Features/UserSettings/CustomKeybindSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomKeybindSetting.cs @@ -19,25 +19,6 @@ protected CustomKeybindSetting(SSKeybindSetting setting) Base = setting; } - /// - /// Initializes a new instance of the class. - /// - /// The ID of the setting. - /// The setting's label. - /// The suggested key. - /// Whether to prevent interaction in a GUI. - /// The hint to show. - [Obsolete("Use CustomKeybindSetting(int?, string, KeyCode, bool, bool, string?)")] - protected CustomKeybindSetting( - int? id, - string label, - KeyCode suggestedKey = KeyCode.None, - bool preventInteractionOnGui = true, - string? hint = null) - : this(id, label, suggestedKey, preventInteractionOnGui, true, hint) - { - } - /// /// Initializes a new instance of the class. /// diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 7aeea17..13ca6d0 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -6,7 +6,6 @@ using System.Linq; using global::UserSettings.ServerSpecific; using LabApi.Events.Handlers; - using LabApi.Features.Console; using LabApi.Features.Wrappers; using Mirror; using SecretAPI.Extensions; @@ -98,15 +97,16 @@ public int Id public static void Register(IEnumerable settings) => CustomSettings.AddRange(settings); /// - /// Tries to get player specific setting. + /// Unregisters collection of settings. /// - /// The player to get settings of. - /// The setting found. - /// The setting type to find. - /// Whether setting was found. - [Obsolete("Use TryGetPlayerSetting(Player, out TSetting)")] - public static bool TryGet(Player player, [NotNullWhen(true)] out T? setting) - where T : CustomSetting => TryGetPlayerSetting(player, out setting); + /// The settings to unregister. + public static void UnRegister(params CustomSetting[] settings) => CustomSettings.RemoveAll(s => settings.Contains(s)); + + /// + /// Unregisters a collection of settings. + /// + /// The settings to unregister. + public static void UnRegister(IEnumerable settings) => CustomSettings.RemoveAll(s => settings.Contains(s)); /// /// Tries to get player specific setting. @@ -135,6 +135,18 @@ public static bool TryGetPlayerSetting(Player player, [NotNullWhen(tru return false; } + /// + /// Gets a player's . + /// + /// The ID of the setting. + /// The player of which to get the setting from. + /// The setting class to check for. + /// The found matching the params, otherwise null. + public static T? GetPlayerSetting(int id, Player player) + where T : CustomSetting => PlayerSettings.TryGetValue(player, out List settings) + ? settings.FirstOrDefault(s => s.Base.SettingId == id && s.GetType() == typeof(T)) as T + : null; + /// /// Gets a , used for validation. /// @@ -154,16 +166,14 @@ public static bool TryGetPlayerSetting(Player player, [NotNullWhen(tru where T : CustomSetting => CustomSettings.FirstOrDefault(s => s.Base.SettingId == id && s.GetType() == typeof(T)) as T; /// - /// Gets a player's . + /// Resyncs all settings to all players. /// - /// The ID of the setting. - /// The player of which to get the setting from. - /// The setting class to check for. - /// The found matching the params, otherwise null. - public static T? GetPlayerSetting(int id, Player player) - where T : CustomSetting => PlayerSettings.TryGetValue(player, out List settings) - ? settings.FirstOrDefault(s => s.Base.SettingId == id && s.GetType() == typeof(T)) as T - : null; + /// The version of the setting. If null will use . + public static void ResyncServer(int? version = null) + { + foreach (Player player in Player.ReadyList) + SendSettingsToPlayer(player, version); + } /// /// Updates the settings of a player based on . @@ -197,6 +207,15 @@ public static void SendSettingsToPlayer(Player player, int? version = null) ServerSpecificSettingsSync.SendToPlayer(player.ReferenceHub, [.. ordered], version); } + /// + /// Resyncs the setting to its owner. + /// + protected void ResyncToOwner() + { + if (KnownOwner != null) + SendSettingsToPlayer(KnownOwner); + } + /// /// Checks if a player is able to view a setting. /// diff --git a/SecretAPI/Features/UserSettings/CustomSliderSetting.cs b/SecretAPI/Features/UserSettings/CustomSliderSetting.cs index 95cdc55..abfc5e2 100644 --- a/SecretAPI/Features/UserSettings/CustomSliderSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSliderSetting.cs @@ -63,8 +63,11 @@ protected CustomSliderSetting( public float MinimumValue { get => Base.MinValue; - [Obsolete("Setting this value is not currently supported.")] - set => Base.MinValue = value; + set + { + Base.MinValue = value; + ResyncToOwner(); + } } /// @@ -73,8 +76,11 @@ public float MinimumValue public float MaximumValue { get => Base.MaxValue; - [Obsolete("Setting this value is not currently supported.")] - set => Base.MaxValue = value; + set + { + Base.MaxValue = value; + ResyncToOwner(); + } } /// @@ -86,5 +92,18 @@ public float DefaultValue [Obsolete("Setting this value is not currently supported.")] set => Base.DefaultValue = value; } + + /// + /// Gets or sets a value indicating whether to use integer. False will use float. + /// + public bool UseInteger + { + get => Base.Integer; + set + { + Base.Integer = value; + ResyncToOwner(); + } + } } } \ No newline at end of file From e289dfc5a3808db492525d6938f607b348eca9b1 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Thu, 19 Jun 2025 13:18:45 +0200 Subject: [PATCH 08/12] remove unused comment --- SecretAPI/Features/UserSettings/CustomSetting.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 13ca6d0..c55d015 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -34,8 +34,7 @@ static CustomSetting() /// Initializes a new instance of the class. /// /// The setting to use for custom setting. - /*/// The owner of the custom setting.*/ - protected CustomSetting(ServerSpecificSettingBase setting/*, Player? owner*/) + protected CustomSetting(ServerSpecificSettingBase setting) { Base = setting; } From 496146d99615723a470eef481d02911abc1b9831 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:33:33 +0200 Subject: [PATCH 09/12] SendSettings(Player/Server)Sync patches --- .../Features/UserSettings/CustomSetting.cs | 6 ++--- .../Features/SendSettingsPlayerSync.cs | 22 +++++++++++++++++++ .../Features/SendSettingsServerSync.cs | 21 ++++++++++++++++++ .../Features/SettingsOriginalDefinitionFix.cs | 2 -- 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 SecretAPI/Patches/Features/SendSettingsPlayerSync.cs create mode 100644 SecretAPI/Patches/Features/SendSettingsServerSync.cs diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index c55d015..05a2b22 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -182,8 +182,6 @@ public static void ResyncServer(int? version = null) /// This will be automatically called on and . public static void SendSettingsToPlayer(Player player, int? version = null) { - version ??= ServerSpecificSettingsSync.Version; - IEnumerable hasAccess = CustomSettings.Where(s => s.CanView(player)); List playerSettings = []; foreach (CustomSetting setting in hasAccess) @@ -203,7 +201,9 @@ public static void SendSettingsToPlayer(Player player, int? version = null) if (ServerSpecificSettingsSync.DefinedSettings != null) ordered.AddRange(ServerSpecificSettingsSync.DefinedSettings); - ServerSpecificSettingsSync.SendToPlayer(player.ReferenceHub, [.. ordered], version); + ServerSpecificSettingBase[] sendSettings = ordered.ToArray(); + ServerSpecificSettingsSync.SendToPlayer(player.ReferenceHub, sendSettings, version); + /*player.ReferenceHub.connectionToClient.Send(new SSSEntriesPack(sendSettings, version ?? ServerSpecificSettingsSync.Version));*/ } /// diff --git a/SecretAPI/Patches/Features/SendSettingsPlayerSync.cs b/SecretAPI/Patches/Features/SendSettingsPlayerSync.cs new file mode 100644 index 0000000..43ec3f7 --- /dev/null +++ b/SecretAPI/Patches/Features/SendSettingsPlayerSync.cs @@ -0,0 +1,22 @@ +namespace SecretAPI.Patches.Features +{ + using HarmonyLib; + using LabApi.Features.Wrappers; + using SecretAPI.Attribute; + using SecretAPI.Features.UserSettings; + using UserSettings.ServerSpecific; + + /// + /// Fixes to resync with . + /// + [HarmonyPatchCategory(nameof(CustomSetting))] + [HarmonyPatch(typeof(ServerSpecificSettingsSync), nameof(ServerSpecificSettingsSync.SendToPlayer), [typeof(ReferenceHub)])] + internal static class SendSettingsPlayerSync + { + private static bool Prefix(ReferenceHub referenceHub) + { + CustomSetting.SendSettingsToPlayer(Player.Get(referenceHub)); + return false; + } + } +} \ No newline at end of file diff --git a/SecretAPI/Patches/Features/SendSettingsServerSync.cs b/SecretAPI/Patches/Features/SendSettingsServerSync.cs new file mode 100644 index 0000000..cb2fd52 --- /dev/null +++ b/SecretAPI/Patches/Features/SendSettingsServerSync.cs @@ -0,0 +1,21 @@ +namespace SecretAPI.Patches.Features +{ + using HarmonyLib; + using SecretAPI.Attribute; + using SecretAPI.Features.UserSettings; + using UserSettings.ServerSpecific; + + /// + /// Fixes to resync with . + /// + [HarmonyPatchCategory(nameof(CustomSetting))] + [HarmonyPatch(typeof(ServerSpecificSettingsSync), nameof(ServerSpecificSettingsSync.SendToAll))] + internal static class SendSettingsServerSync + { + private static bool Prefix() + { + CustomSetting.ResyncServer(); + return false; + } + } +} \ No newline at end of file diff --git a/SecretAPI/Patches/Features/SettingsOriginalDefinitionFix.cs b/SecretAPI/Patches/Features/SettingsOriginalDefinitionFix.cs index 38a9167..0b1c9c1 100644 --- a/SecretAPI/Patches/Features/SettingsOriginalDefinitionFix.cs +++ b/SecretAPI/Patches/Features/SettingsOriginalDefinitionFix.cs @@ -1,8 +1,6 @@ namespace SecretAPI.Patches.Features { - using System; using HarmonyLib; - using LabApi.Features.Console; using SecretAPI.Attribute; using SecretAPI.Features.UserSettings; using UserSettings.ServerSpecific; From 6888d5861ebe9714eace929d86a65b0fb166e808 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:46:07 +0200 Subject: [PATCH 10/12] optimizations my beloved --- SecretAPI/Features/UserSettings/CustomSetting.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 05a2b22..64c7322 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -8,6 +8,7 @@ using LabApi.Events.Handlers; using LabApi.Features.Wrappers; using Mirror; + using NorthwoodLib.Pools; using SecretAPI.Extensions; /// @@ -183,7 +184,7 @@ public static void ResyncServer(int? version = null) public static void SendSettingsToPlayer(Player player, int? version = null) { IEnumerable hasAccess = CustomSettings.Where(s => s.CanView(player)); - List playerSettings = []; + List playerSettings = ListPool.Shared.Rent(); foreach (CustomSetting setting in hasAccess) { CustomSetting playerSpecific = EnsurePlayerSpecificSetting(player, setting); @@ -191,8 +192,8 @@ public static void SendSettingsToPlayer(Player player, int? version = null) playerSettings.Add(playerSpecific); } - List ordered = []; - foreach (IGrouping grouping in playerSettings.GroupBy(setting => setting.Header)) + List ordered = ListPool.Shared.Rent(); + foreach (IGrouping grouping in playerSettings.GroupBy(static setting => setting.Header)) { ordered.Add(grouping.Key.Base); ordered.AddRange(grouping.Select(setting => setting.Base)); @@ -201,9 +202,10 @@ public static void SendSettingsToPlayer(Player player, int? version = null) if (ServerSpecificSettingsSync.DefinedSettings != null) ordered.AddRange(ServerSpecificSettingsSync.DefinedSettings); - ServerSpecificSettingBase[] sendSettings = ordered.ToArray(); - ServerSpecificSettingsSync.SendToPlayer(player.ReferenceHub, sendSettings, version); - /*player.ReferenceHub.connectionToClient.Send(new SSSEntriesPack(sendSettings, version ?? ServerSpecificSettingsSync.Version));*/ + ServerSpecificSettingsSync.SendToPlayer(player.ReferenceHub, ordered.ToArray(), version); + + ListPool.Shared.Return(playerSettings); + ListPool.Shared.Return(ordered); } /// From 489cd55162dfd47054886e8628bbcd67c9afead5 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:48:39 +0200 Subject: [PATCH 11/12] Optimization heaven --- SecretAPI/Features/UserSettings/CustomSetting.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 64c7322..0053c1a 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -183,10 +183,12 @@ public static void ResyncServer(int? version = null) /// This will be automatically called on and . public static void SendSettingsToPlayer(Player player, int? version = null) { - IEnumerable hasAccess = CustomSettings.Where(s => s.CanView(player)); List playerSettings = ListPool.Shared.Rent(); - foreach (CustomSetting setting in hasAccess) + foreach (CustomSetting setting in CustomSettings) { + if (!setting.CanView(player)) + continue; + CustomSetting playerSpecific = EnsurePlayerSpecificSetting(player, setting); playerSpecific.UpdatePlayerSetting(); playerSettings.Add(playerSpecific); @@ -196,7 +198,7 @@ public static void SendSettingsToPlayer(Player player, int? version = null) foreach (IGrouping grouping in playerSettings.GroupBy(static setting => setting.Header)) { ordered.Add(grouping.Key.Base); - ordered.AddRange(grouping.Select(setting => setting.Base)); + ordered.AddRange(grouping.Select(static setting => setting.Base)); } if (ServerSpecificSettingsSync.DefinedSettings != null) From f453e985b68d550df9415936032d4e5c408c2801 Mon Sep 17 00:00:00 2001 From: Misfiy <85962933+Misfiy@users.noreply.github.com> Date: Sat, 21 Jun 2025 20:34:39 +0200 Subject: [PATCH 12/12] fix wtf the issue is --- SecretAPI.Examples/ExampleEntry.cs | 2 +- .../Settings/ExampleDropdownSetting.cs | 4 +-- SecretAPI/Extensions/HarmonyExtensions.cs | 2 +- .../UserSettings/CustomDropdownSetting.cs | 14 +++++---- .../Features/UserSettings/CustomSetting.cs | 31 ++++++++----------- .../UserSettings/CustomSliderSetting.cs | 18 ++--------- .../Features/SendSettingsPlayerSync.cs | 4 +-- SecretAPI/SecretApi.cs | 2 +- 8 files changed, 31 insertions(+), 46 deletions(-) diff --git a/SecretAPI.Examples/ExampleEntry.cs b/SecretAPI.Examples/ExampleEntry.cs index e390ec7..d1b733c 100644 --- a/SecretAPI.Examples/ExampleEntry.cs +++ b/SecretAPI.Examples/ExampleEntry.cs @@ -16,7 +16,7 @@ public class ExampleEntry : Plugin private Harmony? harmony; /// - public override string Name { get; } = "SecretAPI.Example"; + public override string Name { get; } = "SecretAPI.Examples"; /// public override string Description { get; } = "An example plugin"; diff --git a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs index 05e97c4..c9f669d 100644 --- a/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs +++ b/SecretAPI.Examples/Settings/ExampleDropdownSetting.cs @@ -32,13 +32,13 @@ protected override void UpdatePlayerSetting() if (KnownOwner == null || !KnownOwner.HasAnyPermission("example.supporter")) return; - Base.Options = exampleSupporterOptions; + Options = exampleSupporterOptions; } /// protected override void HandleSettingUpdate() { - Logger.Info(SelectedOption); + Logger.Info($"{KnownOwner?.DisplayName ?? "null reference"} selected {SelectedOption} (Index {ValidatedSelectedIndex}/{Options.Length})"); } } } \ No newline at end of file diff --git a/SecretAPI/Extensions/HarmonyExtensions.cs b/SecretAPI/Extensions/HarmonyExtensions.cs index 5373cca..1a62a0b 100644 --- a/SecretAPI/Extensions/HarmonyExtensions.cs +++ b/SecretAPI/Extensions/HarmonyExtensions.cs @@ -56,7 +56,7 @@ private static void SafePatch(Harmony harmony, Type type) } catch (Exception ex) { - Logger.Error($"[GlobalPatcher] 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/CustomDropdownSetting.cs b/SecretAPI/Features/UserSettings/CustomDropdownSetting.cs index 09dacf8..1928fdf 100644 --- a/SecretAPI/Features/UserSettings/CustomDropdownSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomDropdownSetting.cs @@ -1,6 +1,7 @@ namespace SecretAPI.Features.UserSettings { using System; + using System.Linq; using global::UserSettings.ServerSpecific; /// @@ -41,22 +42,23 @@ protected CustomDropdownSetting( /// public new SSDropdownSetting Base { get; } + /// + /// Gets the selected index after validation. + /// + public int ValidatedSelectedIndex => Math.Clamp(Base.SyncSelectionIndexRaw, 0, Options.Length - 1); + /// /// Gets or sets the options. /// public string[] Options { get => Base.Options; - set - { - Base.Options = value; - ResyncToOwner(); - } + set => Base.Options = value; } /// /// Gets the selected option as string. /// - public string SelectedOption => Options[Base.SyncSelectionIndexRaw]; + public string SelectedOption => Options[ValidatedSelectedIndex]; } } \ No newline at end of file diff --git a/SecretAPI/Features/UserSettings/CustomSetting.cs b/SecretAPI/Features/UserSettings/CustomSetting.cs index 0053c1a..908207f 100644 --- a/SecretAPI/Features/UserSettings/CustomSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSetting.cs @@ -6,6 +6,7 @@ using System.Linq; using global::UserSettings.ServerSpecific; using LabApi.Events.Handlers; + using LabApi.Features.Console; using LabApi.Features.Wrappers; using Mirror; using NorthwoodLib.Pools; @@ -57,7 +58,7 @@ protected CustomSetting(ServerSpecificSettingBase setting) /// Gets the known owner. /// /// This is null on the original object . - public Player? KnownOwner { get; internal set; } + public Player? KnownOwner { get; private set; } /// /// Gets the of the setting. @@ -65,24 +66,14 @@ protected CustomSetting(ServerSpecificSettingBase setting) public abstract CustomHeader Header { get; } /// - /// Gets or sets the current label. + /// Gets the current label. /// - public string Label - { - get => Base.Label; - [Obsolete("Should not be set after creation.")] - set => Base.Label = value; - } + public string Label => Base.Label; /// - /// Gets or sets the current id. + /// Gets the current id. /// - public int Id - { - get => Base.SettingId; - [Obsolete("Should not be set after creation.")] - set => Base.SettingId = value; - } + public int Id => Base.SettingId; /// /// Registers a collection of settings. @@ -183,6 +174,9 @@ public static void ResyncServer(int? version = null) /// This will be automatically called on and . public static void SendSettingsToPlayer(Player player, int? version = null) { + if (player.IsHost) + return; + List playerSettings = ListPool.Shared.Rent(); foreach (CustomSetting setting in CustomSettings) { @@ -259,12 +253,13 @@ private static void OnSettingsUpdated(ReferenceHub hub, ServerSpecificSettingBas CustomSetting newSettingPlayer = EnsurePlayerSpecificSetting(player, setting); - NetworkWriter entryWriter = new(); + // NetworkWriter entryWriter = new(); + // settingBase.SerializeEntry(entryWriter); + // newSettingPlayer.Base.DeserializeEntry(new NetworkReader(entryWriter.buffer)); NetworkWriter valueWriter = new(); - settingBase.SerializeEntry(entryWriter); settingBase.SerializeValue(valueWriter); - newSettingPlayer.Base.DeserializeEntry(new NetworkReader(entryWriter.buffer)); newSettingPlayer.Base.DeserializeValue(new NetworkReader(valueWriter.buffer)); + newSettingPlayer.HandleSettingUpdate(); } diff --git a/SecretAPI/Features/UserSettings/CustomSliderSetting.cs b/SecretAPI/Features/UserSettings/CustomSliderSetting.cs index abfc5e2..7786333 100644 --- a/SecretAPI/Features/UserSettings/CustomSliderSetting.cs +++ b/SecretAPI/Features/UserSettings/CustomSliderSetting.cs @@ -63,11 +63,7 @@ protected CustomSliderSetting( public float MinimumValue { get => Base.MinValue; - set - { - Base.MinValue = value; - ResyncToOwner(); - } + set => Base.MinValue = value; } /// @@ -76,11 +72,7 @@ public float MinimumValue public float MaximumValue { get => Base.MaxValue; - set - { - Base.MaxValue = value; - ResyncToOwner(); - } + set => Base.MaxValue = value; } /// @@ -99,11 +91,7 @@ public float DefaultValue public bool UseInteger { get => Base.Integer; - set - { - Base.Integer = value; - ResyncToOwner(); - } + set => Base.Integer = value; } } } \ No newline at end of file diff --git a/SecretAPI/Patches/Features/SendSettingsPlayerSync.cs b/SecretAPI/Patches/Features/SendSettingsPlayerSync.cs index 43ec3f7..dcc3c58 100644 --- a/SecretAPI/Patches/Features/SendSettingsPlayerSync.cs +++ b/SecretAPI/Patches/Features/SendSettingsPlayerSync.cs @@ -13,9 +13,9 @@ [HarmonyPatch(typeof(ServerSpecificSettingsSync), nameof(ServerSpecificSettingsSync.SendToPlayer), [typeof(ReferenceHub)])] internal static class SendSettingsPlayerSync { - private static bool Prefix(ReferenceHub referenceHub) + private static bool Prefix(ReferenceHub hub) { - CustomSetting.SendSettingsToPlayer(Player.Get(referenceHub)); + CustomSetting.SendSettingsToPlayer(Player.Get(hub)); return false; } } diff --git a/SecretAPI/SecretApi.cs b/SecretAPI/SecretApi.cs index bb05f7b..63b6e3f 100644 --- a/SecretAPI/SecretApi.cs +++ b/SecretAPI/SecretApi.cs @@ -43,7 +43,7 @@ public class SecretApi : Plugin /// public override void Enable() { - Harmony = new Harmony("SecretAPI" + DateTime.Now); + Harmony = new Harmony("SecretAPI-" + DateTime.Now.Ticks); CustomPlayerEffect.Initialize(); }