================== idAsyncServer::SendSnapshotToClient ================== */
| 1138 | ================== |
| 1139 | */ |
| 1140 | bool idAsyncServer::SendSnapshotToClient( int clientNum ) { |
| 1141 | int i, j, index, numUsercmds; |
| 1142 | idBitMsg msg; |
| 1143 | byte msgBuf[MAX_MESSAGE_SIZE]; |
| 1144 | usercmd_t * last; |
| 1145 | byte clientInPVS[MAX_ASYNC_CLIENTS >> 3]; |
| 1146 | |
| 1147 | serverClient_t &client = clients[clientNum]; |
| 1148 | |
| 1149 | if ( serverTime - client.lastSnapshotTime < idAsyncNetwork::serverSnapshotDelay.GetInteger() ) { |
| 1150 | return false; |
| 1151 | } |
| 1152 | |
| 1153 | if ( idAsyncNetwork::verbose.GetInteger() == 2 ) { |
| 1154 | common->Printf( "sending snapshot to client %d: gameInitId = %d, gameFrame = %d, gameTime = %d\n", clientNum, gameInitId, gameFrame, gameTime ); |
| 1155 | } |
| 1156 | |
| 1157 | // how far is the client ahead of the server minus the packet delay |
| 1158 | client.clientAheadTime = client.gameTime - ( gameTime + gameTimeResidual ); |
| 1159 | |
| 1160 | // write the snapshot |
| 1161 | msg.Init( msgBuf, sizeof( msgBuf ) ); |
| 1162 | msg.WriteInt( gameInitId ); |
| 1163 | msg.WriteByte( SERVER_UNRELIABLE_MESSAGE_SNAPSHOT ); |
| 1164 | msg.WriteInt( client.snapshotSequence ); |
| 1165 | msg.WriteInt( gameFrame ); |
| 1166 | msg.WriteInt( gameTime ); |
| 1167 | msg.WriteByte( idMath::ClampChar( client.numDuplicatedUsercmds ) ); |
| 1168 | msg.WriteShort( idMath::ClampShort( client.clientAheadTime ) ); |
| 1169 | |
| 1170 | // write the game snapshot |
| 1171 | game->ServerWriteSnapshot( clientNum, client.snapshotSequence, msg, clientInPVS, MAX_ASYNC_CLIENTS ); |
| 1172 | |
| 1173 | // write the latest user commands from the other clients in the PVS to the snapshot |
| 1174 | for ( last = NULL, i = 0; i < MAX_ASYNC_CLIENTS; i++ ) { |
| 1175 | serverClient_t &client = clients[i]; |
| 1176 | |
| 1177 | if ( client.clientState == SCS_FREE || i == clientNum ) { |
| 1178 | continue; |
| 1179 | } |
| 1180 | |
| 1181 | // if the client is not in the PVS |
| 1182 | if ( !( clientInPVS[i >> 3] & ( 1 << ( i & 7 ) ) ) ) { |
| 1183 | continue; |
| 1184 | } |
| 1185 | |
| 1186 | int maxRelay = idMath::ClampInt( 1, MAX_USERCMD_RELAY, idAsyncNetwork::serverMaxUsercmdRelay.GetInteger() ); |
| 1187 | |
| 1188 | // Max( 1, to always send at least one cmd, which we know we have because we call DuplicateUsercmds in RunFrame |
| 1189 | numUsercmds = Max( 1, Min( client.gameFrame, gameFrame + maxRelay ) - gameFrame ); |
| 1190 | msg.WriteByte( i ); |
| 1191 | msg.WriteByte( numUsercmds ); |
| 1192 | for ( j = 0; j < numUsercmds; j++ ) { |
| 1193 | index = ( gameFrame + j ) & ( MAX_USERCMD_BACKUP - 1 ); |
| 1194 | idAsyncNetwork::WriteUserCmdDelta( msg, userCmds[index][i], last ); |
| 1195 | last = &userCmds[index][i]; |
| 1196 | } |
| 1197 | } |
nothing calls this directly
no test coverage detected