Clean up and allow player ID and Friend code in player argument

This commit is contained in:
D1GQ committed 2026-04-11 15:31:47 -05:00
1 parent 6e648692a8
commit f89fdd1d2d
7 files changed
+95 -56

No files matched your search

+5 -7
View File
@@ -25,12 +25,10 @@ internal abstract class BaseArgument(BaseCommand command, string argInfo)
/// <summary>
/// Gets the argument suggestions for auto-completion.
/// </summary>
protected virtual string[] ArgSuggestions => GetArgSuggestions.Invoke();
/// <summary>
/// Gets or sets the function that provides argument suggestions.
/// </summary>
internal Func<string[]> GetArgSuggestions { get; set; } = () => { return []; };
protected virtual string[] GetArgSuggestions()
{
return [];
}
/// <summary>
/// Resets the Argument back to its default state.
@@ -45,5 +43,5 @@ internal abstract class BaseArgument(BaseCommand command, string argInfo)
/// </summary>
/// <returns>The closest matching suggestion, or empty string if none found.</returns>
internal string GetClosestSuggestion() =>
ArgSuggestions.FirstOrDefault(name => name.StartsWith(Arg, StringComparison.OrdinalIgnoreCase)) ?? string.Empty;
GetArgSuggestions().FirstOrDefault(name => name.StartsWith(Arg, StringComparison.OrdinalIgnoreCase)) ?? string.Empty;
}
+13 -17
View File
@@ -7,37 +7,33 @@
/// <param name="argInfo">Information about the argument (default: "{bool}").</param>
internal sealed class BoolArgument(BaseCommand command, string argInfo = "{bool}") : BaseArgument(command, argInfo)
{
/// <summary>
/// Gets the boolean argument suggestions for auto-completion.
/// </summary>
protected override string[] ArgSuggestions => ["true", "false"];
protected override string[] GetArgSuggestions()
{
return ["true", "false"];
}
/// <summary>
/// Parses the argument string to a nullable boolean value.
/// Tries to parse the argument as a boolean value.
/// </summary>
/// <returns>
/// True if the argument is "true",
/// False if the argument is "false" or empty,
/// Null if the argument is invalid.
/// </returns>
/// <remarks>
/// Displays an error message if the argument is invalid.
/// </remarks>
internal bool? GetBool()
/// <param name="result"></param>
/// <returns></returns>
internal bool TryParseBool(out bool result)
{
if (Arg.ToLower() == "true")
{
result = true;
return true;
}
else if (Arg.ToLower() is "false" or "")
{
return false;
result = false;
return true;
}
else
{
BaseCommand.CommandErrorText($"Invalid Syntax!");
result = false;
return false;
}
return null;
}
}
+53 -22
View File
@@ -9,31 +9,62 @@ namespace BetterAmongUs.Commands.Arguments;
/// <param name="argInfo">Information about the argument (default: "{player}").</param>
internal sealed class PlayerArgument(BaseCommand command, string argInfo = "{player}") : BaseArgument(command, argInfo)
{
/// <summary>
/// Gets the player argument suggestions for auto-completion.
/// </summary>
/// <remarks>
/// Suggestions are ordered with the local player first, then other players.
/// Spaces in player names are replaced with underscores for command parsing.
/// </remarks>
protected override string[] ArgSuggestions => BAUPlugin.AllPlayerControls.OrderBy(pc => pc.IsLocalPlayer() ? 0 : 1).Select(pc => pc.Data.PlayerName.Replace(' ', '_')).ToArray();
/// <summary>
/// Attempts to get a PlayerControl instance based on the argument value.
/// </summary>
/// <returns>
/// The PlayerControl if found; otherwise, null.
/// Displays an error message if the player is not found.
/// </returns>
internal PlayerControl? TryGetTarget()
protected override string[] GetArgSuggestions()
{
var player = BAUPlugin.AllPlayerControls.FirstOrDefault(pc => pc.Data.PlayerName.ToLower().Replace(' ', '_') == Arg.ToLower());
if (player == null)
List<string> suggestions = [];
foreach (var player in BAUPlugin.AllPlayerControls.OrderBy(pc => pc.IsLocalPlayer() ? 0 : 1))
{
BaseCommand.CommandErrorText($"Player not found!");
if (player.Data == null)
continue;
if (!string.IsNullOrEmpty(player.Data.PlayerName))
{
suggestions.Add(player.Data.PlayerName.Replace(' ', '_'));
}
if (!string.IsNullOrEmpty(player.Data.FriendCode))
{
suggestions.Add(player.Data.FriendCode);
}
suggestions.Add($"ID{player.Data.PlayerId}");
}
return player;
return [.. suggestions];
}
/// <summary>
/// Tries to parse the player argument and find the corresponding PlayerControl.
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
internal bool TryParsePlayer(out PlayerControl? result)
{
foreach (var player in BAUPlugin.AllPlayerControls)
{
if (player.Data == null) continue;
if (IsMatchingPlayer(player.Data))
{
result = player;
return true;
}
}
result = null;
BaseCommand.CommandErrorText("Player not found!");
return false;
}
/// <summary>
/// Checks if the given player info matches the argument value.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private bool IsMatchingPlayer(NetworkedPlayerInfo data)
{
return Arg.Equals(data.PlayerName, StringComparison.OrdinalIgnoreCase)
|| Arg.Equals(data.FriendCode, StringComparison.OrdinalIgnoreCase)
|| Arg.Equals($"ID{data.PlayerId}", StringComparison.OrdinalIgnoreCase);
}
}
+18 -2
View File
@@ -7,6 +7,22 @@
/// <param name="argInfo">Information about the argument (default: "{String}").</param>
internal sealed class StringArgument(BaseCommand command, string argInfo = "{String}") : BaseArgument(command, argInfo)
{
// This class inherits the basic string argument functionality from BaseArgument
// and can be extended with string-specific parsing or validation if needed.
protected override string[] GetArgSuggestions()
{
return ArgSuggestions.Invoke();
}
/// <summary>
/// Gets or sets the function that provides argument suggestions.
/// </summary>
internal Func<string[]> ArgSuggestions { get; set; } = () => { return []; };
/// <summary>
/// Gets the string argument.
/// </summary>
/// <returns></returns>
internal string GetString()
{
return Arg;
}
}
+4 -5
View File
@@ -31,17 +31,16 @@ internal sealed class KickCommand : BaseCommand
internal override void Run()
{
var player = _playerArgument.TryGetTarget();
if (player == null)
if (!_playerArgument.TryParsePlayer(out var player))
return;
var isBan = _boolArgument.GetBool();
if (isBan == null)
var isBan = _boolArgument.TryParseBool(out var ban);
if (!isBan)
return;
if (!player.IsHost())
{
player.Kick((bool)isBan);
player.Kick(ban);
}
}
}
+1 -2
View File
@@ -20,8 +20,7 @@ internal sealed class PlayerInfoCommand : BaseCommand
internal override void Run()
{
var player = _playerArgument.TryGetTarget();
if (player == null)
if (!_playerArgument.TryParsePlayer(out var player))
return;
if (player.Data == null)
+1 -1
View File
@@ -15,7 +15,7 @@ internal sealed class RemovePlayerCommand : BaseCommand
{
_identifierArgument = new StringArgument(this, "{identifier}")
{
GetArgSuggestions = () =>
ArgSuggestions = () =>
BetterDataManager.Files.BetterDataFile.AllCheatData
.SelectMany(info => new[] { info.HashPuid.Replace(' ', '_'), info.FriendCode.Replace(' ', '_'), info.PlayerName.Replace(' ', '_') })
.ToArray()