Example #1
0
//-----------------------------------------------------------------------------
// 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);
	}
}
Example #2
0
//-----------------------------------------------------------------------------
// 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;
}
Example #6
0
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 );
}
Example #8
0
//-----------------------------------------------------------------------------
// 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;
}
Example #16
0
void CmdLib_AtCleanup( CleanupFn pFn )
{
	g_CleanupFunctions.AddToTail( pFn );
}
Example #17
0
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;
}
Example #22
0
//-----------------------------------------------------------------------------
// 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);
}