|
||
|
|||||||
| Network Modifications This forum is for modifications to the networking code of RunUO |
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 (permalink) |
|
Forum Expert
|
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 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);
}
}
To do that, open Packets.cs and put in this interface. Code:
public interface IGumpPacket
{
void AppendLayout (bool val);
void AppendLayout (int val);
void AppendLayout (byte[] buffer);
void AppendLayoutNS (int val);
int TextEntries { get; set; }
int Switches { get; set; }
}
Code:
public sealed class DisplayGumpFast : Packet, IGumpPacket
Now the time has come to assembly all new packet, let's call it DisplayCompressedGumpFast. Code:
public sealed class DisplayCompressedGumpFast : Packet, IGumpPacket
{
static DisplayCompressedGumpFast()
{
m_True = Gump.StringToBuffer(" 1");
m_False = Gump.StringToBuffer(" 0");
m_Buffer = new byte[0x400];
m_Buffer[0] = 0x20;
}
public DisplayCompressedGumpFast(Gump g)
: base(0xDD)
{
m_Layout = newPacketWriter();
m_Text = newPacketWriter();
EnsureCapacity(0x400);
m_Stream.Write(g.Serial);
m_Stream.Write(g.TypeID);
m_Stream.Write(g.X);
m_Stream.Write(g.Y);
}
public void AppendLayout(bool val)
{
AppendLayout(val ? m_True : m_False);
}
public void AppendLayout(int val)
{
string text = val.ToString();
int num = System.Text.Encoding.ASCII.GetBytes(text, 0, text.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, num);
m_LayoutLength += num;
}
public void AppendLayout(byte[] buffer)
{
int num = buffer.Length;
m_Layout.Write(buffer, 0, num);
m_LayoutLength += num;
}
public void AppendLayoutNS(int val)
{
string text = val.ToString();
int num = System.Text.Encoding.ASCII.GetBytes(text, 0, text.Length, m_Buffer, 1);
m_Layout.Write(m_Buffer, 1, num);
m_LayoutLength += num;
}
public void Output()
{
byte[] buffer = new byte[BufferSize];
int length = buffer.Length;
if (
ZLib.compress2(
buffer,
ref length,
m_Layout.ToArray(),
m_LayoutLength,
ZLibCompressionLevel.Z_BEST_SPEED) == ZLibError.Z_OK
)
{
WriteBuffer(
buffer,
ref length,
m_LayoutLength
);
if (
ZLib.compress2(
buffer,
ref length,
m_Text.ToArray(),
m_TextLength,
ZLibCompressionLevel.Z_BEST_SPEED) == ZLibError.Z_OK
)
{
m_Stream.Write(m_TextLines);
WriteBuffer(
buffer,
ref length,
m_TextLength
);
}
}
}
public void WriteBuffer(byte[] buffer, refint length, int contentLength)
{
m_Stream.Write(length + 4);
m_Stream.Write(contentLength);
m_Stream.Write(buffer, 0, length);
length = buffer.Length;
}
public void WriteText(ArrayList text)
{
m_TextLines = text.Count;
for (int i = 0; i < text.Count; ++i)
{
string v = (string)text[i];
if (v == null)
v = "";
int length = v.Length;
m_TextLength += length * 2;
m_Text.Write((ushort)length);
m_Text.WriteBigUniFixed(v, length);
}
m_TextLength += text.Count * 2;
}
public int Switches
{
get
{
return this.m_Switches;
}
set
{
this.m_Switches = value;
}
}
public int TextEntries
{
get
{
return this.m_TextEntries;
}
set
{
this.m_TextEntries = value;
}
}
private static byte[] m_Buffer;
private static byte[] m_False;
private static byte[] m_True;
private const ushort BufferSize = 0x2000;
private int m_LayoutLength;
private int m_Switches;
private int m_TextEntries;
private int m_TextLength;
private int m_TextLines;
private PacketWriter m_Layout;
private PacketWriter m_Text;
}
Open Gumps/Gump.cs and edit SendTo method: Code:
public void SendTo( NetState state )
{
state.AddGump( this );
if (state.Version != null && state.Version.Major >= 5)
{
state.Send(CompileCompressed());
}
else
{
state.Send(Compile());
}
}
Code:
private Packet CompileCompressed()
{
if (m_Packet == null)
{
DisplayCompressedGumpFast disp = new DisplayCompressedGumpFast(this);
if (!m_Dragable)
{
disp.AppendLayout(m_NoMove);
}
if (!m_Closable)
{
disp.AppendLayout(m_NoClose);
}
if (!m_Disposable)
{
disp.AppendLayout(m_NoDispose);
}
if (!m_Resizable)
{
disp.AppendLayout(m_NoResize);
}
int entries = m_Entries.Count;
for (int i = 0; i < entries; i++)
{
GumpEntry entry = (GumpEntry)this.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;
}
return m_Packet;
}
Code:
private Packet m_Packet; Code:
public abstract void AppendTo(IGumpPacket disp); (edit) the AppendTo method of the VirtueGump ( Engines/Virtues/VirtueGump.cs ) needs to be updated either. example, GumpButton.cs Code:
public override void AppendTo(IGumpPacket disp)
{
disp.AppendLayout( m_LayoutName );
disp.AppendLayout( m_X );
disp.AppendLayout( m_Y );
disp.AppendLayout( m_ID1 );
disp.AppendLayout( m_ID2 );
disp.AppendLayout( (int)m_Type );
disp.AppendLayout( m_Param );
disp.AppendLayout( m_ButtonID );
}
![]()
__________________
Angels are falling the very last time, down they're burning in hate and decline, unfaithful and violent we're breaking the spell, we're god, we're scissor, in heaven and hell! Last edited by arul; 03-03-2006 at 08:19 AM. |
|
|
|
|
|
#2 (permalink) |
|
Join Date: Dec 2003
Posts: 11
|
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 |
|
|
|
|
|
#3 (permalink) |
|
Forum Expert
|
Thanks!
The vBulletins text parsing engine do get me down ![]()
__________________
Angels are falling the very last time, down they're burning in hate and decline, unfaithful and violent we're breaking the spell, we're god, we're scissor, in heaven and hell! |
|
|
|
|
|
#5 (permalink) |
|
Forum Expert
|
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());
}
}
__________________
Angels are falling the very last time, down they're burning in hate and decline, unfaithful and violent we're breaking the spell, we're god, we're scissor, in heaven and hell! |
|
|
|
|
|
#7 (permalink) |
|
Forum Newbie
Join Date: Feb 2006
Posts: 6
|
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); Code:
foreach(NetState state in NetState.Instances) state.Mobile.SendGump(new AnnouncementGump(message)); To remedy this I would recomend using 2 packet variables - Code:
private DisplayGumpFast m_Packet; private DisplayCompressedGumpFast m_CompressedPacket; 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();
}
}
|
|
|
|
|
|
#8 (permalink) |
|
ConnectUO Creator
Join Date: Jan 2004
Age: 28
Posts: 4,892
|
Hmm, necro....anywho i beleve 2.0 already has support for compressed gumps.
__________________
Jeff Boulanger ConnectUO - Core Developer Want to help make ConnectUO better? Click here to submit your ideas/requests Use your talent to compete against other community members in RunUO hosted coding competitions If you know XNA (even if its just a little) or are a good artist(2d or 3d) and are interested in making games for a hobby send me a pm or drop by #xna in irc.runuo.com. I'm looking to put together a small game development team. Please do not pm me for support. If you are having issues please post in the appropriate forum. Thanks for your continued support of both ConnectUO and RunUO |
|
|
|
|
|
#9 (permalink) |
|
Forum Newbie
Join Date: Feb 2006
Posts: 6
|
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? Last edited by BagelMan; 10-12-2006 at 12:45 PM. |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|