* do_after

Ports (most of) do_after from SS13.
Callers are expected to await the DoAfter task from the DoAfterSystem.
I had a dummy component for in-game testing which I removed for the PR so nothing in game uses do_after at the moment.
Currently only the movement cancellation is predicted client-side.

* Minor do_after doc cleanup

* do_the_shuffle

Fix nullable build errors.

* The last nullable

* Implement NeedHand

Thanks zum.

* nullable dereference

* Adjust the system query

Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
This commit is contained in:
metalgearsloth
2020-08-09 02:16:13 +10:00
committed by GitHub
parent ee14d67756
commit 5b3b2e3207
14 changed files with 1186 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
#nullable enable
using System;
using System.Collections.Generic;
using Content.Client.GameObjects.EntitySystems.DoAfter;
using Content.Shared.GameObjects.Components;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Players;
namespace Content.Client.GameObjects.Components
{
[RegisterComponent]
public sealed class DoAfterComponent : SharedDoAfterComponent
{
public override string Name => "DoAfter";
public IReadOnlyDictionary<byte, DoAfterMessage> DoAfters => _doAfters;
private readonly Dictionary<byte, DoAfterMessage> _doAfters = new Dictionary<byte, DoAfterMessage>();
public readonly List<(TimeSpan CancelTime, DoAfterMessage Message)> CancelledDoAfters =
new List<(TimeSpan CancelTime, DoAfterMessage Message)>();
public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession? session = null)
{
base.HandleNetworkMessage(message, netChannel, session);
switch (message)
{
case DoAfterMessage msg:
_doAfters.Add(msg.ID, msg);
EntitySystem.Get<DoAfterSystem>().Gui?.AddDoAfter(msg);
break;
case CancelledDoAfterMessage msg:
Cancel(msg.ID);
break;
}
}
/// <summary>
/// Remove a DoAfter without showing a cancellation graphic.
/// </summary>
/// <param name="doAfter"></param>
public void Remove(DoAfterMessage doAfter)
{
if (_doAfters.ContainsKey(doAfter.ID))
{
_doAfters.Remove(doAfter.ID);
}
for (var i = CancelledDoAfters.Count - 1; i >= 0; i--)
{
var cancelled = CancelledDoAfters[i];
if (cancelled.Message == doAfter)
{
CancelledDoAfters.RemoveAt(i);
break;
}
}
EntitySystem.Get<DoAfterSystem>().Gui?.RemoveDoAfter(doAfter.ID);
}
/// <summary>
/// Mark a DoAfter as cancelled and show a cancellation graphic.
/// </summary>
/// Actual removal is handled by DoAfterEntitySystem.
/// <param name="id"></param>
/// <param name="currentTime"></param>
public void Cancel(byte id, TimeSpan? currentTime = null)
{
foreach (var (_, cancelled) in CancelledDoAfters)
{
if (cancelled.ID == id)
{
return;
}
}
var doAfterMessage = _doAfters[id];
currentTime ??= IoCManager.Resolve<IGameTiming>().CurTime;
CancelledDoAfters.Add((currentTime.Value, doAfterMessage));
EntitySystem.Get<DoAfterSystem>().Gui?.CancelDoAfter(id);
}
}
}