RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Compressed gumps [0xDD]

arul

Sorceror
Compressed gumps [0xDD]

5.x.x client introduces a new packet for Zlib compressed gumps.
Those gump packets are sometimes 5 times smaller then uncompressed ones.

Keep in mind if you modify the core you will lost script support here.

This requires a quite extensive core modification and you will not be able to do it without basic knowledge of C# and RunUO architecture. I cannot fully support this modification, thus if you have no clue what to do disregard this post, thanks.

The architeture of the new compressed gump packet is following:

Code:
BYTE PacketId (0xDD)
DWORD GumpSerial
DWORD GumpTypeID
DWORD X
DWORD Y
 
DWORD LengthOfTheCompressedLayout
DWORD LengthOfTheUncompressedLayout
BYTE
[*] CompressedLayout
 
DWORD TextLines
DWORD LengthOfTheCompressedText
DWORD LengthOfTheUncompressedText
BYTE
[*] CompressedText
First off we need to make the Zlib part of the core.

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Server
{
    public enum ZLibCompressionLevel
    {
        Z_BEST_COMPRESSION = 9,
        Z_BEST_SPEED = 1,
        Z_DEFAULT_COMPRESSION = -1,
        Z_NO_COMPRESSION = 0
    }
    public enum ZLibError
    {
        Z_BUF_ERROR = -5,
        Z_DATA_ERROR = -3,
        Z_ERRNO = -1,
        Z_MEM_ERROR = -4,
        Z_NEED_DICT = 2,
        Z_OK = 0,
        Z_STREAM_END = 1,
        Z_STREAM_ERROR = -2,
        Z_VERSION_ERROR = -6
    } 
    class ZLib
    {
        public ZLib()
        {
        }
        [DllImport("zlib")]
        public static extern ZLibError compress(byte[] dest, ref int destLength, byte[] source, int sourceLength);
        [DllImport("zlib")]
        public static extern ZLibError compress2(byte[] dest, ref int destLength, byte[] source, int sourceLength, ZLibCompressionLevel level);
 
        [DllImport("zlib")]
        public static extern ZLibError uncompress(byte[] dest, ref int destLen, byte[] source, int sourceLen);
    }
}

