Files
RobustToolbox/Robust.Shared/Input/BoundKeyMap.cs
Acruid 2183cd7ca1 Massive Namespace Cleanup (#1544)
* Removed the Interfaces folder.
* All objects inside the GameObjects subfolders are now in the GameObjects namespace.
* Added a Resharper DotSettings file to mark the GameObjects subfolders as not providing namespaces.
* Simplified Robust.client.Graphics namespace.
* Automated remove redundant using statements.
2021-02-10 23:27:19 -08:00

133 lines
3.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
using Robust.Shared.Reflection;
using Robust.Shared.Serialization;
namespace Robust.Shared.Input
{
/// <summary>
/// A networked identifier for a <see cref="BoundKeyFunction"/>.
/// </summary>
[Serializable, NetSerializable]
public readonly struct KeyFunctionId : IEquatable<KeyFunctionId>
{
private readonly int _value;
public KeyFunctionId(int id)
{
_value = id;
}
public static explicit operator int(KeyFunctionId funcId)
{
return funcId._value;
}
public override string ToString()
{
return _value.ToString();
}
public bool Equals(KeyFunctionId other)
{
return _value == other._value;
}
public override bool Equals(object? obj)
{
return obj is KeyFunctionId other && Equals(other);
}
public override int GetHashCode()
{
return _value;
}
public static bool operator ==(KeyFunctionId left, KeyFunctionId right)
{
return left.Equals(right);
}
public static bool operator !=(KeyFunctionId left, KeyFunctionId right)
{
return !left.Equals(right);
}
}
/// <summary>
/// Sets up a mapping of <see cref="BoundKeyFunction"/> to <see cref="KeyFunctionId"/> for network messages.
/// </summary>
public class BoundKeyMap
{
private readonly IReflectionManager reflectionManager;
private readonly Dictionary<BoundKeyFunction, KeyFunctionId> KeyFunctionsMap = new();
private readonly List<BoundKeyFunction> KeyFunctionsList = new();
public BoundKeyMap(IReflectionManager reflectionManager)
{
this.reflectionManager = reflectionManager;
}
public void PopulateKeyFunctionsMap()
{
if (KeyFunctionsMap.Count != 0)
{
throw new InvalidOperationException("Cannot run this method twice.");
}
foreach (var type in reflectionManager.FindTypesWithAttribute<KeyFunctionsAttribute>())
{
foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy))
{
// This check makes sure we ONLY get readonly fields with the type we want.
if (field.IsLiteral || !field.IsInitOnly || field.FieldType != typeof(BoundKeyFunction))
{
continue;
}
KeyFunctionsList.Add((BoundKeyFunction)field.GetValue(null)!);
}
}
KeyFunctionsList.Sort();
for (var i = 0; i < KeyFunctionsList.Count; i++)
{
KeyFunctionsMap.Add(KeyFunctionsList[i], new KeyFunctionId(i));
}
}
public bool FunctionExists(string name)
{
return KeyFunctionsMap.ContainsKey(new BoundKeyFunction(name));
}
public KeyFunctionId KeyFunctionID(BoundKeyFunction function)
{
return KeyFunctionsMap[function];
}
public BoundKeyFunction KeyFunctionName(KeyFunctionId function)
{
return KeyFunctionsList[(int) function];
}
public bool TryGetKeyFunction(KeyFunctionId funcId, out BoundKeyFunction func)
{
var list = KeyFunctionsList;
var index = (int) funcId;
if (0 > index || index >= list.Count)
{
func = default;
return false;
}
func = list[index];
return true;
}
}
}