netcode good condition

This commit is contained in:
2023-04-19 21:38:28 +03:00
parent 3b4d50e75e
commit 353db087a6
8 changed files with 403 additions and 79 deletions

1
.gitignore vendored
View File

@@ -24,3 +24,4 @@ Assets/desktop.ini
Assets/Maps/autosave/
Demos/
omnisharp.json
console.log

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -78,6 +79,7 @@ namespace Game
public static ReadOnlySpan<ConsoleLine> Lines => instance.Lines;
public static void Init()
{
if (instance != null)
@@ -210,8 +212,15 @@ namespace Game
public bool ShowExecutedLines = true;
private StreamWriter logStream;
internal ConsoleInstance()
{
#if FLAX_EDITOR
logStream = new StreamWriter(@"C:\dev\GoakeFlax\console.log", false);
#else
logStream = new StreamWriter(Path.Combine(Directory.GetCurrentDirectory(), "console.log"), false);
#endif
}
public bool IsOpen { get; internal set; } = true;
@@ -225,6 +234,12 @@ namespace Game
public void Dispose()
{
if (logStream != null)
{
logStream.Flush();
logStream.Dispose();
logStream = null;
}
}
// Initializes the Console system.
@@ -413,6 +428,7 @@ namespace Game
{
ConsoleLine lineEntry = new ConsoleLine(line);
consoleLines.Add(lineEntry);
logStream.WriteLine(line);
OnPrint?.Invoke(text);
}
}
@@ -420,8 +436,10 @@ namespace Game
{
ConsoleLine lineEntry = new ConsoleLine(text);
consoleLines.Add(lineEntry);
logStream.WriteLine(text);
OnPrint?.Invoke(text);
}
logStream.Flush();
if (Debugger.IsAttached)
System.Diagnostics.Debug.WriteLine(text);
}

View File

