using System; using System.Collections.Generic; using Robust.Server.Interfaces.Player; using Robust.Server.Player; using Robust.Shared.Enums; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Input; using Robust.Shared.Interfaces.Network; using Robust.Shared.IoC; namespace Robust.Server.GameObjects.EntitySystems { /// /// Server side processing of incoming user commands. /// public class InputSystem : EntitySystem { [Dependency] private readonly IPlayerManager _playerManager; private readonly Dictionary _playerInputs = new Dictionary(); private readonly CommandBindMapping _bindMap = new CommandBindMapping(); /// /// Server side input command binds. /// public ICommandBindMapping BindMap => _bindMap; /// public override void RegisterMessageTypes() { RegisterMessageType(); } /// public override void Initialize() { _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; } /// public override void Shutdown() { _playerManager.PlayerStatusChanged -= OnPlayerStatusChanged; } /// public override void HandleNetMessage(INetChannel channel, EntitySystemMessage message) { if (!(message is FullInputCmdMessage msg)) return; //Client Sanitization: out of bounds functionID if (!_playerManager.KeyMap.TryGetKeyFunction(msg.InputFunctionId, out var function)) return; var session = _playerManager.GetSessionByChannel(channel); //Client Sanitization: bad enum key state value if (!Enum.IsDefined(typeof(BoundKeyState), msg.State)) return; // route the cmdMessage to the proper bind //Client Sanitization: unbound command, just ignore if (_bindMap.TryGetHandler(function, out var command)) { // set state, only bound key functions get state changes var states = GetInputStates(session); states.SetState(function, msg.State); command.HandleCmdMessage(session, msg); } } public IPlayerCommandStates GetInputStates(IPlayerSession session) { return _playerInputs[session]; } private void OnPlayerStatusChanged(object sender, SessionStatusEventArgs args) { switch (args.NewStatus) { case SessionStatus.Connected: _playerInputs.Add(args.Session, new PlayerCommandStates()); break; case SessionStatus.Disconnected: _playerInputs.Remove(args.Session); break; } } } }