void CGameGibManager::AddGibToLRU( CBaseAnimating *pEntity ) { int i, next; if ( pEntity == NULL ) return; //Find stale gibs. for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next ) { next = m_LRU.Next(i); if ( m_LRU[i].Get() == NULL ) { m_LRU.Remove(i); } } // We're not tracking gibs at the moment if ( m_iCurrentMaxPieces <= 0 ) return; while ( m_LRU.Count() >= m_iCurrentMaxPieces ) { i = m_LRU.Head(); //TODO: Make this fade out instead of pop. UTIL_Remove( m_LRU[i] ); m_LRU.Remove(i); } m_LRU.AddToTail( pEntity ); m_iLastFrame = gpGlobals->framecount; }
void CFrameSnapshotManager::LevelChanged() { // Clear all lists... Assert( m_FrameSnapshots.Count() == 0 ); // Release the most recent snapshot... m_PackedEntities.RemoveAll(); memset( m_pPackedData, 0xFF, MAX_EDICTS * sizeof(PackedEntityHandle_t) ); }
void HandleFoundryEntitySpawnRecords() { if ( g_FoundryEntitySpawnRecords.Count() == 0 ) return; VPROF("HandleFoundryEntitySpawnRecords"); // Create all the entities. CUtlVector<CBaseEntity*> newEnts; CMapEntitySpawner spawner; spawner.m_bFoundryMode = true; FOR_EACH_LL( g_FoundryEntitySpawnRecords, i ) { CFoundryEntitySpawnRecord *pRecord = g_FoundryEntitySpawnRecords[i]; if ( pRecord->m_iEntityIndex > 0 ) { gEntList.ForceEntSerialNumber( pRecord->m_iEntityIndex, pRecord->m_iSerialNumber ); engine->ForceFlushEntity( pRecord->m_iEntityIndex ); } // Figure out the class name. CEntityMapData entData( pRecord->m_VMFText.Base() ); char szClassName[MAPKEY_MAXLENGTH]; if ( !entData.ExtractValue( "classname", szClassName ) ) { Assert( false ); continue; } // Respawn it in the same slot. int nIndexToSpawn = pRecord->m_iEntityIndex; if ( nIndexToSpawn == 0 ) nIndexToSpawn = -1; CBaseEntity *pNewEntity = ::CreateEntityByName( szClassName, nIndexToSpawn ); if ( !pNewEntity ) { Warning( "HandleFoundryEntitySpawnRecords - CreateEntityByName( %s, %d ) failed\n", szClassName, pRecord->m_iEntityIndex ); continue; } const char *pBaseMapDataForThisEntity = entData.CurrentBufferPosition(); pNewEntity->ParseMapData( &entData ); if ( pRecord->m_debugOverlays != -1 ) pNewEntity->m_debugOverlays = pRecord->m_debugOverlays; pNewEntity->m_iHammerID = pRecord->m_iHammerID; spawner.AddEntity( pNewEntity, pBaseMapDataForThisEntity, (entData.CurrentBufferPosition() - pBaseMapDataForThisEntity) + 2 ); }
//----------------------------------------------------------------------------- // Purpose: Gets any failed sends - returns any packet that could not be delivered //----------------------------------------------------------------------------- IReceiveMessage *CTrackerNET::GetFailedMessage() { if (m_FailedMsgs.Count()) { // pop the failed message from the front of the queue and return it FailedMsg_t &msg = m_FailedMsgs[m_FailedMsgs.Head()]; IReceiveMessage *recvMsg = msg.message; m_FailedMsgs.Remove(m_FailedMsgs.Head()); return recvMsg; } return NULL; }
//----------------------------------------------------------------------------- // Purpose: Checks for any waiting messages //----------------------------------------------------------------------------- IReceiveMessage *CTrackerNET::GetIncomingData() { // check the receive list if (m_ReceivedMsgs.Count()) { int head = m_ReceivedMsgs.Head(); IReceiveMessage *msg = m_ReceivedMsgs[head].message; m_ReceivedMsgs.Remove(head); return msg; } return NULL; }
bool CGameGibManager::AllowedToSpawnGib( void ) { if ( m_bAllowNewGibs ) return true; // We're not tracking gibs at the moment if ( m_iCurrentMaxPieces < 0 ) return true; if ( m_iCurrentMaxPieces == 0 ) return false; if ( m_iLastFrame == gpGlobals->framecount ) { if ( m_LRU.Count() >= m_iCurrentMaxPieces ) { return false; } } return true; }
//----------------------------------------------------------------------------- // Purpose: Checks to see if we need to send any ack packets // in response to reliable messages we've received //----------------------------------------------------------------------------- void CTrackerNET::CheckSendingAcknowledgements() { float time = (float)m_pThreads->GetTime(); // the target list is in order of ackTime's while (m_TargetList.Count()) { int targetIndex = m_TargetList.Head(); NetworkTarget_t &target = m_TargetList[targetIndex]; if (!target.needAck) break; // target does not need acknowledging, we're at the end of the list if (target.ackTime > time) break; // this packet not yet ready to be acknowledged if (target.incomingSequence > target.incomingAcknowledged) { // send an acknowledgement ISendMessage *pMsg = CreateMessage(TMSG_ACK); pMsg->SetNetAddress(target.netAddress); SendMessage(pMsg, NET_UNRELIABLE); } // this target has been acknowledged, move to the end of the list target.needAck = false; m_TargetList.Unlink(targetIndex); m_TargetList.LinkToTail(targetIndex); // check to see if the highest ack target needs to be reset if (targetIndex == m_iHighestAckTarget) { m_iHighestAckTarget = -1; } } }
bool CHLTVClientState::ProcessPacketEntities( SVC_PacketEntities *entmsg ) { CClientFrame *oldFrame = NULL; #ifdef _HLTVTEST if ( g_RecvDecoders.Count() == 0 ) return false; #endif if ( entmsg->m_bIsDelta ) { if ( GetServerTickCount() == entmsg->m_nDeltaFrom ) { Host_Error( "Update self-referencing, connection dropped.\n" ); return false; } // Otherwise, mark where we are valid to and point to the packet entities we'll be updating from. oldFrame = m_pHLTV->GetClientFrame( entmsg->m_nDeltaFrom ); } // create new empty snapshot CFrameSnapshot* pSnapshot = framesnapshotmanager->CreateEmptySnapshot( GetServerTickCount(), entmsg->m_nMaxEntries ); Assert( m_pNewClientFrame == NULL ); m_pNewClientFrame = new CClientFrame( pSnapshot ); Assert( entmsg->m_nBaseline >= 0 && entmsg->m_nBaseline < 2 ); if ( entmsg->m_bUpdateBaseline ) { // server requested to use this snapshot as baseline update int nUpdateBaseline = (entmsg->m_nBaseline == 0) ? 1 : 0; CopyEntityBaseline( entmsg->m_nBaseline, nUpdateBaseline ); // send new baseline acknowledgement(as reliable) CLC_BaselineAck baseline( GetServerTickCount(), entmsg->m_nBaseline ); m_NetChannel->SendNetMsg( baseline, true ); } // copy classes and serial numbers from current frame if ( m_pCurrentClientFrame ) { CFrameSnapshot* pLastSnapshot = m_pCurrentClientFrame->GetSnapshot(); CFrameSnapshotEntry *pEntry = pSnapshot->m_pEntities; CFrameSnapshotEntry *pLastEntry = pLastSnapshot->m_pEntities; Assert( pLastSnapshot->m_nNumEntities <= pSnapshot->m_nNumEntities ); for ( int i = 0; i<pLastSnapshot->m_nNumEntities; i++ ) { pEntry->m_nSerialNumber = pLastEntry->m_nSerialNumber; pEntry->m_pClass = pLastEntry->m_pClass; pEntry++; pLastEntry++; } } CEntityReadInfo u; u.m_pBuf = &entmsg->m_DataIn; u.m_pFrom = oldFrame; u.m_pTo = m_pNewClientFrame; u.m_bAsDelta = entmsg->m_bIsDelta; u.m_nHeaderCount = entmsg->m_nUpdatedEntries; u.m_nBaseline = entmsg->m_nBaseline; u.m_bUpdateBaselines = entmsg->m_bUpdateBaseline; ReadPacketEntities( u ); // adjust reference count to be 1 pSnapshot->ReleaseReference(); return CBaseClientState::ProcessPacketEntities( entmsg ); }
~CEffectChecker() { Assert( g_ParticleEffects.Count() == 0 ); }
//----------------------------------------------------------------------------- // Purpose: message pump // loops through and sends all active messages // note that more messages may be posted during the process //----------------------------------------------------------------------------- bool CVGui::DispatchMessages() { int time = g_pSystem->GetTimeMillis(); m_InDispatcher = true; bool doneWork = (m_MessageQueue.Count() > 12); bool bUsingDelayedQueue = (m_DelayedMessageQueue.Count() > 0); // Need two passes because we send the mouse move message after all // other messages are done, but the mouse move message may itself generate // some more messages int nPassCount = 0; while ( nPassCount < 2 ) { while (m_MessageQueue.Count() > 0 || (m_SecondaryQueue.Count() > 0) || bUsingDelayedQueue) { // get the first message MessageItem_t *messageItem = NULL; int messageIndex = 0; // use the secondary queue until it empties. empty it after each message in the // primary queue. this makes primary messages completely resolve bool bUsingSecondaryQueue = (m_SecondaryQueue.Count() > 0); if (bUsingSecondaryQueue) { doneWork = true; messageIndex = m_SecondaryQueue.Head(); messageItem = &m_SecondaryQueue[messageIndex]; } else if (bUsingDelayedQueue) { if (m_DelayedMessageQueue.Count() >0) { messageItem = (MessageItem_t*)&m_DelayedMessageQueue.ElementAtHead(); } if (!messageItem || messageItem->_arrivalTime > time) { // no more items in the delayed message queue, move to the system queue bUsingDelayedQueue = false; continue; } } else { messageIndex = m_MessageQueue.Head(); messageItem = &m_MessageQueue[messageIndex]; } // message debug code if ( m_bDebugMessages ) { char *qname = bUsingSecondaryQueue ? "Secondary" : "Primary"; if (strcmp(messageItem->_params->GetName(), "Tick") && strcmp(messageItem->_params->GetName(), "MouseFocusTicked") && strcmp(messageItem->_params->GetName(), "KeyFocusTicked") && strcmp(messageItem->_params->GetName(), "CursorMoved")) { if (!stricmp(messageItem->_params->GetName(), "command")) { g_pIVgui->DPrintf2( "%s Queue dispatching command( %s, %s -- %i )\n", qname, messageItem->_params->GetName(), messageItem->_params->GetString("command"), messageItem->_messageID ); } else { g_pIVgui->DPrintf2( "%s Queue dispatching( %s -- %i )\n", qname ,messageItem->_params->GetName(), messageItem->_messageID ); } } } // send it KeyValues *params = messageItem->_params; // Deal with special internal cursor movement messages if ( messageItem->_messageTo == 0xFFFFFFFF ) { if ( !Q_stricmp( params->GetName(), "SetCursorPosInternal" ) ) { int nXPos = params->GetInt( "xpos", 0 ); int nYPos = params->GetInt( "ypos", 0 ); g_pInput->UpdateCursorPosInternal( nXPos, nYPos ); } } else { VPanel *vto = (VPanel *)g_pIVgui->HandleToPanel(messageItem->_messageTo); if (vto) { // Msg("Sending message: %s to %s\n", params ? params->GetName() : "\"\"", vto->GetName() ? vto->GetName() : "\"\""); vto->SendMessage(params, g_pIVgui->HandleToPanel(messageItem->_from)); } } // free the keyvalues memory // we can't reference the messageItem pointer anymore since the queue might have moved in memory if (params) { params->deleteThis(); } // remove it from the queue if (bUsingSecondaryQueue) { m_SecondaryQueue.Remove(messageIndex); } else if (bUsingDelayedQueue) { m_DelayedMessageQueue.RemoveAtHead(); } else { m_MessageQueue.Remove(messageIndex); } } ++nPassCount; if ( nPassCount == 1 ) { // Specifically post the current mouse position as a message g_pInput->PostCursorMessage(); } } // Make sure the windows cursor is in the right place after processing input // Needs to be done here because a message provoked by the cursor moved // message may move the cursor also g_pInput->HandleExplicitSetCursor( ); m_InDispatcher = false; return doneWork; }
//----------------------------------------------------------------------------- // Purpose: Checks to see if we should resend any reliable packets //----------------------------------------------------------------------------- void CTrackerNET::CheckReliablePacketSending() { float time = m_pThreads->GetTime(); // reliable packets are held in the m_ReliableMessages queue in the order that they were sent // if a packet is resent, it is moved to the end of the queue // packets are also checked at this time to see if they have been acknowledged while (m_ReliableMessages.Count()) { // get the first message int index = m_ReliableMessages.Head(); // get the message SentMessage_t &msg = m_ReliableMessages[index]; // check the resend time, if it's not time to resend then we have nothing more to do if (msg.resendTime > time) break; // get the network target for this message if (!m_TargetList.IsValidIndex(msg.networkTargetHandle) || !m_TargetList.IsInList(msg.networkTargetHandle) || m_TargetList[msg.networkTargetHandle].targetID != msg.networkTargetID) { // message's target has been removed, kill if (msg.message) { msg.message->deleteThis(); } m_ReliableMessages.Remove(index); continue; } NetworkTarget_t &target = m_TargetList[msg.networkTargetHandle]; // check to see if it's already been acknowledged if (msg.sequenceNumber <= target.outgoingAcknowledged) { // message has been acknowledged, kill if (msg.message) { msg.message->deleteThis(); } m_ReliableMessages.Remove(index); // move onto next message continue; } // check to see if we should resend this packet msg.resendAttempt++; if (msg.resendAttempt < MAX_SEND_ATTEMPTS) { // only send the message if it's in the message send window if (msg.sequenceNumber < target.outgoingAcknowledged + MESSAGE_WINDOW) { WriteToLog("-> Resending '%d' (os:%d > %d) (%s)\n", msg.message->GetMsgID(), msg.sequenceNumber, target.outgoingAcknowledged, target.netAddress.ToStaticString()); // send that it again InternalSendMessage(msg.message, &target, msg.sequenceNumber); } else { // hold back on sending the message WriteToLog("-> Holding back resend '%d' (os:%d > %d) (%s)\n", msg.message->GetMsgID(), msg.sequenceNumber, target.outgoingAcknowledged, target.netAddress.ToStaticString()); msg.resendAttempt--; } // set the time before retrying again // send times: 0.0 1.5 1.5 1.5 (1.5) = 6.0 second timeout, 4 packets sent msg.resendTime = time + RESEND_TIME; // move it to the end of the list m_ReliableMessages.Unlink(index); m_ReliableMessages.LinkToTail(index); // next packet continue; } // target has failed to respond, remove the target and respond with a failed message WriteToLog("Could not deliver packet: %d (os:%d)\n", msg.message->GetMsgID(), msg.sequenceNumber); // send back a send failure message to the app // convert the send message into a receive message CSendMessage *sendMsg = dynamic_cast<CSendMessage *>(msg.message); if (sendMsg) { IBinaryBuffer *buf = sendMsg->GetBuffer(); buf->SetPosition(buf->GetBufferData()); buf->Advance(buf->GetReservedSize()); CReceiveMessage *failMsg = new CReceiveMessage(buf, true); if (failMsg->IsValid()) { failMsg->SetFailed(); failMsg->SetNetAddress(target.netAddress); failMsg->SetSessionID(sendMsg->SessionID()); int newIndex = m_FailedMsgs.AddToTail(); FailedMsg_t &fmsg = m_FailedMsgs[newIndex]; fmsg.message = failMsg; } else { delete failMsg; } } // target not responding, so cancel the connection // remove from target map int mapindex = FindTargetIndexByAddress(target.netAddress); assert(m_TargetMap.IsValidIndex(mapindex)); m_TargetMap.RemoveAt(mapindex); // remove target from list m_TargetList.Remove(msg.networkTargetHandle); // message will automatically be delete since it's target is gone } }