@@ -45,6 +45,8 @@ namespace Game
private static Dictionary<uint, PlayerActor> players;
private static Dictionary<uint, NetworkConnection> playerConnections;
public static Dictionary<uint, ulong> playerLastReceivedFrames;
private static Dictionary<uint, ulong> playerLastFrame;
private static bool welcomed = false;
private static WorldState serverWorldState;
@@ -65,6 +67,8 @@ namespace Game
players = new Dictionary<uint, PlayerActor>();
playerConnections = new Dictionary<uint, NetworkConnection>();
playerLastReceivedFrames = new Dictionary<uint, ulong>();
playerLastFrame = new Dictionary<uint, ulong>();
serverWorldState = new WorldState();
clientWorldState = new WorldState();
@@ -138,24 +142,28 @@ namespace Game
foreach (KeyValuePair<uint, PlayerActor> kv in players)
{
var playerId = kv.Key;
var otherPlayerId = kv.Key;
foreach (KeyValuePair<uint, PlayerActor> kv2 in players)
{
//if (kv2.Key == playerId)
// continue;
var otherPlayerActor = kv2.Value;
var playerActor = kv2.Value;
var playerId = kv2.Key;
// TODO: relevancy checks here etc.
PlayerMovement playerMovement = otherPlayerActor.GetScript<PlayerMovement>();
PlayerMovement playerMovement = playerActor.GetScript<PlayerMovement>();
//PlayerActorState actorState = playerMovement.input.GetCurrentActorState();
//PlayerInputState inputState = playerMovement.input.GetCurrentInputState();
playerMovement.input.GetState(serverWorldState.frame, out var inputState, out var actorState);
var playerFrame = playerLastFrame[playerId];
if (!playerMovement.input.GetState(playerFrame, out var inputState, out var actorState))
Console.Print("send input failure to client");
{
NetworkMessage message = NetworkManager.ServerBeginSendMessage();
message.WriteByte((byte)GameModeMessageType.PlayerPosition);
message.WriteUInt64(serverWorldState.frame);
message.WriteUInt64(playerFrame);
message.WriteUInt32(kv2.Key);
message.WriteSingle(actorState.position.X);
message.WriteSingle(actorState.position.Y);
@@ -171,6 +179,8 @@ namespace Game
message.WriteSingle(actorState.viewAngles.Y);
message.WriteSingle(actorState.viewAngles.Z);
message.WriteSingle(actorState.lastJumpTime);
message.WriteInt32(actorState.numJumps);
message.WriteBoolean(actorState.jumped);
//inputState.frame
message.WriteSingle(inputState.viewDeltaX);
@@ -180,7 +190,7 @@ namespace Game
message.WriteBoolean(inputState.attacking);
message.WriteBoolean(inputState.jumping);
NetworkManager.ServerEndSendMessage(ref message, playerConnections[playerId]);
NetworkManager.ServerEndSendMessage(ref message, playerConnections[otherPlayerId]);
}
}
}
@@ -195,6 +205,13 @@ namespace Game
foreach (PlayerActor playerActor in Level.GetActors<PlayerActor>())
{
var playerId = playerActor.PlayerId;
if (!clientWorldState.playerFrameHistory.ContainsKey(playerId))
{
var playerFrames = new PlayerFrame[120];
for (int j = 0; j < playerFrames.Length; j++)
playerFrames[j] = new PlayerFrame();
clientWorldState.playerFrameHistory.Add(playerId, playerFrames);
}
var playerFrameHistory = clientWorldState.playerFrameHistory[playerId];
var playerFrame = playerFrameHistory[clientWorldState.frame % 120];
@@ -274,6 +291,11 @@ namespace Game
if (NetworkManager.IsClient || NetworkManager.IsLocalClient)
{
var serverFrame = networkEvent.Message.ReadUInt64();
if (!NetworkManager.IsLocalClient)
serverWorldState.frame = serverFrame;
//lastReceivedServerFrame = serverFrame;
clientWorldState.frame += serverFrame;
ClientTime = networkEvent.Message.ReadSingle();
int numActors = (int)networkEvent.Message.ReadUInt32();
for (int i = 0; i < numActors; i++)
@@ -294,11 +316,6 @@ namespace Game
Console.Print("received welcome: frame " + serverWorldState.frame);
if (!NetworkManager.IsLocalClient)
serverWorldState.frame = serverFrame;
//lastReceivedServerFrame = serverFrame;
clientWorldState.frame += serverFrame;
if (!players.ContainsKey(NetworkManager.LocalPlayerClientId)) // listen server
players.Add(NetworkManager.LocalPlayerClientId, null);
//playerConnections.Add(NetworkManager.LocalPlayerClientId, connection);
@@ -340,11 +357,15 @@ namespace Game
inputState.jumping = networkEvent.Message.ReadBoolean();
UpdatePlayerInput(playerId, inputState);
playerLastReceivedFrames[playerId] = inputState.frame;
break;
}
case GameModeMessageType.PlayerPosition:
{
uint playerId = networkEvent.Sender.ConnectionId;
//uint playerId = networkEvent.Sender.ConnectionId;
PlayerInputState inputState = default; //?
PlayerActorState actorState;
@@ -364,6 +385,8 @@ namespace Game
actorState.viewAngles.Y = networkEvent.Message.ReadSingle();
actorState.viewAngles.Z = networkEvent.Message.ReadSingle();
actorState.lastJumpTime = networkEvent.Message.ReadSingle();
actorState.numJumps = networkEvent.Message.ReadInt32();
actorState.jumped = networkEvent.Message.ReadBoolean();
inputState.frame = reportedFrame;
inputState.viewDeltaX = networkEvent.Message.ReadSingle();
@@ -373,16 +396,21 @@ namespace Game
inputState.attacking = networkEvent.Message.ReadBoolean();
inputState.jumping = networkEvent.Message.ReadBoolean();
//if (actorState.viewAngles != new Float3(90f, 0f, 0f))
// Console.Print($"{reportedFrame} has viewangles: {actorState.viewAngles}");
//Assert.IsTrue(reportedFrame >= lastReceivedServerFrame);
if (reportedFrame < lastReceivedServerFrame)
if (reportedPlayerId == NetworkManager.LocalPlayerClientId && reportedFrame < lastReceivedServerFrame)
{
//Console.Print($"packet wrong order, received {lastReceivedServerFrame}, new {reportedFrame}");
Console.Print($"packet wrong order, received {lastReceivedServerFrame}, new {reportedFrame}");
break;
}
if (NetworkManager.IsClient)
{
lastReceivedServerFrame = reportedFrame;
if (reportedPlayerId == NetworkManager.LocalPlayerClientId)
lastReceivedServerFrame = reportedFrame;
//Console.Print($"we drifted, corrected. client frame: {serverWorldState.frame}, server frame: {reportedFrame}");
PlayerActor playerActor = Level.GetActors<PlayerActor>().FirstOrDefault(x =>
x.GetScript<PlayerMovement>().PlayerId == reportedPlayerId);
@@ -392,9 +420,19 @@ namespace Game
{
PlayerInput playerInput = playerActor.GetScript<PlayerMovement>().input;
playerInput.SetState(reportedFrame, inputState, actorState);
{
if (NetworkManager.IsLocalClient && reportedPlayerId == NetworkManager.LocalPlayerClientId)
{ }
else
playerInput.SetState(reportedFrame, inputState, actorState);
if (!NetworkManager.IsLocalClient && playerInput is PlayerInputNetwork)
{
playerActor.Position = actorState.position;
playerActor.GetScript<PlayerMovement>().currentVelocity = actorState.velocity;
playerActor.GetScript<PlayerMovement>().lastJumped = actorState.lastJumpTime;
playerActor.GetScript<PlayerMovement>().numJumps = actorState.numJumps;
playerActor.GetScript<PlayerMovement>().jumped = actorState.jumped;
playerActor.GetScript<PlayerMovement>().SetCameraEulerAngles(actorState.viewAngles, true);
}
//playerActor.SetPosition(reportedPosition);
}
@@ -426,8 +464,20 @@ namespace Game
message.WriteSingle(playerActor.Position.X);
message.WriteSingle(playerActor.Position.Y);
message.WriteSingle(playerActor.Position.Z);
playerActor.GetScript<PlayerMovement>().input.SetState(serverWorldState.frame, new PlayerInputState(), new PlayerActorState()
{
position = playerActor.Position,
velocity = playerActor.GetScript<PlayerMovement>().currentVelocity,
orientation = playerActor.GetScript<PlayerMovement>().rootActor.Orientation,
viewAngles = playerActor.GetScript<PlayerMovement>().viewAngles,
lastJumpTime = playerActor.GetScript<PlayerMovement>().lastJumped,
numJumps = playerActor.GetScript<PlayerMovement>().numJumps,
jumped = playerActor.GetScript<PlayerMovement>().jumped,
});
}
NetworkManager.ServerEndSendMessage(ref message, connection);
}
return true;
}
@@ -475,7 +525,10 @@ namespace Game
private static void SpawnPlayer(uint playerId, Float3 position, Vector3 eulerAngles)
{
if (NetworkManager.IsLocalClient)
if (NetworkManager.IsServer && !playerLastFrame.ContainsKey(playerId))
playerLastFrame.Add(playerId, serverWorldState.frame);
if (NetworkManager.IsLocalClient && playerId == NetworkManager.LocalPlayerClientId)
return; // Handled by listenserver
//spawned = true;
@@ -495,13 +548,71 @@ namespace Game
PlayerInput playerInput = playerActor.GetScript<PlayerMovement>().input;
playerInput.frame = (NetworkManager.IsServer) ? serverWorldState.frame : clientWorldState.frame;
if (NetworkManager.IsServer)
{
serverWorldState.actors.Add(playerActor);
if (!playerLastReceivedFrames.ContainsKey(playerId))
playerLastReceivedFrames.Add(playerId, 0);
}
}
private static void UpdatePlayerInput(uint playerId, PlayerInputState inputState)
{
if (playerId == NetworkManager.LocalPlayerClientId)
{
playerLastFrame[playerId] = inputState.frame;
return;
}
PlayerActor playerActor = players[playerId];
PlayerMovement playerMovement = playerActor.GetScript<PlayerMovement>();
playerActor.UpdateNetworkInput(inputState);
ulong startFrame = playerLastFrame[playerId];
if (startFrame >= inputState.frame)
return; // dropped frame, ignore
// 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 _);
for (; frame <= inputState.frame; frame++)
{
if (!playerMovement.input.GetState(frame, out var lastInputState, out var lastActorState))
{
// dropped frame, use previous input
lastInputState = prevInputState;
lastInputState.frame = frame;
}
playerMovement.ApplyInputToCamera(lastInputState, true);
playerMovement.SimulatePlayerMovement(lastInputState);
playerMovement.input.SetState(frame, lastInputState, new PlayerActorState()
{
position = playerActor.Position,
velocity = playerMovement.currentVelocity,
orientation = playerMovement.rootActor.Orientation,
viewAngles = playerMovement.viewAngles,
lastJumpTime = playerMovement.lastJumped,
numJumps = playerMovement.numJumps,
jumped = playerMovement.jumped,
});
simframs++;
prevInputState = lastInputState;
}
if (playerActor.Position.Length < 1.0f)
simframs = simframs;
playerLastFrame[playerId] = inputState.frame;//frame;
if (simframs > 1)
Console.Print($"simulated {simframs} frames");
}
}
}

