Packet 0xdd (Compressed Gump). Help!

Here you can discuss packets, implementation and design, and software related to the packet sniffing and such. This is not the place to post packages for POL, but rather discuss the packet side of them.

Moderator: POL Developer

Post Reply
RonaldoBRILHA
New User
Posts: 1
Joined: Fri Jan 08, 2010 5:52 am

Packet 0xdd (Compressed Gump). Help!

Post by RonaldoBRILHA »

Hi Guys,

I´m trying to decode this gump in c language. Can someone help me?

My Code:

Code: Select all

int compressed_gump(char *buf, int len) // 0xdd

int PlayerSerial,GumpID,x,y,CLen,DLen,size;

    size = unpack16(buf+1);
	PlayerSerial = unpack32(buf+3);
	GumpID  = unpack32(buf+7);
	x  = unpack32(buf+11);
	y  = unpack32(buf+15);
	
	CLen = unpack32(buf+19);

	if (CLen < 4)
	{
	 LogPrint(3, "[ERROR] Compress Length < 4.");
     return 0;
	}

	CLen -= 4;
    
    if((28 + CLen) > (size))
	{
	LogPrint(3, "[ERROR] Bad Compressed Gumpdata !");
    return 0;
    }

	DLen = unpack32(buf+23);
	return 0;
}
Packet Description:

Packet Name: Compressed Gump
Last Modified: 2009-09-10 16:06:57
Modified By: Grin

Packet: 0xDD
Sent By: Server
Size: variable

Packet Build
BYTE[1] Cmd
BYTE[2] len
BYTE[4] Player Serial
BYTE[4] Gump ID
BYTE[4] x
BYTE[4] y
BYTE[4] Compressed Gump Layout Length (CLen)
BYTE[4] Decompressed Gump Layout Length (DLen)
BYTE[CLen-4] Gump Data, zlib compressed
BYTE[4] Number of text lines
BYTE[4] Compressed Text Line Length (CTxtLen)
BYTE[4] Decompressed Text Line Length (DTxtLen)
BYTE[CTxtLen-4] Gump's Compressed Text data, zlib compressed

Subcommand Build
N/A

Notes
text lines is in Big-Endian Unicode formate, not NULL terminated
loop:

BYTE[2] Length
BYTE[Length*2] text

endloop

Default level for decompresion

I Founded some open sources . But my dev is in C++.

C# code

Code: Select all

private void CompressedGump( PacketReader pvSrc ) {
			int serial = pvSrc.ReadInt32();
			int dialogID = pvSrc.ReadInt32();
			int x = pvSrc.ReadInt32();
			int y = pvSrc.ReadInt32();
			string layout = GetCompressedReader( pvSrc ).ReadString();
			string[] text = new string[pvSrc.ReadInt32()];
			pvSrc = GetCompressedReader( pvSrc );
			for ( int i = 0; i < text.Length; i++ ) {
				text[i] = pvSrc.ReadUnicodeString( pvSrc.ReadUInt16() );
			}

		}

		public PacketReader GetCompressedReader( PacketReader pvSrc ) {
			if ( m_CompBuffer == null ) {
				m_CompBuffer = new byte[0x1000];
			}
			int num = pvSrc.ReadInt32();
			if ( num == 0 ) {
				return new PacketReader( m_CompBuffer, 0, 3, false, 0, "Gump Subset" );
			}
			int destLength = pvSrc.ReadInt32();
			if ( destLength == 0 ) {
				return new PacketReader( m_CompBuffer, 0, 3, false, 0, "Gump Subset" );
			}
			byte[] source = pvSrc.ReadBytes( num - 4 );
			if ( destLength > m_CompBuffer.Length ) {
				m_CompBuffer = new byte[( destLength + 0xfff ) & -4096];
			}
			Zlib.Unpack( m_CompBuffer, ref destLength, source, source.Length );
			PacketReader reader = new PacketReader( m_CompBuffer, 0, destLength, true, 0, "Gump Subset" );
			reader.Seek( 0, SeekOrigin.Begin );
			return reader;
		}
Source: http://www.runuo.com/forums/third-party ... -0xdd.html

C# [2] code

Code: Select all

