Predict general interactions. (#6856)

This commit is contained in:
Leon Friedrich
2022-03-09 20:12:17 +13:00
committed by GitHub
parent 60e7ef6073
commit 0f435f31c8
10 changed files with 283 additions and 256 deletions

View File

@@ -8,7 +8,6 @@ using Content.Shared.CombatMode;
using Content.Shared.Database;
using Content.Shared.Hands.Components;
using Content.Shared.Input;
using Content.Shared.Interaction.Helpers;
using Content.Shared.Interaction.Components;
using Content.Shared.Physics;
using Content.Shared.Popups;
@@ -25,6 +24,7 @@ using Robust.Shared.Serialization;
using Content.Shared.Wall;
using Content.Shared.Item;
using Robust.Shared.Player;
using Robust.Shared.Input;
#pragma warning disable 618
@@ -43,6 +43,7 @@ namespace Content.Shared.Interaction
[Dependency] private readonly SharedAdminLogSystem _adminLogSystem = default!;
[Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly UseDelaySystem _useDelay = default!;
[Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
public const float InteractionRange = 2;
@@ -61,6 +62,10 @@ namespace Content.Shared.Interaction
CommandBinds.Builder
.Bind(ContentKeyFunctions.AltActivateItemInWorld,
new PointerInputCmdHandler(HandleAltUseInteraction))
.Bind(EngineKeyFunctions.Use,
new PointerInputCmdHandler(HandleUseInteraction))
.Bind(ContentKeyFunctions.ActivateItemInWorld,
new PointerInputCmdHandler(HandleActivateItemInWorld))
.Register<SharedInteractionSystem>();
}
@@ -144,6 +149,20 @@ namespace Content.Shared.Interaction
return false;
}
public bool HandleUseInteraction(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
{
// client sanitization
if (!ValidateClientInput(session, coords, uid, out var userEntity))
{
Logger.InfoS("system.interaction", $"Use input validation failed");
return true;
}
UserInteraction(userEntity.Value, coords, !Deleted(uid) ? uid : null);
return false;
}
/// <summary>
/// Resolves user interactions with objects.
/// </summary>
@@ -243,9 +262,31 @@ namespace Content.Shared.Interaction
inRangeUnobstructed);
}
public virtual void InteractHand(EntityUid user, EntityUid target)
public void InteractHand(EntityUid user, EntityUid target)
{
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
// all interactions should only happen when in range / unobstructed, so no range check is needed
var message = new InteractHandEvent(user, target);
RaiseLocalEvent(target, message);
_adminLogSystem.Add(LogType.InteractHand, LogImpact.Low, $"{ToPrettyString(user):user} interacted with {ToPrettyString(target):target}");
if (message.Handled)
return;
var interactHandEventArgs = new InteractHandEventArgs(user, target);
var interactHandComps = AllComps<IInteractHand>(target).ToList();
foreach (var interactHandComp in interactHandComps)
{
// If an InteractHand returns a status completion we finish our interaction
#pragma warning disable 618
if (interactHandComp.InteractHand(interactHandEventArgs))
#pragma warning restore 618
return;
}
// Else we run Activate.
InteractionActivate(user, target,
checkCanInteract: false,
checkUseDelay: true,
checkAccess: false);
}
public virtual void DoAttack(EntityUid user, EntityCoordinates coordinates, bool wideAttack,
@@ -254,10 +295,22 @@ namespace Content.Shared.Interaction
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
}
public virtual void InteractUsingRanged(EntityUid user, EntityUid used, EntityUid? target,
public void InteractUsingRanged(EntityUid user, EntityUid used, EntityUid? target,
EntityCoordinates clickLocation, bool inRangeUnobstructed)
{
// TODO PREDICTION move server-side interaction logic into the shared system for interaction prediction.
if (RangedInteractDoBefore(user, used, target, clickLocation, inRangeUnobstructed))
return;
if (target != null)
{
var rangedMsg = new RangedInteractEvent(user, used, target.Value, clickLocation);
RaiseLocalEvent(target.Value, rangedMsg);
if (rangedMsg.Handled)
return;
}
InteractDoAfter(user, used, target, clickLocation, inRangeUnobstructed);
}
protected bool ValidateInteractAndFace(EntityUid user, EntityCoordinates coordinates)
@@ -594,8 +647,8 @@ namespace Content.Shared.Interaction
return;
var interactUsingEventArgs = new InteractUsingEventArgs(user, clickLocation, used, target);
var interactUsings = AllComps<IInteractUsing>(target).OrderByDescending(x => x.Priority);
foreach (var interactUsing in interactUsings)
{
// If an InteractUsing returns a status completion we finish our interaction
@@ -636,6 +689,21 @@ namespace Content.Shared.Interaction
}
#region ActivateItemInWorld
private bool HandleActivateItemInWorld(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
{
if (!ValidateClientInput(session, coords, uid, out var user))
{
Logger.InfoS("system.interaction", $"ActivateItemInWorld input validation failed");
return false;
}
if (Deleted(uid))
return false;
InteractionActivate(user.Value, uid);
return false;
}
/// <summary>
/// Raises <see cref="ActivateInWorldEvent"/> events and activates the IActivate behavior of an object.
/// </summary>
@@ -671,18 +739,20 @@ namespace Content.Shared.Interaction
RaiseLocalEvent(used, activateMsg);
if (activateMsg.Handled)
{
BeginDelay(delayComponent);
_useDelay.BeginDelay(used, delayComponent);
_adminLogSystem.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(user):user} activated {ToPrettyString(used):used}");
return true;
}
if (!TryComp(used, out IActivate? activateComp))
var activatable = AllComps<IActivate>(used).FirstOrDefault();
if (activatable == null)
return false;
var activateEventArgs = new ActivateEventArgs(user, used);
activateComp.Activate(activateEventArgs);
BeginDelay(delayComponent);
_adminLogSystem.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(user):user} activated {ToPrettyString(used):used}"); // No way to check success.
activatable.Activate(new ActivateEventArgs(user, used));
// No way to check success.
_useDelay.BeginDelay(used, delayComponent);
_adminLogSystem.Add(LogType.InteractActivate, LogImpact.Low, $"{ToPrettyString(user):user} activated {ToPrettyString(used):used}");
return true;
}
#endregion
@@ -718,7 +788,7 @@ namespace Content.Shared.Interaction
RaiseLocalEvent(used, useMsg);
if (useMsg.Handled)
{
BeginDelay(delayComponent);
_useDelay.BeginDelay(used, delayComponent);
return true;
}
@@ -730,7 +800,7 @@ namespace Content.Shared.Interaction
// If a Use returns a status completion we finish our interaction
if (use.UseEntity(new UseEntityEventArgs(user)))
{
BeginDelay(delayComponent);
_useDelay.BeginDelay(used, delayComponent);
return true;
}
}
@@ -739,12 +809,6 @@ namespace Content.Shared.Interaction
return InteractionActivate(user, used, false, false, false);
}
protected virtual void BeginDelay(UseDelayComponent? component = null)
{
// This is temporary until we have predicted UseDelay.
return;
}
/// <summary>
/// Alternative interactions on an entity.
/// </summary>