//----------------------------------------------------------------------------- // Purpose: Adds a message to the queue to be sent to a user //----------------------------------------------------------------------------- void CVGui::PostMessage(VPANEL target, KeyValues *params, VPANEL from, float delay) { // Ignore all messages in re-entrant mode if ( IsReentrant() ) { Assert( 0 ); if (params) { params->deleteThis(); } return; } if (!target) { if (params) { params->deleteThis(); } return; } MessageItem_t messageItem; messageItem._messageTo = (target != (VPANEL)-1) ? g_pIVgui->PanelToHandle(target) : 0xFFFFFFFF; messageItem._params = params; Assert(params->GetName()); messageItem._from = g_pIVgui->PanelToHandle(from); messageItem._arrivalTime = 0; messageItem._messageID = m_iCurrentMessageID++; /* message debug code //if ( stricmp(messageItem._params->GetName(),"CursorMoved") && stricmp(messageItem._params->GetName(),"KeyFocusTicked")) { g_pIVgui->DPrintf2( "posting( %s -- %i )\n", messageItem._params->GetName(), messageItem._messageID ); } */ // add the message to the correct message queue if (delay > 0.0f) { messageItem._arrivalTime = g_pSystem->GetTimeMillis() + (delay * 1000); m_DelayedMessageQueue.Insert(messageItem); } else if (m_InDispatcher) { m_SecondaryQueue.AddToTail(messageItem); } else { m_MessageQueue.AddToTail(messageItem); } }
//----------------------------------------------------------------------------- // Creates a new renderable //----------------------------------------------------------------------------- void CClientLeafSystem::NewRenderable( IClientRenderable* pRenderable, RenderGroup_t type, int flags ) { Assert( pRenderable ); Assert( pRenderable->RenderHandle() == INVALID_CLIENT_RENDER_HANDLE ); ClientRenderHandle_t handle = m_Renderables.AddToTail(); RenderableInfo_t &info = m_Renderables[handle]; // We need to know if it's a brush model for shadows int modelType = modelinfo->GetModelType( pRenderable->GetModel() ); if (modelType == mod_brush) { flags |= RENDER_FLAGS_BRUSH_MODEL; } else if ( modelType == mod_studio ) { flags |= RENDER_FLAGS_STUDIO_MODEL; } info.m_pRenderable = pRenderable; info.m_RenderFrame = -1; info.m_RenderFrame2 = -1; info.m_FirstShadow = m_ShadowsOnRenderable.InvalidIndex(); info.m_LeafList = m_RenderablesInLeaf.InvalidIndex(); info.m_Flags = flags; info.m_RenderGroup = (unsigned char)type; info.m_EnumCount = 0; info.m_RenderLeaf = 0xFFFF; if ( IsViewModelRenderGroup( (RenderGroup_t)info.m_RenderGroup ) ) { AddToViewModelList( handle ); } pRenderable->RenderHandle() = handle; }
//----------------------------------------------------------------------------- // Purpose: creates the full path for a node //----------------------------------------------------------------------------- void DirectorySelectDialog::GenerateFullPathForNode(int nodeIndex, char *path, int pathBufferSize) { // get all the nodes CUtlLinkedList<int, int> nodes; nodes.AddToTail(nodeIndex); int parentIndex = nodeIndex; while (1) { parentIndex = m_pDirTree->GetItemParent(parentIndex); if (parentIndex == -1) break; nodes.AddToHead(parentIndex); } // walk the nodes, adding to the path path[0] = 0; bool bFirst = true; FOR_EACH_LL( nodes, i ) { KeyValues *kv = m_pDirTree->GetItemData( nodes[i] ); strcat(path, kv->GetString("Text")); if (!bFirst) { strcat(path, "\\"); } bFirst = false; }
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; }
//----------------------------------------------------------------------------- // Purpose: // Input : framenumber - //----------------------------------------------------------------------------- CFrameSnapshot* CFrameSnapshotManager::TakeTickSnapshot( int ticknumber ) { CFrameSnapshot *snap = new CFrameSnapshot; snap->AddReference(); snap->m_nTickNumber = ticknumber; memset( snap->m_Entities, 0, sizeof( snap->m_Entities ) ); edict_t *ed; for ( int i = 0; i < sv.num_edicts; i++ ) { CFrameSnapshotEntry *entry = &snap->m_Entities[ i ]; ed = &sv.edicts[ i ]; // FIXME, this will cause EF_NODRAW entities to behave like // they need to be deleted from the client, even though // the client was never sent the entity entry->m_bExists = ed->m_pEnt && !ed->free; entry->m_nSerialNumber = ed->serial_number; entry->m_ClassName = ed->classname; } // Blat out packed data memset( snap->m_pPackedData, 0xFF, MAX_EDICTS * sizeof(PackedEntityHandle_t) ); snap->m_ListIndex = m_FrameSnapshots.AddToTail( snap ); return snap; }
BSPTreeDataHandle_t CBSPTreeData::NewHandle( int userId ) { BSPTreeDataHandle_t handle = m_Handles.AddToTail(); m_Handles[handle].m_UserId = userId; m_Handles[handle].m_LeafList = m_HandleLeafList.InvalidIndex(); return handle; }
void AddJobMemory( int id[4] ) { TimeoutJobIDs(); CJobMemory job; memcpy( job.m_ID, id, sizeof( job.m_ID ) ); job.m_Time = Plat_FloatTime(); g_JobMemories.AddToTail( job ); }
//----------------------------------------------------------------------------- // Create/destroy shadows... //----------------------------------------------------------------------------- ClientLeafShadowHandle_t CClientLeafSystem::AddShadow( unsigned short userId, unsigned short flags ) { ClientLeafShadowHandle_t idx = m_Shadows.AddToTail(); m_Shadows[idx].m_Shadow = userId; m_Shadows[idx].m_FirstLeaf = m_ShadowsInLeaf.InvalidIndex(); m_Shadows[idx].m_FirstRenderable = m_ShadowsOnRenderable.InvalidIndex(); m_Shadows[idx].m_EnumCount = 0; m_Shadows[idx].m_Flags = flags; return idx; }
C_GasolineBlob::C_GasolineBlob() { m_pEmitter = CGasolineEmitter::Create( this ); m_vSurfaceNormal.Init(); m_flLitStartTime = 0; m_bSoundOn = false; g_GasolineBlobs.AddToTail( this ); m_flPuddleSize = PUDDLE_START_SIZE; m_flPuddleFade = 1; }
//----------------------------------------------------------------------------- // Purpose: Updates the current sequence info with the new packet // scans the message window to see if future packets can be used //----------------------------------------------------------------------------- void CTrackerNET::UpdateSequence(NetworkTarget_t *target, int targetIndex, int seqNum) { // update sequence target->incomingSequence = seqNum; // check to see when we should send acknowledgement if (!target->needAck) { target->ackTime = m_pThreads->GetTime() + ACK_DELAY; target->needAck = true; // move the target to the end of the ack list m_TargetList.Unlink(targetIndex); if (m_TargetList.IsValidIndex(m_iHighestAckTarget) && m_TargetList.IsInList(m_iHighestAckTarget)) { m_TargetList.LinkAfter(m_iHighestAckTarget, targetIndex); } else { m_TargetList.LinkToHead(targetIndex); } // set the need high mark for the packets that need ack m_iHighestAckTarget = targetIndex; } // check to see if packets in the window are now valid while (target->m_MessageWindow.Count()) { int index = target->m_MessageWindow.Head(); if (target->m_MessageWindow[index].sequenceNumber == target->incomingSequence + 1) { // this is the next message // update sequence numbers target->incomingSequence = target->m_MessageWindow[index].sequenceNumber; // add message to received list int receivedIndex = m_ReceivedMsgs.AddToTail(); m_ReceivedMsgs[receivedIndex].message = target->m_MessageWindow[index].message; WriteToLog("-> Recv match in window (is: %d)\n", target->m_MessageWindow[index].sequenceNumber); // remove message from window target->m_MessageWindow.Remove(index); } else { // no more break; } } }
//----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CParticleEffect::CParticleEffect( const char *pName ) { m_pDebugName = pName; m_vSortOrigin.Init(); m_Flags = FLAG_ALLOCATED; m_RefCount = 0; g_ParticleMgr.AddEffect( &m_ParticleEffect, this ); #if defined( _DEBUG ) g_ParticleEffects.AddToTail( this ); #endif }
//----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CParticleEffect::CParticleEffect( const char *pName ) { m_pDebugName = pName; m_vSortOrigin.Init(); m_Flags = FLAG_ALLOCATED; m_nToolParticleEffectId = TOOLPARTICLESYSTEMID_INVALID; m_RefCount = 0; m_bSimulate = true; ParticleMgr()->AddEffect( &m_ParticleEffect, this ); #if defined( _DEBUG ) g_ParticleEffects.AddToTail( this ); #endif }
bool AddDataChangeEvent( IClientNetworkable *ent, DataUpdateType_t updateType, int *pStoredEvent ) { Assert( ent ); // Make sure we don't already have an event queued for this guy. if ( *pStoredEvent >= 0 ) { Assert( g_DataChangedEvents[*pStoredEvent].m_pEntity == ent ); // DATA_UPDATE_CREATED always overrides DATA_UPDATE_CHANGED. if ( updateType == DATA_UPDATE_CREATED ) g_DataChangedEvents[*pStoredEvent].m_UpdateType = updateType; return false; } else { *pStoredEvent = g_DataChangedEvents.AddToTail( CDataChangedEvent( ent, updateType, pStoredEvent ) ); return true; } }
PackedEntity* CFrameSnapshotManager::CreatePackedEntity( CFrameSnapshot* pSnapshot, int entity ) { PackedEntityHandle_t handle = m_PackedEntities.AddToTail(); // Referenced twice: in the mru m_PackedEntities[handle].m_ReferenceCount = 2; pSnapshot->m_pPackedData[entity] = handle; // Add a reference into the global list of last entity packets seen... // and remove the reference to the last entity packet we saw if (m_pPackedData[entity] != m_PackedEntities.InvalidIndex()) { if (--m_PackedEntities[ m_pPackedData[entity] ].m_ReferenceCount <= 0) { DestroyPackedEntity( m_pPackedData[entity] ); } } m_pPackedData[entity] = handle; m_pSerialNumber[entity] = pSnapshot->m_Entities[entity].m_nSerialNumber; return &m_PackedEntities[handle]; }
//----------------------------------------------------------------------------- // Creates/ destroys "input" contexts, which contains information // about which controls have mouse + key focus, for example. //----------------------------------------------------------------------------- HInputContext CInputWin32::CreateInputContext() { HInputContext i = m_Contexts.AddToTail(); InitInputContext( &m_Contexts[i] ); return i; }
void CmdLib_AtCleanup( CleanupFn pFn ) { g_CleanupFunctions.AddToTail( pFn ); }
void InstallExtraSpewHook( SpewHookFn pFn ) { g_ExtraSpewHooks.AddToTail( pFn ); }
CFuncAreaPortalBase::CFuncAreaPortalBase() { m_portalNumber = -1; m_AreaPortalsElement = g_AreaPortals.AddToTail( this ); m_iPortalVersion = 0; }
bool DataTable_SetupReceiveTableFromSendTable( SendTable *sendTable, bool bNeedsDecoder ) { CClientSendTable *pClientSendTable = new CClientSendTable; SendTable *pTable = &pClientSendTable->m_SendTable; g_ClientSendTables.AddToTail( pClientSendTable ); // Read the name. pTable->m_pNetTableName = COM_StringCopy( sendTable->m_pNetTableName ); // Create a decoder for it if necessary. if ( bNeedsDecoder ) { // Make a decoder for it. CRecvDecoder *pDecoder = new CRecvDecoder; g_RecvDecoders.AddToTail( pDecoder ); RecvTable *pRecvTable = FindRecvTable( pTable->m_pNetTableName ); if ( !pRecvTable ) { DataTable_Warning( "No matching RecvTable for SendTable '%s'.\n", pTable->m_pNetTableName ); return false; } pRecvTable->m_pDecoder = pDecoder; pDecoder->m_pTable = pRecvTable; pDecoder->m_pClientSendTable = pClientSendTable; pDecoder->m_Precalc.m_pSendTable = pClientSendTable->GetSendTable(); pClientSendTable->GetSendTable()->m_pPrecalc = &pDecoder->m_Precalc; // Initialize array properties. SetupArrayProps_R<RecvTable, RecvTable::PropType>( pRecvTable ); } // Read the property list. pTable->m_nProps = sendTable->m_nProps; pTable->m_pProps = pTable->m_nProps ? new SendProp[ pTable->m_nProps ] : 0; pClientSendTable->m_Props.SetSize( pTable->m_nProps ); for ( int iProp=0; iProp < pTable->m_nProps; iProp++ ) { CClientSendProp *pClientProp = &pClientSendTable->m_Props[iProp]; SendProp *pProp = &pTable->m_pProps[iProp]; const SendProp *pSendTableProp = &sendTable->m_pProps[ iProp ]; pProp->m_Type = (SendPropType)pSendTableProp->m_Type; pProp->m_pVarName = COM_StringCopy( pSendTableProp->GetName() ); pProp->SetFlags( pSendTableProp->GetFlags() ); if ( pProp->m_Type == DPT_DataTable ) { char *pDTName = pSendTableProp->m_pExcludeDTName; // HACK if ( pSendTableProp->GetDataTable() ) pDTName = pSendTableProp->GetDataTable()->m_pNetTableName; Assert( pDTName && Q_strlen(pDTName) > 0 ); pClientProp->SetTableName( COM_StringCopy( pDTName ) ); // Normally we wouldn't care about this but we need to compare it against // proxies in the server DLL in SendTable_BuildHierarchy. pProp->SetDataTableProxyFn( pSendTableProp->GetDataTableProxyFn() ); pProp->SetOffset( pSendTableProp->GetOffset() ); } else { if ( pProp->IsExcludeProp() ) { pProp->m_pExcludeDTName = COM_StringCopy( pSendTableProp->GetExcludeDTName() ); } else if ( pProp->GetType() == DPT_Array ) { pProp->SetNumElements( pSendTableProp->GetNumElements() ); } else { pProp->m_fLowValue = pSendTableProp->m_fLowValue; pProp->m_fHighValue = pSendTableProp->m_fHighValue; pProp->m_nBits = pSendTableProp->m_nBits; } } } return true; }
CObjMCVSelectionPanel::CObjMCVSelectionPanel() { g_MCVSelectionPanels.AddToTail( this ); }
//----------------------------------------------------------------------------- // Purpose: Creates a target address, for sending messages to reliably //----------------------------------------------------------------------------- int CTrackerNET::FindTarget(CNetAddress &address, int targetID, int sequenceNumber) { bool createNew = true; NetworkTarget_t *target = NULL; int listIndex = 0; // find the address in the map int targetIndex = FindTargetIndexByAddress(address); if (m_TargetMap.IsValidIndex(targetIndex)) { listIndex = m_TargetMap[targetIndex].targetIndex; target = &(m_TargetList[listIndex]); // make sure the targetID's match, otherwise the connection has been invalidated if (targetID == -1 || target->targetID == targetID) { return listIndex; } else { if (sequenceNumber == 1) { //!! reset the connection WriteToLog("-> Connection Reset (%d) (%d, %d)\n", sequenceNumber, targetID, target->targetID); } else { WriteToLog("-> Connection Restart (%d) (%d, %d)\n", sequenceNumber, targetID, target->targetID); } createNew = false; } } if (createNew) { // add a new connection to the end of the list listIndex = m_TargetList.AddToTail(); target = &(m_TargetList[listIndex]); target->needAck = false; // add the target to the map TargetMapItem_t newItem; newItem.targetIndex = listIndex; newItem.netAddress = address; m_TargetMap.Insert(newItem); // ensure that it's the first one in the sequence if (sequenceNumber > 1) { WriteToLog("-> Contacted by unknown old connection (targetID:%d)\n", targetID); } } // append to the end of the list target->netAddress = address; // initialize sequence numbers target->outgoingSequence = 1; target->outgoingAcknowledged = 0; target->incomingSequence = 0; target->incomingAcknowledged = 0; if (sequenceNumber != -1) { // this is the first packet we've received, but from and old connection; so jump the correct sequence number target->incomingSequence = sequenceNumber - 1; } // target->createTime = m_pThreads->GetTime(); if (targetID >= 0) { target->targetID = targetID; } else { target->targetID = RandomLong(1, MAX_RANDOM_RANGE); } if (createNew && targetID >= 0) { WriteToLog("Creating new target ID (%d)\n", target->targetID); } else { WriteToLog("Establishing connection to target ID (%d)\n", target->targetID); } return listIndex; }
//----------------------------------------------------------------------------- // Creates/ destroys "input" contexts, which contains information // about which controls have mouse + key focus, for example. //----------------------------------------------------------------------------- HContext CVGui::CreateContext() { HContext i = m_Contexts.AddToTail(); m_Contexts[i].m_hInputContext = g_pInput->CreateInputContext(); return i; }
//----------------------------------------------------------------------------- // 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 } }
//----------------------------------------------------------------------------- // Purpose: Constructs a network message out of the packet //----------------------------------------------------------------------------- void CTrackerNET::ParseIncomingPacket(IBinaryBuffer *packet, CNetAddress netAddress, bool encrypted) { // construct a ReceiveMessage from it // parse out the packet header void *bufData = packet->GetBufferData(); packet_header_t *pHeader = (packet_header_t *)bufData; // check the protocol version if (pHeader->protocolNumber != PROTOCOL_VERSION) { // just throw away the packet if protocol is bad WriteToLog("!! Packet with invalid protocol - dropped\n"); packet->Release(); return; } // check the packet header size if (pHeader->headerSize != PACKET_HEADER_SIZE) { // just throw away the packet if protocol is bad packet->Release(); WriteToLog("!! Malformed packet - dropped\n"); return; } // match to a target int targetIndex = FindTarget(netAddress, pHeader->targetID, pHeader->sequenceNumber); NetworkTarget_t *target = &m_TargetList[targetIndex]; // mark the activity time // target->activityTime = m_pThreads->GetTime(); // update received if (pHeader->sequenceReply) { if (pHeader->sequenceReply > target->outgoingAcknowledged) { WriteToLog("<- Sequence acknowledged (%d in target %d)\n", target->outgoingAcknowledged, target->targetID); // this affects which packets we have to resend target->outgoingAcknowledged = pHeader->sequenceReply; } if (pHeader->sequenceReply > target->outgoingSequence) { // we've got a mismatch in the network stream; the Client is acknowledging a packet we haven't sent yet // just bump our outgoing up to match WriteToLog("<- Mismatched sequence numbers; increasing local outgoingSequence to match (%d -> %d)\n", target->outgoingSequence, pHeader->sequenceReply); target->outgoingSequence = pHeader->sequenceReply + 1; } } if (pHeader->sequenceNumber) { // check it against the incoming sequence number // if it's not the next packet in the sequence, just throw it away if (pHeader->sequenceNumber != target->incomingSequence + 1 && (target->incomingSequence > 0)) { HandleOutOfSequencePacket(packet, pHeader, target, netAddress, encrypted); return; } } // advance in the buffer over the packet header packet->Advance(pHeader->headerSize); //!! check for fragmentation/reassembly // build a receive message out of it CReceiveMessage *msg = new CReceiveMessage(packet, encrypted); msg->SetNetAddress(netAddress); msg->SetSessionID(pHeader->sessionID); // throw away bad messages if (!msg->IsValid()) { delete msg; return; } WriteToLog("<- Received '%d' (is:%d reply:%d)\n", msg->GetMsgID(), pHeader->sequenceNumber, pHeader->sequenceReply); // throw away any Ack packets if (msg->GetMsgID() == TMSG_ACK) { delete msg; return; } // add message to received list int receivedIndex = m_ReceivedMsgs.AddToTail(); m_ReceivedMsgs[receivedIndex].message = msg; if (pHeader->sequenceNumber) { // update the sequence, this may add more messages to the queue UpdateSequence(target, targetIndex, pHeader->sequenceNumber); } }
//----------------------------------------------------------------------------- // Purpose: Sends a message to a target address //----------------------------------------------------------------------------- void CTrackerNET::SendMessage(ISendMessage *pMsg, Reliability_e state) { pMsg->SetReliable(state == NET_RELIABLE); if (state == NET_RELIABLE && (pMsg->NetAddress().IP() == 0 || pMsg->NetAddress().Port() == 0)) return; assert(state != NET_RELIABLE || pMsg->NetAddress().IP() > 0); assert(state != NET_RELIABLE || pMsg->NetAddress().Port() > 0); CNetAddress address; int sequenceNumber = 0; int targetIndex = -1; NetworkTarget_t *target = NULL; if (state != NET_BROADCAST) { targetIndex = FindTarget(pMsg->NetAddress()); target = &m_TargetList[targetIndex]; // mark the activity time // target->activityTime = m_pThreads->GetTime(); // setup the message with the target info address = target->netAddress; } if (pMsg->IsReliable()) { // set and increment the sequence number if (target) { sequenceNumber = target->outgoingSequence++; } // save off the message int newIndex = m_ReliableMessages.AddToTail(); SentMessage_t &msg = m_ReliableMessages[newIndex]; msg.sequenceNumber = sequenceNumber; msg.message = pMsg; msg.resendAttempt = 0; msg.resendTime = m_pThreads->GetTime() + RESEND_TIME; msg.networkTargetHandle = targetIndex; msg.networkTargetID = target->targetID; // make sure we're in the message window before sending, other just hold until the resend attempt if (msg.sequenceNumber < target->outgoingAcknowledged + MESSAGE_WINDOW) { WriteToLog("-> Sending '%d' (os:%d) (%s)\n", pMsg->GetMsgID(), sequenceNumber, target->netAddress.ToStaticString()); } else { // don't send yet WriteToLog("-> Holding for send '%d' (os:%d) (%s)\n", pMsg->GetMsgID(), sequenceNumber, target->netAddress.ToStaticString()); return; } } else if (state == NET_BROADCAST) { WriteToLog("-> Sending '%d' (BROADCAST)\n", pMsg->GetMsgID(), sequenceNumber); } else { WriteToLog("-> Sending '%d' (UNRELIABLE)\n", pMsg->GetMsgID(), sequenceNumber); } InternalSendMessage(pMsg, target, sequenceNumber); }