View File

@@ -96,6 +96,12 @@ namespace Game
server.EndSendMessage(channelType, message, connection);
}
public static void ServerEndSendMessage(ref NetworkMessage message, NetworkConnection[] connections, NetworkChannelType channelType = NetworkChannelType.Reliable)
{
server.EndSendMessage(channelType, message, connections);
}
public static NetworkMessage ClientBeginSendMessage()
{
NetworkMessage message = client.BeginSendMessage();

View File

@@ -127,7 +127,8 @@ namespace Game
return;
//PlayerInputState inputState = new PlayerInputState(frame, viewDeltaXYMoveForwardRight.X, viewDeltaXYMoveForwardRight.Y, viewDeltaXYMoveForwardRight.Z, viewDeltaXYMoveForwardRight.W, attacking, jumping);
playerInputNetwork.currentState.input = inputState;
//playerInputNetwork.currentState.input = inputState;
playerInputNetwork.SetState(inputState.frame, inputState);
}
public void SetPosition(Float3 newPosition)

View File

@@ -76,6 +76,8 @@ namespace Game
public Quaternion orientation;
public Float3 viewAngles; // yaw, pitch, roll
public float lastJumpTime;
public int numJumps;
public bool jumped;
}
[StructLayout(LayoutKind.Sequential)]
@@ -106,8 +108,8 @@ namespace Game
public virtual void OnEndFrame()
{
Console.Print("recorded frame " + frame);
currentState.input.frame = frame;
//Console.Print("recorded frame " + frame);
states[frame % 120] = currentState;
/*ulong oldest = ulong.MaxValue;
@@ -116,10 +118,14 @@ namespace Game
oldestFrame = oldest;*/
frame++;
currentState.input.frame = frame;
}
public virtual void RecordCurrentActorState(PlayerActorState actorState)
{
if (actorState.position.Length <= 0.01)
Console.Print("wrong recorded position?");
currentState.actor = actorState;
}
public bool GetState(ulong frame, out PlayerInputState inputState, out PlayerActorState actorState)
@@ -137,6 +143,14 @@ namespace Game
return true;
}
public void SetState(ulong frame, PlayerInputState inputState)
{
int frameIndex = (int)frame % 120;
states[frameIndex].input = inputState;
states[frameIndex].input.frame = frame;
states[frameIndex].actor = new PlayerActorState();
}
public void SetState(ulong frame, PlayerInputState inputState, PlayerActorState actorState)
{
int frameIndex = (int)frame % 120;

View File

@@ -116,9 +116,7 @@ namespace Game
if (!IsRecording)
return;
if (actorState.position.Length <= 0.01)
Console.Print("wrong recorded position?");
currentState.actor = actorState;
base.RecordCurrentActorState(actorState);
}
public void FlushDemo()

