Example #1
0
// ----------------------------------------------------------------------------- //
// Add/remove decals
// ----------------------------------------------------------------------------- //
DispDecalHandle_t CDispInfo::NotifyAddDecal( decal_t *pDecal )
{
    // FIXME: Add decal retirement...
//	if( m_Decals.Size() < MAX_DISP_DECALS )
//		return;

    // Create a new decal, link it in
    DispDecalHandle_t h = s_DispDecals.Alloc( true );

    // When linking, insert it in sorted order based on material enumeration ID
    // This will help us when rendering later
    int last = DISP_DECAL_HANDLE_INVALID;
    int i = m_FirstDecal;
    int enumerationId = pDecal->material->GetEnumerationID();
    while( i != s_DispDecals.InvalidIndex() )
    {
        int testId = s_DispDecals[i].m_pDecal->material->GetEnumerationID();
        if (enumerationId <= testId)
            break;

        last = i;
        i = s_DispDecals.Next(i);
    }

    // NOTE: when the list is used in multimode, we can't use LinkBefore( i, INVALID_INDEX ),
    // since the Head and Tail of the linked list are meaningless...

    if ( last != DISP_DECAL_HANDLE_INVALID )
        s_DispDecals.LinkAfter( last, h );
    else
    {
        s_DispDecals.LinkBefore( m_FirstDecal, h );
        m_FirstDecal = h;
    }

    CDispDecal *pDispDecal = &s_DispDecals[h];
    pDispDecal->m_pDecal = pDecal;
    pDispDecal->m_FirstFragment = DISP_DECAL_FRAGMENT_HANDLE_INVALID;
    pDispDecal->m_nVerts = 0;
    pDispDecal->m_nTris = 0;

    // Setup a basis for it.
    CDecalVert *pOutVerts = NULL;
    R_SetupDecalClip(
        pOutVerts,
        pDispDecal->m_pDecal,
        MSurf_Plane( m_ParentSurfID ).normal,
        pDispDecal->m_pDecal->material,
        pDispDecal->m_TextureSpaceBasis,
        pDispDecal->m_DecalWorldScale );

    // Recurse and precalculate which nodes this thing can touch.
    SetupDecalNodeIntersect(
        m_pPowerInfo->m_RootNode,
        0,			// node bit index into CDispDecal::m_NodeIntersects
        pDispDecal,
        0 );

    return h;
}
//-----------------------------------------------------------------------------
// 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;
		}
	}
}