This commit is contained in:
2025-03-28 15:24:44 +02:00
parent cc9eacca8d
commit 6783efdb6a
25 changed files with 1077 additions and 364 deletions

View File

@@ -107,7 +107,10 @@ public class PlayerMovement : Script
private readonly bool demoDeltasVerify = true;
private WorldStateManager worldStateManager;
//private WorldStateManager worldStateManager;
private World _world;
private World World => _world ??= this.GetWorld();
private bool predicting = false;
@@ -115,8 +118,8 @@ public class PlayerMovement : Script
//public int currentInputFrame;
//private int currentInputFrame2;
public IPlayerInput Input;
[NoSerialize, HideInEditor]
public IPlayerInput Input => playerActor?.Input ?? PlayerInputNone.Instance;
//private bool physicsInteractions = false;
@@ -136,7 +139,7 @@ public class PlayerMovement : Script
public Float3 viewAngles;
private Float3 viewAnglesLastFrame;
public uint PlayerId = 0;
public uint PlayerId => playerActor ? playerActor.PlayerId : 0;
[ReadOnly]
public float CurrentVelocity
@@ -161,7 +164,6 @@ public class PlayerMovement : Script
{
base.OnAwake();
Console.Print("player awake, playerid: " + PlayerId);
rootActor = Actor.GetChild("RootActor");
rigidBody = Actor.As<RigidBody>();
playerActor = Actor.As<PlayerActor>();
@@ -176,36 +178,6 @@ public class PlayerMovement : Script
//rigidBody.TriggerExit += OnTriggerExit;
}
public void SetInput(uint playerId)
{
//if (playerId == 0)
// input = new PlayerInput();
Assert.IsTrue(playerId != uint.MaxValue);
PlayerId = playerId;
bool isServerScene = Scene.Name == "ServerScene";
if (isServerScene)
worldStateManager = NetworkManager.serverWorldStateManager;
else
worldStateManager = NetworkManager.clientWorldStateManager;
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 PlayerInput2();//new PlayerInputLocal(playerActor);
}
else
{
Console.Print("network player: " + playerId.ToString());
Input = new PlayerInputNetwork2(playerId, worldStateManager);
}
Assert.IsTrue(worldStateManager != null);
}
#if false
public void SetInput(string demoFile)
{
@@ -286,7 +258,7 @@ public class PlayerMovement : Script
//if (Input is PlayerInputDemo /*&& currentInputFrame2 >= currentInputFrame*/)
// return;
Input.SetFrame(worldStateManager.Frame);
Input.SetFrame(World.Frame);
Input.UpdateState();
/*if (input.frame > 0)
@@ -345,7 +317,107 @@ public class PlayerMovement : Script
//Input.OnFixedUpdate();
PlayerInputState2 inputState = Input.GetState();
bool predict = World.IsClient;
if (predict)
{
// Get the latest frame we have predicted
ulong lastFrame = World.ServerFrame;
for (; lastFrame < World.Frame; lastFrame++)
{
if (!World.HasPlayerFrame(PlayerId, lastFrame))
//if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
//Console.Print($"not predicting");
predict = false;
break;
}
}
if (predict)
{
var oldAngles = viewAngles;
var oldPos = movementState.position;
var oldVel = movementState.currentVelocity;
ulong currentFrame = World.ServerFrame;
if (currentFrame == World.ServerFrame)
{
// Reset all state to latest confirmed state from server
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
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);
//cameraHolder.Orientation = Quaternion.Euler(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
//ApplyInputToCamera(pastInputState, true);
//if (pastActorState.viewAngles != new Float3(90f, 0f, 0f))
// Console.Print($"moved server frame: {currentFrame}, {pastActorState.viewAngles}");
currentFrame++;
//rootActor.Orientation = pastActorState.orientation;
//viewAngles = pastActorState.viewAngles;
//viewAngles = new Float3(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
}
// Predict the frames since last received frame from server up to latest client frame
predicting = true;
for (; currentFrame < lastFrame; currentFrame++)
{
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
if (frameInfo == null)
{
Console.Print($"unexpected predict failure: {currentFrame}");
break;
}
ApplyInputToCamera(frameInfo.inputState, true);
SimulatePlayerMovement(frameInfo.inputState, frameInfo.frame);
}
predicting = false;
var posDelta = (movementState.position - oldPos);
var velDelta = (movementState.currentVelocity - oldVel);
if (posDelta.Length > 0.001)
Console.Print($"mispredicted final position");
if (velDelta.Length > 0.001)
Console.Print($"mispredicted final velocity");
// Run simulation for the upcoming frame
//if (input is not PlayerInputNetwork)
{
/*if ((movementState.position - oldPos).Length > 0.001)
Console.Print($"mispredicted final position");
if ((currentVelocity - oldVel).Length > 0.001)
Console.Print($"mispredicted final velocity");*/
ApplyInputToCamera(inputState, true);
// Ensure orientation is always up-to-date after predicting
//rootActor.Orientation = Quaternion.Euler(0, viewAngles.X, 0);
cameraHolder.Orientation = Quaternion.Euler(viewAngles.Y, viewAngles.X, viewAngles.Z);
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
var viewDelta = (viewAngles - oldAngles);
if (viewDelta.Length > 0.001)
Console.Print($"mispredicted final viewangles: {viewAngles} <- {oldAngles}");
}
}
if (!predict)
{
SetCameraEulerAngles(viewAnglesLastFrame, true);
ApplyInputToCamera(inputState, true);
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
viewAnglesLastFrame = viewAngles;
#if false
if (false && Input is PlayerInputNetwork2)
{
#if false
@@ -456,12 +528,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*/ && World.Frame > 0 && World.ServerFrame > 0)
{
ulong currentFrame = worldStateManager.ServerFrame;
for (; currentFrame < worldStateManager.ClientFrame; currentFrame++)
// Get the latest frame we have predicted
ulong currentFrame = World.ServerFrame;
for (; currentFrame < World.Frame; currentFrame++)
{
if (!worldStateManager.HasPlayerFrame(PlayerId, currentFrame))
if (!World.HasPlayerFrame(PlayerId, currentFrame))
//if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
//Console.Print($"not predicting");
@@ -471,22 +544,19 @@ public class PlayerMovement : Script
}
ulong lastFrame = currentFrame;
if (canpredict)
{
var oldAngles = viewAngles;
var oldPos = movementState.position;
var oldVel = movementState.currentVelocity;
// Predict the frames since last received frame from server up to latest client frame
predicting = true;
currentFrame = worldStateManager.ServerFrame;
currentFrame = World.ServerFrame;
for (; currentFrame < lastFrame; currentFrame++)
{
//if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState))
var frameInfo = worldStateManager.GetPlayerFrame(PlayerId, currentFrame);
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
if (frameInfo == null)
{
Console.Print($"unexpected predict failure: {currentFrame}");
@@ -496,7 +566,7 @@ public class PlayerMovement : Script
//if (currentFrame == inputState.frame)
// movementState.jumped = movementState.jumped;
if (currentFrame == worldStateManager.ServerFrame)
if (currentFrame == World.ServerFrame)
{
movementState.position = frameInfo.movementState.position;
movementState.currentVelocity = frameInfo.movementState.currentVelocity;
@@ -563,7 +633,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, worldStateManager.Frame); // MAYBE?
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
var viewDelta = (viewAngles - oldAngles);
@@ -585,7 +655,7 @@ public class PlayerMovement : Script
{
SetCameraEulerAngles(viewAnglesLastFrame, true);
ApplyInputToCamera(inputState, true);
SimulatePlayerMovement(inputState, worldStateManager.Frame); // MAYBE?
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
}
if (movementState.position.Length < 0.1)
@@ -625,7 +695,7 @@ public class PlayerMovement : Script
});*/
//Console.Print($"recording frame {input.frame}, client: {GameModeManager.ClientFrame}, server: {GameModeManager.ServerFrame}");
worldStateManager.RecordPlayerInput(PlayerId, worldStateManager.Frame, inputState, movementState); // MAYBE?
World.RecordPlayerInput(PlayerId, World.Frame, inputState, movementState); // MAYBE?
Input.ResetState();
}
@@ -649,6 +719,7 @@ public class PlayerMovement : Script
currentVelocity = pastActorState2.velocity;
SetCameraEulerAngles(pastActorState2.viewAngles, true);
}*/
#endif
}
public void ApplyInputToCamera(PlayerInputState2 inputState, bool wrapAround = true)
@@ -925,10 +996,10 @@ public class PlayerMovement : Script
}
#endif
}
else if (worldStateManager.IsClient)
else if (World.IsClient)
{
var serverBbox = boxCollider.OrientedBox.GetBoundingBox();
var frameInfo = worldStateManager.GetPlayerFrame(PlayerId, worldStateManager.ServerFrame);
var frameInfo = World.GetPlayerFrame(PlayerId, World.ServerFrame);
if (frameInfo != null)
serverBbox.Center = frameInfo.movementState.position;
@@ -1178,7 +1249,7 @@ public class PlayerMovement : Script
public void SimulatePlayerMovement(PlayerInputState2 inputState, ulong frame)
{
simulationTime = worldStateManager.ClientTime + (frame * (1.0f / Time.PhysicsFPS));
simulationTime = World.GetFrameTime(frame);
Vector3 inputDirection =
new Float3(inputState.MoveRight, 0.0f, inputState.MoveForward);