diff --git a/Source/Game/GameMode/WorldStateManager.cs b/Source/Game/GameMode/WorldStateManager.cs index 630dce6..3b0c5d8 100644 --- a/Source/Game/GameMode/WorldStateManager.cs +++ b/Source/Game/GameMode/WorldStateManager.cs @@ -41,10 +41,12 @@ public class WorldStateManager } } - private class PlayerFrame + public class PlayerFrame { public ulong frame; public Float3 position; + public PlayerInputState2 inputState; + public PlayerMovementState movementState; } private Dictionary players; @@ -62,6 +64,7 @@ public class WorldStateManager private ulong lastReceivedServerFrame = 0; public ulong ServerFrame => /*NetworkManager.server != null ? serverWorldState.frame :*/ lastReceivedServerFrame; public ulong ClientFrame => clientWorldState.frame; + public ulong Frame => IsServer ? serverWorldState.frame : clientWorldState.frame; public float ServerTime = 0f; public float ClientTime = 0f; @@ -193,18 +196,42 @@ public class WorldStateManager } } - private PlayerFrame GetPlayerFrame(uint playerIndex, ulong playerFrameIndex) + public PlayerFrame GetPlayerFrame(uint playerIndex, ulong frame) { WorldState worldState = NetworkManager.server != null ? serverWorldState : clientWorldState; PlayerFrame[] playerFrames = worldState.playerFrameHistory[playerIndex]; - PlayerFrame playerFrame = playerFrames[playerFrameIndex % 120]; + PlayerFrame playerFrame = playerFrames[frame % 120]; - if (playerFrame.frame != playerFrameIndex) + if (playerFrame.frame != frame) return null; return playerFrame; } + public bool HasPlayerFrame(uint playerIndex, ulong frame) + { + return GetPlayerFrame(playerIndex, frame) != null; + } + + public bool GetPlayerInputState(uint playerIndex, ulong frame, out PlayerInputState2 inputState) + { + PlayerFrame frameInfo = GetPlayerFrame(playerIndex, frame); + inputState = frameInfo?.inputState ?? default; + return frameInfo != null; + } + + public void RecordPlayerInput(uint playerIndex, ulong frame, PlayerInputState2 inputState, PlayerMovementState movementState) + { + WorldState worldState = NetworkManager.server != null ? serverWorldState : clientWorldState; + PlayerFrame[] playerFrames = worldState.playerFrameHistory[playerIndex]; + PlayerFrame playerFrame = playerFrames[frame % 120]; + + playerFrame.frame = frame; + playerFrame.inputState = inputState; + playerFrame.movementState = movementState; + Console.Print($"recorded frame {frame}, client: {IsClient || IsLocalClient}"); + } + public void OnLevelLoaded(Scene scene, Guid assetGuid) { serverWorldState.frame = 0; @@ -243,8 +270,8 @@ public class WorldStateManager playerFrame.frame = serverWorldState.frame; //playerFrame.position = playerActor.Position; PlayerMovement playerMovement = playerActor.GetScript(); - playerMovement.input.GetState(serverWorldState.frame, out var inputState, out var actorState); - playerFrame.position = actorState.position; + //playerMovement.Input.GetState(serverWorldState.frame, out var inputState, out var actorState); + playerFrame.position = playerMovement.movementState.position; } foreach (KeyValuePair kv in players) @@ -264,9 +291,12 @@ public class WorldStateManager //PlayerActorState actorState = playerMovement.input.GetCurrentActorState(); //PlayerInputState inputState = playerMovement.input.GetCurrentInputState(); var playerFrame = playerLastFrame[playerId]; - if (!playerMovement.input.GetState(playerFrame, out var inputState, out var actorState)) + var frameInfo = GetPlayerFrame(playerId, playerFrame); + //if (!playerMovement.Input.GetState(playerFrame, out var inputState, out var actorState)) + if (frameInfo == null) { - //Console.Print("send input failure to client"); + Console.Print("send input failure to client"); + continue; } { @@ -274,30 +304,30 @@ public class WorldStateManager message.WriteByte((byte)GameModeMessageType.PlayerPosition); message.WriteUInt64(playerFrame); message.WriteUInt32(kv2.Key); - message.WriteSingle(actorState.position.X); - message.WriteSingle(actorState.position.Y); - message.WriteSingle(actorState.position.Z); - message.WriteSingle(actorState.velocity.X); - message.WriteSingle(actorState.velocity.Y); - message.WriteSingle(actorState.velocity.Z); - message.WriteSingle(actorState.orientation.X); - message.WriteSingle(actorState.orientation.Y); - message.WriteSingle(actorState.orientation.Z); - message.WriteSingle(actorState.orientation.W); - message.WriteSingle(actorState.viewAngles.X); - message.WriteSingle(actorState.viewAngles.Y); - message.WriteSingle(actorState.viewAngles.Z); - message.WriteSingle(actorState.lastJumpTime); - message.WriteInt32(actorState.numJumps); - message.WriteBoolean(actorState.jumped); + message.WriteSingle(frameInfo.movementState.position.X); + message.WriteSingle(frameInfo.movementState.position.Y); + message.WriteSingle(frameInfo.movementState.position.Z); + message.WriteSingle(frameInfo.movementState.currentVelocity.X); + message.WriteSingle(frameInfo.movementState.currentVelocity.Y); + message.WriteSingle(frameInfo.movementState.currentVelocity.Z); + //message.WriteSingle(frameInfo.movementState.orientation.X); + //message.WriteSingle(frameInfo.movementState.orientation.Y); + //message.WriteSingle(frameInfo.movementState.orientation.Z); + //message.WriteSingle(frameInfo.movementState.orientation.W); + message.WriteSingle(frameInfo.movementState.viewAngles.X); + message.WriteSingle(frameInfo.movementState.viewAngles.Y); + message.WriteSingle(frameInfo.movementState.viewAngles.Z); + message.WriteSingle(frameInfo.movementState.lastJumped); + message.WriteInt32(frameInfo.movementState.numJumps); + message.WriteBoolean(frameInfo.movementState.jumped); //inputState.frame - message.WriteSingle(inputState.viewDeltaX); - message.WriteSingle(inputState.viewDeltaY); - message.WriteSingle(inputState.moveForward); - message.WriteSingle(inputState.moveRight); - message.WriteBoolean(inputState.attacking); - message.WriteBoolean(inputState.jumping); + message.WriteSingle(frameInfo.inputState.ViewDelta.X); + message.WriteSingle(frameInfo.inputState.ViewDelta.Y); + message.WriteSingle(frameInfo.inputState.MoveForward); + message.WriteSingle(frameInfo.inputState.MoveRight); + message.WriteBoolean(frameInfo.inputState.Attack); + message.WriteBoolean(frameInfo.inputState.Jump); NetworkManager.ServerEndSendMessage(ref message, playerConnections[otherPlayerId]); } @@ -453,7 +483,7 @@ public class WorldStateManager new Float3(networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle(), networkEvent.Message.ReadSingle())); //if (NetworkManager.IsClient) - players[playerId].GetScript().input.frame = ClientFrame; + players[playerId].GetScript().Input.SetFrame(ClientFrame); break; } case GameModeMessageType.PlayerInput: @@ -478,7 +508,7 @@ public class WorldStateManager case GameModeMessageType.PlayerPosition: { //uint playerId = networkEvent.Sender.ConnectionId; - PlayerInputState inputState = default; //? + PlayerInputState2 inputState; //? PlayerActorState actorState; ulong reportedFrame = networkEvent.Message.ReadUInt64(); @@ -489,10 +519,10 @@ public class WorldStateManager actorState.velocity.X = networkEvent.Message.ReadSingle(); actorState.velocity.Y = networkEvent.Message.ReadSingle(); actorState.velocity.Z = networkEvent.Message.ReadSingle(); - actorState.orientation.X = networkEvent.Message.ReadSingle(); + /*actorState.orientation.X = networkEvent.Message.ReadSingle(); actorState.orientation.Y = networkEvent.Message.ReadSingle(); actorState.orientation.Z = networkEvent.Message.ReadSingle(); - actorState.orientation.W = networkEvent.Message.ReadSingle(); + actorState.orientation.W = networkEvent.Message.ReadSingle();*/ actorState.viewAngles.X = networkEvent.Message.ReadSingle(); actorState.viewAngles.Y = networkEvent.Message.ReadSingle(); actorState.viewAngles.Z = networkEvent.Message.ReadSingle(); @@ -500,13 +530,13 @@ public class WorldStateManager actorState.numJumps = networkEvent.Message.ReadInt32(); actorState.jumped = networkEvent.Message.ReadBoolean(); - inputState.frame = reportedFrame; - inputState.viewDeltaX = networkEvent.Message.ReadSingle(); - inputState.viewDeltaY = networkEvent.Message.ReadSingle(); - inputState.moveForward = networkEvent.Message.ReadSingle(); - inputState.moveRight = networkEvent.Message.ReadSingle(); - inputState.attacking = networkEvent.Message.ReadBoolean(); - inputState.jumping = networkEvent.Message.ReadBoolean(); + //inputState.frame = reportedFrame; + inputState.ViewDelta.X = networkEvent.Message.ReadSingle(); + inputState.ViewDelta.Y = networkEvent.Message.ReadSingle(); + inputState.MoveForward = networkEvent.Message.ReadSingle(); + inputState.MoveRight = networkEvent.Message.ReadSingle(); + inputState.Attack = networkEvent.Message.ReadBoolean(); + inputState.Jump = networkEvent.Message.ReadBoolean(); //if (actorState.viewAngles != new Float3(90f, 0f, 0f)) // Console.Print($"{reportedFrame} has viewangles: {actorState.viewAngles}"); @@ -530,14 +560,14 @@ public class WorldStateManager if (playerActor != null) { - PlayerInput playerInput = playerActor.GetScript().input; + IPlayerInput playerInput = playerActor.GetScript().Input; if (IsLocalClient && reportedPlayerId == NetworkManager.LocalPlayerClientId) { } else - playerInput.SetState(reportedFrame, inputState, actorState); + playerInput.SetFrame(reportedFrame);//playerInput.SetState(reportedFrame, inputState, actorState); - if (!IsLocalClient && playerInput is PlayerInputNetwork) + if (!IsLocalClient && playerInput is PlayerInputNetwork2) { playerActor.Position = actorState.position; playerActor.GetScript().movementState.currentVelocity = actorState.velocity; @@ -577,7 +607,7 @@ public class WorldStateManager playerInfo.playerId = playerActor.GetScript().PlayerId; playerInfo.playerPosition = playerActor.Position; - playerActor.GetScript().input.SetState(serverWorldState.frame, new PlayerInputState(), new PlayerActorState() + /*playerActor.GetScript().Input.SetState(serverWorldState.frame, new PlayerInputState(), new PlayerActorState() { position = playerActor.Position, velocity = playerActor.GetScript().movementState.currentVelocity, @@ -587,7 +617,7 @@ public class WorldStateManager numJumps = playerActor.GetScript().movementState.numJumps, jumped = playerActor.GetScript().movementState.jumped, //onGround = playerActor.GetScript().movementState.onGround, - }); + });*/ } NetworkMessage message = NetworkManager.ServerBeginSendMessage(); welcomeMessage.Write(ref message); @@ -659,8 +689,8 @@ public class WorldStateManager if (!players.ContainsKey(playerId)) players.Add(playerId, null); players[playerId] = playerActor; - PlayerInput playerInput = playerActor.GetScript().input; - playerInput.frame = IsServer ? serverWorldState.frame : ClientFrame; + IPlayerInput playerInput = playerActor.GetScript().Input; + playerInput.SetFrame(IsServer ? serverWorldState.frame : ClientFrame); if (IsServer) { serverWorldState.actors.Add(playerActor); @@ -686,7 +716,7 @@ public class WorldStateManager PlayerActor playerActor = players[playerId]; PlayerMovement playerMovement = playerActor.GetScript(); - playerActor.UpdateNetworkInput(inputState); + //playerActor.UpdateNetworkInput(inputState); ulong startFrame = playerLastFrame[playerId]; @@ -697,21 +727,26 @@ public class WorldStateManager // simulate at least one or more frame when receiving input frames from player. missing frames use inputs from previous frames var simframs = 0; ulong frame = startFrame+1; - PlayerInputState prevInputState; - playerMovement.input.GetState(frame - 1, out prevInputState, out var _); + PlayerFrame prevFrame = GetPlayerFrame(playerId, frame - 1); + PlayerInputState2 prevInputState = prevFrame?.inputState ?? default; + //playerMovement.Input.GetState(frame - 1, out prevInputState, out var _); for (; frame <= inputState.frame; frame++) { - if (!playerMovement.input.GetState(frame, out var lastInputState, out var lastActorState)) + PlayerFrame frameInfo = GetPlayerFrame(playerId, frame); + PlayerInputState2 lastInputState = frameInfo?.inputState ?? prevInputState; + //if (!playerMovement.Input.GetState(frame, out var lastInputState, out var lastActorState)) + /*if (frameInfo == null) { // dropped frame, use previous input lastInputState = prevInputState; lastInputState.frame = frame; - } + }*/ playerMovement.ApplyInputToCamera(lastInputState, true); - playerMovement.SimulatePlayerMovement(lastInputState); + playerMovement.SimulatePlayerMovement(lastInputState, frame); - playerMovement.input.SetState(frame, lastInputState, new PlayerActorState() + RecordPlayerInput(playerId, Frame, lastInputState, playerMovement.movementState); + /*playerMovement.Input.SetState(frame, lastInputState, new PlayerActorState() { position = playerActor.Position, velocity = playerMovement.movementState.currentVelocity, @@ -721,7 +756,7 @@ public class WorldStateManager numJumps = playerMovement.movementState.numJumps, jumped = playerMovement.movementState.jumped, //onGround = playerMovement.movementState.onGround, - }); + });*/ simframs++; prevInputState = lastInputState; diff --git a/Source/Game/Player/PlayerActor.cs b/Source/Game/Player/PlayerActor.cs index 6694c89..9c191ba 100644 --- a/Source/Game/Player/PlayerActor.cs +++ b/Source/Game/Player/PlayerActor.cs @@ -104,7 +104,8 @@ public class PlayerActor : RigidBody//, INetworkSerializable PlayerId = playerId; playerMovement.SetInput(playerId); - if (playerId == NetworkManager.LocalPlayerClientId) + bool isServerScene = Scene.Name == "ServerScene"; + if (playerId == NetworkManager.LocalPlayerClientId && !isServerScene) { FindActor("CameraHolder").IsActive = true; //FindActor("ViewModelHolder").IsActive = true; @@ -120,12 +121,12 @@ public class PlayerActor : RigidBody//, INetworkSerializable //[NetworkRpc(server: true)] public void UpdateNetworkInput(PlayerInputState inputState/*, Float4 viewDeltaXYMoveForwardRight, bool attacking, bool jumping*/) { - if (playerMovement.input is not PlayerInputNetwork playerInputNetwork) + if (playerMovement.Input is not PlayerInputNetwork2 playerInputNetwork) return; //PlayerInputState inputState = new PlayerInputState(frame, viewDeltaXYMoveForwardRight.X, viewDeltaXYMoveForwardRight.Y, viewDeltaXYMoveForwardRight.Z, viewDeltaXYMoveForwardRight.W, attacking, jumping); //playerInputNetwork.currentState.input = inputState; - playerInputNetwork.SetState(inputState.frame, inputState); + //playerInputNetwork.SetState(inputState.frame, inputState); } public void SetPosition(Float3 newPosition) diff --git a/Source/Game/Player/PlayerInput2.cs b/Source/Game/Player/PlayerInput2.cs new file mode 100644 index 0000000..c2e8cf9 --- /dev/null +++ b/Source/Game/Player/PlayerInput2.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using FlaxEngine; + +namespace Game; + +[StructLayout(LayoutKind.Sequential)] +public struct PlayerInputState2 +{ + //public ulong frame; + public Float2 ViewDelta; + public float MoveForward; + public float MoveRight; + public bool Attack; + public bool Jump; +} + +public interface IPlayerInput +{ + /// + /// Sets the frame number for current frame. + /// + /// The frame number + void SetFrame(ulong frame); + + /// + /// Updates the current state, gathering the latest input. + /// + void UpdateState(); + + /// + /// Gets the current input state of the current frame. + /// + PlayerInputState2 GetState(); + + /// + /// Resets the input state for a new frame. + /// + void ResetState(); +} + +public class PlayerInput2 : IPlayerInput +{ + /// + /// The state currently being recorded, may get modified during multiple in-flight frames. + /// + private PlayerInputState2 _recordState; + + public void SetFrame(ulong frame) + { + } + + public void UpdateState() + { + // Axis values should be either accumulated (view delta) + // or taken with the peak values (axis direction), + // binary values should be OR'ed so triggered action is not lost if button debounces mid-frame. + + float sensitivity = 1.0f / 8.0f; + sensitivity = 1.0f; + float turnSpeed = 100.0f; + + _recordState.ViewDelta += new Float2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")) * sensitivity; + _recordState.ViewDelta += new Float2(Input.GetAxisRaw("LookRight"), Input.GetAxisRaw("LookUp")) * Time.DeltaTime * turnSpeed; + + _recordState.MoveForward = Math.Max(_recordState.MoveForward, Input.GetAxis("Vertical")); + _recordState.MoveRight = Math.Max(_recordState.MoveRight, Input.GetAxis("Horizontal")); + _recordState.Attack |= Input.GetAction("Attack"); + _recordState.Jump |= Input.GetAction("Jump"); + } + + public PlayerInputState2 GetState() => _recordState; + + public void ResetState() => _recordState = new PlayerInputState2(); +} + +public class PlayerInputNetwork2 : IPlayerInput +{ + public void SetFrame(ulong frame) { } + public void UpdateState() { } + public PlayerInputState2 GetState() { return default; } + public void ResetState() { } +} \ No newline at end of file diff --git a/Source/Game/Player/PlayerInputDemo.cs b/Source/Game/Player/PlayerInputDemo.cs index 303304b..d461099 100644 --- a/Source/Game/Player/PlayerInputDemo.cs +++ b/Source/Game/Player/PlayerInputDemo.cs @@ -10,6 +10,7 @@ using Console = Game.Console; namespace Game; +#if false public class PlayerInputDemo : PlayerInput { protected List buffer = new List(); @@ -98,4 +99,5 @@ public class PlayerInputDemo : PlayerInput //frame++; //currentState.actor = actorState; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Source/Game/Player/PlayerInputNetwork.cs b/Source/Game/Player/PlayerInputNetwork.cs index 73ff415..4fe98a0 100644 --- a/Source/Game/Player/PlayerInputNetwork.cs +++ b/Source/Game/Player/PlayerInputNetwork.cs @@ -1,5 +1,6 @@ namespace Game; +#if false public class PlayerInputNetwork : PlayerInput { public override bool Predict => true; @@ -9,4 +10,5 @@ public class PlayerInputNetwork : PlayerInput currentState.input.frame = frame; base.OnEndFrame(); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Source/Game/Player/PlayerMovement.cs b/Source/Game/Player/PlayerMovement.cs index b10a93a..49dc900 100644 --- a/Source/Game/Player/PlayerMovement.cs +++ b/Source/Game/Player/PlayerMovement.cs @@ -116,7 +116,7 @@ public class PlayerMovement : Script //private int currentInputFrame2; - public PlayerInput input; + public IPlayerInput Input; //private bool physicsInteractions = false; @@ -183,36 +183,39 @@ public class PlayerMovement : Script Assert.IsTrue(playerId != uint.MaxValue); PlayerId = playerId; - if (PlayerId == NetworkManager.LocalPlayerClientId)//if (NetworkReplicator.GetObjectRole(this.Parent) == NetworkObjectRole.OwnedAuthoritative)// if (playerId == NetworkManager.LocalPlayerClientId) + bool isServerScene = Scene.Name == "ServerScene"; + if (PlayerId == NetworkManager.LocalPlayerClientId && !isServerScene)//if (NetworkReplicator.GetObjectRole(this.Parent) == NetworkObjectRole.OwnedAuthoritative)// if (playerId == NetworkManager.LocalPlayerClientId) { Console.Print("local player?: " + playerId.ToString()); //string demoPath = System.IO.Path.Combine(AssetManager.DemoPath, $"{DateTimeOffset.Now.UtcTicks}.gdem"); //input = new PlayerInputLocal(playerActor, demoPath); // TODO: support recording - input = new PlayerInputLocal(playerActor); + Input = new PlayerInput2();//new PlayerInputLocal(playerActor); worldStateManager = NetworkManager.serverWorldStateManager; } else { Console.Print("network player: " + playerId.ToString()); - input = new PlayerInputNetwork(); + Input = new PlayerInputNetwork2(); worldStateManager = NetworkManager.clientWorldStateManager; } Assert.IsTrue(worldStateManager != null); } +#if false public void SetInput(string demoFile) { - input = new PlayerInputDemo(demoFile); + Input = new PlayerInputDemo(demoFile); /*movementState.position = input.GetCurrentActorState().position; currentVelocity = input.GetCurrentActorState().velocity; f SetCameraEulerAngles(input.GetCurrentActorState().viewAngles);*/ - movementState.position = input.GetCurrentInputState().verificationPosition; + movementState.position = Input.GetCurrentInputState().verificationPosition; Actor.Position = movementState.position; //rootActor.Orientation = input.GetCurrentInputState().verificationOrientation; - movementState.currentVelocity = input.GetCurrentInputState().verificationVelocity; - SetCameraEulerAngles(input.GetCurrentInputState().verificationViewAngles); + movementState.currentVelocity = Input.GetCurrentInputState().verificationVelocity; + SetCameraEulerAngles(Input.GetCurrentInputState().verificationViewAngles); } +#endif public override void OnEnable() { @@ -225,8 +228,8 @@ public class PlayerMovement : Script { base.OnDisable(); - if (input != null && input is PlayerInputLocal) // FIXME - (input as PlayerInputLocal).StopRecording(); + if (Input != null && Input is PlayerInputLocal) // FIXME + (Input as PlayerInputLocal).StopRecording(); } private void OnTriggerEnter(PhysicsColliderActor colliderActor) @@ -275,10 +278,10 @@ public class PlayerMovement : Script //input.OnUpdate(); - if (input is PlayerInputDemo /*&& currentInputFrame2 >= currentInputFrame*/) - return; + //if (Input is PlayerInputDemo /*&& currentInputFrame2 >= currentInputFrame*/) + // return; - input.OnUpdate(); + Input.UpdateState(); /*if (input.frame > 0) { @@ -292,10 +295,10 @@ public class PlayerMovement : Script viewAngles = viewAnglesLastFrame; - if (input is not PlayerInputNetwork) + //if (Input is not PlayerInputNetwork2) { - PlayerInputState inputState = input.GetCurrentInputState(); + PlayerInputState2 inputState = Input.GetState(); //if (inputState.viewDeltaX != 0 || inputState.viewDeltaY != 0) // inputState = inputState; @@ -303,7 +306,7 @@ public class PlayerMovement : Script ApplyInputToCamera(inputState); - input.RecordCurrentActorState(new PlayerActorState + /*Input.RecordCurrentActorState(new PlayerActorState { position = movementState.position, velocity = movementState.currentVelocity, @@ -313,7 +316,7 @@ public class PlayerMovement : Script numJumps = movementState.numJumps, jumped = movementState.jumped, //viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z) - }); + });*/ } /*input.RecordCurrentActorState(new PlayerActorState() @@ -334,10 +337,10 @@ public class PlayerMovement : Script if (Time.PhysicsFPS > 0 && Math.Abs(timeDeltaDiff) > 0.0001f) Console.Print("Time.DeltaTime is not stable: " + timeDeltaDiff); - input.OnFixedUpdate(); - PlayerInputState inputState = input.GetCurrentInputState(); + //Input.OnFixedUpdate(); + PlayerInputState2 inputState = Input.GetState(); - if (input is PlayerInputNetwork) + if (Input is PlayerInputNetwork2) { #if false bool canpredict = true; @@ -447,12 +450,13 @@ public class PlayerMovement : Script //viewAngles = viewAnglesLastFrame; bool canpredict = true; - if (true && input.Predict /*&& !NetworkManager.IsDemoPlaying*/ && worldStateManager.ClientFrame > 0 && worldStateManager.ServerFrame > 0) + if (true /*&& Input.Predict*/ /*&& !NetworkManager.IsDemoPlaying*/ && worldStateManager.ClientFrame > 0 && worldStateManager.ServerFrame > 0) { ulong currentFrame = worldStateManager.ServerFrame; for (; currentFrame < worldStateManager.ClientFrame; currentFrame++) { - if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState)) + if (!worldStateManager.HasPlayerFrame(PlayerId, currentFrame)) + //if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState)) { //Console.Print($"not predicting"); canpredict = false; @@ -475,24 +479,26 @@ public class PlayerMovement : Script currentFrame = worldStateManager.ServerFrame; for (; currentFrame < lastFrame; currentFrame++) { - if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState)) + //if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState)) + var frameInfo = worldStateManager.GetPlayerFrame(PlayerId, currentFrame); + if (frameInfo == null) { Console.Print($"unexpected predict failure: {currentFrame}"); break; } - if (currentFrame == inputState.frame) - movementState.jumped = movementState.jumped; + //if (currentFrame == inputState.frame) + // movementState.jumped = movementState.jumped; if (currentFrame == worldStateManager.ServerFrame) { - movementState.position = pastActorState.position; - movementState.currentVelocity = pastActorState.velocity; - movementState.lastJumped = pastActorState.lastJumpTime; - movementState.numJumps = pastActorState.numJumps; - movementState.jumped = pastActorState.jumped; + movementState.position = frameInfo.movementState.position; + movementState.currentVelocity = frameInfo.movementState.currentVelocity; + movementState.lastJumped = frameInfo.movementState.lastJumped; + movementState.numJumps = frameInfo.movementState.numJumps; + movementState.jumped = frameInfo.movementState.jumped; Actor.Position = movementState.position; - SetCameraEulerAngles(pastActorState.viewAngles, true); + SetCameraEulerAngles(frameInfo.movementState.viewAngles, true); //cameraHolder.Orientation = Quaternion.Euler(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z); //ApplyInputToCamera(pastInputState, true); @@ -508,7 +514,7 @@ public class PlayerMovement : Script //viewAngles = new Float3(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z); } else - ApplyInputToCamera(pastInputState, true); + ApplyInputToCamera(frameInfo.inputState, true); //SetCameraEulerAngles(pastActorState.viewAngles, true); //if (currentVelocity.Length > 0) @@ -516,7 +522,7 @@ public class PlayerMovement : Script //else // ApplyInputToCamera(pastInputState, true); - SimulatePlayerMovement(pastInputState); + SimulatePlayerMovement(frameInfo.inputState, frameInfo.frame); /*if ((movementState.position - pastActorState.position).Length > 0.001) Console.Print($"mispredicted position"); @@ -551,7 +557,7 @@ public class PlayerMovement : Script //rootActor.Orientation = Quaternion.Euler(0, viewAngles.X, 0); cameraHolder.Orientation = Quaternion.Euler(viewAngles.Y, viewAngles.X, viewAngles.Z); - SimulatePlayerMovement(inputState); + SimulatePlayerMovement(inputState, worldStateManager.Frame); // MAYBE? } var viewDelta = (viewAngles - oldAngles); @@ -573,7 +579,7 @@ public class PlayerMovement : Script { SetCameraEulerAngles(viewAnglesLastFrame, true); ApplyInputToCamera(inputState, true); - SimulatePlayerMovement(inputState); + SimulatePlayerMovement(inputState, worldStateManager.Frame); // MAYBE? } if (movementState.position.Length < 0.1) @@ -600,7 +606,7 @@ public class PlayerMovement : Script //SetCameraEulerAngles(new Float3(viewAnglesLastFrame.Y, viewAnglesLastFrame.X, viewAnglesLastFrame.Z), true); //SimulatePlayerMovement(inputState); - input.RecordCurrentActorState(new PlayerActorState + /*Input.RecordCurrentActorState(new PlayerActorState { position = movementState.position, velocity = movementState.currentVelocity, @@ -610,16 +616,17 @@ public class PlayerMovement : Script numJumps = movementState.numJumps, jumped = movementState.jumped, //viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z) - }); + });*/ //Console.Print($"recording frame {input.frame}, client: {GameModeManager.ClientFrame}, server: {GameModeManager.ServerFrame}"); - input.OnEndFrame(); + worldStateManager.RecordPlayerInput(PlayerId, worldStateManager.Frame, inputState, movementState); // MAYBE? + //Input.OnEndFrame(); } if (movementState.position.Length < 0.1) movementState.jumped = movementState.jumped; - if (input is PlayerInputNetwork) + if (Input is PlayerInputNetwork2) movementState.jumped = movementState.jumped; @@ -638,13 +645,13 @@ public class PlayerMovement : Script }*/ } - public void ApplyInputToCamera(PlayerInputState inputState, bool wrapAround = true) + public void ApplyInputToCamera(PlayerInputState2 inputState, bool wrapAround = true) { - if (inputState.viewDeltaX == 0.0f && inputState.viewDeltaY == 0.0f) + if (inputState.ViewDelta == Float2.Zero) return; - float viewPitch = Mathf.Clamp(viewAngles.Y + inputState.viewDeltaY, -90.0f, 90.0f); - float viewYaw = viewAngles.X + inputState.viewDeltaX; + float viewPitch = Mathf.Clamp(viewAngles.Y + inputState.ViewDelta.Y, -90.0f, 90.0f); + float viewYaw = viewAngles.X + inputState.ViewDelta.X; SetCameraEulerAngles(new Float3(viewYaw, viewPitch, viewAngles.Z), wrapAround); } @@ -894,10 +901,11 @@ public class PlayerMovement : Script if (false) { +#if false if (worldStateManager.ServerFrame > 0 && worldStateManager.ClientFrame > 0) for (ulong frame = worldStateManager.ServerFrame; frame < worldStateManager.ClientFrame; frame++) { - if (!input.GetState(frame, out var pastInputState, out var pastActorState)) + if (!Input.GetState(frame, out var pastInputState, out var pastActorState)) continue; var bbox = clientBbox; @@ -909,19 +917,21 @@ public class PlayerMovement : Script Color color = new Color(color3.X, color3.Y, color3.Z, color3.W); DebugDraw.DrawBox(bbox, color * 1f); } +#endif } - else + else if (worldStateManager.IsClient) { var serverBbox = boxCollider.OrientedBox.GetBoundingBox(); - if (input.GetState(worldStateManager.ServerFrame, out var serverInputState, out var serverActorState)) - serverBbox.Center = serverActorState.position; + var frameInfo = worldStateManager.GetPlayerFrame(PlayerId, worldStateManager.ServerFrame); + if (frameInfo != null) + serverBbox.Center = frameInfo.movementState.position; if (serverBbox.Center == clientBbox.Center) DebugDraw.DrawBox(clientBbox, Color.Magenta * 0.6f); else { - DebugDraw.DrawBox(serverBbox, Color.Red * 0.6f); - DebugDraw.DrawBox(clientBbox, Color.Blue * 0.6f); + //DebugDraw.DrawBox(serverBbox, Color.Red * 0.6f); + //DebugDraw.DrawBox(clientBbox, Color.Blue * 0.6f); } } } @@ -1160,12 +1170,12 @@ public class PlayerMovement : Script return slideMoveHit; } - public void SimulatePlayerMovement(PlayerInputState inputState) + public void SimulatePlayerMovement(PlayerInputState2 inputState, ulong frame) { - simulationTime = worldStateManager.ClientTime + (inputState.frame * (1.0f / Time.PhysicsFPS)); + simulationTime = worldStateManager.ClientTime + (frame * (1.0f / Time.PhysicsFPS)); Vector3 inputDirection = - new Float3(inputState.moveRight, 0.0f, inputState.moveForward); + new Float3(inputState.MoveRight, 0.0f, inputState.MoveForward); Vector3 moveDirection = rootActor.Transform.TransformDirection(inputDirection); Vector3 position = movementState.position; Vector3 velocity = movementState.currentVelocity; //rigidBody.LinearVelocity; @@ -1180,7 +1190,7 @@ public class PlayerMovement : Script TraceInfo traceGround = CategorizePosition(position, ref velocity); - bool jumpAction = inputState.jumping; + bool jumpAction = inputState.Jump; if (movementState.jumped && !jumpAction) movementState.jumped = false; // jump released