Go Back   RunUO - Ultima Online Emulation > RunUO > Core Modifications > Network Modifications

Network Modifications This forum is for modifications to the networking code of RunUO

Reply
 
Thread Tools Display Modes
Old 03-13-2007, 06:50 PM   #1 (permalink)
Newbie
 
Join Date: Sep 2006
Age: 20
Posts: 11
Smile Making a packethandler for a variable length packet?

Ok, so I'm making a WoW emu using a stripped down version of the RunUO core. So far, everything's fine, however I need to figure out how on earth to read variable length packets?

This is the description for the packet I'm trying to receive:

Code:
'Client Side Description: 

Data Type  Field Name  Details  
uint8  OpCode  The Opcode that identifies the current packet. (CMD_AUTH_LOGON_CHALLENGE)  
uint8  Error  Ignored. (0x02)  
uint16  Size  Size of the rest of the packet excluding previous fields.  
uint8[4]  GameName  4 bytes containing the name of the game. ("WoW\0")  
uint8[3]  GameVersion  3 bytes containing the version of the game. (0x01,0x0C,0x00)  
uint16  GameBuild  Build Number of the Client  
uint8[4]  Platform  Client Platform Name ("x86\0")  
uint8[4]  OperatingSystem  Client OS Name ("Win\0")  
uint8[4]  Area  Client Area/Localization ("enUS")  
uint32  TimeZone  Client Time Zone  
uint8[4]  ClientIP  Client IP (got locally)  
uint8  AccountNameLen  Length of Account name. (\0) terminator excluded.  
uint8[x]  AccountName  Account name. (\0) terminator excluded.'
Now, my brother and I (my mathskills sucks -_-) have figured out that this packet should be roughly (^^) 35 bytes in size if it HAD NOT BEEN FOR the last packet "parameter" that takes is of variable length. My problem is that when registering a packet handler, I have to specify it's length, otherwise the packet won't get read properly. So, how do I modify the code for reading a packet (I'm assuming this is located in PacketHandler.cs?) so that I can register a packethandler for a variable length packet OR inspect the packet when it is being read so that I can determine the size of the AccountName 'parameter' by looking at AccountNameLen?

I don't know if it's of any importance, but here is my PacketHandlers.cs file so far:

Code:
using System;
using System.Collections.Generic;
using System.Text;

namespace LoginServer.Network
{
    class PacketHandlers
    {
        private static PacketHandler[] m_Handlers;

        static PacketHandlers()
        {
            m_Handlers = new PacketHandler[0x100];

            //This packet seems to take 35 bytes + Accountname,
            //which is of variable length. I.E I HAVE A PROBLEM! o.O
            Register(0x00, 35, false, new OnPacketReceive(AuthLogon));
        }

        public static PacketHandler GetHandler(int PacketID)
        {
            return m_Handlers[PacketID];
        }

        public static void Register(int packetID, int length, bool ingame, OnPacketReceive onReceive)
        {
            m_Handlers[packetID] = new PacketHandler(packetID, length, ingame, onReceive);
        }

        public static void AuthLogon(NetState state, PacketReader pvSrc)
        {

        }
    }
}
Thanks in advance for any replies!

Edit: D'oh! The Packethandler events are where you actually read the packet data - the size of the packet registered for a particular Packethandler doesn't actually matter when you receive the packet, because the Bytequeue class seems to take care of aqcuiring the full packet anyway, as seen in Messagepump.cs here:

Code:
                    Console.WriteLine("Length: {0}, PacketLength: {1}", length, packetLength);
                    if (length >= packetLength)
                    {
                        byte[] packetBuffer;

                        if (BufferSize >= packetLength)
                            packetBuffer = m_Buffers.AcquireBuffer();
                        else
                            packetBuffer = new byte[packetLength];

                        packetLength = buffer.Dequeue(packetBuffer, 0, packetLength);

                        PacketReader r = new PacketReader(packetBuffer, packetLength, handler.Length != 0);

                        handler.OnReceive(ns, r);
                        length = buffer.Length;

                        if (BufferSize >= packetLength)
                            m_Buffers.ReleaseBuffer(packetBuffer);
                    }
If I am at a loss in my assumption here, please correct me.

BTW: Kudos to the devs for making the best core I have ever seen so far. The quality of it never ceases to amaze me, even when I am at a loss in times like these!

Last edited by Afr0man; 03-13-2007 at 07:05 PM.
Afr0man is offline   Reply With Quote
Old 04-23-2007, 03:33 AM   #2 (permalink)
Forum Newbie
 
Join Date: Jun 2006
Posts: 93
Default

You should set length to 0 for custom length packets.
Code:
Register( 0x12,   0,  true, new OnPacketReceive( TextCommand ) );
And here is the packet itself:
Code:
		public static void TextCommand( NetState state, PacketReader pvSrc )
		{
			int type = pvSrc.ReadByte();
			string command = pvSrc.ReadString();

			Mobile m = state.Mobile;

			switch ( type )
			{
				case 0x00: // Go
				{
					if ( VerifyGC( state ) )
					{
						try
						{
							string[] split = command.Split( ' ' );

							int x = Utility.ToInt32( split[0] );
							int y = Utility.ToInt32( split[1] );

							int z;

							if ( split.Length >= 3 )
								z = Utility.ToInt32( split[2] );
							else if ( m.Map != null )
								z = m.Map.GetAverageZ( x, y );
							else
								z = 0;

							m.Location = new Point3D( x, y, z );
						}
						catch
						{
						}
					}

					break;
				}
				case 0xC7: // Animate
				{
					EventSink.InvokeAnimateRequest( new AnimateRequestEventArgs( m, command ) );

					break;
				}
				case 0x24: // Use skill
				{
					int skillIndex;

					try{ skillIndex = Convert.ToInt32( command.Split( ' ' )[0] ); }
					catch{ break; }

					Skills.UseSkill( m, skillIndex );

					break;
				}
				case 0x43: // Open spellbook
				{
					int booktype;

					try{ booktype = Convert.ToInt32( command ); }
					catch{ booktype = 1; }

					EventSink.InvokeOpenSpellbookRequest( new OpenSpellbookRequestEventArgs( m, booktype ) );

					break;
				}
				case 0x27: // Cast spell from book
				{
					string[] split = command.Split( ' ' );

					if ( split.Length > 0 )
					{
						int spellID = Utility.ToInt32( split[0] ) - 1;
						int serial = split.Length > 1 ? Utility.ToInt32( split[1] ) : -1;

						EventSink.InvokeCastSpellRequest( new CastSpellRequestEventArgs( m, spellID, World.FindItem( serial ) ) );
					}

					break;
				}
				case 0x58: // Open door
				{
					EventSink.InvokeOpenDoorMacroUsed( new OpenDoorMacroEventArgs( m ) );

					break;
				}
				case 0x56: // Cast spell from macro
				{
					int spellID = Utility.ToInt32( command ) - 1;

					EventSink.InvokeCastSpellRequest( new CastSpellRequestEventArgs( m, spellID, null ) );

					break;
				}
				case 0xF4: // Invoke virtues from macro
				{
					int virtueID = Utility.ToInt32( command ) - 1;

					EventSink.InvokeVirtueMacroRequest( new VirtueMacroRequestEventArgs( m, virtueID ) );

					break;
				}
				default:
				{
					Console.WriteLine( "Client: {0}: Unknown text-command type 0x{1:X2}: {2}", state, type, command );
					break;
				}
			}
		}
As you can see, if you set length to 0, RunUO just reads the first byte (with packet number), and then starts your function, where you should read all the variable packet manually, and do whatever you wish.
Beyonder is offline   Reply With Quote
Reply

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off



Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0 RC5