void CHLTVDemoRecorder::WriteMessages( unsigned char cmd, bf_write &message )
{
	int len = message.GetNumBytesWritten();

	if (len <= 0)
		return;

	// fill last bits in last byte with NOP if necessary
	int nRemainingBits = message.GetNumBitsWritten() % 8;
	if ( nRemainingBits > 0 &&  nRemainingBits <= (8-NETMSG_TYPE_BITS) )
	{
		message.WriteUBitLong( net_NOP, NETMSG_TYPE_BITS );
	}

	Assert( len < NET_MAX_MESSAGE );

	// if signondata read as fast as possible, no rewind
	// and wait for packet time
	// byte cmd = (m_pDemoFileHeader != NULL)  ? dem_signon : dem_packet;

	if ( cmd == dem_packet )
	{
		m_nFrameCount++;
	}

	// write command & time
	m_DemoFile.WriteCmdHeader( cmd, GetRecordingTick() ); 
	
	// write NULL democmdinfo just to keep same format as client demos
	democmdinfo_t info;
	Q_memset( &info, 0, sizeof( info ) );
	m_DemoFile.WriteCmdInfo( info );

	// write continously increasing sequence numbers
	m_DemoFile.WriteSequenceInfo( m_SequenceInfo, m_SequenceInfo );
	m_SequenceInfo++;
	
	// Output the buffer.  Skip the network packet stuff.
	m_DemoFile.WriteRawData( (char*)message.GetBasePointer(), len );
	
	if ( tv_debug.GetInt() > 1 )
	{
		Msg( "Writing SourceTV demo message %i bytes at file pos %i\n", len, m_DemoFile.GetCurPos( false ) );
	}
}
int CNetworkStringTable::WriteUpdate( CBaseClient *client, bf_write &buf, int tick_ack )
{
	CUtlVector< StringHistoryEntry > history;

	int entriesUpdated = 0;
	int lastEntry = -1;

	int count = m_pItems->Count();

	for ( int i = 0; i < count; i++ )
	{
		CNetworkStringTableItem *p = &m_pItems->Element( i );

		// Client is up to date
		if ( p->GetTickChanged() <= tick_ack )
			continue;

		int nStartBit = buf.GetNumBitsWritten();

		// Write Entry index
		if ( (lastEntry+1) == i )
		{
			buf.WriteOneBit( 1 );
		}
		else
		{
			buf.WriteOneBit( 0 );
			buf.WriteUBitLong( i, m_nEntryBits );
		}

		// check if string can use older string as base eg "models/weapons/gun1" & "models/weapons/gun2"
		char const *pEntry = m_pItems->String( i );

		if ( p->GetTickCreated() > tick_ack )
		{
			// this item has just been created, send string itself
			buf.WriteOneBit( 1 );
			
			int substringsize = 0;
			int bestprevious = GetBestPreviousString( history, pEntry, substringsize );
			if ( bestprevious != -1 )
			{
				buf.WriteOneBit( 1 );
				buf.WriteUBitLong( bestprevious, 5 );	// history never has more than 32 entries
				buf.WriteUBitLong( substringsize, SUBSTRING_BITS );
				buf.WriteString( pEntry + substringsize );
			}
			else
			{
				buf.WriteOneBit( 0 );
				buf.WriteString( pEntry  );
			}
		}
		else
		{
			buf.WriteOneBit( 0 );
		}

		// Write the item's user data.
		int len;
		const void *pUserData = GetStringUserData( i, &len );
		if ( pUserData && len > 0 )
		{
			buf.WriteOneBit( 1 );

			if ( IsUserDataFixedSize() )
			{
				// Don't have to send length, it was sent as part of the table definition
				buf.WriteBits( pUserData, GetUserDataSizeBits() );
			}
			else
			{
				buf.WriteUBitLong( len, CNetworkStringTableItem::MAX_USERDATA_BITS );
				buf.WriteBits( pUserData, len*8 );
			}
		}
		else
		{
			buf.WriteOneBit( 0 );
		}

		// limit string history to 32 entries
		if ( history.Count() > 31 )
		{
			history.Remove( 0 );
		}

		// add string to string history
		StringHistoryEntry she;
		Q_strncpy( she.string, pEntry, sizeof( she.string ) );
		history.AddToTail( she );

		entriesUpdated++;
		lastEntry = i;

		if ( client && client->IsTracing() )
		{
			int nBits = buf.GetNumBitsWritten() - nStartBit;
			client->TraceNetworkMsg( nBits, " [%s] %d:%s ", GetTableName(), i, GetString( i ) );
		}
	}

	return entriesUpdated;
}
inline bool NET_SendDatagram(bool subchans = false)
{
	if (senddata.GetNumBytesWritten() == 0)
	{
		return false;
	}
	unsigned char flags = 0;

	netdatagram.WriteLong(netchan->m_nOutSequenceNr); // outgoing sequence
	netdatagram.WriteLong(netchan->m_nInSequenceNr); // incoming sequence

	bf_write flagpos = netdatagram;

	netdatagram.WriteByte(0); // flags
	netdatagram.WriteWord(0); // crc16

	int nCheckSumStart = netdatagram.GetNumBytesWritten();



	netdatagram.WriteByte(netchan->m_nInReliableState);


	if (subchans)
	{
		flags |= PACKET_FLAG_RELIABLE;
	}



	netdatagram.WriteBits(senddata.GetData(), senddata.GetNumBitsWritten()); // Data

	int nMinRoutablePayload = MIN_ROUTABLE_PAYLOAD;


	while ((netdatagram.GetNumBytesWritten() < MIN_ROUTABLE_PAYLOAD&&netdatagram.GetNumBitsWritten() % 8 != 0))
	{
		netdatagram.WriteUBitLong(0, NETMSG_TYPE_BITS);
	}

	flagpos.WriteByte(flags);

	void *pvData = datagram + nCheckSumStart;

	if (pvData)
	{


		int nCheckSumBytes = netdatagram.GetNumBytesWritten() - nCheckSumStart;
		if (nCheckSumBytes > 0)
		{

			unsigned short usCheckSum = BufferToShortChecksum(pvData, nCheckSumBytes);
			flagpos.WriteUBitLong(usCheckSum, 16);

			netchan->m_nOutSequenceNr++;

			net.SendTo(serverip, serverport, datagram, netdatagram.GetNumBytesWritten());
		}
	}

	NET_ResetDatagram();

	return true;
}