Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions SecretAPI/Features/UserSettings/CustomButtonSetting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,34 @@ protected CustomButtonSetting(int? id, string label, string buttonText, float? h
public TimeSpan LastPress => Base.SyncLastPress.Elapsed;

/// <summary>
/// Gets the text of the button.
/// Gets or sets the text of the button.
/// </summary>
public string Text => Base.ButtonText;
public string Text
{
get => Base.ButtonText;
set
{
Base.ButtonText = value;
SendButtonUpdate();
}
}

/// <summary>
/// Gets or sets the amount of time to hold the button in seconds.
/// </summary>
public float RequiredHoldTime
{
get => Base.HoldTimeSeconds;
set
{
Base.HoldTimeSeconds = value;
SendButtonUpdate();
}
}

/// <summary>
/// Gets the amount of time to hold the button in seconds.
/// Sends an update to <see cref="CustomSetting.KnownOwner"/> that <see cref="Text"/> or <see cref="RequiredHoldTime"/> has updated.
/// </summary>
public float HoldTime => Base.HoldTimeSeconds;
private void SendButtonUpdate() => Base.SendButtonUpdate(Text, RequiredHoldTime, false, IsKnownOwnerHub);
}
}
53 changes: 50 additions & 3 deletions SecretAPI/Features/UserSettings/CustomDropdownSetting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,27 @@ protected CustomDropdownSetting(SSDropdownSetting setting)
/// <param name="defaultOptionIndex">The default option (int index).</param>
/// <param name="entryType">The entry type.</param>
/// <param name="hint">The hint to show.</param>
/// <param name="collectionId">The <see cref="CustomSetting.CollectionId"/>.</param>
/// <param name="isServerSetting">See <see cref="CustomSetting.IsServerSetting"/>.</param>
protected CustomDropdownSetting(
int? id,
string label,
string[] options,
int defaultOptionIndex = 0,
SSDropdownSetting.DropdownEntryType entryType = SSDropdownSetting.DropdownEntryType.Regular,
string? hint = null)
: this(new SSDropdownSetting(id, label, options, defaultOptionIndex, entryType, hint))
string? hint = null,
byte collectionId = byte.MaxValue,
bool isServerSetting = false)
: this(new SSDropdownSetting(id, label, options, defaultOptionIndex, entryType, hint, collectionId, isServerSetting))
{
}

/// <inheritdoc/>
public new SSDropdownSetting Base { get; }

/// <inheritdoc />
public override bool HasValueChanged => LastSelectedIndex != SyncedIndex;

