[STICKY] How to send custom network packets through JavaScripts

Need help with your JScripts? Got questions concerning the DFNs? Come forward, step inside :)
Post Reply
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

How to send custom network packets through JavaScripts

Post by Xuri »

One little known (and used) feature in UOX3 is the ability to create and send (and intercept, though I'll write about that in a different post) network-packets through JavaScripts. In this thread I will post some examples of how this feature can be used, as well as try to explain (based on my own testing and understanding) how the basics work.

First, the syntax for usage of the JS Packet Class:
var myPacket = new Packet;
myPacket.WriteByte( pos, byte );
myPacket.WriteShort( pos, short );
myPacket.WriteLong( pos, long );
myPacket.WriteString( pos, string, len );
socket.Send( myPacket );
myPacket.Free();
Next up, some useful tidbits:
WriteByte = add 1 to pos(ition) value for next entry
WriteShort = add 2 to pos value for next entry
WriteLong = add 4 to pos value for next entry
WriteString = add 8? to pos value for next entry
The first entry (WriteByte) in any packet starts at position 0, and contains the command - or packet ID. The second entry starts at position 1, and for each subsequent entry afterwards you add a value (size of WriteByte/WriteShort/WriteLong/WriteString used in previous entry, see table above) to the position-value of the previous entry to find the new position. So if you have a WriteShort at position 1, the next entry will start at position 1+2. If this entry was a WriteLong, you take the position it started at - in this case 3 (1+2) - and add 4 for a total of 7, which becomes either the position of the next entry - or the total packet length if this was the last entry.

Example:
var myPacket = new Packet;
myPacket.ReserveSize( 7 ); // Last entry was a WriteShort starting at position 5, so add 2 to find total packet size
myPacket.WriteByte( 0, 0x0B ); // Start position 0, packetID
myPacket.WriteLong( 1, pUser.serial ); //First entry was WriteByte, so add 1 to find this position
myPacket.WriteShort( 5, 0x9 ); //Previous entry was WriteLong, so add 4 to previous position to find this position
socket.Send( myPacket );
myPacket.Free();
Also, check this thread for links to various UO Packet Guides with detailed information about what each packet is supposed to contain.
-= Ho Eyo He Hum =-
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

Display damage numbers over character head:
function onUseChecked( pUser, iUsed )
{
    var socket = pUser.socket;
   
    var myPacket = new Packet; // Create new packet stream
    myPacket.ReserveSize( 11 ); // Reserve packet size of 11, which is optimal for packet 0xBF in this case
    myPacket.WriteByte( 0, 0xBF ); // Write packetID (0xBF) at position 0
    myPacket.WriteShort( 1, 11 ); // Write total packet length at position 1 (0+WriteByte, or 0+1)
    myPacket.WriteShort( 3, 0x22 ); // Write subcommand 0x22 (Damage) at position 3 (1+WriteShort, or 0+2)
    myPacket.WriteByte( 5, 0x01 ); // Write unknown 0x01 at position 5 (3+WriteShort, or 3+2)
    myPacket.WriteLong( 6, pUser.serial ); //Write character serial at position 6 (5+WriteByte, or 5+2)
    myPacket.WriteByte( 10, 0x9 ); //Write damage number value at position 10 (6+WriteLong, or 6+4)
    socket.Send( myPacket );
    myPacket.Free();
    return false;
}
Display damage numbers over character head (or item), v2 (different packet):
function onUseChecked( pUser, iUsed )
{
    var socket = pUser.socket;
   
    var myPacket = new Packet; // Create new packet stream
    myPacket.ReserveSize( 7 ); // Reserve packet size of 7, which is optimal for packet 0x0B
    myPacket.WriteByte( 0, 0x0B ); // Write packetID (0x0B) at position 0
    myPacket.WriteLong( 1, pUser.serial ); // Write character serial at position 1 (0+WriteByte, or 0+1)
    myPacket.WriteShort( 5, 0x09 ); // Write damage number at position 5 (1+WriteLong, or 1+4)
    socket.Send( myPacket ); // Send stream to socket
    myPacket.Free(); // Free up stream
    return false;
}
-= Ho Eyo He Hum =-
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

Force-close gump opened by a specific JS:
function onUseChecked( pUser, iUsed )
{
    //Create global variable to store gumpID of all gumps created in this script
    gumpID = iUsed.scripttrigger+0xffff;
   
    //Create a new gump
    myCustomGump( pUser );
   
    //Start timer to destroy gump
    pUser.StartTimer( 2000, 1, true );
    return false;
}

function myCustomGump( pUser )
{
    var socket = pUser.socket;
    var skillGump = new Gump;
    skillGump.AddPage (1);
    skillGump.AddBackground(0, 0, 300, 300, 0xA3C);
    skillGump.AddButton( 270, 5, 0xa50, 1, 0, 1); //Close gump
    skillGump.AddButton( 200, 40, 2469, 1, 0, 32 ); //Next page
    skillGump.Send( socket );
    skillGump.Free();
}

function onTimer( timerObj, timerID )
{
    if( timerID == 1 )
    {
        var socket = timerObj.socket;
        var myPacket = new Packet;
        myPacket.ReserveSize( 13 );
        myPacket.WriteByte( 0, 0xBF ); //Command: Packet 0xBF - General Information Packet
        myPacket.WriteShort( 1, 13 ); // Packet length
        myPacket.WriteShort( 3, 0x04 ); //Subcommand 0x04 - Close Generic Gump
        myPacket.WriteLong( 5, gumpID ); //dialogID - which gump to destroy
        myPacket.WriteLong( 9, 0 ); //buttonID // response buttonID for packet 0xB1
        socket.Send( myPacket );
        myPacket.Free();   
    }
}
-= Ho Eyo He Hum =-
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

Send season-change to client:
function onUseChecked( pUser, iUsed )
{
    var socket = pUser.socket;
   
    // Notes
    // Season flags:
    // 0x00 = Spring
    // 0x01 = Summer
    // 0x02 = Fall
    // 0x03 = Winter
    // 0x04 = Desolation
   
    var myPacket = new Packet; // Create new packet stream
    myPacket.ReserveSize( 3 ); // Reserve packet size of 3, which is optimal for packet 0xBC in this case
    myPacket.WriteByte( 0, 0xBC ); // Write packetID (0xBC) at position 0
    myPacket.WriteByte( 1, 0x02 ); // Write Season flag at position 1 (0+WriteByte, or 0+1)
    myPacket.WriteByte( 2, 0x01 ); // Write PlayMusic (0x00 = no, 0x01 = yes - doesn't seem to work) at position 2 (1+WriteByte, or 0+1)
    socket.Send( myPacket );
    myPacket.Free();
    return false;
}
-= Ho Eyo He Hum =-
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

Force player to move at a specific speed
var toSend = new Packet;
toSend.ReserveSize( 5 )
toSend.WriteByte( 0, 0xbf ) // General Information Packet
toSend.WriteShort( 1, 0x06 ) // Packet length
toSend.WriteShort( 3, 0x26 ) // SubCmd - control movement mode/speed
toSend.WriteByte( 5, 0x1 ) // Movement mode- 0x0 = normal, 0x1 = fast (mounted run), 0x2 = slow (walk only), 0x3 = hybrid (mounted walk?), 0x4 = frozen, unable to move
pSock.Send( toSend );
toSend.Free();
-= Ho Eyo He Hum =-
Post Reply