Now, we want to have ability to send both compressed and uncompressed gump depending on the client version.
To do that, open Packets.cs and put in this interface.
Code:
[SIZE=2]
[/SIZE][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]interface [/COLOR][/SIZE][SIZE=2][COLOR=#008080]IGumpPacket
[/COLOR][/SIZE][SIZE=2]{
[/SIZE][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][SIZE=2] AppendLayout ([/SIZE][SIZE=2][COLOR=#0000ff]bool[/COLOR][/SIZE][SIZE=2] val);
[/SIZE][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][SIZE=2] AppendLayout ([/SIZE][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][SIZE=2] val);
[/SIZE][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][SIZE=2] AppendLayout ([/SIZE][SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2][] buffer);
[/SIZE][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][SIZE=2] AppendLayoutNS ([/SIZE][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][SIZE=2] val);
[/SIZE][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][SIZE=2] TextEntries { [/SIZE][SIZE=2][COLOR=#0000ff]get[/COLOR][/SIZE][SIZE=2]; [/SIZE][SIZE=2][COLOR=#0000ff]set[/COLOR][/SIZE][SIZE=2]; }
[/SIZE][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][SIZE=2] Switches { [/SIZE][SIZE=2][COLOR=#0000ff]get[/COLOR][/SIZE][SIZE=2]; [/SIZE][SIZE=2][COLOR=#0000ff]set[/COLOR][/SIZE][SIZE=2]; }
}
[/SIZE]

Now find the definition of DisplayGumpFast packet and let it inhert the new interface
Code:
[SIZE=2][COLOR=#0000ff]
    public [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]sealed [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]class [/COLOR][/SIZE][SIZE=2][COLOR=#008080]DisplayGumpFast[/COLOR][/SIZE][SIZE=2] : [/SIZE][SIZE=2][COLOR=#008080]Packet[/COLOR][/SIZE][SIZE=2][COLOR=red], [/COLOR][/SIZE][SIZE=2][COLOR=#008080][COLOR=red]IGumpPacket[/COLOR]
[/COLOR][/SIZE]
Easy, isn't it ?

Now the time has come to assembly all new packet, let's call it DisplayCompressedGumpFast.

Code:
[SIZE=2]public [/SIZE][SIZE=2]sealed [/SIZE][SIZE=2]class [/SIZE][SIZE=2]DisplayCompressedGumpFast[/SIZE][SIZE=2] : [/SIZE][SIZE=2]Packet[/SIZE][SIZE=2], [/SIZE][SIZE=2]IGumpPacket
[/SIZE][SIZE=2]{
[/SIZE][SIZE=2][COLOR=#0000ff]static[/COLOR][/SIZE][SIZE=2] DisplayCompressedGumpFast()
     {
          m_True = [/SIZE][SIZE=2][COLOR=#008080]Gump[/COLOR][/SIZE][SIZE=2].StringToBuffer([/SIZE][SIZE=2][COLOR=#800000]" 1"[/COLOR][/SIZE][SIZE=2]);
          m_False = [/SIZE][SIZE=2][COLOR=#008080]Gump[/COLOR][/SIZE][SIZE=2].StringToBuffer([/SIZE][SIZE=2][COLOR=#800000]" 0"[/COLOR][/SIZE][SIZE=2]);
          m_Buffer = [/SIZE][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE] [SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2][0x400]; [/SIZE][SIZE=2][COLOR=#008000]
[/COLOR][/SIZE][SIZE=2]   m_Buffer[0] = 0x20;[/SIZE][SIZE=2][COLOR=#008000]
[/COLOR][/SIZE][SIZE=2]}
[/SIZE]
[SIZE=2]public[/SIZE][SIZE=2] DisplayCompressedGumpFast([/SIZE][SIZE=2]Gump[/SIZE][SIZE=2] g)
          : [/SIZE][SIZE=2]base[/SIZE][SIZE=2](0xDD)
     {
          m_Layout = [/SIZE][SIZE=2]new[/SIZE][SIZE=2]PacketWriter[/SIZE][SIZE=2]();
          m_Text = [/SIZE][SIZE=2]new[/SIZE][SIZE=2]PacketWriter[/SIZE][SIZE=2]();
          EnsureCapacity(0x400);
          m_Stream.Write(g.Serial);
          m_Stream.Write(g.TypeID);
          m_Stream.Write(g.X);
          m_Stream.Write(g.Y);
     }
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]void[/SIZE][SIZE=2] AppendLayout([/SIZE][SIZE=2]bool[/SIZE][SIZE=2] val)
     {
          AppendLayout(val ? m_True : m_False);
     }
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]void[/SIZE][SIZE=2] AppendLayout([/SIZE][SIZE=2]int[/SIZE][SIZE=2] val)
     {
[/SIZE][SIZE=2]   string[/SIZE][SIZE=2] text = val.ToString();
[/SIZE][SIZE=2]   int[/SIZE][SIZE=2] num = [/SIZE][SIZE=2]System.Text.Encoding[/SIZE][SIZE=2].ASCII.GetBytes(text, 0, text.Length, m_Buffer, 1) + 1;
          m_Layout.Write(m_Buffer, 0, num);
          m_LayoutLength += num;
     }
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]void[/SIZE][SIZE=2] AppendLayout([/SIZE][SIZE=2]byte[/SIZE][SIZE=2][] buffer)
     {
[/SIZE][SIZE=2]   int[/SIZE][SIZE=2] num = buffer.Length;
          m_Layout.Write(buffer, 0, num);
          m_LayoutLength += num;
     }
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]void[/SIZE][SIZE=2] AppendLayoutNS([/SIZE][SIZE=2]int[/SIZE][SIZE=2] val)
     {
[/SIZE][SIZE=2]   string[/SIZE][SIZE=2] text = val.ToString();
[/SIZE][SIZE=2]   int[/SIZE][SIZE=2] num = [/SIZE][SIZE=2]System.Text.Encoding[/SIZE][SIZE=2].ASCII.GetBytes(text, 0, text.Length, m_Buffer, 1);
          m_Layout.Write(m_Buffer, 1, num);
          m_LayoutLength += num;
     }
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]void[/SIZE][SIZE=2] Output()
     {
[/SIZE][SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2][] buffer = [/SIZE][SIZE=2][COLOR=#0000ff]new[/COLOR][/SIZE] [SIZE=2][COLOR=#0000ff]byte[/COLOR][/SIZE][SIZE=2][BufferSize];[/SIZE][SIZE=2][COLOR=#008000]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]   int[/COLOR][/SIZE][SIZE=2] length = buffer.Length;[/SIZE]
 
[SIZE=2]
[/SIZE][SIZE=2]   if[/SIZE][SIZE=2] (
[/SIZE][SIZE=2]        ZLib[/SIZE][SIZE=2].compress2(
                    buffer,
[/SIZE][SIZE=2]             ref[/SIZE][SIZE=2] length,
                    m_Layout.ToArray(),
                    m_LayoutLength,
[/SIZE][SIZE=2]             ZLibCompressionLevel[/SIZE][SIZE=2].Z_BEST_SPEED) == [/SIZE][SIZE=2]ZLibError[/SIZE][SIZE=2].Z_OK
               )
               {
 
                    WriteBuffer(
                    buffer, 
[/SIZE][SIZE=2]             ref[/SIZE][SIZE=2] length, 
                    m_LayoutLength
                    );
 
[/SIZE][SIZE=2]
[/SIZE][SIZE=2]        if[/SIZE][SIZE=2] (
[/SIZE][SIZE=2]        ZLib[/SIZE][SIZE=2].compress2(
                    buffer,
[/SIZE][SIZE=2]             ref[/SIZE][SIZE=2] length,
                    m_Text.ToArray(),
                    m_TextLength,
[/SIZE][SIZE=2]             ZLibCompressionLevel[/SIZE][SIZE=2].Z_BEST_SPEED) == [/SIZE][SIZE=2]ZLibError[/SIZE][SIZE=2].Z_OK
                    )
               {
 
                    m_Stream.Write(m_TextLines);
[/SIZE][SIZE=2]
[/SIZE][SIZE=2]             WriteBuffer(
                    buffer, 
[/SIZE][SIZE=2]             ref[/SIZE][SIZE=2] length, 
                    m_TextLength
                    );
[/SIZE][SIZE=2]
[/SIZE][SIZE=2]       }
          }
     }
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]void[/SIZE][SIZE=2] WriteBuffer([/SIZE][SIZE=2]byte[/SIZE][SIZE=2][] buffer, [/SIZE][SIZE=2]ref[/SIZE][SIZE=2]int[/SIZE][SIZE=2] length, [/SIZE][SIZE=2]int[/SIZE][SIZE=2] contentLength)
     {
         m_Stream.Write(length + 4); 
[/SIZE][SIZE=2]  m_Stream.Write(contentLength);[/SIZE][SIZE=2]
[/SIZE][SIZE=2]  m_Stream.Write(buffer, 0, length); 
[/SIZE][SIZE=2]  length = buffer.Length; [/SIZE][SIZE=2]
[/SIZE][SIZE=2]}
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]void[/SIZE][SIZE=2] WriteText([/SIZE][SIZE=2]ArrayList[/SIZE][SIZE=2] text)
     {
          m_TextLines = text.Count; 
 
[/SIZE][SIZE=2]   for[/SIZE][SIZE=2] ([/SIZE][SIZE=2]int[/SIZE][SIZE=2] i = 0; i < text.Count; ++i)
          {
[/SIZE][SIZE=2]        string[/SIZE][SIZE=2] v = ([/SIZE][SIZE=2]string[/SIZE][SIZE=2])text[i];
[/SIZE][SIZE=2][COLOR=#0000ff]if[/COLOR][/SIZE][SIZE=2] (v == [/SIZE][SIZE=2][COLOR=#0000ff]null[/COLOR][/SIZE][SIZE=2])
                    v = [/SIZE][SIZE=2][COLOR=#800000]""[/COLOR][/SIZE][SIZE=2];[/SIZE]
 
[SIZE=2]
[/SIZE][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][SIZE=2] length = v.Length;[/SIZE]
[SIZE=2]
               m_TextLength += length * 2;
               m_Text.Write(([/SIZE][SIZE=2]ushort[/SIZE][SIZE=2])length);
               m_Text.WriteBigUniFixed(v, length);
          }
 
          m_TextLength += text.Count * 2;
     }
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]int[/SIZE][SIZE=2] Switches
     {
[/SIZE][SIZE=2]  get
[/SIZE][SIZE=2]  {
[/SIZE][SIZE=2]        return [/SIZE][SIZE=2]this[/SIZE][SIZE=2].m_Switches;
         }
 
[/SIZE][SIZE=2]  set
[/SIZE][SIZE=2]  {
[/SIZE][SIZE=2]        this[/SIZE][SIZE=2].m_Switches = [/SIZE][SIZE=2]value[/SIZE][SIZE=2];
         }
     }
 
[/SIZE][SIZE=2]public [/SIZE][SIZE=2]int[/SIZE][SIZE=2] TextEntries
     {
[/SIZE][SIZE=2]   get
[/SIZE][SIZE=2]   {
[/SIZE][SIZE=2]        return [/SIZE][SIZE=2]this[/SIZE][SIZE=2].m_TextEntries;
          }
 
[/SIZE][SIZE=2]   set
[/SIZE][SIZE=2]   {
[/SIZE][SIZE=2]        this[/SIZE][SIZE=2].m_TextEntries = [/SIZE][SIZE=2]value[/SIZE][SIZE=2];
          }
     }
 
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]static [/SIZE][SIZE=2]byte[/SIZE][SIZE=2][] m_Buffer;
 
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]static [/SIZE][SIZE=2]byte[/SIZE][SIZE=2][] m_False;
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]static [/SIZE][SIZE=2]byte[/SIZE][SIZE=2][] m_True;
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]const [/SIZE][SIZE=2]ushort[/SIZE][SIZE=2] BufferSize = 0x2000;
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]int[/SIZE][SIZE=2] m_LayoutLength;
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]int[/SIZE][SIZE=2] m_Switches;
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]int[/SIZE][SIZE=2] m_TextEntries;
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]int[/SIZE][SIZE=2] m_TextLength;
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]int[/SIZE][SIZE=2] m_TextLines;
[/SIZE][SIZE=2]private [/SIZE][SIZE=2]PacketWriter[/SIZE][SIZE=2] m_Layout;
[/SIZE][SIZE=2][COLOR=#0000ff]private [/COLOR][/SIZE][SIZE=2][COLOR=#008080]PacketWriter[/COLOR][/SIZE][SIZE=2] m_Text;
}
[/SIZE]

Okay, it's a search&replace job till now.

Open Gumps/Gump.cs and edit SendTo method:
Code:
[SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][SIZE=2] SendTo( [/SIZE][SIZE=2][COLOR=#008080]NetState[/COLOR][/SIZE][SIZE=2] state )
    {
          state.AddGump( [/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2] );
[/SIZE][SIZE=2][COLOR=#0000ff]    if[/COLOR][/SIZE][SIZE=2] (state.Version != [/SIZE][SIZE=2][COLOR=#0000ff]null[/COLOR][/SIZE][SIZE=2] && state.Version.Major >= 5)
          {
               state.Send(CompileCompressed());
          }
[/SIZE][SIZE=2][COLOR=#0000ff]   else
[/COLOR][/SIZE][SIZE=2]   {
               state.Send(Compile());
          }
     }
[/SIZE]

Now add a new method to the Gump class
Code:
[SIZE=2]private [/SIZE][SIZE=2]Packet[/SIZE][SIZE=2] CompileCompressed()
     {
[/SIZE][SIZE=2]  if[/SIZE][SIZE=2] (m_Packet == [/SIZE][SIZE=2]null[/SIZE][SIZE=2])
          {
[/SIZE][SIZE=2][COLOR=#008080]DisplayCompressedGumpFast[/COLOR][/SIZE][SIZE=2] disp = [/SIZE][SIZE=2][COLOR=#0000ff]new [/COLOR][/SIZE][SIZE=2][COLOR=#008080]DisplayCompressedGumpFast[/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2]);
[/SIZE][SIZE=2][COLOR=#0000ff]       if[/COLOR][/SIZE][SIZE=2] (!m_Dragable)
               {
                    disp.AppendLayout(m_NoMove);
               }
[/SIZE][SIZE=2][COLOR=#0000ff]       if[/COLOR][/SIZE][SIZE=2] (!m_Closable)
               {
                    disp.AppendLayout(m_NoClose);
               }
[/SIZE][SIZE=2][COLOR=#0000ff]       if[/COLOR][/SIZE][SIZE=2] (!m_Disposable)
               {
                    disp.AppendLayout(m_NoDispose);
               }
[/SIZE][SIZE=2][COLOR=#0000ff]       if[/COLOR][/SIZE][SIZE=2] (!m_Resizable)
               {
                    disp.AppendLayout(m_NoResize);
               }
 
[/SIZE][SIZE=2][COLOR=#0000ff]       int[/COLOR][/SIZE][SIZE=2] entries = m_Entries.Count;[/SIZE]
[SIZE=2]
[/SIZE][SIZE=2]       for[/SIZE][SIZE=2] ([/SIZE][SIZE=2]int[/SIZE][SIZE=2] i = 0; i < entries; i++)
               {
[/SIZE][SIZE=2][COLOR=#008080]GumpEntry[/COLOR][/SIZE][SIZE=2] entry = ([/SIZE][SIZE=2][COLOR=#008080]GumpEntry[/COLOR][/SIZE][SIZE=2])[/SIZE][SIZE=2][COLOR=#0000ff]this[/COLOR][/SIZE][SIZE=2].m_Entries[i];
                    disp.AppendLayout(m_BeginLayout);
                    entry.AppendTo(disp);
                    disp.AppendLayout(m_EndLayout);
               }
 
               disp.WriteText(m_Strings);
 
               m_TextEntries = disp.TextEntries;
               m_Switches = disp.Switches;
 
               disp.Output();
 
               m_Packet = disp;
          }
 
[/SIZE][SIZE=2][COLOR=#0000ff]return[/COLOR][/SIZE][SIZE=2] m_Packet;
     }
[/SIZE]

You will probably need to change the type of m_Packet variable
Code:
[SIZE=2][COLOR=#0000ff]private [/COLOR][/SIZE][SIZE=2][COLOR=#008080]Packet[/COLOR][/SIZE][SIZE=2] m_Packet;
[/SIZE]

Open GumpEntry.cs and edit AppendTo method this way
Code:
[SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]abstract [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][SIZE=2] AppendTo([/SIZE][SIZE=2][COLOR=red]IGumpPacket[/COLOR][/SIZE][SIZE=2] disp);
[/SIZE]

ok, now the most annoying part, you have to open all classes which inherts the GumpEntry class and edit the AppendTo method the similar way as above.
(edit)
the AppendTo method of the VirtueGump ( Engines/Virtues/VirtueGump.cs ) needs to be updated either.

example, GumpButton.cs
Code:
[SIZE=2]
[/SIZE][SIZE=2][COLOR=#0000ff]public [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]override [/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]void[/COLOR][/SIZE][SIZE=2] AppendTo([/SIZE][SIZE=2][COLOR=red]IGumpPacket[/COLOR][/SIZE][SIZE=2] disp)
     {
          disp.AppendLayout( m_LayoutName );
          disp.AppendLayout( m_X );
          disp.AppendLayout( m_Y );
          disp.AppendLayout( m_ID1 );
          disp.AppendLayout( m_ID2 );
          disp.AppendLayout( ([/SIZE][SIZE=2][COLOR=#0000ff]int[/COLOR][/SIZE][SIZE=2])m_Type );
          disp.AppendLayout( m_Param );
          disp.AppendLayout( m_ButtonID );
     }
[/SIZE]

This should be all, if I forget to post something, let me know please, also sorry for the code format, I copied the code out of Visual Studio and it auto-formated the code so terribly :eek:
 

redwolf1024

Wanderer
Spaces and small thing forgot...

ya i found a few things prolly becouse of the way it pasted but also small thing ya forgot

newbyte[ >> new byte[
Encoding.ASCII.GetBytes( >> System.Text. Encoding.ASCII.GetBytes(
refint >> ref int

System.Text. had to be add'd becouse the file that comes in the package
isnt using System.Text by default... :p
but looks good and works great... thx
 

brodock

Sorceror
using this mod everybody needs to have ML or any updated client is able to receive compressed gumps?
 

arul

Sorceror
Compressed gumps are sent only to client clients with 5 or higher major version number. To the rest are sent uncompressed gumps as you can see here
Code:
 public void SendTo( NetState state )
    {
    state.AddGump( this );
    if (state.Version != null && state.Version.Major >= 5)
          {
               state.Send(CompileCompressed());
          }
   else
   {
               state.Send(Compile());
          }
     }
 

BagelMan

Wanderer
an issue

There is one issue with your code - you seem to have overlooked the purpose of m_packet. It is there to cache the compiled (and in this case compressed) version of a gump. This is usefull if you have a gump that does not change based on recipient or any frequently changing variables, e.g. a Message of the Day gump. It means you can create a single gump and send it to anyone who needs it, rather than calling the constructor and compile methods every time you want to send it. For example, the code
Code:
Gump Announcement = new AnnouncementGump(message);
foreach(NetState state in NetState.Instances)
	state.Mobile.SendGump(Announcement);
is much more efficient than
Code:
foreach(NetState state in NetState.Instances)
	state.Mobile.SendGump(new AnnouncementGump(message));

Your code would create a bug, however, because it uses m_packet to cache both compressed and uncompressed packets. Therefore, if you send a gump to someone with a new client, it will cache a compressed gump. If you then send it to an old client, it will send the same compressed gump.

To remedy this I would recomend using 2 packet variables -
Code:
		private DisplayGumpFast m_Packet;
		private DisplayCompressedGumpFast m_CompressedPacket;
and using m_CompressedPacket in place of m_Packet in CompileCompressed(). In addition, extend Invalidate() to
Code:
		public void Invalidate()
		{
			if ( m_Packet != null || m_CompressedPacket != null )
			{
				m_Packet = null;
				m_CompressedPacket = null;

				if ( m_Strings.Count > 0 )
					m_Strings.Clear();
			}
		}
This should allow the same gump to be sent to both old and new clients. It may also be a good idea to enable scripts to set the desired level of compression, so that, for example, a very large message of the day gump, or any other large gump with constant appearance, can be compressed once with high compression and sent repeatedly. I'll be working on that later today.
 

BagelMan

Wanderer
I assumed a "necro" of a 7 month old thread would be acceptable on a board that still has posts from february of last year on the first page. And since RunUO 2.0 is still reffered to as "coming soon", I thought this could still be usefull.

edit: And uppon inspection of RunUO 2.0 source, it would appear that they removed packet caching from the gump code altogether. Does anyone know why?
 
Top