/// <summary>
/// Gets the index the client is claiming to have selected.
/// </summary>
Expand All @@ -58,12 +65,52 @@ protected CustomDropdownSetting(
public string[] Options
{
get => Base.Options;
set => Base.Options = value;
set
{
Base.Options = value;
SendDropdownUpdate();
}
}

/// <summary>
/// Gets the selected option as string.
/// </summary>
public string SelectedOption => Options[ValidatedSelectedIndex];

/// <summary>
/// Gets the <see cref="SSDropdownSetting.DropdownEntryType"/>.
/// </summary>
/// <remarks>Refer to https://github.com/HubertMoszka/Server-Specific-Settings-System/blob/main/SSDropdownSetting.cs#L151 for proper documentation.</remarks>
public SSDropdownSetting.DropdownEntryType EntryType => Base.EntryType;

/// <summary>
/// Gets the last selected index, or -1 if none was selected previously.
/// </summary>
public int LastSelectedIndex { get; private set; } = -1;

/// <summary>
/// Gets the selected option prior to the most recent <see cref="CustomSetting.HandleSettingUpdate"/> call as a string, or null if none was selected previously.
/// </summary>
public string? LastSelectedOption => LastSelectedIndex < 0 || LastSelectedIndex >= Options.Length ? null : Options[LastSelectedIndex];

/// <summary>
/// Sends an update to <see cref="CustomSetting.KnownOwner"/> that this has been updated on Server. Only works if <see cref="CustomSetting.IsServerSetting"/> is true.
/// </summary>
/// <param name="selectionId">The new ID selected.</param>
public void SendServerUpdate(int selectionId) => Base.SendValueUpdate(selectionId, false, IsKnownOwnerHub);

/// <inheritdoc />
protected internal override void HandleBeforeSettingUpdate()
{
base.HandleBeforeSettingUpdate();

if (LastUpdateType != SettingResponseType.Initial)
LastSelectedIndex = SyncedIndex;
}

/// <summary>
/// Sends an update to <see cref="CustomSetting.KnownOwner"/> that <see cref="Options"/> has been updated.
/// </summary>
private void SendDropdownUpdate() => Base.SendDropdownUpdate(Options, false, IsKnownOwnerHub);
}
}
2 changes: 2 additions & 0 deletions SecretAPI/Features/UserSettings/CustomHeader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace SecretAPI.Features.UserSettings
{
using System;
using global::UserSettings.ServerSpecific;

/// <summary>
Expand All @@ -21,6 +22,7 @@ public CustomHeader(string label, bool reducedPadding = false, string? hint = nu
/// <summary>
/// Gets a <see cref="CustomHeader"/> for Gameplay purposes.
/// </summary>
[Obsolete("3.0 will remove this - Please handle your setting header yourself!")]
public static CustomHeader Gameplay { get; } = new("Gameplay", hint: "Features that affect gameplay");

/// <summary>
Expand Down
6 changes: 4 additions & 2 deletions SecretAPI/Features/UserSettings/CustomKeybindSetting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ protected CustomKeybindSetting(SSKeybindSetting setting)
/// <param name="preventInteractionOnGui">Whether to prevent interaction in a GUI.</param>
/// <param name="allowSpectatorTrigger">Whether to allow spectators to trigger.</param>
/// <param name="hint">The hint to show.</param>
/// <param name="collectionId">The <see cref="CustomSetting.CollectionId"/>.</param>
protected CustomKeybindSetting(
int? id,
string label,
KeyCode suggestedKey = KeyCode.None,
bool preventInteractionOnGui = true,
bool allowSpectatorTrigger = true,
string? hint = null)
: this(new SSKeybindSetting(id, label, suggestedKey, preventInteractionOnGui, allowSpectatorTrigger, hint))
string? hint = null,
byte collectionId = byte.MaxValue)
: this(new SSKeybindSetting(id, label, suggestedKey, preventInteractionOnGui, allowSpectatorTrigger, hint, collectionId))
{
}

Expand Down
64 changes: 58 additions & 6 deletions SecretAPI/Features/UserSettings/CustomPlainTextSetting.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace SecretAPI.Features.UserSettings
{
using System;
using global::UserSettings.ServerSpecific;
using TMPro;

Expand Down Expand Up @@ -41,24 +42,75 @@ protected CustomPlainTextSetting(
/// <inheritdoc />
public new SSPlaintextSetting Base { get; }

/// <summary>
/// Gets the input text prior to the most recent <see cref="CustomSetting.HandleSettingUpdate"/> call.
/// </summary>
public string LastInputText
{
get => field ??= string.Empty;
private set;
}

/// <summary>
/// Gets the synced input text.
/// </summary>
public string InputText => Base.SyncInputText;

/// <summary>
/// Gets the content type.
/// Gets or sets the content type.
/// </summary>
public TMP_InputField.ContentType ContentType => Base.ContentType;
public TMP_InputField.ContentType ContentType
{
get => Base.ContentType;
set
{
Base.ContentType = value;
SendPlaintextUpdate();
}
}

/// <summary>
/// Gets the placeholder.
/// Gets or sets the placeholder.
/// </summary>
public string Placeholder => Base.Placeholder;
public string Placeholder
{
get => Base.Placeholder;
set
{
Base.Placeholder = value;
SendPlaintextUpdate();
}
}

/// <summary>
/// Gets or sets the character limit.
/// </summary>
public int CharacterLimit
{
get => Base.CharacterLimit;
set
{
Base.CharacterLimit = value;
SendPlaintextUpdate();
}
}

/// <summary>
/// Sends an update to <see cref="CustomSetting.KnownOwner"/> that this has been updated on Server. Only works if <see cref="CustomSetting.IsServerSetting"/> is true.
/// </summary>
/// <param name="text">The new text.</param>
public void SendServerUpdate(string text) => Base.SendValueUpdate(text, false, IsKnownOwnerHub);

/// <inheritdoc />
protected internal override void HandleBeforeSettingUpdate()
{
base.HandleBeforeSettingUpdate();
LastInputText = InputText;
}

/// <summary>
/// Gets the character limit.
/// Sends an update to the <see cref="CustomSetting.KnownOwner"/> that <see cref="Placeholder"/> <see cref="CharacterLimit"/> or <see cref="ContentType"/> has changed values.
/// </summary>
public int CharacterLimit => Base.CharacterLimit;
private void SendPlaintextUpdate() => Base.SendPlaintextUpdate(Placeholder, (ushort)Math.Clamp(CharacterLimit, ushort.MinValue, ushort.MaxValue), ContentType, false, IsKnownOwnerHub);
}
}
67 changes: 58 additions & 9 deletions SecretAPI/Features/UserSettings/CustomSetting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public abstract class CustomSetting : ISetting<ServerSpecificSettingBase>

static CustomSetting()
{
SecretApi.Harmony?.PatchCategory(nameof(CustomSetting));
SecretApi.Harmony?.PatchCategory(nameof(CustomSetting), SecretApi.Assembly);

ServerSpecificSettingsSync.SendOnJoinFilter = null;
ServerSpecificSettingsSync.DefinedSettings ??= []; // fix null ref
Expand Down Expand Up @@ -66,22 +66,42 @@ protected CustomSetting(ServerSpecificSettingBase setting)
public abstract CustomHeader Header { get; }

/// <summary>
/// Gets or sets a value indicating whether the setting is server side only.
/// Gets an enum indicating the type of the last update.
/// </summary>
/// <remarks>The setting value cannot be updated from client side and can be used to indicate server features being toggled.</remarks>
public bool IsServerOnly
/// <remarks>When used inside of <see cref="HandleSettingUpdate"/> it will indicate the current status.</remarks>
public SettingResponseType LastUpdateType { get; private set; } = SettingResponseType.None;

/// <summary>
/// Gets a value indicating whether the current value received is different to that prior to the most recent <see cref="CustomSetting.HandleSettingUpdate"/> call.
/// </summary>
public virtual bool HasValueChanged { get; }

/// <summary>
/// Gets or sets a value indicating whether the setting is server side.
/// </summary>
/// <remarks>This will result in client not saving the setting values and allows the server to change the setting .</remarks>
public bool IsServerSetting
{
get => Base.IsServerOnly;
set => Base.IsServerOnly = value;
}

/// <summary>
/// Gets a value indicating whether the setting is the default and not tied to a <see cref="Player"/>.
/// </summary>
public bool IsDefaultSetting => KnownOwner == null;

/// <summary>
/// Gets or sets the current label.
/// </summary>
public string Label
{
get => Base.Label;
set => Base.Label = value;
set
{
Base.Label = value;
SendSettingUpdate();
}
}

/// <summary>
Expand All @@ -90,7 +110,11 @@ public string Label
public string DescriptionHint
{
get => Base.HintDescription;
set => Base.HintDescription = value;
set
{
Base.HintDescription = value;
SendSettingUpdate();
}
}

/// <summary>
Expand Down Expand Up @@ -138,13 +162,13 @@ public bool IsShared
/// Unregisters collection of settings.
/// </summary>
/// <param name="settings">The settings to unregister.</param>
public static void UnRegister(params CustomSetting[] settings) => CustomSettings.RemoveAll(s => settings.Contains(s));
public static void UnRegister(params CustomSetting[] settings) => CustomSettings.RemoveAll(settings.Contains);

/// <summary>
/// Unregisters a collection of settings.
/// </summary>
/// <param name="settings">The settings to unregister.</param>
public static void UnRegister(IEnumerable<CustomSetting> settings) => CustomSettings.RemoveAll(s => settings.Contains(s));
public static void UnRegister(IEnumerable<CustomSetting> settings) => CustomSettings.RemoveAll(settings.Contains);

/// <summary>
/// Tries to get player specific setting.
Expand Down Expand Up @@ -252,6 +276,24 @@ public static void SendSettingsToPlayer(Player player, int? version = null)
ListPool<ServerSpecificSettingBase>.Shared.Return(ordered);
}

/// <summary>
/// Checks whether a <see cref="ReferenceHub"/> is equal to <see cref="KnownOwner"/>.
/// </summary>
/// <param name="hub">The <see cref="ReferenceHub"/> to check.</param>
/// <returns>Whether <see cref="ReferenceHub"/> is equal to Owner <see cref="ReferenceHub"/>.</returns>
internal bool IsKnownOwnerHub(ReferenceHub? hub) => hub && KnownOwner?.ReferenceHub == hub;

/// <summary>
/// Called before <see cref="HandleSettingUpdate"/>, adding <see cref="HasValueChanged"/> & <see cref="LastUpdateType"/>.
/// </summary>
/// <remarks>This will not have the current status.</remarks>
protected internal virtual void HandleBeforeSettingUpdate()
{
LastUpdateType = LastUpdateType == SettingResponseType.None
? SettingResponseType.Initial
: SettingResponseType.Update;
}

/// <summary>
/// Resyncs the setting to its owner.
/// </summary>
Expand Down Expand Up @@ -287,6 +329,7 @@ protected virtual void PersonalizeSetting()
/// <summary>
/// Called when client sends a new value on the setting.
/// </summary>
/// <remarks>You can use <see cref="LastUpdateType"/> to get the current update type.</remarks>
protected abstract void HandleSettingUpdate();

private static void RemoveStoredPlayer(Player player) => ReceivedPlayerSettings.Remove(player);
Expand All @@ -304,10 +347,11 @@ private static void OnSettingsUpdated(ReferenceHub hub, ServerSpecificSettingBas

// validate setting existence and then write data from client
CustomSetting newSettingPlayer = EnsurePlayerSpecificSetting(player, setting);
newSettingPlayer.HandleBeforeSettingUpdate();

NetworkWriterPooled valueWriter = NetworkWriterPool.Get();
settingBase.SerializeValue(valueWriter);
newSettingPlayer.Base.DeserializeValue(new NetworkReader(valueWriter.buffer));

NetworkWriterPool.Return(valueWriter);

newSettingPlayer.HandleSettingUpdate();
Expand All @@ -326,5 +370,10 @@ private static CustomSetting EnsurePlayerSpecificSetting(Player player, CustomSe

return currentSetting;
}

/// <summary>
/// Sends an update to <see cref="KnownOwner"/> that <see cref="Label"/> or <see cref="DescriptionHint"/> has changed.
/// </summary>
private void SendSettingUpdate() => Base.SendUpdate(Label, DescriptionHint, false, IsKnownOwnerHub);
}
}
Loading
Loading