From 8c9c6dad823428fd58ace23e175245a2422d5ef9 Mon Sep 17 00:00:00 2001
From: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Date: Thu, 13 Nov 2025 00:10:48 +0100
Subject: [PATCH] Add keybinds for openening a specified component in VV
(#41348)
* quick inspect
* Update Content.Client/Commands/QuickInspectCommand.cs
Co-authored-by: Kyle Tyo <36606155+VerinSenpai@users.noreply.github.com>
* documentation!!!
---------
Co-authored-by: Kyle Tyo <36606155+VerinSenpai@users.noreply.github.com>
---
.../Commands/QuickInspectCommand.cs | 52 +++++++++++++++++++
Content.Client/Gameplay/GameplayStateBase.cs | 20 +++++++
Content.Client/Input/ContentContexts.cs | 2 +
.../Options/UI/Tabs/KeyRebindTab.xaml.cs | 2 +
Content.Shared/CCVar/CCVars.Debug.cs | 13 +++++
Content.Shared/Input/ContentKeyFunctions.cs | 3 +-
.../en-US/commands/quick-inspect-command.ftl | 5 ++
.../en-US/escape-menu/ui/options-menu.ftl | 5 ++
Resources/clientCommandPerms.yml | 1 +
Resources/keybinds.yml | 8 +++
10 files changed, 110 insertions(+), 1 deletion(-)
create mode 100644 Content.Client/Commands/QuickInspectCommand.cs
create mode 100644 Content.Shared/CCVar/CCVars.Debug.cs
create mode 100644 Resources/Locale/en-US/commands/quick-inspect-command.ftl
diff --git a/Content.Client/Commands/QuickInspectCommand.cs b/Content.Client/Commands/QuickInspectCommand.cs
new file mode 100644
index 0000000000..dc3aae615a
--- /dev/null
+++ b/Content.Client/Commands/QuickInspectCommand.cs
@@ -0,0 +1,52 @@
+using System.Linq;
+using Content.Shared.CCVar;
+using Content.Shared.Input;
+using Robust.Client.Input;
+using Robust.Shared.Configuration;
+using Robust.Shared.Console;
+
+namespace Content.Client.Commands;
+
+///
+/// Sets the a CVar to the name of a component, which allows the client to quickly open a VV window for that component
+/// by using the Alt+C or Alt+B hotkeys.
+///
+public sealed class QuickInspectCommand : LocalizedEntityCommands
+{
+ [Dependency] private readonly IConfigurationManager _configurationManager = default!;
+ [Dependency] private readonly IInputManager _inputManager = default!;
+
+ public override string Command => "quickinspect";
+
+ public override void Execute(IConsoleShell shell, string argStr, string[] args)
+ {
+ if (args.Length != 1)
+ {
+ shell.WriteLine(Loc.GetString("shell-wrong-arguments-number"));
+ return;
+ }
+
+ _configurationManager.SetCVar(CCVars.DebugQuickInspect, args[0]);
+
+ var serverKey = _inputManager.GetKeyFunctionButtonString(ContentKeyFunctions.InspectServerComponent);
+ var clientKey = _inputManager.GetKeyFunctionButtonString(ContentKeyFunctions.InspectClientComponent);
+ shell.WriteLine(Loc.GetString($"cmd-quickinspect-success", ("component", args[0]), ("serverKeybind", serverKey), ("clientKeybind", clientKey)));
+ }
+
+ public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
+ {
+ if (args.Length == 1)
+ {
+ // Not ideal since it only shows client-side components, but you can still type in any name you want.
+ // If you know how to get server component names on the client then please fix this.
+ var options = EntityManager.ComponentFactory.AllRegisteredTypes
+ .Select(p => new CompletionOption(
+ EntityManager.ComponentFactory.GetComponentName(p)
+ ));
+
+ return CompletionResult.FromOptions(options);
+ }
+
+ return CompletionResult.Empty;
+ }
+}
diff --git a/Content.Client/Gameplay/GameplayStateBase.cs b/Content.Client/Gameplay/GameplayStateBase.cs
index 69e6e0b58b..c2b10fd01a 100644
--- a/Content.Client/Gameplay/GameplayStateBase.cs
+++ b/Content.Client/Gameplay/GameplayStateBase.cs
@@ -3,6 +3,7 @@ using System.Numerics;
using Content.Client.Clickable;
using Content.Client.UserInterface;
using Content.Client.Viewport;
+using Content.Shared.CCVar;
using Content.Shared.Input;
using Robust.Client.ComponentTrees;
using Robust.Client.GameObjects;
@@ -13,6 +14,7 @@ using Robust.Client.State;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
+using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Graphics;
using Robust.Shared.Input;
@@ -40,6 +42,7 @@ namespace Content.Client.Gameplay
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IViewVariablesManager _vvm = default!;
[Dependency] private readonly IConsoleHost _conHost = default!;
+ [Dependency] private readonly IConfigurationManager _configurationManager = default!;
private ClickableEntityComparer _comparer = default!;
@@ -83,6 +86,8 @@ namespace Content.Client.Gameplay
_comparer = new ClickableEntityComparer();
CommandBinds.Builder
.Bind(ContentKeyFunctions.InspectEntity, new PointerInputCmdHandler(HandleInspect, outsidePrediction: true))
+ .Bind(ContentKeyFunctions.InspectServerComponent, new PointerInputCmdHandler(HandleInspectServerComponent, outsidePrediction: true))
+ .Bind(ContentKeyFunctions.InspectClientComponent, new PointerInputCmdHandler(HandleInspectClientComponent, outsidePrediction: true))
.Register();
}
@@ -99,6 +104,21 @@ namespace Content.Client.Gameplay
return true;
}
+ private bool HandleInspectServerComponent(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
+ {
+ var component = _configurationManager.GetCVar(CCVars.DebugQuickInspect);
+ if (_entityManager.TryGetNetEntity(uid, out var net))
+ _conHost.ExecuteCommand($"vv /entity/{net.Value.Id}/{component}");
+ return true;
+ }
+
+ private bool HandleInspectClientComponent(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
+ {
+ var component = _configurationManager.GetCVar(CCVars.DebugQuickInspect);
+ _conHost.ExecuteCommand($"vv /c/entity/{uid}/{component}");
+ return true;
+ }
+
public EntityUid? GetClickedEntity(MapCoordinates coordinates)
{
return GetClickedEntity(coordinates, _eyeManager.CurrentEye);
diff --git a/Content.Client/Input/ContentContexts.cs b/Content.Client/Input/ContentContexts.cs
index 47f0cda2f6..01e7dc367c 100644
--- a/Content.Client/Input/ContentContexts.cs
+++ b/Content.Client/Input/ContentContexts.cs
@@ -38,6 +38,8 @@ namespace Content.Client.Input
common.AddFunction(ContentKeyFunctions.ZoomIn);
common.AddFunction(ContentKeyFunctions.ResetZoom);
common.AddFunction(ContentKeyFunctions.InspectEntity);
+ common.AddFunction(ContentKeyFunctions.InspectServerComponent);
+ common.AddFunction(ContentKeyFunctions.InspectClientComponent);
common.AddFunction(ContentKeyFunctions.ToggleRoundEndSummaryWindow);
// Not in engine, because engine cannot check for sanbox/admin status before starting placement.
diff --git a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
index f92f66df31..40d1836c08 100644
--- a/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
+++ b/Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
@@ -268,6 +268,8 @@ namespace Content.Client.Options.UI.Tabs
AddButton(EngineKeyFunctions.ShowDebugMonitors);
AddButton(EngineKeyFunctions.HideUI);
AddButton(ContentKeyFunctions.InspectEntity);
+ AddButton(ContentKeyFunctions.InspectServerComponent);
+ AddButton(ContentKeyFunctions.InspectClientComponent);
AddHeader("ui-options-header-text-cursor");
AddButton(EngineKeyFunctions.TextCursorLeft);
diff --git a/Content.Shared/CCVar/CCVars.Debug.cs b/Content.Shared/CCVar/CCVars.Debug.cs
new file mode 100644
index 0000000000..a95acc4dac
--- /dev/null
+++ b/Content.Shared/CCVar/CCVars.Debug.cs
@@ -0,0 +1,13 @@
+using Robust.Shared.Configuration;
+
+namespace Content.Shared.CCVar;
+
+public sealed partial class CCVars
+{
+ ///
+ /// Component to be inspected using the "Quick Inspect Component" keybind.
+ /// Set by the "quickinspect" command.
+ ///
+ public static readonly CVarDef DebugQuickInspect =
+ CVarDef.Create("debug.quick_inspect", "", CVar.CLIENTONLY | CVar.ARCHIVE);
+}
diff --git a/Content.Shared/Input/ContentKeyFunctions.cs b/Content.Shared/Input/ContentKeyFunctions.cs
index 50ea218b00..63f6310322 100644
--- a/Content.Shared/Input/ContentKeyFunctions.cs
+++ b/Content.Shared/Input/ContentKeyFunctions.cs
@@ -123,7 +123,8 @@ namespace Content.Shared.Input
public static readonly BoundKeyFunction EditorCopyObject = "EditorCopyObject";
public static readonly BoundKeyFunction EditorFlipObject = "EditorFlipObject";
public static readonly BoundKeyFunction InspectEntity = "InspectEntity";
-
+ public static readonly BoundKeyFunction InspectServerComponent = "InspectServerComponent";
+ public static readonly BoundKeyFunction InspectClientComponent = "InspectClientComponent";
public static readonly BoundKeyFunction MappingUnselect = "MappingUnselect";
public static readonly BoundKeyFunction SaveMap = "SaveMap";
public static readonly BoundKeyFunction MappingEnablePick = "MappingEnablePick";
diff --git a/Resources/Locale/en-US/commands/quick-inspect-command.ftl b/Resources/Locale/en-US/commands/quick-inspect-command.ftl
new file mode 100644
index 0000000000..e057fd982f
--- /dev/null
+++ b/Resources/Locale/en-US/commands/quick-inspect-command.ftl
@@ -0,0 +1,5 @@
+cmd-quickinspect-desc = Sets a component name to be opened for a hovered entity via the "Inspect Server/Client Component" keybind.
+cmd-quickinspect-help = Usage: {$command}
+cmd-quickinspect-success = Component set to: {$component}.
+ Press {$serverKeybind} to open a VV window for the server.
+ Press {$clientKeybind} to open a VV window for the client.
diff --git a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
index 98ee2543c1..a263e52229 100644
--- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
+++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
@@ -227,6 +227,11 @@ ui-options-function-editor-copy-object = Copy
ui-options-function-show-debug-console = Open Console
ui-options-function-show-debug-monitors = Show Debug Monitors
ui-options-function-inspect-entity = Inspect Entity
+ui-options-function-inspect-entity-tooltip = Open a ViewVariables window for the entity your mouse is currently hovering over.
+ui-options-function-inspect-server-component = Inspect Server Component
+ui-options-function-inspect-server-component-tooltip = Open a ViewVariables window with the server component set by the "quickinspect" command for the entity your mouse is currently hovering over.
+ui-options-function-inspect-client-component = Inspect Client Component
+ui-options-function-inspect-client-component-tooltip = Open a ViewVariables window with the client component set by the "quickinspect" command for the entity your mouse is currently hovering over.
ui-options-function-hide-ui = Hide UI
ui-options-function-hotbar1 = Hotbar slot 1
diff --git a/Resources/clientCommandPerms.yml b/Resources/clientCommandPerms.yml
index d83fdcc353..a177bc5fe1 100644
--- a/Resources/clientCommandPerms.yml
+++ b/Resources/clientCommandPerms.yml
@@ -74,6 +74,7 @@
- fullstatereset
- dumpentities
- showaccessreaders
+ - quickinspect
- Flags: MAPPING
Commands:
diff --git a/Resources/keybinds.yml b/Resources/keybinds.yml
index 870c8e1435..aa7b2918e1 100644
--- a/Resources/keybinds.yml
+++ b/Resources/keybinds.yml
@@ -281,6 +281,14 @@ binds:
type: State
key: v
mod1: Alt
+- function: InspectServerComponent
+ type: State
+ key: b
+ mod1: Alt
+- function: InspectClientComponent
+ type: State
+ key: c
+ mod1: Alt
- function: MouseMiddle
type: State
key: MouseMiddle