2018-11-21 20:58:11 +01:00
|
|
|
using System.Collections.Generic;
|
2021-10-05 14:29:03 +11:00
|
|
|
using System.Linq;
|
2021-06-09 22:19:39 +02:00
|
|
|
using Content.Client.ContextMenu.UI;
|
2020-10-26 12:11:32 +01:00
|
|
|
using Content.Shared.GameTicking;
|
2021-06-09 22:19:39 +02:00
|
|
|
using Content.Shared.Verbs;
|
2019-08-25 12:54:55 +02:00
|
|
|
using JetBrains.Annotations;
|
2019-04-15 21:11:38 -06:00
|
|
|
using Robust.Client.Player;
|
2020-05-23 03:09:44 +02:00
|
|
|
using Robust.Client.UserInterface;
|
2019-04-15 21:11:38 -06:00
|
|
|
using Robust.Client.UserInterface.Controls;
|
|
|
|
|
using Robust.Shared.GameObjects;
|
|
|
|
|
using Robust.Shared.IoC;
|
2021-02-25 19:42:16 -06:00
|
|
|
using Robust.Shared.Localization;
|
2019-04-15 21:11:38 -06:00
|
|
|
using Robust.Shared.Map;
|
|
|
|
|
using Robust.Shared.Maths;
|
2018-11-21 20:58:11 +01:00
|
|
|
|
2021-06-09 22:19:39 +02:00
|
|
|
namespace Content.Client.Verbs
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
2019-08-25 12:54:55 +02:00
|
|
|
[UsedImplicitly]
|
2021-06-29 15:56:07 +02:00
|
|
|
public sealed class VerbSystem : SharedVerbSystem
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
2020-08-24 14:10:28 +02:00
|
|
|
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
2021-10-05 14:29:03 +11:00
|
|
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
|
|
|
|
|
|
|
|
|
public ContextMenuPresenter ContextMenuPresenter = default!;
|
2018-11-21 20:58:11 +01:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
public EntityUid CurrentTarget;
|
|
|
|
|
public ContextMenuPopup? CurrentVerbPopup;
|
|
|
|
|
public ContextMenuPopup? CurrentCategoryPopup;
|
|
|
|
|
public Dictionary<VerbType, SortedSet<Verb>> CurrentVerbs = new();
|
2021-02-25 19:42:16 -06:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
/// <summary>
|
|
|
|
|
/// Whether to show all entities on the context menu.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// Verb execution will only be affected if the server also agrees that this player can see the target
|
|
|
|
|
/// entity.
|
|
|
|
|
/// </remarks>
|
|
|
|
|
public bool CanSeeAllContext = false;
|
2018-11-21 20:58:11 +01:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
// TODO VERBS Move presenter out of the system
|
|
|
|
|
// TODO VERBS Separate the rest of the UI from the logic
|
2018-11-21 20:58:11 +01:00
|
|
|
public override void Initialize()
|
|
|
|
|
{
|
|
|
|
|
base.Initialize();
|
2020-09-06 16:11:53 +02:00
|
|
|
|
2021-06-29 15:56:07 +02:00
|
|
|
SubscribeNetworkEvent<RoundRestartCleanupEvent>(Reset);
|
2021-10-05 14:29:03 +11:00
|
|
|
SubscribeNetworkEvent<VerbsResponseEvent>(HandleVerbResponse);
|
|
|
|
|
SubscribeNetworkEvent<SetSeeAllContextEvent>(SetSeeAllContext);
|
2020-02-18 19:43:54 -08:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
ContextMenuPresenter = new ContextMenuPresenter(this);
|
|
|
|
|
}
|
2018-11-21 20:58:11 +01:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
private void Reset(RoundRestartCleanupEvent ev)
|
|
|
|
|
{
|
|
|
|
|
ContextMenuPresenter.CloseAllMenus();
|
2020-05-31 14:32:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Shutdown()
|
|
|
|
|
{
|
2021-04-09 16:08:12 +02:00
|
|
|
base.Shutdown();
|
2021-10-05 14:29:03 +11:00
|
|
|
ContextMenuPresenter?.Dispose();
|
2018-11-21 20:58:11 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
public override void Update(float frameTime)
|
2020-10-26 12:11:32 +01:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
base.Update(frameTime);
|
|
|
|
|
ContextMenuPresenter?.Update();
|
2020-10-26 12:11:32 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
private void SetSeeAllContext(SetSeeAllContextEvent args)
|
2021-02-25 19:42:16 -06:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
CanSeeAllContext = args.CanSeeAllContext;
|
2021-02-25 19:42:16 -06:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
/// <summary>
|
|
|
|
|
/// Execute actions associated with the given verb. If there are no defined actions, this will instead ask
|
|
|
|
|
/// the server to run the given verb.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void TryExecuteVerb(Verb verb, EntityUid target, VerbType verbType)
|
2021-02-25 19:42:16 -06:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
if (!TryExecuteVerb(verb))
|
|
|
|
|
RaiseNetworkEvent(new TryExecuteVerbEvent(target, verb, verbType));
|
2020-10-26 12:11:32 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
public void OpenVerbMenu(IEntity target, ScreenCoordinates screenCoordinates)
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
if (CurrentVerbPopup != null)
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
2020-05-23 03:09:44 +02:00
|
|
|
CloseVerbMenu();
|
2018-11-21 20:58:11 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
var user = _playerManager.LocalPlayer?.ControlledEntity;
|
|
|
|
|
if (user == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
CurrentTarget = target.Uid;
|
|
|
|
|
|
|
|
|
|
CurrentVerbPopup = new ContextMenuPopup();
|
|
|
|
|
_userInterfaceManager.ModalRoot.AddChild(CurrentVerbPopup);
|
|
|
|
|
CurrentVerbPopup.OnPopupHide += CloseVerbMenu;
|
2018-11-21 20:58:11 +01:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
CurrentVerbs = GetVerbs(target, user, VerbType.All);
|
|
|
|
|
|
|
|
|
|
if (!target.Uid.IsClientSide())
|
2020-07-23 00:56:30 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
CurrentVerbPopup.AddToMenu(new Label { Text = Loc.GetString("verb-system-waiting-on-server-text") });
|
|
|
|
|
RaiseNetworkEvent(new RequestServerVerbsEvent(CurrentTarget, VerbType.All));
|
2020-07-23 00:56:30 +02:00
|
|
|
}
|
2018-11-21 20:58:11 +01:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
// Show the menu
|
|
|
|
|
FillVerbPopup(CurrentVerbPopup);
|
2020-05-23 03:09:44 +02:00
|
|
|
var box = UIBox2.FromDimensions(screenCoordinates.Position, (1, 1));
|
2021-10-05 14:29:03 +11:00
|
|
|
CurrentVerbPopup.Open(box);
|
2018-11-21 20:58:11 +01:00
|
|
|
}
|
|
|
|
|
|
2021-02-25 19:42:16 -06:00
|
|
|
public void OnContextButtonPressed(IEntity entity)
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
OpenVerbMenu(entity, _userInterfaceManager.MousePositionScaled);
|
2018-11-21 20:58:11 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
private void HandleVerbResponse(VerbsResponseEvent msg)
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
if (CurrentTarget != msg.Entity || CurrentVerbPopup == null)
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
// This **should** not happen.
|
|
|
|
|
if (msg.Verbs == null)
|
2019-10-30 11:31:35 -04:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
// update "waiting for server...".
|
|
|
|
|
CurrentVerbPopup.List.DisposeAllChildren();
|
|
|
|
|
CurrentVerbPopup.AddToMenu(new Label { Text = Loc.GetString("verb-system-null-server-response") });
|
|
|
|
|
FillVerbPopup(CurrentVerbPopup);
|
|
|
|
|
return;
|
2018-11-21 20:58:11 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
// Add the new server-side verbs.
|
|
|
|
|
foreach (var (verbType, verbSet) in msg.Verbs)
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
SortedSet<Verb> sortedVerbs = new (verbSet);
|
|
|
|
|
if (!CurrentVerbs.TryAdd(verbType, sortedVerbs))
|
2018-11-21 20:58:11 +01:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
CurrentVerbs[verbType].UnionWith(sortedVerbs);
|
2018-11-21 20:58:11 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
// Clear currently shown verbs and show new ones
|
|
|
|
|
CurrentVerbPopup.List.DisposeAllChildren();
|
|
|
|
|
FillVerbPopup(CurrentVerbPopup);
|
2020-05-23 03:09:44 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
private void FillVerbPopup(ContextMenuPopup popup)
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
if (CurrentTarget == EntityUid.Invalid)
|
|
|
|
|
return;
|
2020-05-23 03:09:44 +02:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
// Add verbs to pop-up, grouped by type. Order determined by how types are defined VerbTypes
|
|
|
|
|
var types = CurrentVerbs.Keys.ToList();
|
|
|
|
|
types.Sort();
|
|
|
|
|
foreach (var type in types)
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
AddVerbSet(popup, type);
|
2020-05-23 03:09:44 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
// Were the verb lists empty?
|
|
|
|
|
if (popup.List.ChildCount == 0)
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
var panel = new PanelContainer();
|
|
|
|
|
panel.AddChild(new Label { Text = Loc.GetString("verb-system-no-verbs-text") });
|
|
|
|
|
popup.AddChild(panel);
|
2020-05-23 03:09:44 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
popup.InvalidateMeasure();
|
2020-05-23 03:09:44 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
/// <summary>
|
|
|
|
|
/// Add a list of verbs to a BoxContainer. Iterates over the given verbs list and creates GUI buttons.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void AddVerbSet(ContextMenuPopup popup, VerbType type)
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
if (!CurrentVerbs.TryGetValue(type, out var verbSet) || verbSet.Count == 0)
|
|
|
|
|
return;
|
2020-05-23 03:09:44 +02:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
HashSet<string> listedCategories = new();
|
2020-05-23 03:09:44 +02:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
foreach (var verb in verbSet)
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
if (verb.Category == null)
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
// Lone verb without a category. just create a button for it
|
|
|
|
|
popup.AddToMenu(new VerbButton(this, verb, type, CurrentTarget));
|
|
|
|
|
continue;
|
2020-05-23 03:09:44 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
if (listedCategories.Contains(verb.Category.Text))
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
// This verb was already included in a verb-category button added by a previous verb
|
|
|
|
|
continue;
|
2020-05-23 03:09:44 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
// Get the verbs in the category
|
|
|
|
|
var verbsInCategory = verbSet.Where(v => v.Category?.Text == verb.Category.Text);
|
2020-05-23 03:09:44 +02:00
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
popup.AddToMenu(
|
|
|
|
|
new VerbCategoryButton(this, verb.Category, verbsInCategory, type, CurrentTarget));
|
|
|
|
|
listedCategories.Add(verb.Category.Text);
|
|
|
|
|
continue;
|
|
|
|
|
|
2020-05-23 03:09:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-05 14:29:03 +11:00
|
|
|
public void CloseVerbMenu()
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
if (CurrentVerbPopup != null)
|
2020-05-23 03:09:44 +02:00
|
|
|
{
|
2021-10-05 14:29:03 +11:00
|
|
|
CurrentVerbPopup.OnPopupHide -= CloseVerbMenu;
|
|
|
|
|
CurrentVerbPopup.Dispose();
|
|
|
|
|
CurrentVerbPopup = null;
|
2019-08-25 12:54:55 +02:00
|
|
|
}
|
2021-10-05 14:29:03 +11:00
|
|
|
|
|
|
|
|
CurrentCategoryPopup?.Dispose();
|
|
|
|
|
CurrentCategoryPopup = null;
|
|
|
|
|
CurrentTarget = EntityUid.Invalid;
|
|
|
|
|
CurrentVerbs.Clear();
|
2019-08-25 12:54:55 +02:00
|
|
|
}
|
2018-11-21 20:58:11 +01:00
|
|
|
}
|
|
|
|
|
}
|