netcode progress, improved handling of missing frames

This commit is contained in:
2025-09-07 18:45:24 +03:00
parent 0d324c0ff0
commit 95de571eb5
9 changed files with 259 additions and 46 deletions

View File

@@ -74,6 +74,7 @@ public struct PlayerMovementState
public int numJumps;
public bool jumped;
public bool onGround;
public ulong frame;
public PlayerMovementState()
@@ -250,9 +251,20 @@ public class PlayerMovement : Script
viewAnglesLastFrame = viewAngles;
}
private static int framedropped = 0;
public override void OnUpdate()
{
Console.Print("playerMovement OnUpdate");
if (World.IsServer && Mathf.Abs(Time.DeltaTime - (1.0f / Time.UpdateFPS)) > (1.0f / Time.UpdateFPS) * 0.999f)
{
Console.Print($"drop: {Time.DeltaTime*1000.0f}ms");
framedropped = 3;
}
else if (World.IsServer && framedropped > 0)
{
Console.Print("dropping...");
framedropped--;
}
//Console.Print($"{(World.IsClient ? "[cl] " : "[sv] ") + World.Frame.ToString()} playerMovement OnUpdate");
//input.OnUpdate();
@@ -315,7 +327,7 @@ public class PlayerMovement : Script
public override void OnFixedUpdate()
{
Console.Print("playerMovement OnFixedUpdate");
//Console.Print($"{(World.IsClient ? "[cl] " : "[sv] ") + World.Frame.ToString()} playerMovement OnFixedUpdate");
float timeDeltaDiff = Time.DeltaTime - 1.0f / Time.PhysicsFPS;
if (Time.PhysicsFPS > 0 && Math.Abs(timeDeltaDiff) > 0.0001f)
Console.Print("Time.DeltaTime is not stable: " + timeDeltaDiff);
@@ -413,13 +425,93 @@ public class PlayerMovement : Script
}
}
if (!predict)
if (World.IsServer)
{
ulong currentFrame = World.GetLastProcessedFrame(PlayerId);
{
// Rewind to last confirmed state
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
if (frameInfo != null && frameInfo.movementState.frame == currentFrame)
{
// Reset all state to latest confirmed state from server
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(frameInfo.movementState.viewAngles, true);
//ApplyInputToCamera(frameInfo.inputState, true);
}
else if (frameInfo == null)
{
// First frame, update the known state
movementState.viewAngles = viewAngles;
World.UpdatePlayerState(PlayerId, currentFrame, movementState);
}
currentFrame++;
}
//Console.Print("before:" + viewAngles.ToString());
ulong lastFrame = World.GetLastReceivedFrame(PlayerId);
PlayerFrame lastFrameInfo = null;
for (; currentFrame < lastFrame+1; currentFrame++)
{
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
if (frameInfo == null || frameInfo.inputState.Frame != currentFrame)
//if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
Console.Print($"frame {currentFrame} missing");
frameInfo = lastFrameInfo; // Use last known input
if (frameInfo == null)
{
// FIXME
frameInfo = new PlayerFrame()
{
inputState =
{
Frame = currentFrame,
},
movementState = movementState,
};
frameInfo.movementState.frame = currentFrame;
}
//continue;
//Console.Print($"not predicting");
//predict = false;
//break;
}
else
{
Input.SetFrame(currentFrame);
Input.UpdateState();
ApplyInputToCamera(frameInfo.inputState, true);
lastFrameInfo = frameInfo;
}
SimulatePlayerMovement(frameInfo.inputState, currentFrame);
movementState.viewAngles = viewAngles;
//Console.Print("tick: " + viewAngles.ToString());
//if (frameInfo.movementState.frame != currentFrame)
World.UpdatePlayerState(PlayerId, currentFrame, movementState);
//else
// currentFrame = currentFrame;
}
}
else if (!predict)
{
SetCameraEulerAngles(viewAnglesLastFrame, true);
ApplyInputToCamera(inputState, true);
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
//if (!movementState.currentVelocity.IsZero)
// Console.Print($"{(World.IsClient ? "client" : "server")} {World.Frame} vel: {movementState.currentVelocity}, pos: {movementState.position}");
viewAnglesLastFrame = viewAngles;
#if false