mirror of
https://github.com/WWhiteDreamProject/wwdpublic.git
synced 2026-04-18 14:07:53 +03:00
## Mirror of PR #26292: [Code cleanup: Purge calls to obsolete EntityCoordinates methods](https://github.com/space-wizards/space-station-14/pull/26292) from <img src="https://avatars.githubusercontent.com/u/10567778?v=4" alt="space-wizards" width="22"/> [space-wizards](https://github.com/space-wizards)/[space-station-14](https://github.com/space-wizards/space-station-14) ###### `f4cb02fb0ca385c858569c07c51afb0d24ade949` PR opened by <img src="https://avatars.githubusercontent.com/u/85356?v=4" width="16"/><a href="https://github.com/Tayrtahn"> Tayrtahn</a> at 2024-03-20 16:04:43 UTC --- PR changed 34 files with 70 additions and 56 deletions. The PR had the following labels: - Status: Needs Review --- <details open="true"><summary><h1>Original Body</h1></summary> > <!-- Please read these guidelines before opening your PR: https://docs.spacestation14.io/en/getting-started/pr-guideline --> > <!-- The text between the arrows are comments - they will not be visible on your PR. --> > > ## About the PR > <!-- What did you change in this PR? --> > Cleaned up some outdated code. > > ## Why / Balance > <!-- Why was it changed? Link any discussions or issues here. Please discuss how this would affect game balance. --> > Clean code is happy code. > > ## Technical details > <!-- If this is a code change, summarize at high level how your new code works. This makes it easier to review. --> > Updated all calls to obsolete EntityCoordinates methods (ToMap, ToMapPos, FromMap, ToVector2i, InRange) to non-obsolete ones (by passing in SharedTransformSystem as an arg). > > ## Media > <!-- > PRs which make ingame changes (adding clothing, items, new features, etc) are required to have media attached that showcase the changes. > Small fixes/refactors are exempt. > Any media may be used in SS14 progress reports, with clear credit given. > > If you're unsure whether your PR will require media, ask a maintainer. > > Check the box below to confirm that you have in fact seen this (put an X in the brackets, like [X]): > --> > Code > - [X] I have added screenshots/videos to this PR showcasing its changes ingame, **or** this PR does not require an ingame showcase > > ## Breaking changes > <!-- > List any breaking changes, including namespace, public class/method/field changes, prototype renames; and provide instructions for fixing them. This will be pasted in #codebase-changes. > --> > > **Changelog** > <!-- > Make players aware of new features and changes that could affect how they play the game by adding a Changelog entry. Please read the Changelog guidelines located at: https://docs.spacestation14.io/en/getting-started/pr-guideline#changelog > --> > > <!-- > Make sure to take this Changelog template out of the comment block in order for it to show up. > 🆑 > - add: Added fun! > - remove: Removed fun! > - tweak: Changed fun! > - fix: Fixed fun! > --> > </details> --------- Signed-off-by: VMSolidus <evilexecutive@gmail.com> Co-authored-by: SimpleStation14 <Unknown> Co-authored-by: VMSolidus <evilexecutive@gmail.com>
214 lines
8.5 KiB
C#
214 lines
8.5 KiB
C#
using System.Linq;
|
|
using System.Numerics;
|
|
using Content.Client.Clickable;
|
|
using Content.Client.UserInterface;
|
|
using Content.Shared.Input;
|
|
using Robust.Client.ComponentTrees;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.Graphics;
|
|
using Robust.Client.Input;
|
|
using Robust.Client.Player;
|
|
using Robust.Client.State;
|
|
using Robust.Client.UserInterface;
|
|
using Robust.Client.UserInterface.Controls;
|
|
using Robust.Client.UserInterface.CustomControls;
|
|
using Robust.Shared.Console;
|
|
using Robust.Shared.Input;
|
|
using Robust.Shared.Input.Binding;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Player;
|
|
using Robust.Shared.Timing;
|
|
|
|
namespace Content.Client.Gameplay
|
|
{
|
|
// OH GOD.
|
|
// Ok actually it's fine.
|
|
// Instantiated dynamically through the StateManager, Dependencies will be resolved.
|
|
[Virtual]
|
|
public class GameplayStateBase : State, IEntityEventSubscriber
|
|
{
|
|
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
|
[Dependency] private readonly IInputManager _inputManager = default!;
|
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
|
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
|
[Dependency] private readonly IGameTiming _timing = default!;
|
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
|
[Dependency] protected readonly IUserInterfaceManager UserInterfaceManager = default!;
|
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
|
[Dependency] private readonly IViewVariablesManager _vvm = default!;
|
|
[Dependency] private readonly IConsoleHost _conHost = default!;
|
|
|
|
private ClickableEntityComparer _comparer = default!;
|
|
|
|
private (ViewVariablesPath? path, string[] segments) ResolveVvHoverObject(string path)
|
|
{
|
|
var segments = path.Split('/');
|
|
var uid = RecursivelyFindUiEntity(UserInterfaceManager.CurrentlyHovered);
|
|
var netUid = _entityManager.GetNetEntity(uid);
|
|
return (netUid != null ? new ViewVariablesInstancePath(netUid) : null, segments);
|
|
}
|
|
|
|
private EntityUid? RecursivelyFindUiEntity(Control? control)
|
|
{
|
|
if (control == null)
|
|
return null;
|
|
|
|
switch (control)
|
|
{
|
|
case IViewportControl vp:
|
|
if (_inputManager.MouseScreenPosition.IsValid)
|
|
return GetClickedEntity(vp.PixelToMap(_inputManager.MouseScreenPosition.Position));
|
|
return null;
|
|
case SpriteView sprite:
|
|
return sprite.Entity;
|
|
case IEntityControl ui:
|
|
return ui.UiEntity;
|
|
}
|
|
|
|
return RecursivelyFindUiEntity(control.Parent);
|
|
}
|
|
|
|
private IEnumerable<string>? ListVVHoverPaths(string[] segments)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
protected override void Startup()
|
|
{
|
|
_vvm.RegisterDomain("enthover", ResolveVvHoverObject, ListVVHoverPaths);
|
|
_inputManager.KeyBindStateChanged += OnKeyBindStateChanged;
|
|
_comparer = new ClickableEntityComparer();
|
|
CommandBinds.Builder
|
|
.Bind(ContentKeyFunctions.InspectEntity, new PointerInputCmdHandler(HandleInspect, outsidePrediction: true))
|
|
.Register<GameplayStateBase>();
|
|
}
|
|
|
|
protected override void Shutdown()
|
|
{
|
|
_vvm.UnregisterDomain("enthover");
|
|
_inputManager.KeyBindStateChanged -= OnKeyBindStateChanged;
|
|
CommandBinds.Unregister<GameplayStateBase>();
|
|
}
|
|
|
|
private bool HandleInspect(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
|
{
|
|
_conHost.ExecuteCommand($"vv /c/enthover");
|
|
return true;
|
|
}
|
|
|
|
public EntityUid? GetClickedEntity(MapCoordinates coordinates)
|
|
{
|
|
var first = GetClickableEntities(coordinates).FirstOrDefault();
|
|
return first.IsValid() ? first : null;
|
|
}
|
|
|
|
public IEnumerable<EntityUid> GetClickableEntities(EntityCoordinates coordinates)
|
|
{
|
|
return GetClickableEntities(coordinates.ToMap(_entityManager, _entitySystemManager.GetEntitySystem<SharedTransformSystem>()));
|
|
}
|
|
|
|
public IEnumerable<EntityUid> GetClickableEntities(MapCoordinates coordinates)
|
|
{
|
|
// Find all the entities intersecting our click
|
|
var spriteTree = _entityManager.EntitySysManager.GetEntitySystem<SpriteTreeSystem>();
|
|
var entities = spriteTree.QueryAabb(coordinates.MapId, Box2.CenteredAround(coordinates.Position, new Vector2(1, 1)));
|
|
|
|
// Check the entities against whether or not we can click them
|
|
var foundEntities = new List<(EntityUid, int, uint, float)>(entities.Count);
|
|
var clickQuery = _entityManager.GetEntityQuery<ClickableComponent>();
|
|
var xformQuery = _entityManager.GetEntityQuery<TransformComponent>();
|
|
|
|
// TODO: Smelly
|
|
var eye = _eyeManager.CurrentEye;
|
|
|
|
foreach (var entity in entities)
|
|
{
|
|
if (clickQuery.TryGetComponent(entity.Uid, out var component) &&
|
|
component.CheckClick(entity.Component, entity.Transform, xformQuery, coordinates.Position, eye, out var drawDepthClicked, out var renderOrder, out var bottom))
|
|
{
|
|
foundEntities.Add((entity.Uid, drawDepthClicked, renderOrder, bottom));
|
|
}
|
|
}
|
|
|
|
if (foundEntities.Count == 0)
|
|
return Array.Empty<EntityUid>();
|
|
|
|
// Do drawdepth & y-sorting. First index is the top-most sprite (opposite of normal render order).
|
|
foundEntities.Sort(_comparer);
|
|
|
|
return foundEntities.Select(a => a.Item1);
|
|
}
|
|
|
|
private sealed class ClickableEntityComparer : IComparer<(EntityUid clicked, int depth, uint renderOrder, float bottom)>
|
|
{
|
|
public int Compare((EntityUid clicked, int depth, uint renderOrder, float bottom) x,
|
|
(EntityUid clicked, int depth, uint renderOrder, float bottom) y)
|
|
{
|
|
var cmp = y.depth.CompareTo(x.depth);
|
|
if (cmp != 0)
|
|
{
|
|
return cmp;
|
|
}
|
|
|
|
cmp = y.renderOrder.CompareTo(x.renderOrder);
|
|
|
|
if (cmp != 0)
|
|
{
|
|
return cmp;
|
|
}
|
|
|
|
cmp = -y.bottom.CompareTo(x.bottom);
|
|
|
|
if (cmp != 0)
|
|
{
|
|
return cmp;
|
|
}
|
|
|
|
return y.clicked.CompareTo(x.clicked);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a state change event from outside the simulation to inside the simulation.
|
|
/// </summary>
|
|
/// <param name="args">Event data values for a bound key state change.</param>
|
|
protected virtual void OnKeyBindStateChanged(ViewportBoundKeyEventArgs args)
|
|
{
|
|
// If there is no InputSystem, then there is nothing to forward to, and nothing to do here.
|
|
if(!_entitySystemManager.TryGetEntitySystem(out InputSystem? inputSys))
|
|
return;
|
|
|
|
var kArgs = args.KeyEventArgs;
|
|
var func = kArgs.Function;
|
|
var funcId = _inputManager.NetworkBindMap.KeyFunctionID(func);
|
|
|
|
EntityCoordinates coordinates = default;
|
|
EntityUid? entityToClick = null;
|
|
if (args.Viewport is IViewportControl vp)
|
|
{
|
|
var mousePosWorld = vp.PixelToMap(kArgs.PointerLocation.Position);
|
|
entityToClick = GetClickedEntity(mousePosWorld);
|
|
|
|
coordinates = _mapManager.TryFindGridAt(mousePosWorld, out _, out var grid) ?
|
|
grid.MapToGrid(mousePosWorld) :
|
|
EntityCoordinates.FromMap(_mapManager, mousePosWorld);
|
|
}
|
|
|
|
var message = new ClientFullInputCmdMessage(_timing.CurTick, _timing.TickFraction, funcId)
|
|
{
|
|
State = kArgs.State,
|
|
Coordinates = coordinates,
|
|
ScreenCoordinates = kArgs.PointerLocation,
|
|
Uid = entityToClick ?? default,
|
|
}; // TODO make entityUid nullable
|
|
|
|
// client side command handlers will always be sent the local player session.
|
|
var session = _playerManager.LocalSession;
|
|
if (inputSys.HandleInputCommand(session, func, message))
|
|
{
|
|
kArgs.Handle();
|
|
}
|
|
}
|
|
}
|
|
}
|