/// <inheritdoc /> protected override Task HandleMessage(IPeerSessionMessageContext <GameServerPacketPayload> context, ClientMovementDataUpdateRequest payload, NetworkEntityGuid guid) { try { IMovementGenerator <GameObject> generator = MovementGenerator.RetrieveEntity(guid); IMovementData movementData = MovementDataMap.RetrieveEntity(guid); PositionChangeMovementData changeMovementData = BuildPositionChangeMovementData(payload, generator, movementData); MovementDataMap.ReplaceObject(guid, changeMovementData); IActorRef playerActorRef = ActorReferenceMappable.RetrieveEntity(guid); playerActorRef.TellSelf(new PlayerMovementStateChangedMessage(changeMovementData.Direction)); //If the generator is running, we should use its initial position instead of the last movement data's position. MovementGenerator.ReplaceObject(guid, BuildCharacterControllerMovementGenerator(guid, changeMovementData, generator, movementData)); } catch (Exception e) { if (Logger.IsErrorEnabled) { Logger.Error($"Failed to update MovementData for GUID: {guid} Reason: {e.Message}"); } throw; } return(Task.CompletedTask); }
protected override void OnEventFired(object source, MovementInputChangedEventArgs args) { //Don't predict on heartbeat if (args.isHeartBeat) { return; } Vector2 direction = new Vector2(args.NewHorizontalInput, args.NewVerticalInput); WorldTransform worldTransform = TransformMap.RetrieveEntity(PlayerDetails.LocalPlayerGuid); long predictedTime = TimeService.CurrentRemoteTime; IMovementData data = new PositionChangeMovementData(predictedTime, new Vector3(worldTransform.PositionX, worldTransform.PositionY, worldTransform.PositionZ), direction, worldTransform.YAxisRotation); MovementDataMappable.ReplaceObject(PlayerDetails.LocalPlayerGuid, data); MovementUpdateHandler.HandleMovementUpdate(new EntityAssociatedData <IMovementData>(PlayerDetails.LocalPlayerGuid, data), true); }
private CharacterControllerInputMovementGenerator BuildCharacterControllerMovementGenerator(NetworkEntityGuid guid, PositionChangeMovementData data, IMovementGenerator <GameObject> generator, IMovementData movementData) { //TODO: Sanity check timestamp and position. //We used to use the last generators current position //However we now use the hint position from the client. //This NEEDS to be sanity checked before used. //This semi-authorative approach is less secure but more responsive for the user. return(new CharacterControllerInputMovementGenerator(data, new Lazy <CharacterController>(() => this.CharacterControllerMappable.RetrieveEntity(guid)), data.InitialPosition)); }
public ClientCharacterControllerInputMovementGenerator(PositionChangeMovementData movementData, Lazy <CharacterController> controller, bool shouldSetRotation = true) : base(movementData, controller) { ShouldSetRotation = shouldSetRotation; }