
Newer clients to display tooltip information use a combination of 0xDC and 0xD6

client usually can request a background send of new tooltips with an empty (or with uid list) 0xd6

then you should send generate a correct 0xd6 (see code of runuo below) than extract uid and hash from it
and send first a 0xdc with these data and then the generated 0xd6.. this prevent client crashing from flooding.


Example of a requesting d6 (with list of uids)

0000: D6 3F 00 40 00 00 02 40 00 00 03 40 00 00 04 40	.?.@...@...@...@
0010: 00 00 05 40 00 00 06 40 00 00 07 40 00 00 08 40	...@...@...@...@
0020: 00 00 09 40 00 00 0A 40 00 00 0B 40 00 00 0C 40	...@...@...@...@
0030: 00 00 0D 40 00 00 0E 40 00 00 0F 40 00 00 10 --	...@...@...@...


Code to parse it:

		public static void BatchQueryProperties( NetState state, PacketReader pvSrc )
		{
			if ( !ObjectPropertyList.Enabled )
				return;

			Mobile from = state.Mobile;

			int length = pvSrc.Size-3;

			if ( length < 0 || (length%4) != 0 )
				return;

			int count = length/4;

			for ( int i = 0; i < count; ++i )
			{
				Serial s = pvSrc.ReadInt32();

				if ( s.IsMobile )
				{
					Mobile m = World.FindMobile( s );

					if ( m != null && from.CanSee( m ) && Utility.InUpdateRange( from, m ) )
						m.SendPropertiesTo( from );
				}
				else if ( s.IsItem )
				{
					Item item = World.FindItem( s );

					if ( item != null && !item.Deleted && from.CanSee( item ) && Utility.InUpdateRange( from.Location, item.GetWorldLocation() ) )
						item.SendPropertiesTo( from );
				}
			}
		}

The GetHashCode() in below code applied to string.. it's a .NET thing that return a DWORD hash code for that istance of
the string, we should use a similar thing :)

Example:
The hash code for "" is: 0x00001505, 5381
The hash code for "a" is: 0x0002B5C4, 177604
The hash code for "ab" is: 0x00596E26, 5860902
The hash code for "abc" is: 0x0B873285, 193409669
The hash code for "abd" is: 0x0B873282, 193409666
The hash code for "abe" is: 0x0B873283, 193409667
The hash code for "abcdef" is: 0x4DDB4BE2, 1306217442
The hash code for "abcdeg" is: 0x4DDB4BE3, 1306217443
The hash code for "abcdeh" is: 0x4DDB4BEC, 1306217452
The hash code for "abcdei" is: 0x4DDB4BED, 1306217453
The hash code for "Abcdeg" is: 0x941C4FC3, -1810083901
The hash code for "Abcdeh" is: 0x941C4FCC, -1810083892
The hash code for "Abcdei" is: 0x941C4FCD, -1810083891


Example of d6 (structure in docs/kairpacketguide)

 Recv - 19:45:50.81 (command: 0xD6, length: 0x57)
