mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-01 17:47:24 +02:00
215 lines
8.7 KiB
C#
215 lines
8.7 KiB
C#
using System;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Player;
|
|
|
|
namespace Robust.Shared.Input.Binding
|
|
{
|
|
public delegate void StateInputCmdDelegate(ICommonSession? session);
|
|
|
|
public abstract class InputCmdHandler
|
|
{
|
|
public virtual bool FireOutsidePrediction => false;
|
|
|
|
public virtual void Enabled(ICommonSession? session)
|
|
{
|
|
}
|
|
|
|
public virtual void Disabled(ICommonSession? session)
|
|
{
|
|
}
|
|
|
|
public abstract bool HandleCmdMessage(IEntityManager entManager, ICommonSession? session, IFullInputCmdMessage message);
|
|
|
|
/// <summary>
|
|
/// Makes a quick input command from enabled and disabled delegates.
|
|
/// </summary>
|
|
/// <param name="enabled">The delegate to be ran when this command is enabled.</param>
|
|
/// <param name="disabled">The delegate to be ran when this command is disabled.</param>
|
|
/// <returns>The new input command.</returns>
|
|
public static InputCmdHandler FromDelegate(StateInputCmdDelegate? enabled = null,
|
|
StateInputCmdDelegate? disabled = null, bool handle=true, bool outsidePrediction=true)
|
|
{
|
|
return new StateInputCmdHandler
|
|
{
|
|
EnabledDelegate = enabled,
|
|
DisabledDelegate = disabled,
|
|
Handle = handle,
|
|
OutsidePrediction = outsidePrediction
|
|
};
|
|
}
|
|
|
|
private sealed class StateInputCmdHandler : InputCmdHandler
|
|
{
|
|
public StateInputCmdDelegate? EnabledDelegate;
|
|
public StateInputCmdDelegate? DisabledDelegate;
|
|
public bool Handle { get; set; }
|
|
public bool OutsidePrediction;
|
|
public override bool FireOutsidePrediction => OutsidePrediction;
|
|
|
|
public override void Enabled(ICommonSession? session)
|
|
{
|
|
EnabledDelegate?.Invoke(session);
|
|
}
|
|
|
|
public override void Disabled(ICommonSession? session)
|
|
{
|
|
DisabledDelegate?.Invoke(session);
|
|
}
|
|
|
|
public override bool HandleCmdMessage(IEntityManager entManager, ICommonSession? session, IFullInputCmdMessage message)
|
|
{
|
|
switch (message.State)
|
|
{
|
|
case BoundKeyState.Up:
|
|
Disabled(session);
|
|
return Handle;
|
|
case BoundKeyState.Down:
|
|
Enabled(session);
|
|
return Handle;
|
|
}
|
|
|
|
//Client Sanitization: unknown key state, just ignore
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public delegate bool PointerInputCmdDelegate(ICommonSession? session, EntityCoordinates coords, EntityUid uid);
|
|
|
|
public delegate bool PointerInputCmdDelegate2(in PointerInputCmdHandler.PointerInputCmdArgs args);
|
|
|
|
public sealed class PointerInputCmdHandler : InputCmdHandler
|
|
{
|
|
private PointerInputCmdDelegate2 _callback;
|
|
private bool _ignoreUp;
|
|
|
|
public override bool FireOutsidePrediction { get; }
|
|
|
|
/// <summary>
|
|
/// Handler which will handle the command using the indicated callback
|
|
/// </summary>
|
|
/// <param name="callback">callback to handle the command</param>
|
|
/// <param name="ignoreUp">whether keyup actions will be ignored by this handler (like lifting a key or releasing
|
|
/// mouse button)</param>
|
|
public PointerInputCmdHandler(PointerInputCmdDelegate callback, bool ignoreUp = true, bool outsidePrediction = false)
|
|
: this((in PointerInputCmdArgs args) =>
|
|
callback(args.Session, args.Coordinates, args.EntityUid), ignoreUp, outsidePrediction) { }
|
|
|
|
/// <summary>
|
|
/// Handler which will handle the command using the indicated callback
|
|
/// </summary>
|
|
/// <param name="callback">callback to handle the command</param>
|
|
/// <param name="ignoreUp">whether keyup actions will be ignored by this handler (like lifting a key or releasing
|
|
/// mouse button)</param>
|
|
public PointerInputCmdHandler(PointerInputCmdDelegate2 callback, bool ignoreUp = true, bool outsidePrediction = false)
|
|
{
|
|
_callback = callback;
|
|
_ignoreUp = ignoreUp;
|
|
FireOutsidePrediction = outsidePrediction;
|
|
}
|
|
|
|
public override bool HandleCmdMessage(IEntityManager entManager, ICommonSession? session, IFullInputCmdMessage message)
|
|
{
|
|
if ((_ignoreUp && message.State != BoundKeyState.Down))
|
|
return false;
|
|
|
|
switch (message)
|
|
{
|
|
case ClientFullInputCmdMessage clientInput:
|
|
{
|
|
var handled = _callback?.Invoke(new PointerInputCmdArgs(session, clientInput.Coordinates,
|
|
clientInput.ScreenCoordinates, clientInput.Uid, message.State, message));
|
|
return handled.HasValue && handled.Value;
|
|
}
|
|
case FullInputCmdMessage fullInput:
|
|
{
|
|
var handled = _callback?.Invoke(new PointerInputCmdArgs(session, entManager.GetCoordinates(fullInput.Coordinates),
|
|
fullInput.ScreenCoordinates, entManager.GetEntity(fullInput.Uid), fullInput.State, message));
|
|
return handled.HasValue && handled.Value;
|
|
}
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
public readonly struct PointerInputCmdArgs
|
|
{
|
|
public readonly ICommonSession? Session;
|
|
public readonly EntityCoordinates Coordinates;
|
|
public readonly ScreenCoordinates ScreenCoordinates;
|
|
public readonly EntityUid EntityUid;
|
|
public readonly BoundKeyState State;
|
|
public readonly IFullInputCmdMessage OriginalMessage;
|
|
|
|
public PointerInputCmdArgs(ICommonSession? session, EntityCoordinates coordinates,
|
|
ScreenCoordinates screenCoordinates, EntityUid entityUid, BoundKeyState state,
|
|
IFullInputCmdMessage originalMessage)
|
|
{
|
|
Session = session;
|
|
Coordinates = coordinates;
|
|
ScreenCoordinates = screenCoordinates;
|
|
EntityUid = entityUid;
|
|
State = state;
|
|
OriginalMessage = originalMessage;
|
|
}
|
|
}
|
|
}
|
|
|
|
public sealed class PointerStateInputCmdHandler : InputCmdHandler
|
|
{
|
|
private PointerInputCmdDelegate _enabled;
|
|
private PointerInputCmdDelegate _disabled;
|
|
public override bool FireOutsidePrediction { get; }
|
|
|
|
public PointerStateInputCmdHandler(PointerInputCmdDelegate enabled, PointerInputCmdDelegate disabled, bool outsidePrediction = false)
|
|
{
|
|
_enabled = enabled;
|
|
_disabled = disabled;
|
|
FireOutsidePrediction = outsidePrediction;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override bool HandleCmdMessage(IEntityManager entManager, ICommonSession? session, IFullInputCmdMessage message)
|
|
{
|
|
switch (message)
|
|
{
|
|
case ClientFullInputCmdMessage clientInput:
|
|
switch (clientInput.State)
|
|
{
|
|
case BoundKeyState.Up:
|
|
return _disabled?.Invoke(session, clientInput.Coordinates, clientInput.Uid) == true;
|
|
case BoundKeyState.Down:
|
|
return _enabled?.Invoke(session, clientInput.Coordinates, clientInput.Uid) == true;
|
|
}
|
|
break;
|
|
case FullInputCmdMessage fullInput:
|
|
switch (fullInput.State)
|
|
{
|
|
case BoundKeyState.Up:
|
|
return _disabled?.Invoke(session, entManager.GetCoordinates(fullInput.Coordinates), entManager.GetEntity(fullInput.Uid)) == true;
|
|
case BoundKeyState.Down:
|
|
return _enabled?.Invoke(session, entManager.GetCoordinates(fullInput.Coordinates), entManager.GetEntity(fullInput.Uid)) == true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//Client Sanitization: unknown key state, just ignore
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Consumes both up and down states without calling any handler delegates. Primarily used on the client to
|
|
/// prevent an input message from being sent to the server.
|
|
/// </summary>
|
|
public sealed class NullInputCmdHandler : InputCmdHandler
|
|
{
|
|
/// <inheritdoc />
|
|
public override bool HandleCmdMessage(IEntityManager entManager, ICommonSession? session, IFullInputCmdMessage message)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|