case 0xDD: //generic gump
                    int serialdd = packet[3] << 24 | packet[4] << 16 | packet[5] << 8 | packet[6];
                    int iddd = packet[7] << 24 | packet[8] << 16 | packet[9] << 8 | packet[10];
                    int xdd = packet[11] << 24 | packet[12] << 16 | packet[13] << 8 | packet[14];
                    int ydd = packet[15] << 24 | packet[16] << 16 | packet[17] << 8 | packet[18];
                    int compressLendd = packet[19] << 24 | packet[20] << 16 | packet[21] << 8 | packet[22];
                    if (compressLendd <= 4) return;
                    else compressLendd -= 4;
                    int decompressLendd = packet[23] << 24 | packet[24] << 16 | packet[25] << 8 | packet[26] + 1;
                    byte[] decompresseddd = new byte[decompressLendd];
                    byte[] compresseddd = new byte[compressLendd];
                    Buffer.BlockCopy(packet, 27, compresseddd, 0, compressLendd);
                    int success;
                    //if (IntPtr.Size == 8) success = Win32.uncompress64(decompresseddd, ref decompressLendd, compresseddd, compressLendd);
                    success = Win32.uncompress32(decompresseddd, ref decompressLendd, compresseddd, compressLendd);
                    if (success != 0)
                    {
                        Log.LogDataMessage(client, packet, "*** Error decompressing gump layout:");
                        return;
                    }
                    
                    string layoutdd = ASCIIEncoding.ASCII.GetString(decompresseddd).TrimEnd('\0');
                    int offsetdd = 27 + compressLendd;
                    int linesdd = packet[offsetdd] << 24 | packet[offsetdd + 1] << 16 | packet[offsetdd + 2] << 8 | packet[offsetdd + 3];
                    compressLendd = packet[offsetdd + 4] << 24 | packet[offsetdd + 5] << 16 | packet[offsetdd + 6] << 8 | packet[offsetdd + 7];
                    string[] textdd = new string[linesdd];
                    if (compressLendd > 4)
                    {
                        compressLendd -= 4;
                        compresseddd = new byte[compressLendd];
                        Buffer.BlockCopy(packet, offsetdd + 12, compresseddd, 0, compressLendd);
                        decompressLendd = packet[offsetdd + 8] << 24 | packet[offsetdd + 9] << 16 | packet[offsetdd + 10] << 8 | packet[offsetdd + 11] + 1;
                        decompresseddd = new byte[decompressLendd];
                        //if (IntPtr.Size == 8) success = Win32.uncompress64(decompresseddd, ref decompressLendd, compresseddd, compressLendd);
                        success = Win32.uncompress32(decompresseddd, ref decompressLendd, compresseddd, compressLendd);
                        if (success != 0)
                        {
                            Log.LogDataMessage(client, packet, "*** Error decompressing gump strings:");
                            return;
                        }
                        offsetdd = 0;
                        int lendd = 0;
                        for (int x = 0; x < linesdd; x++)
                        {
                            lendd = (decompresseddd[offsetdd] << 8 | decompresseddd[offsetdd + 1]) * 2;
                            offsetdd += 2;
                            textdd[x] = UnicodeEncoding.BigEndianUnicode.GetString(decompresseddd, offsetdd, lendd);
                            offsetdd += lendd;
                        }
                    }
                    IncomingPackets.OnGenericGump(client, serialdd, iddd, xdd, ydd, layoutdd, textdd);
                    return;
Source: UO Machine Source Code

LUA Code

Code: Select all

-- compressed Gump
function gPacketHandler.kPacket_Compressed_Gump ()	--0xDD
	local input = GetRecvFIFO()
	local popped_start = input:GetTotalPopped()
	local id = input:PopNetUint8()
	local size = input:PopNetUint16()
	local newgump = {}

	newgump.playerid = input:PopNetUint32()
	newgump.dialogId = input:PopNetUint32()
	newgump.x = input:PopNetUint32()
	newgump.y = input:PopNetUint32()

	newgump.Length_CompressedData = input:PopNetUint32() - 4
	newgump.Length_Data = input:PopNetUint32()

	printdebug("net",sprintf("NET: Length_CompressedData=%d Length_UncompressedData=%d\n",newgump.Length_CompressedData,newgump.Length_Data))

	if (28 + newgump.Length_CompressedData > size) then 
		printf("NET: BROKEN - kPacket_Compressed_Gump packet, compressed gumplen = 0x%08x\n",newgump.Length_CompressedData)
		print("Error: Server Sends bad Compressed Gumpdata ! Please report.")
		print("FATAL ! kPacket_Compressed_Gump -> forced Crash")
		NetCrash()
	end

	--- Data Part ---
	local decompressed = CreateFIFO()
	-- pop and decompress data into decompress fifo
	input:PeekDecompressIntoFifo(newgump.Length_CompressedData,newgump.Length_Data,decompressed)
	-- skip compressed part (peeked)
	input:PopRaw(newgump.Length_CompressedData)
	newgump.Data = decompressed:PopFilledString(decompressed:Size())
	-- and clear the decompress fifo for later usage
	decompressed:Clear()
	
	-- WARNING  strange -4 on compression ahead (see runuo2 source)
	--- Textlines Part ---
	newgump.numTextLines = input:PopNetUint32()

	if (newgump.numTextLines ~= 0) then
		newgump.Length_CompressedTextLines = input:PopNetUint32() - 4
		newgump.Length_TextLines = input:PopNetUint32()
	
		-- pop and decompress data into decompress fifo
		input:PeekDecompressIntoFifo(newgump.Length_CompressedTextLines,newgump.Length_TextLines,decompressed)
		-- skip compressed part (peeked)
		input:PopRaw(newgump.Length_CompressedTextLines)
		
		-- print gumpdata
		for k,v in pairs(newgump) do printdebug("gump",sprintf("newgump.%s = ",k),v) end
		
		local textlen = 0
		newgump.textline = {}
		newgump.textline_unicode = {}
		--Index 0 because Serverside Gump Commands use this Index as textline references
		for i = 0,newgump.numTextLines-1 do
			textlen = decompressed:PopNetUint16()
			printdebug("gump","reading text line ",i," with length ",textlen)
			newgump.textline[i],newgump.textline_unicode[i] = UniCodeDualPop(decompressed,textlen)
			printdebug("gump",sprintf("newgump.textline[%d](len=%d)=\n",i,textlen),newgump.textline[i])
		end
	end

	decompressed:Destroy()

	if ( (input:Size() >= 4) and (input:GetTotalPopped()-popped_start < size) ) then
		local unknownterminator=input:PopNetUint32()
	end

	local dialog = GumpParser(newgump)
	NotifyListener("Hook_OpenServersideGump",dialog,newgump.playerid,newgump.dialogId,newgump.Length_Data,true,newgump)	
end

Source: http://iris.schattenkind.net/svn/branch ... t.gump.lua
Post Reply