0000: D6 57 00 00 01 02 E0 DB 4F 00 00 03 55 0D 55 00	.W......O...U.U.
0010: 10 05 BD 00 10 20 00 09 00 44 00 72 00 61 00 6B	..... ...D.r.a.k
0020: 00 09 00 20 00 00 10 2F EF 00 28 4B 00 69 00 6C	... .../..(K.i.l
0030: 00 6C 00 73 00 3A 00 20 00 30 00 09 00 2F 00 20	.l.s.:. .0.../. 
0040: 00 44 00 65 00 61 00 74 00 68 00 73 00 3A 00 20	.D.e.a.t.h.s.:. 
0050: 00 30 00 00 00 00 00 -- -- -- -- -- -- -- -- --	.0.....


// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************


using System;
using System.Text;
using Server;
using Server.Network;

namespace Server
{
	public class ObjectPropertyList : Packet
	{
		private IEntity m_Entity;
		private int m_Hash;
		private int m_Header;
		private string m_HeaderArgs;

		public IEntity Entity{ get{ return m_Entity; } }
		public int Hash{ get{ return 0x40000000 + m_Hash; } }

		public int Header{ get{ return m_Header; } set{ m_Header = value; } }
		public string HeaderArgs{ get{ return m_HeaderArgs; } set{ m_HeaderArgs = value; } }

		private static bool m_Enabled = false;

		public static bool Enabled{ get{ return m_Enabled; } set{ m_Enabled = value; } }

		public ObjectPropertyList( IEntity e ) : base( 0xD6 )
		{
			EnsureCapacity( 128 );

			m_Entity = e;

			m_Stream.Write( (short) 1 );
			m_Stream.Write( (int) e.Serial );
			m_Stream.Write( (byte) 0 );
			m_Stream.Write( (byte) 0 );
			m_Stream.Write( (int) e.Serial );
		}

		public void Add( int number )
		{
			if ( number == 0 )
				return;

			AddHash( number );

			if ( m_Header == 0 )
			{
				m_Header = number;
				m_HeaderArgs = "";
			}

			m_Stream.Write( number );
			m_Stream.Write( (short) 0 );
		}

		public void Terminate()
		{
			m_Stream.Write( (int) 0 );

			m_Stream.Seek( 11, System.IO.SeekOrigin.Begin );
			m_Stream.Write( (int) m_Hash );
		}

		private static byte[] m_Buffer = new byte[1024];
		private static Encoding m_Encoding = Encoding.Unicode;

		public void AddHash( int val )
		{
			m_Hash ^= (val & 0x3FFFFFF);
			m_Hash ^= (val >> 26) & 0x3F;
		}

		public void Add( int number, string arguments )
		{
			if ( number == 0 )
				return;

			if ( arguments == null )
				arguments = "";

			if ( m_Header == 0 )
			{
				m_Header = number;
				m_HeaderArgs = arguments;
			}

			AddHash( number );
			AddHash( arguments.GetHashCode() );

			m_Stream.Write( number );

			int byteCount = m_Encoding.GetByteCount( arguments );

			if ( byteCount > m_Buffer.Length )
				m_Buffer = new byte[byteCount];

			byteCount = m_Encoding.GetBytes( arguments, 0, arguments.Length, m_Buffer, 0 );

			m_Stream.Write( (short) byteCount );
			m_Stream.Write( m_Buffer, 0, byteCount );
		}

		public void Add( int number, string format, object arg0 )
		{
			Add( number, String.Format( format, arg0 ) );
		}

		public void Add( int number, string format, object arg0, object arg1 )
		{
			Add( number, String.Format( format, arg0, arg1 ) );
		}

		public void Add( int number, string format, object arg0, object arg1, object arg2 )
		{
			Add( number, String.Format( format, arg0, arg1, arg2 ) );
		}

		public void Add( int number, string format, params object[] args )
		{
			Add( number, String.Format( format, args ) );
		}

		public void Add( string text )
		{
			Add( 1042971, text );
		}

		public void Add( string format, string arg0 )
		{
			Add( 1042971, String.Format( format, arg0 ) );
		}

		public void Add( string format, string arg0, string arg1 )
		{
			Add( 1042971, String.Format( format, arg0, arg1 ) );
		}

		public void Add( string format, string arg0, string arg1, string arg2 )
		{
			Add( 1042971, String.Format( format, arg0, arg1, arg2 ) );
		}

		public void Add( string format, params object[] args )
		{
			Add( 1042971, String.Format( format, args ) );
		}
	}

	public class OPLInfo : Packet
	{
		/*public OPLInfo( ObjectPropertyList list ) : base( 0xBF )
		{
			EnsureCapacity( 13 );

			m_Stream.Write( (short) 0x10 );
			m_Stream.Write( (int) list.Entity.Serial );
			m_Stream.Write( (int) list.Hash );
		}*/

		public OPLInfo( ObjectPropertyList list ) : base( 0xDC, 9 )
		{
			m_Stream.Write( (int) list.Entity.Serial );
			m_Stream.Write( (int) list.Hash );
		}
	}
}
