/// <summary> /// Inserts an Input Command into the simulation. /// </summary> /// <param name="session">Player session that raised the command. On client, this is always the LocalPlayer session.</param> /// <param name="function">Function that is being changed.</param> /// <param name="message">Arguments for this event.</param> /// <param name="replay">if true, current cmd state will not be checked or updated - use this for "replaying" an /// old input that was saved or buffered until further processing could be done</param> public bool HandleInputCommand(ICommonSession session, BoundKeyFunction function, FullInputCmdMessage message, bool replay = false) { #if DEBUG var funcId = _inputManager.NetworkBindMap.KeyFunctionID(function); DebugTools.Assert(funcId == message.InputFunctionId, "Function ID in message does not match function."); #endif if (!replay) { // set state, state change is updated regardless if it is locally bound if (_cmdStates.GetState(function) == message.State) { return(false); } _cmdStates.SetState(function, message.State); } // handle local binds before sending off foreach (var handler in BindRegistry.GetHandlers(function)) { // local handlers can block sending over the network. if (handler.HandleCmdMessage(session, message)) { return(true); } } // send it off to the server DispatchInputCommand(message); return(false); }
/// <summary> /// Handle a predicted input command. /// </summary> /// <param name="inputCmd">Input command to handle as predicted.</param> public void PredictInputCommand(FullInputCmdMessage inputCmd) { DebugTools.AssertNotNull(_playerManager.LocalPlayer); var keyFunc = _inputManager.NetworkBindMap.KeyFunctionName(inputCmd.InputFunctionId); Predicted = true; var session = _playerManager.LocalPlayer !.Session; foreach (var handler in BindRegistry.GetHandlers(keyFunc)) { if (handler.HandleCmdMessage(session, inputCmd)) { break; } } Predicted = false; }
private void InputMessageHandler(InputCmdMessage message, EntitySessionEventArgs eventArgs) { if (!(message is FullInputCmdMessage msg)) { return; } //Client Sanitization: out of bounds functionID if (!_playerManager.KeyMap.TryGetKeyFunction(msg.InputFunctionId, out var function)) { return; } //Client Sanitization: bad enum key state value if (!Enum.IsDefined(typeof(BoundKeyState), msg.State)) { return; } var session = (IPlayerSession)eventArgs.SenderSession; if (_lastProcessedInputCmd[session] < msg.InputSequence) { _lastProcessedInputCmd[session] = msg.InputSequence; } // set state, only bound key functions get state changes var states = GetInputStates(session); states.SetState(function, msg.State); // route the cmdMessage to the proper bind //Client Sanitization: unbound command, just ignore foreach (var handler in BindRegistry.GetHandlers(function)) { if (handler.HandleCmdMessage(session, msg)) { return; } } }