protected void ProcessAcksForConnection( Context context, Context.ConnectionData connectionData ) { Profiler.BeginSample( "ProcessAcksForConnection" ); int numAcks = 0; connectionData.connection.GetAcks( ref acks, ref numAcks ); for ( int i = 0; i < numAcks; ++i ) { int packetNumCubeStates; int[] packetCubeIds; CubeState[] packetCubeState; if ( connectionData.sendDeltaBuffer.GetPacketData( acks[i], context.GetResetSequence(), out packetNumCubeStates, out packetCubeIds, out packetCubeState ) ) { for ( int j = 0; j < packetNumCubeStates; ++j ) { context.UpdateMostRecentAckedState( connectionData, packetCubeIds[j], acks[i], context.GetResetSequence(), ref packetCubeState[j] ); } } } Profiler.EndSample(); }
void ProcessPacketsFromServer() { Packet packet; while ((packet = Net.ReadPacket()) != null) { if (packet.SenderID != hostUserId) { continue; } packet.ReadBytes(readBuffer); byte packetType = readBuffer[0]; if ((state == GuestState.Connecting || state == GuestState.Connected) && packetType == (byte)PacketSerializer.PacketType.ServerInfo) { ProcessServerInfoPacket(readBuffer); } if (!IsConnectedToServer()) { continue; } if (packetType == (byte)PacketSerializer.PacketType.StateUpdate) { if (enableJitterBuffer) { AddStateUpdatePacketToJitterBuffer(context, context.GetClientConnectionData(), readBuffer); } else { ProcessStateUpdatePacket(context.GetClientConnectionData(), readBuffer); } } timeLastPacketReceived = renderTime; } // process state update from jitter buffer if (enableJitterBuffer && IsConnectedToServer()) { ProcessStateUpdateFromJitterBuffer(context, context.GetClientConnectionData(), 0, clientIndex, enableJitterBuffer && renderTime > timeConnected + 0.25); } // advance remote frame number if (IsConnectedToServer()) { Context.ConnectionData connectionData = context.GetClientConnectionData(); if (!connectionData.firstRemotePacket) { connectionData.remoteFrameNumber++; } } }
protected void DetermineNotChangedAndDeltas( Context context, Context.ConnectionData connectionData, ushort currentSequence, int numCubes, ref int[] cubeIds, ref bool[] notChanged, ref bool[] hasDelta, ref ushort[] baselineSequence, ref CubeState[] cubeState, ref CubeDelta[] cubeDelta ) { Profiler.BeginSample( "DeterminedNotChangedAndDeltas" ); #if !DISABLE_DELTA_COMPRESSION CubeState baselineCubeState = CubeState.defaults; #endif // #if !DISABLE_DELTA_COMPRESSION for ( int i = 0; i < numCubes; ++i ) { notChanged[i] = false; hasDelta[i] = false; #if !DISABLE_DELTA_COMPRESSION #if DEBUG_DELTA_COMPRESSION cubeDelta[i].absolute_position_x = cubeState[i].position_x; cubeDelta[i].absolute_position_y = cubeState[i].position_y; cubeDelta[i].absolute_position_z = cubeState[i].position_z; #endif // #if DEBUG_DELTA_COMPRESSION if ( context.GetMostRecentAckedState( connectionData, cubeIds[i], ref baselineSequence[i], context.GetResetSequence(), ref baselineCubeState ) ) { if ( Network.Util.BaselineDifference( currentSequence, baselineSequence[i] ) > Constants.MaxBaselineDifference ) { // baseline is too far behind => send the cube state absolute. continue; } if ( baselineCubeState.Equals( cubeState[i] ) ) { notChanged[i] = true; } else { hasDelta[i] = true; cubeDelta[i].position_delta_x = cubeState[i].position_x - baselineCubeState.position_x; cubeDelta[i].position_delta_y = cubeState[i].position_y - baselineCubeState.position_y; cubeDelta[i].position_delta_z = cubeState[i].position_z - baselineCubeState.position_z; cubeDelta[i].linear_velocity_delta_x = cubeState[i].linear_velocity_x - baselineCubeState.linear_velocity_x; cubeDelta[i].linear_velocity_delta_y = cubeState[i].linear_velocity_y - baselineCubeState.linear_velocity_y; cubeDelta[i].linear_velocity_delta_z = cubeState[i].linear_velocity_z - baselineCubeState.linear_velocity_z; cubeDelta[i].angular_velocity_delta_x = cubeState[i].angular_velocity_x - baselineCubeState.angular_velocity_x; cubeDelta[i].angular_velocity_delta_y = cubeState[i].angular_velocity_y - baselineCubeState.angular_velocity_y; cubeDelta[i].angular_velocity_delta_z = cubeState[i].angular_velocity_z - baselineCubeState.angular_velocity_z; } } #endif // #if !DISABLE_DELTA_COMPRESSION } Profiler.EndSample(); }
void ProcessAcks() { Profiler.BeginSample("Process Acks"); { Context.ConnectionData connectionData = context.GetClientConnectionData(); ProcessAcksForConnection(context, connectionData); } Profiler.EndSample(); }
public static void SetContext <T>(this ObservableList <T> ts, IMongoDatabase database, string collection) { var mc = new Context.ConnectionData { Database = database, Collection = collection }; if (ts.Properties.ContainsKey("MongoContext")) { ts.Properties.Remove("MongoContext"); } ts.Properties.Add("MongoContext", mc); }
public void ProcessStateUpdatePacket(byte[] packetData, int fromClientIndex) { int readNumAvatarStates = 0; int readNumStateUpdates = 0; Context.ConnectionData connectionData = context.GetServerConnectionData(fromClientIndex); Network.PacketHeader readPacketHeader; if (ReadStateUpdatePacket(packetData, out readPacketHeader, out readNumAvatarStates, ref readAvatarStateQuantized, out readNumStateUpdates, ref readCubeIds, ref readNotChanged, ref readHasDelta, ref readPerfectPrediction, ref readHasPredictionDelta, ref readBaselineSequence, ref readCubeState, ref readCubeDelta, ref readPredictionDelta)) { // unquantize avatar states for (int i = 0; i < readNumAvatarStates; ++i) { AvatarState.Unquantize(ref readAvatarStateQuantized[i], out readAvatarState[i]); } // ignore any updates from a client with a different reset sequence # if (context.GetResetSequence() != readPacketHeader.resetSequence) { return; } // decode the predicted cube states from baselines DecodePrediction(connectionData.receiveDeltaBuffer, readPacketHeader.sequence, context.GetResetSequence(), readNumStateUpdates, ref readCubeIds, ref readPerfectPrediction, ref readHasPredictionDelta, ref readBaselineSequence, ref readCubeState, ref readPredictionDelta); // decode the not changed and delta cube states from baselines DecodeNotChangedAndDeltas(connectionData.receiveDeltaBuffer, context.GetResetSequence(), readNumStateUpdates, ref readCubeIds, ref readNotChanged, ref readHasDelta, ref readBaselineSequence, ref readCubeState, ref readCubeDelta); // add the cube states to the receive delta buffer AddPacketToDeltaBuffer(ref connectionData.receiveDeltaBuffer, readPacketHeader.sequence, context.GetResetSequence(), readNumStateUpdates, ref readCubeIds, ref readCubeState); // apply the state updates to cubes context.ApplyCubeStateUpdates(readNumStateUpdates, ref readCubeIds, ref readCubeState, fromClientIndex, 0, enableJitterBuffer); // apply avatar state updates context.ApplyAvatarStateUpdates(readNumAvatarStates, ref readAvatarState, fromClientIndex, 0); // process the packet header connectionData.connection.ProcessPacketHeader(ref readPacketHeader); } }
protected void AddStateUpdatePacketToJitterBuffer( Context context, Context.ConnectionData connectionData, byte[] packetData ) { long packetFrameNumber; if ( connectionData.jitterBuffer.AddStateUpdatePacket( packetData, connectionData.receiveDeltaBuffer, context.GetResetSequence(), out packetFrameNumber ) ) { if ( connectionData.firstRemotePacket ) { connectionData.firstRemotePacket = false; connectionData.remoteFrameNumber = packetFrameNumber - Constants.NumJitterBufferFrames; connectionData.jitterBuffer.Start( connectionData.remoteFrameNumber ); } } }
void SendPacketToServer() { if (!IsConnectedToServer()) { return; } Context.ConnectionData connectionData = context.GetClientConnectionData(); byte[] packetData = GenerateStateUpdatePacket(connectionData, (float)(physicsTime - renderTime)); Net.SendPacket(hostUserId, packetData, SendPolicy.Unreliable); timeLastPacketSent = renderTime; }
void ProcessAcks() { Profiler.BeginSample("Process Acks"); { for (int clientIndex = 1; clientIndex < Constants.MaxClients; ++clientIndex) { for (int i = 1; i < Constants.MaxClients; ++i) { Context.ConnectionData connectionData = context.GetServerConnectionData(i); ProcessAcksForConnection(context, connectionData); } } } Profiler.EndSample(); }
protected void ProcessStateUpdateFromJitterBuffer( Context context, Context.ConnectionData connectionData, int fromClientIndex, int toClientIndex, bool applySmoothing = true ) { if ( connectionData.remoteFrameNumber < 0 ) return; JitterBufferEntry entry = connectionData.jitterBuffer.GetEntry( (uint) connectionData.remoteFrameNumber ); if ( entry == null ) return; if ( fromClientIndex == 0 ) { // server -> client // Ignore updates from before the last reset. if ( Network.Util.SequenceGreaterThan( context.GetResetSequence(), entry.packetHeader.resetSequence ) ) return; // Reset if the server reset sequence is more recent than ours. if ( Network.Util.SequenceGreaterThan( entry.packetHeader.resetSequence, context.GetResetSequence() ) ) { context.Reset(); context.SetResetSequence( entry.packetHeader.resetSequence ); } } else { // client -> server // Ignore any updates from the client with a different reset sequence # if ( context.GetResetSequence() != entry.packetHeader.resetSequence ) return; } // add the cube states to the receive delta buffer AddPacketToDeltaBuffer( ref connectionData.receiveDeltaBuffer, entry.packetHeader.sequence, context.GetResetSequence(), entry.numStateUpdates, ref entry.cubeIds, ref entry.cubeState ); // apply the state updates to cubes context.ApplyCubeStateUpdates( entry.numStateUpdates, ref entry.cubeIds, ref entry.cubeState, fromClientIndex, toClientIndex, applySmoothing ); // process the packet header (handles acks) connectionData.connection.ProcessPacketHeader( ref entry.packetHeader ); }
void SendPacketsToConnectedClients() { for (int clientIndex = 1; clientIndex < Constants.MaxClients; ++clientIndex) { if (!IsClientConnected(clientIndex)) { continue; } Context.ConnectionData connectionData = context.GetServerConnectionData(clientIndex); byte[] packetData = GenerateStateUpdatePacket(connectionData, clientIndex, (float)(physicsTime - renderTime)); Net.SendPacket(client[clientIndex].userId, packetData, SendPolicy.Unreliable); client[clientIndex].timeLastPacketSent = renderTime; } }
public byte[] GenerateStateUpdatePacket(Context.ConnectionData connectionData, float avatarSampleTimeOffset) { Profiler.BeginSample("GenerateStateUpdatePacket"); int maxStateUpdates = Math.Min(Constants.NumCubes, Constants.MaxStateUpdates); int numStateUpdates = maxStateUpdates; context.UpdateCubePriority(); context.GetMostImportantCubeStateUpdates(connectionData, ref numStateUpdates, ref cubeIds, ref cubeState); Network.PacketHeader writePacketHeader; connectionData.connection.GeneratePacketHeader(out writePacketHeader); writePacketHeader.resetSequence = context.GetResetSequence(); writePacketHeader.frameNumber = (uint)frameNumber; writePacketHeader.avatarSampleTimeOffset = avatarSampleTimeOffset; DetermineNotChangedAndDeltas(context, connectionData, writePacketHeader.sequence, numStateUpdates, ref cubeIds, ref notChanged, ref hasDelta, ref baselineSequence, ref cubeState, ref cubeDelta); DeterminePrediction(context, connectionData, writePacketHeader.sequence, numStateUpdates, ref cubeIds, ref notChanged, ref hasDelta, ref perfectPrediction, ref hasPredictionDelta, ref baselineSequence, ref cubeState, ref predictionDelta); int numAvatarStates = 1; localAvatar.GetComponent <Avatar>().GetAvatarState(out avatarState[0]); AvatarState.Quantize(ref avatarState[0], out avatarStateQuantized[0]); WriteStateUpdatePacket(ref writePacketHeader, numAvatarStates, ref avatarStateQuantized, numStateUpdates, ref cubeIds, ref notChanged, ref hasDelta, ref perfectPrediction, ref hasPredictionDelta, ref baselineSequence, ref cubeState, ref cubeDelta, ref predictionDelta); byte[] packetData = writeStream.GetData(); AddPacketToDeltaBuffer(ref connectionData.sendDeltaBuffer, writePacketHeader.sequence, context.GetResetSequence(), numStateUpdates, ref cubeIds, ref cubeState); context.ResetCubePriority(connectionData, numStateUpdates, cubeIds); Profiler.EndSample(); return(packetData); }
new void Update() { base.Update(); // apply host avatar per-remote client at render time with interpolation for (int i = 1; i < Constants.MaxClients; ++i) { if (client[i].state != ClientState.Connected) { continue; } Context.ConnectionData connectionData = context.GetServerConnectionData(i); int fromClientIndex = i; int toClientIndex = 0; int numInterpolatedAvatarStates; ushort avatarResetSequence; if (connectionData.jitterBuffer.GetInterpolatedAvatarState(ref interpolatedAvatarState, out numInterpolatedAvatarStates, out avatarResetSequence)) { if (avatarResetSequence == context.GetResetSequence()) { context.ApplyAvatarStateUpdates(numInterpolatedAvatarStates, ref interpolatedAvatarState, fromClientIndex, toClientIndex); } } } // advance jitter buffer time for (int i = 1; i < Constants.MaxClients; ++i) { if (client[i].state == ClientState.Connected) { context.GetServerConnectionData(i).jitterBuffer.AdvanceTime(Time.deltaTime); } } // check for timeouts CheckForTimeouts(); }
void ProcessAcks() { Profiler.BeginSample("Process Acks"); { // host context { Context context = GetContext(0); if (context) { for (int i = 1; i < Constants.MaxClients; ++i) { Context.ConnectionData connectionData = context.GetServerConnectionData(i); ProcessAcksForConnection(context, connectionData); } } } // guest contexts for (int clientIndex = 1; clientIndex < Constants.MaxClients; ++clientIndex) { Context context = GetContext(clientIndex); if (!context) { continue; } Context.ConnectionData connectionData = context.GetClientConnectionData(); ProcessAcksForConnection(context, connectionData); } } Profiler.EndSample(); }
void ProcessPlayerScored(PacketSerializer.GameEvent eventType, ushort senderId, ushort targetId) { //handle locally ScoreManager.HandleScore(senderId, targetId); if (targetId == 0) //server { SFX.Play(SFXType.SCORED_OTHER); } else if (senderId == 0) { SFX.Play(SFXType.SCORED_SELF); } else { SFX.Play(SFXType.SCORED_UNRELATED); } ushort[] perClientScores = ScoreManager.GetScores(); //send to clients other than myself byte[] packetData = GeneratePlayerScoredPacket(eventType, senderId, targetId, perClientScores); for (int clientIndex = 1; clientIndex < Constants.MaxClients; ++clientIndex) { if (!IsClientConnected(clientIndex)) { continue; } Context.ConnectionData connectionData = context.GetServerConnectionData(clientIndex); Net.SendPacket(client[clientIndex].userId, packetData, SendPolicy.Unreliable); client[clientIndex].timeLastPacketSent = renderTime; } }
new void Update() { base.Update(); if (Input.GetKeyDown("return")) { hostContext.TestSmoothing(); } // apply host avatar state at render time with interpolation for (int i = 1; i < Constants.MaxClients; ++i) { Context context = hostContext; Context.ConnectionData connectionData = context.GetServerConnectionData(i); int fromClientIndex = i; int toClientIndex = 0; int numInterpolatedAvatarStates; ushort avatarResetSequence; if (connectionData.jitterBuffer.GetInterpolatedAvatarState(ref interpolatedAvatarState, out numInterpolatedAvatarStates, out avatarResetSequence)) { if (avatarResetSequence == context.GetResetSequence()) { context.ApplyAvatarStateUpdates(numInterpolatedAvatarStates, ref interpolatedAvatarState, fromClientIndex, toClientIndex); } } } // apply guest avatar state at render time with interpolation { Context context = guestContext; Context.ConnectionData connectionData = context.GetClientConnectionData(); int fromClientIndex = 0; int toClientIndex = 1; int numInterpolatedAvatarStates; ushort avatarResetSequence; if (connectionData.jitterBuffer.GetInterpolatedAvatarState(ref interpolatedAvatarState, out numInterpolatedAvatarStates, out avatarResetSequence)) { if (avatarResetSequence == context.GetResetSequence()) { context.ApplyAvatarStateUpdates(numInterpolatedAvatarStates, ref interpolatedAvatarState, fromClientIndex, toClientIndex); } } } // advance jitter buffer time guestContext.GetClientConnectionData().jitterBuffer.AdvanceTime(Time.deltaTime); for (int i = 1; i < Constants.MaxClients; ++i) { hostContext.GetServerConnectionData(i).jitterBuffer.AdvanceTime(Time.deltaTime); } }
new void Update() { base.Update(); if (Input.GetKeyDown("space")) { Debug.Log("Forcing reconnect"); successfullyConnected = false; RetryUntilConnectedToServer(); } if (state == GuestState.Matchmaking && timeMatchmakingStarted + 30.0 < renderTime) { Debug.Log("No result from matchmaker"); RetryUntilConnectedToServer(); return; } if (state == GuestState.Connecting && !acceptedConnectionRequest) { if (hostUserId != 0 && connectionRequests.Contains(hostUserId)) { Debug.Log("Accepting connection request from host"); Net.Accept(hostUserId); acceptedConnectionRequest = true; } } if (state == GuestState.Connected) { // apply guest avatar state at render time with interpolation Context.ConnectionData connectionData = context.GetClientConnectionData(); int numInterpolatedAvatarStates; ushort avatarResetSequence; if (connectionData.jitterBuffer.GetInterpolatedAvatarState(ref interpolatedAvatarState, out numInterpolatedAvatarStates, out avatarResetSequence)) { if (avatarResetSequence == context.GetResetSequence()) { context.ApplyAvatarStateUpdates(numInterpolatedAvatarStates, ref interpolatedAvatarState, 0, clientIndex); } } // advance jitter buffer time context.GetClientConnectionData().jitterBuffer.AdvanceTime(Time.deltaTime); } if (state == GuestState.WaitingForRetry && timeRetryStarted + RetryTime < renderTime) { StartMatchmaking(); return; } CheckForTimeouts(); }
public void ProcessStateUpdatePacket(Context.ConnectionData connectionData, byte[] packetData) { Profiler.BeginSample("ProcessStateUpdatePacket"); int readNumAvatarStates = 0; int readNumStateUpdates = 0; Network.PacketHeader readPacketHeader; if (ReadStateUpdatePacket(packetData, out readPacketHeader, out readNumAvatarStates, ref readAvatarStateQuantized, out readNumStateUpdates, ref readCubeIds, ref readNotChanged, ref readHasDelta, ref readPerfectPrediction, ref readHasPredictionDelta, ref readBaselineSequence, ref readCubeState, ref readCubeDelta, ref readPredictionDelta)) { // unquantize avatar states for (int i = 0; i < readNumAvatarStates; ++i) { AvatarState.Unquantize(ref readAvatarStateQuantized[i], out readAvatarState[i]); } // ignore updates from before the last server reset if (Network.Util.SequenceGreaterThan(context.GetResetSequence(), readPacketHeader.resetSequence)) { return; } // reset if the server reset sequence is more recent than ours if (Network.Util.SequenceGreaterThan(readPacketHeader.resetSequence, context.GetResetSequence())) { context.Reset(); context.SetResetSequence(readPacketHeader.resetSequence); } // decode the predicted cube states from baselines DecodePrediction(connectionData.receiveDeltaBuffer, readPacketHeader.sequence, context.GetResetSequence(), readNumStateUpdates, ref readCubeIds, ref readPerfectPrediction, ref readHasPredictionDelta, ref readBaselineSequence, ref readCubeState, ref readPredictionDelta); // decode the not changed and delta cube states from baselines DecodeNotChangedAndDeltas(connectionData.receiveDeltaBuffer, context.GetResetSequence(), readNumStateUpdates, ref readCubeIds, ref readNotChanged, ref readHasDelta, ref readBaselineSequence, ref readCubeState, ref readCubeDelta); // add the cube states to the receive delta buffer AddPacketToDeltaBuffer(ref connectionData.receiveDeltaBuffer, readPacketHeader.sequence, context.GetResetSequence(), readNumStateUpdates, ref readCubeIds, ref readCubeState); // apply the state updates to cubes int fromClientIndex = 0; int toClientIndex = clientIndex; context.ApplyCubeStateUpdates(readNumStateUpdates, ref readCubeIds, ref readCubeState, fromClientIndex, toClientIndex, enableJitterBuffer && renderTime > timeConnected + 0.25); // apply avatar state updates context.ApplyAvatarStateUpdates(readNumAvatarStates, ref readAvatarState, fromClientIndex, toClientIndex); // process the packet header connectionData.connection.ProcessPacketHeader(ref readPacketHeader); } Profiler.EndSample(); }
protected void UpdateJitterBuffer( Context context, Context.ConnectionData connectionData ) { if ( !connectionData.firstRemotePacket ) connectionData.remoteFrameNumber++; }
protected void DeterminePrediction( Context context, Context.ConnectionData connectionData, ushort currentSequence, int numCubes, ref int[] cubeIds, ref bool[] notChanged, ref bool[] hasDelta, ref bool[] perfectPrediction, ref bool[] hasPredictionDelta, ref ushort[] baselineSequence, ref CubeState[] cubeState, ref CubeDelta[] predictionDeltas ) { Profiler.BeginSample( "DeterminePrediction" ); CubeState baselineCubeState = CubeState.defaults; for ( int i = 0; i < numCubes; ++i ) { perfectPrediction[i] = false; hasPredictionDelta[i] = false; #if !DISABLE_DELTA_ENCODING if ( notChanged[i] ) continue; if ( !hasDelta[i] ) continue; if ( !cubeState[i].active ) continue; if ( context.GetMostRecentAckedState( connectionData, cubeIds[i], ref baselineSequence[i], context.GetResetSequence(), ref baselineCubeState ) ) { if ( Network.Util.BaselineDifference( currentSequence, baselineSequence[i] ) <= Constants.MaxBaselineDifference ) { // baseline is too far behind. send the cube state absolute continue; } if ( !baselineCubeState.active ) { // no point predicting if the cube is at rest. continue; } int baseline_sequence = baselineSequence[i]; int current_sequence = currentSequence; if ( current_sequence < baseline_sequence ) current_sequence += 65536; int baseline_position_x = baselineCubeState.position_x; int baseline_position_y = baselineCubeState.position_y; int baseline_position_z = baselineCubeState.position_z; int baseline_linear_velocity_x = baselineCubeState.linear_velocity_x; int baseline_linear_velocity_y = baselineCubeState.linear_velocity_y; int baseline_linear_velocity_z = baselineCubeState.linear_velocity_z; int baseline_angular_velocity_x = baselineCubeState.angular_velocity_x; int baseline_angular_velocity_y = baselineCubeState.angular_velocity_y; int baseline_angular_velocity_z = baselineCubeState.angular_velocity_z; if ( current_sequence < baseline_sequence ) current_sequence += 65536; int numFrames = current_sequence - baseline_sequence; int predicted_position_x; int predicted_position_y; int predicted_position_z; int predicted_linear_velocity_x; int predicted_linear_velocity_y; int predicted_linear_velocity_z; int predicted_angular_velocity_x; int predicted_angular_velocity_y; int predicted_angular_velocity_z; Prediction.PredictBallistic( numFrames, baseline_position_x, baseline_position_y, baseline_position_z, baseline_linear_velocity_x, baseline_linear_velocity_y, baseline_linear_velocity_z, baseline_angular_velocity_x, baseline_angular_velocity_y, baseline_angular_velocity_z, out predicted_position_x, out predicted_position_y, out predicted_position_z, out predicted_linear_velocity_x, out predicted_linear_velocity_y, out predicted_linear_velocity_z, out predicted_angular_velocity_x, out predicted_angular_velocity_y, out predicted_angular_velocity_z ); int current_position_x = cubeState[i].position_x; int current_position_y = cubeState[i].position_y; int current_position_z = cubeState[i].position_z; int current_linear_velocity_x = cubeState[i].linear_velocity_x; int current_linear_velocity_y = cubeState[i].linear_velocity_y; int current_linear_velocity_z = cubeState[i].linear_velocity_z; int current_angular_velocity_x = cubeState[i].angular_velocity_x; int current_angular_velocity_y = cubeState[i].angular_velocity_y; int current_angular_velocity_z = cubeState[i].angular_velocity_z; int position_error_x = current_position_x - predicted_position_x; int position_error_y = current_position_y - predicted_position_y; int position_error_z = current_position_z - predicted_position_z; int linear_velocity_error_x = current_linear_velocity_x - predicted_linear_velocity_x; int linear_velocity_error_y = current_linear_velocity_y - predicted_linear_velocity_y; int linear_velocity_error_z = current_linear_velocity_z - predicted_linear_velocity_z; int angular_velocity_error_x = current_angular_velocity_x - predicted_angular_velocity_x; int angular_velocity_error_y = current_angular_velocity_y - predicted_angular_velocity_y; int angular_velocity_error_z = current_angular_velocity_z - predicted_angular_velocity_z; if ( position_error_x == 0 && position_error_y == 0 && position_error_z == 0 && linear_velocity_error_x == 0 && linear_velocity_error_y == 0 && linear_velocity_error_z == 0 && angular_velocity_error_x == 0 && angular_velocity_error_y == 0 && angular_velocity_error_z == 0 ) { perfectPrediction[i] = true; } else { int abs_position_error_x = Math.Abs( position_error_x ); int abs_position_error_y = Math.Abs( position_error_y ); int abs_position_error_z = Math.Abs( position_error_z ); int abs_linear_velocity_error_x = Math.Abs( linear_velocity_error_x ); int abs_linear_velocity_error_y = Math.Abs( linear_velocity_error_y ); int abs_linear_velocity_error_z = Math.Abs( linear_velocity_error_z ); int abs_angular_velocity_error_x = Math.Abs( angular_velocity_error_x ); int abs_angular_velocity_error_y = Math.Abs( angular_velocity_error_y ); int abs_angular_velocity_error_z = Math.Abs( angular_velocity_error_z ); int total_prediction_error = abs_position_error_x + abs_position_error_y + abs_position_error_z + linear_velocity_error_x + linear_velocity_error_y + linear_velocity_error_z + angular_velocity_error_x + angular_velocity_error_y + angular_velocity_error_z; int total_absolute_error = Math.Abs( cubeState[i].position_x - baselineCubeState.position_x ) + Math.Abs( cubeState[i].position_y - baselineCubeState.position_y ) + Math.Abs( cubeState[i].position_z - baselineCubeState.position_z ) + Math.Abs( cubeState[i].linear_velocity_x - baselineCubeState.linear_velocity_x ) + Math.Abs( cubeState[i].linear_velocity_y - baselineCubeState.linear_velocity_y ) + Math.Abs( cubeState[i].linear_velocity_z - baselineCubeState.linear_velocity_z ) + Math.Abs( cubeState[i].angular_velocity_x - baselineCubeState.angular_velocity_x ) + Math.Abs( cubeState[i].angular_velocity_y - baselineCubeState.angular_velocity_y ) + Math.Abs( cubeState[i].angular_velocity_z - baselineCubeState.angular_velocity_z ); if ( total_prediction_error < total_absolute_error ) { int max_position_error = abs_position_error_x; if ( abs_position_error_y > max_position_error ) max_position_error = abs_position_error_y; if ( abs_position_error_z > max_position_error ) max_position_error = abs_position_error_z; int max_linear_velocity_error = abs_linear_velocity_error_x; if ( abs_linear_velocity_error_y > max_linear_velocity_error ) max_linear_velocity_error = abs_linear_velocity_error_y; if ( abs_linear_velocity_error_z > max_linear_velocity_error ) max_linear_velocity_error = abs_linear_velocity_error_z; int max_angular_velocity_error = abs_angular_velocity_error_x; if ( abs_angular_velocity_error_y > max_angular_velocity_error ) max_angular_velocity_error = abs_angular_velocity_error_y; if ( abs_angular_velocity_error_z > max_angular_velocity_error ) max_angular_velocity_error = abs_angular_velocity_error_z; if ( max_position_error <= Constants.PositionDeltaMax && max_linear_velocity_error <= Constants.LinearVelocityDeltaMax && max_angular_velocity_error <= Constants.AngularVelocityDeltaMax ) { hasPredictionDelta[i] = true; predictionDelta[i].position_delta_x = position_error_x; predictionDelta[i].position_delta_y = position_error_y; predictionDelta[i].position_delta_z = position_error_z; predictionDelta[i].linear_velocity_delta_x = linear_velocity_error_x; predictionDelta[i].linear_velocity_delta_y = linear_velocity_error_y; predictionDelta[i].linear_velocity_delta_z = linear_velocity_error_z; predictionDelta[i].angular_velocity_delta_x = angular_velocity_error_x; predictionDelta[i].angular_velocity_delta_y = angular_velocity_error_y; predictionDelta[i].angular_velocity_delta_z = angular_velocity_error_z; } } } } } #endif // #if !DISABLE_DELTA_ENCODING Profiler.EndSample(); }
public byte[] GenerateStateUpdatePacket(Context.ConnectionData connectionData, int toClientIndex, float avatarSampleTimeOffset) { int maxStateUpdates = Math.Min(Constants.NumCubes, Constants.MaxStateUpdates); int numStateUpdates = maxStateUpdates; context.UpdateCubePriority(); context.GetMostImportantCubeStateUpdates(connectionData, ref numStateUpdates, ref cubeIds, ref cubeState); Network.PacketHeader writePacketHeader; connectionData.connection.GeneratePacketHeader(out writePacketHeader); writePacketHeader.resetSequence = context.GetResetSequence(); writePacketHeader.frameNumber = (uint)frameNumber; writePacketHeader.avatarSampleTimeOffset = avatarSampleTimeOffset; DetermineNotChangedAndDeltas(context, connectionData, writePacketHeader.sequence, numStateUpdates, ref cubeIds, ref notChanged, ref hasDelta, ref baselineSequence, ref cubeState, ref cubeDelta); DeterminePrediction(context, connectionData, writePacketHeader.sequence, numStateUpdates, ref cubeIds, ref notChanged, ref hasDelta, ref perfectPrediction, ref hasPredictionDelta, ref baselineSequence, ref cubeState, ref predictionDelta); int numAvatarStates = 0; numAvatarStates = 0; for (int i = 0; i < Constants.MaxClients; ++i) { if (i == toClientIndex) { continue; } if (i == 0) { // grab state from the local avatar. localAvatar.GetComponent <Avatar>().GetAvatarState(out avatarState[numAvatarStates]); AvatarState.Quantize(ref avatarState[numAvatarStates], out avatarStateQuantized[numAvatarStates]); numAvatarStates++; } else { // grab state from a remote avatar. var remoteAvatar = context.GetRemoteAvatar(i); if (remoteAvatar) { remoteAvatar.GetAvatarState(out avatarState[numAvatarStates]); AvatarState.Quantize(ref avatarState[numAvatarStates], out avatarStateQuantized[numAvatarStates]); numAvatarStates++; } } } WriteStateUpdatePacket(ref writePacketHeader, numAvatarStates, ref avatarStateQuantized, numStateUpdates, ref cubeIds, ref notChanged, ref hasDelta, ref perfectPrediction, ref hasPredictionDelta, ref baselineSequence, ref cubeState, ref cubeDelta, ref predictionDelta); byte[] packetData = writeStream.GetData(); // add the sent cube states to the send delta buffer AddPacketToDeltaBuffer(ref connectionData.sendDeltaBuffer, writePacketHeader.sequence, context.GetResetSequence(), numStateUpdates, ref cubeIds, ref cubeState); // reset cube priority for the cubes that were included in the packet (so other cubes have a chance to be sent...) context.ResetCubePriority(connectionData, numStateUpdates, cubeIds); return(packetData); }
void ProcessPacketsFromConnectedClients() { Packet packet; while ((packet = Net.ReadPacket()) != null) { int clientIndex = FindClientByUserId(packet.SenderID); if (clientIndex == -1) { continue; } if (!IsClientConnected(clientIndex)) { continue; } packet.ReadBytes(readBuffer); byte packetType = readBuffer[0]; if (packetType == (byte)PacketSerializer.PacketType.StateUpdate) { if (enableJitterBuffer) { AddStateUpdatePacketToJitterBuffer(context, context.GetServerConnectionData(clientIndex), readBuffer); } else { ProcessStateUpdatePacket(readBuffer, clientIndex); } } client[clientIndex].timeLastPacketReceived = renderTime; } ProcessAcks(); // process client state update from jitter buffer if (enableJitterBuffer) { for (int i = 1; i < Constants.MaxClients; ++i) { if (client[i].state == ClientState.Connected) { ProcessStateUpdateFromJitterBuffer(context, context.GetServerConnectionData(i), i, 0, enableJitterBuffer); } } } // advance remote frame number for (int i = 1; i < Constants.MaxClients; ++i) { if (client[i].state == ClientState.Connected) { Context.ConnectionData connectionData = context.GetServerConnectionData(i); if (!connectionData.firstRemotePacket) { connectionData.remoteFrameNumber++; } } } }
new void FixedUpdate() { var avatar = localAvatar.GetComponent <Avatar>(); bool reset = Input.GetKey("space") || (avatar.IsPressingIndex() && avatar.IsPressingX()); if (reset) { hostContext.Reset(); hostContext.IncreaseResetSequence(); } if (Input.GetKey("1") || avatar.IsPressingX()) { SwitchToHostContext(); } else if (Input.GetKey("2") || avatar.IsPressingY()) { SwitchToGuestContext(); } MirrorLocalAvatarToRemote(); hostContext.CheckForAtRestObjects(); guestContext.CheckForAtRestObjects(); byte[] serverToClientPacketData = GenerateStateUpdatePacket(hostContext, hostContext.GetServerConnectionData(1), 0, 1, (float)(physicsTime - renderTime)); networkSimulator.SendPacket(0, 1, serverToClientPacketData); byte[] clientToServerPacketData = GenerateStateUpdatePacket(guestContext, guestContext.GetClientConnectionData(), 1, 0, (float)(physicsTime - renderTime)); networkSimulator.SendPacket(1, 0, clientToServerPacketData); networkSimulator.AdvanceTime(frameNumber * 1.0 / Constants.PhysicsFrameRate); while (true) { int from, to; byte[] packetData = networkSimulator.ReceivePacket(out from, out to); if (packetData == null) { break; } Context context = GetContext(to); if (to == 0) { Assert.IsTrue(from >= 1); Assert.IsTrue(from < Constants.MaxClients); if (enableJitterBuffer) { AddStateUpdatePacketToJitterBuffer(context, context.GetServerConnectionData(from), packetData); } else { ProcessStateUpdatePacket(context, context.GetServerConnectionData(from), packetData, from, to); } } else { Assert.IsTrue(from == 0); if (enableJitterBuffer) { AddStateUpdatePacketToJitterBuffer(context, context.GetClientConnectionData(), packetData); } else { ProcessStateUpdatePacket(context, context.GetClientConnectionData(), packetData, from, to); } } } // process packet from host jitter buffer for (int from = 1; from < Constants.MaxClients; ++from) { const int to = 0; Context context = GetContext(to); ProcessStateUpdateFromJitterBuffer(context, context.GetServerConnectionData(from), from, to, enableJitterBuffer); } // process packet from guest jitter buffer if (enableJitterBuffer) { const int from = 0; const int to = 1; Context context = GetContext(to); ProcessStateUpdateFromJitterBuffer(context, context.GetClientConnectionData(), from, to, enableJitterBuffer); } // advance host remote frame number for each connected client for (int i = 1; i < Constants.MaxClients; ++i) { Context context = GetContext(0); Context.ConnectionData connectionData = context.GetServerConnectionData(i); if (!connectionData.firstRemotePacket) { connectionData.remoteFrameNumber++; } } // advance guest remote frame number { Context context = GetContext(1); Context.ConnectionData connectionData = context.GetClientConnectionData(); if (!connectionData.firstRemotePacket) { connectionData.remoteFrameNumber++; } } hostContext.CheckForAtRestObjects(); guestContext.CheckForAtRestObjects(); ProcessAcks(); base.FixedUpdate(); }