Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add /help command #2984

Merged
merged 3 commits into from
Dec 12, 2024
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
18 changes: 7 additions & 11 deletions Explorer/Assets/DCL/Chat/ChatCommandsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,22 @@ public class ChatCommandsHandler
{
private const string CHAT_COMMAND_CHAR = "/";

private readonly Dictionary<Regex, IChatCommand> commandsCache = new ();
private readonly IReadOnlyDictionary<Regex, Func<IChatCommand>> commandsFactory;
private readonly IReadOnlyList<IChatCommand> commands;

public ChatCommandsHandler(IReadOnlyDictionary<Regex, Func<IChatCommand>> commandsFactory)
public ChatCommandsHandler(IReadOnlyList<IChatCommand> commands)
{
this.commandsFactory = commandsFactory;
this.commands = commands;
}

public bool TryGetChatCommand(in string message, ref (IChatCommand command, Match match) commandTuple)
{
foreach (Regex? commandRegex in commandsFactory.Keys)
foreach (IChatCommand cmd in commands)
{
commandTuple.match = commandRegex.Match(message);
commandTuple.match = cmd.Regex.Match(message);

if (!commandTuple.match.Success) continue;

if (!commandsCache.TryGetValue(commandRegex, out commandTuple.command))
{
commandTuple.command = commandsFactory[commandRegex]();
commandsCache[commandRegex] = commandTuple.command;
}
commandTuple.command = cmd;

return true;
}
Expand Down
3 changes: 3 additions & 0 deletions Explorer/Assets/DCL/Chat/ChatController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ protected override void OnViewInstantiated()
viewInstance.ChatBubblesToggle.Toggle.SetIsOnWithoutNotify(nametagsData.showChatBubbles);
OnToggleChatBubblesValueChanged(nametagsData.showChatBubbles);
OnFocus();

// Intro message
chatHistory.AddMessage(ChatMessage.NewFromSystem("Type /help for available commands."));
}

protected override void OnViewShow()
Expand Down
2 changes: 2 additions & 0 deletions Explorer/Assets/DCL/Chat/Commands/IChatCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ namespace DCL.Chat.Commands
{
public interface IChatCommand
{
Regex Regex { get; }

string Description { get; }

UniTask<string> ExecuteAsync(Match match, CancellationToken ct);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ public class CommandsHandleChatMessageBus : IChatMessagesBus

public event Action<ChatMessage>? MessageAdded;

public CommandsHandleChatMessageBus(IChatMessagesBus origin, IReadOnlyDictionary<Regex, Func<IChatCommand>> commandsFactory)
public CommandsHandleChatMessageBus(IChatMessagesBus origin, IReadOnlyList<IChatCommand> commands)
{
this.origin = origin;
this.chatCommandsHandler = new ChatCommandsHandler(commandsFactory);
this.chatCommandsHandler = new ChatCommandsHandler(commands);
origin.MessageAdded += OriginOnOnMessageAdded;
}

Expand Down
4 changes: 2 additions & 2 deletions Explorer/Assets/DCL/Chat/MessageBus/IChatMessagesBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ void CreateTestChatEntry()
return messagesBus;
}

public static IChatMessagesBus WithCommands(this IChatMessagesBus messagesBus, IReadOnlyDictionary<Regex, Func<IChatCommand>> commandsFactory) =>
new CommandsHandleChatMessageBus(messagesBus, commandsFactory);
public static IChatMessagesBus WithCommands(this IChatMessagesBus messagesBus, IReadOnlyList<IChatCommand> commands) =>
new CommandsHandleChatMessageBus(messagesBus, commands);

public static IChatMessagesBus WithIgnoreSymbols(this IChatMessagesBus messagesBus) =>
new IgnoreWithSymbolsChatMessageBus(messagesBus);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ public class ChangeRealmChatCommand : IChatCommand
// Parameters to URL mapping
private readonly Dictionary<string, string> paramUrls;

public static readonly Regex REGEX =
public Regex Regex { get; } =
new (
$@"^/({COMMAND_WORLD}|{ChatCommandsUtils.COMMAND_GOTO})\s+((?!-?\d+\s*,\s*-?\d+$).+?)(?:\s+(-?\d+)\s*,\s*(-?\d+))?$",
RegexOptions.Compiled);
public string Description => "<b>/world <i><world></i></b> - Teleport to a different realm";

private readonly URLDomain worldDomain = URLDomain.FromString(IRealmNavigator.WORLDS_DOMAIN);

private readonly Dictionary<string, URLAddress> worldAddressesCaches = new ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ namespace Global.Dynamic.ChatCommands
{
public class ClearChatCommand : IChatCommand
{
public static readonly Regex REGEX = new ($@"^/(clear).*", RegexOptions.Compiled);
public Regex Regex { get; } = new ("^/(clear).*", RegexOptions.Compiled);
public string Description => "<b>/clear</b> - Clear the chat";

private readonly IChatHistory chatHistory;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ namespace Global.Dynamic.ChatCommands
{
public class DebugPanelChatCommand : IChatCommand
{
public static readonly Regex REGEX = new (@"^/debug(?:\s+(\w+))?$", RegexOptions.Compiled);
public Regex Regex { get; } = new (@"^/debug(?:\s+(\w+))?$", RegexOptions.Compiled);
public string Description => "<b>/debug</b> - Toggle debug panel";

private readonly IDebugContainerBuilder debugContainerBuilder;
private readonly ConnectionStatusPanelPlugin connectionStatusPanelPlugin;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ public class GoToChatCommand : IChatCommand
private const string COMMAND_GOTO_LOCAL = "goto-local";
private const string PARAMETER_RANDOM = "random";

public static readonly Regex REGEX =
public Regex Regex { get; } =
new (
$@"^/({ChatCommandsUtils.COMMAND_GOTO}|{COMMAND_GOTO_LOCAL})\s+(?:(-?\d+)\s*,\s*(-?\d+)|{PARAMETER_RANDOM})$",
RegexOptions.Compiled);
public string Description => "<b>/goto <i><world | x,y | random></i></b> - Teleport to a specific location.";

private readonly IRealmNavigator realmNavigator;

private int x;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Cysharp.Threading.Tasks;
using DCL.Chat.Commands;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace Global.Dynamic.ChatCommands
{
public class HelpChatCommand : IChatCommand
{
public Regex Regex { get; } = new ("^/(help).*", RegexOptions.Compiled);
public string Description => "<b>/help</b> - Shows this help message";

private readonly List<IChatCommand> commands;

public HelpChatCommand(List<IChatCommand> commands)
{
this.commands = commands;
}

public UniTask<string> ExecuteAsync(Match match, CancellationToken ct)
{
var sb = new StringBuilder();

sb.AppendLine("Available commands:\n");

foreach (IChatCommand cmd in commands)
{
if (string.IsNullOrEmpty(cmd.Description)) continue;

sb.AppendLine(cmd.Description);
}

return UniTask.FromResult(sb.ToString());
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using DCL.Chat.Commands;
using DCL.FeatureFlags;
using PortableExperiences.Controller;
using System;
using System.Text.RegularExpressions;
using System.Threading;

Expand All @@ -17,7 +18,8 @@ public class KillPortableExperienceChatCommand : IChatCommand
private static readonly string COMMAND_PATTERN = $"^/(?<command>{Regex.Escape(COMMAND_PX)})";
private static readonly string OPTIONAL_SUFFIX_PATTERN = $"(?<suffix>{Regex.Escape(ENS_SUFFIX)})?";

public static readonly Regex REGEX = new($"{COMMAND_PATTERN}{NAME_PATTERN}{OPTIONAL_SUFFIX_PATTERN}$", RegexOptions.Compiled);
public Regex Regex { get; } = new($"{COMMAND_PATTERN}{NAME_PATTERN}{OPTIONAL_SUFFIX_PATTERN}$", RegexOptions.Compiled);
public string Description => string.Empty; // Internal command, don't advertise it in /help

private readonly IPortableExperiencesController portableExperiencesController;
private readonly FeatureFlagsCache featureFlagsCache;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public class LoadPortableExperienceChatCommand : IChatCommand
private static readonly string COMMAND_PATTERN = $"^/(?<command>{Regex.Escape(COMMAND_PX)})";
private static readonly string OPTIONAL_SUFFIX_PATTERN = $"(?<suffix>{Regex.Escape(ENS_SUFFIX)})?";

public static readonly Regex REGEX = new($"{COMMAND_PATTERN}{NAME_PATTERN}{OPTIONAL_SUFFIX_PATTERN}$", RegexOptions.Compiled);
public Regex Regex { get; } = new($"{COMMAND_PATTERN}{NAME_PATTERN}{OPTIONAL_SUFFIX_PATTERN}$", RegexOptions.Compiled);
public string Description => string.Empty; // Internal command, don't advertise it in /help

private readonly IPortableExperiencesController portableExperiencesController;
private readonly FeatureFlagsCache featureFlagsCache;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
using Cysharp.Threading.Tasks;
using DCL.Chat.Commands;
using ECS.SceneLifeCycle;
using ECS.SceneLifeCycle.Systems;
using System;

namespace Global.Dynamic.ChatCommands
{
public class ReloadSceneChatCommand : IChatCommand
{
public static readonly Regex REGEX = new (@"^/reload(?:\s+(\w+))?$", RegexOptions.Compiled);
public Regex Regex { get; } = new (@"^/reload(?:\s+(\w+))?$", RegexOptions.Compiled);
public string Description => "<b>/reload</b> - Reload the current scene";

private readonly ECSReloadScene reloadScene;

Expand All @@ -23,6 +22,7 @@ public async UniTask<string> ExecuteAsync(Match match, CancellationToken ct)
{
if (await reloadScene.TryReloadSceneAsync(ct))
return "🟢 Current scene has been reloaded";

return "🔴 You need to be in a SDK7 scene to reload it.";
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public class ShowEntityInfoChatCommand : IChatCommand
private const string COMMAND_SHOW = "show-entity-components";
private const string EXAMPLE = "/show-entity-components scene_name entity_id";

public static readonly Regex REGEX = new ($@"^/({COMMAND_SHOW}).*", RegexOptions.Compiled);
public Regex Regex { get; } = new ($"^/({COMMAND_SHOW}).*", RegexOptions.Compiled);
public string Description => "<b>/show <i><entity></i></b> - Show entity components info";

private readonly IWorldInfoHub worldInfoHub;

Expand Down
37 changes: 13 additions & 24 deletions Explorer/Assets/Scripts/Global/Dynamic/DynamicWorldContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@ IMultiPool MultiPoolFactory() =>
staticContainer.WebRequestsContainer.WebRequestController
);


bool localSceneDevelopment = !string.IsNullOrEmpty(dynamicWorldParams.LocalSceneDevelopmentRealm);

container.RealmController = new RealmController(
Expand Down Expand Up @@ -419,34 +418,24 @@ IMultiPool MultiPoolFactory() =>
var currentSceneInfo = new CurrentSceneInfo();
var connectionStatusPanelPlugin = new ConnectionStatusPanelPlugin(container.UserInAppInAppInitializationFlow, container.MvcManager, mainUIView, roomsStatus, currentSceneInfo, container.reloadSceneController, globalWorld, playerEntity, debugBuilder);

var chatCommandsFactory = new Dictionary<Regex, Func<IChatCommand>>
var chatCommands = new List<IChatCommand>
{
{ GoToChatCommand.REGEX, () => new GoToChatCommand(realmNavigator) },
{
ChangeRealmChatCommand.REGEX,
() => new ChangeRealmChatCommand(realmNavigator, bootstrapContainer.DecentralandUrlsSource,
new EnvironmentValidator(bootstrapContainer.Environment))
},
{ DebugPanelChatCommand.REGEX, () => new DebugPanelChatCommand(debugBuilder, connectionStatusPanelPlugin) },
{ ShowEntityInfoChatCommand.REGEX, () => new ShowEntityInfoChatCommand(worldInfoHub) },
{ ClearChatCommand.REGEX, () => new ClearChatCommand(chatHistory) },
{ ReloadSceneChatCommand.REGEX, () => new ReloadSceneChatCommand(container.reloadSceneController) },
{
LoadPortableExperienceChatCommand.REGEX,
() => new LoadPortableExperienceChatCommand(staticContainer.PortableExperiencesController,
staticContainer.FeatureFlagsCache)
},
{
KillPortableExperienceChatCommand.REGEX,
() => new KillPortableExperienceChatCommand(staticContainer.PortableExperiencesController,
staticContainer.FeatureFlagsCache)
}
new GoToChatCommand(realmNavigator),
new ChangeRealmChatCommand(realmNavigator, bootstrapContainer.DecentralandUrlsSource, new EnvironmentValidator(bootstrapContainer.Environment)),
new DebugPanelChatCommand(debugBuilder, connectionStatusPanelPlugin),
new ShowEntityInfoChatCommand(worldInfoHub),
new ClearChatCommand(chatHistory),
new ReloadSceneChatCommand(container.reloadSceneController),
new LoadPortableExperienceChatCommand(staticContainer.PortableExperiencesController, staticContainer.FeatureFlagsCache),
new KillPortableExperienceChatCommand(staticContainer.PortableExperiencesController, staticContainer.FeatureFlagsCache),
};

chatCommands.Add(new HelpChatCommand(chatCommands));

IChatMessagesBus coreChatMessageBus = new MultiplayerChatMessagesBus(container.MessagePipesHub, container.ProfileRepository, new MessageDeduplication<double>())
.WithSelfResend(identityCache, container.ProfileRepository)
.WithIgnoreSymbols()
.WithCommands(chatCommandsFactory)
.WithCommands(chatCommands)
.WithDebugPanel(debugBuilder);

container.ChatMessagesBus = dynamicWorldParams.EnableAnalytics
Expand Down Expand Up @@ -627,7 +616,7 @@ IMultiPool MultiPoolFactory() =>
assetsProvisioner,
container.MvcManager,
dclCursor,
realmUrl => container.ChatMessagesBus.Send($"/{ChatCommandsUtils.COMMAND_GOTO} {realmUrl}", "RestrictedActionAPI")),
realmUrl => container.ChatMessagesBus.Send($"/{ChatCommandsUtils.COMMAND_GOTO} {realmUrl}", "RestrictedActionAPI")),
new NftPromptPlugin(assetsProvisioner, webBrowser, container.MvcManager, nftInfoAPIClient, staticContainer.WebRequestsContainer.WebRequestController, dclCursor),
staticContainer.CharacterContainer.CreateGlobalPlugin(),
staticContainer.QualityContainer.CreatePlugin(),
Expand Down
Loading