netcode good condition
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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++;
|
||||
|
||||
Reference in New Issue
Block a user