View File

@@ -86,17 +86,17 @@ namespace Game
//public int currentInputFrame;
//private int currentInputFrame2;
private Float3 currentVelocity;
public Float3 currentVelocity;
public PlayerInput input;
//private bool physicsInteractions = false;
private bool jumped;
public bool jumped;
//private int lastInputFrame;
private float lastJumped = -1f;
public float lastJumped = -1f;
private float lastLanded = -1f;
private int numJumps;
public int numJumps;
private float simulationTime = 0f;
[ReadOnly] public bool onGround;
@@ -104,8 +104,7 @@ namespace Game
private Actor cameraHolder;
private PlayerActor playerActor;
private Actor rootActor;
private float startupTime;
public Actor rootActor;
public Float3 viewAngles;
private Float3 viewAnglesLastFrame;
@@ -164,8 +163,6 @@ namespace Game
//rigidBody.CollisionEnter += OnCollisionEnter;
//rigidBody.TriggerEnter += OnTriggerEnter;
//rigidBody.TriggerExit += OnTriggerExit;
startupTime = Time.TimeSinceStartup;
}
public void SetInput(uint playerId)
@@ -279,23 +276,31 @@ namespace Game
viewRoll = actorState.viewRoll;
}*/
PlayerInputState inputState = input.GetCurrentInputState();
//if (inputState.viewDeltaX != 0 || inputState.viewDeltaY != 0)
// inputState = inputState;
viewAngles = viewAnglesLastFrame;
ApplyInputToCamera(inputState);
input.RecordCurrentActorState(new PlayerActorState
if (input is not PlayerInputNetwork)
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
PlayerInputState inputState = input.GetCurrentInputState();
//if (inputState.viewDeltaX != 0 || inputState.viewDeltaY != 0)
// inputState = inputState;
ApplyInputToCamera(inputState);
input.RecordCurrentActorState(new PlayerActorState
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
numJumps = numJumps,
jumped = jumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
}
/*input.RecordCurrentActorState(new PlayerActorState()
{
@@ -372,6 +377,106 @@ namespace Game
}*/
}
}
else if (input is PlayerInputNetwork)
{
#if false
bool canpredict = true;
if (false && input.Predict && GameModeManager.ClientFrame > 0 && GameModeManager.ServerFrame > 0)
{
ulong maxFrame = /*NetworkManager.IsServer ? GameModeManager.playerLastReceivedFrames[PlayerId] :*/ GameModeManager.ClientFrame;
ulong currentFrame = GameModeManager.ServerFrame;
for (; currentFrame <= maxFrame; currentFrame++)
{
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
//Console.Print($"not predicting");
//canpredict = false;
break;
}
}
ulong lastFrame = currentFrame;
if (input is PlayerInputNetwork)
{
//canpredict = true;
//lastFrame = GameModeManager.ServerFrame+1;
}
predicting = true;
currentFrame = GameModeManager.ServerFrame;
for (; currentFrame < lastFrame; currentFrame++)
{
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
Console.Print($"unexpected predict failure: {currentFrame}");
break;
}
if (currentFrame == inputState.frame)
jumped = jumped;
if (currentFrame == GameModeManager.ServerFrame)
{
Actor.Position = pastActorState.position;
currentVelocity = pastActorState.velocity;
lastJumped = pastActorState.lastJumpTime;
numJumps = pastActorState.numJumps;
jumped = pastActorState.jumped;
SetCameraEulerAngles(pastActorState.viewAngles, true);
if (Actor.Position.Length < 0.1)
jumped = jumped;
continue;
//rootActor.Orientation = pastActorState.orientation;
//viewAngles = pastActorState.viewAngles;
//viewAngles = new Float3(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z);
}
else
ApplyInputToCamera(pastInputState, true);
//SetCameraEulerAngles(pastActorState.viewAngles, true);
//if (currentVelocity.Length > 0)
// currentVelocity = currentVelocity;
//else
// ApplyInputToCamera(pastInputState, true);
SimulatePlayerMovement(pastInputState);
break;
/*if ((Actor.Position - pastActorState.position).Length > 0.001)
Console.Print($"mispredicted position");
if ((currentVelocity - pastActorState.velocity).Length > 0.001)
Console.Print($"mispredicted velocity");
if ((viewAngles - pastActorState.viewAngles).Length > 0.001)
Console.Print($"mispredicted viewangles: {viewAngles - oldAngles}");*/
//Console.Print($"predicted: {currentFrame}");
}
/*if (input is PlayerInputNetwork)
{
currentFrame = lastFrame - 1;
if (input.GetState(currentFrame, out var lastInputState, out var lastActorState))
{
for (; currentFrame < GameModeManager.ClientFrame; currentFrame++)
{
ApplyInputToCamera(lastInputState, true);
SimulatePlayerMovement(lastInputState);
}
}
}*/
predicting = false;
}
else
{
//ApplyInputToCamera(inputState, true);
//SimulatePlayerMovement(inputState);
}
#endif
}
else
{
if (Actor.Position.Length < 0.1)
@@ -379,41 +484,59 @@ namespace Game
//viewAngles = viewAnglesLastFrame;
//ApplyInputToCamera(inputState);
var oldAngles = viewAngles;
//viewAngles = viewAnglesLastFrame;
bool canpredict = true;
if (true && input.Predict && GameModeManager.ClientFrame > 0 && GameModeManager.ServerFrame > 0)
{
for (ulong currentFrame = GameModeManager.ServerFrame; currentFrame < GameModeManager.ClientFrame; currentFrame++)
ulong currentFrame = GameModeManager.ServerFrame;
for (; currentFrame < GameModeManager.ClientFrame; currentFrame++)
{
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
Console.Print($"not predicting");
//Console.Print($"not predicting");
canpredict = false;
break;
}
}
ulong lastFrame = currentFrame;
if (canpredict)
{
//var oldPos = Actor.Position;
//var oldVel = currentVelocity;
{
var oldAngles = viewAngles;
var oldPos = Actor.Position;
var oldVel = currentVelocity;
predicting = true;
for (ulong currentFrame = GameModeManager.ServerFrame; currentFrame < GameModeManager.ClientFrame; currentFrame++)
currentFrame = GameModeManager.ServerFrame;
for (; currentFrame < lastFrame; currentFrame++)
{
if (!input.GetState(currentFrame, out var pastInputState, out var pastActorState))
{
Console.Print($"predict failure: {currentFrame}");
Console.Print($"unexpected predict failure: {currentFrame}");
break;
}
if (currentFrame == inputState.frame)
jumped = jumped;
if (currentFrame == GameModeManager.ServerFrame)
{
Actor.Position = pastActorState.position;
currentVelocity = pastActorState.velocity;
lastJumped = pastActorState.lastJumpTime;
numJumps = pastActorState.numJumps;
jumped = pastActorState.jumped;
SetCameraEulerAngles(pastActorState.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}");
if (Actor.Position.Length < 0.1)
jumped = jumped;
@@ -434,35 +557,45 @@ namespace Game
// ApplyInputToCamera(pastInputState, true);
SimulatePlayerMovement(pastInputState);
if ((Actor.Position - pastActorState.position).Length > 0.001)
/*if ((Actor.Position - pastActorState.position).Length > 0.001)
Console.Print($"mispredicted position");
if ((currentVelocity - pastActorState.velocity).Length > 0.001)
Console.Print($"mispredicted velocity");
if ((viewAngles - pastActorState.viewAngles).Length > 0.001)
Console.Print($"mispredicted viewangles: {viewAngles - oldAngles}");
Console.Print($"mispredicted viewangles: {viewAngles - oldAngles}");*/
//Console.Print($"predicted: {currentFrame}");
}
predicting = false;
/*if ((Actor.Position - oldPos).Length > 0.001)
if ((Actor.Position - oldPos).Length > 0.001)
Console.Print($"mispredicted final position");
if ((currentVelocity - oldVel).Length > 0.001)
Console.Print($"mispredicted final velocity");*/
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);
//if (input is not PlayerInputNetwork)
{
/*if ((Actor.Position - oldPos).Length > 0.001)
Console.Print($"mispredicted final position");
if ((currentVelocity - oldVel).Length > 0.001)
Console.Print($"mispredicted final velocity");*/
SimulatePlayerMovement(inputState);
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);
}
if ((viewAngles - oldAngles).Length > 0.001)
Console.Print($"mispredicted final viewangles: {viewAngles - oldAngles}");
Console.Print($"mispredicted final viewangles: {viewAngles} <- {oldAngles}");
//if (viewAngles != new Float3(90f, 0f, 0f))
// Console.Print($"moved client frame: {GameModeManager.ClientFrame}, {viewAngles}");
//Console.Print($"current: {inputState.frame}");
//if (GameModeManager.ClientFrame - GameModeManager.ServerFrame > 0)
@@ -474,7 +607,6 @@ namespace Game
if (!canpredict)
{
SetCameraEulerAngles(viewAnglesLastFrame, true);
ApplyInputToCamera(inputState, true);
SimulatePlayerMovement(inputState);
@@ -503,21 +635,30 @@ namespace Game
//SetCameraEulerAngles(new Float3(pastActorState.viewAngles.Y, pastActorState.viewAngles.X, pastActorState.viewAngles.Z), true);
//SetCameraEulerAngles(new Float3(viewAnglesLastFrame.Y, viewAnglesLastFrame.X, viewAnglesLastFrame.Z), true);
//SimulatePlayerMovement(inputState);
input.RecordCurrentActorState(new PlayerActorState
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
numJumps = numJumps,
jumped = jumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
//Console.Print($"recording frame {input.frame}, client: {GameModeManager.ClientFrame}, server: {GameModeManager.ServerFrame}");
input.OnEndFrame();
}
if (Actor.Position.Length < 0.1)
jumped = jumped;
input.RecordCurrentActorState(new PlayerActorState
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewAngles = viewAngles,
lastJumpTime = lastJumped,
//viewAngles = new Float3(viewAngles.Y, viewAngles.X, viewAngles.Z)
});
input.OnEndFrame();
if (input is PlayerInputNetwork)
jumped = jumped;
//lastInputFrame = currentInputFrame;
@@ -533,7 +674,7 @@ namespace Game
}*/
}
private void ApplyInputToCamera(PlayerInputState inputState, bool wrapAround = true)
public void ApplyInputToCamera(PlayerInputState inputState, bool wrapAround = true)
{
if (inputState.viewDeltaX == 0.0f && inputState.viewDeltaY == 0.0f)
return;
@@ -543,7 +684,7 @@ namespace Game
SetCameraEulerAngles(new Float3(viewYaw, viewPitch, viewAngles.Z), wrapAround);
}
private void SetCameraEulerAngles(Float3 angles, bool wrapAround = true)
public void SetCameraEulerAngles(Float3 angles, bool wrapAround = true)
{
if (viewAngles == angles)
return;
@@ -785,7 +926,40 @@ namespace Game
}
else if (boxCollider && boxCollider.IsActive)
{
DebugDraw.DrawWireBox(boxCollider.OrientedBox.GetBoundingBox(), Color.GreenYellow * 0.8f);
var clientBbox = boxCollider.OrientedBox.GetBoundingBox();
if (false)
{
if (GameModeManager.ServerFrame > 0 && GameModeManager.ClientFrame > 0)
for (ulong frame = GameModeManager.ServerFrame; frame < GameModeManager.ClientFrame; frame++)
{
if (!input.GetState(frame, out var pastInputState, out var pastActorState))
continue;
var bbox = clientBbox;
bbox.Center = pastActorState.position;
Float4 color1 = new Float4(Color.Red.R, Color.Red.G, Color.Red.B, Color.Red.A);
Float4 color2 = new Float4(Color.Blue.R, Color.Blue.G, Color.Blue.B, Color.Blue.A);
Float4 color3 = Float4.Lerp(color1, color2, (float)(frame - GameModeManager.ServerFrame) / (float)(GameModeManager.ClientFrame - GameModeManager.ServerFrame));
Color color = new Color(color3.X, color3.Y, color3.Z, color3.W);
DebugDraw.DrawBox(bbox, color * 1f);
}
}
else
{
var serverBbox = boxCollider.OrientedBox.GetBoundingBox();
if (input.GetState(GameModeManager.ServerFrame, out var serverInputState, out var serverActorState))
serverBbox.Center = serverActorState.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);
}
}
}
}
#endif
@@ -1051,6 +1225,7 @@ namespace Game
if (onGround && jumpAction && !jumped)
if (OnJump(traceGround, ref position, ref velocity))
{
//Console.Print($"{inputState.frame} jumped " + ", predicting: " + predicting + ", vel: " + velocity.Y);
jumped = true;
lastJumped = simulationTime;
numJumps++;