packet - Windower/packages GitHub Wiki

This library facilitates dealing with packets.

local packet = require('packet')

Dependency Required

To use this library, you must include packet in the manifest.xml file for your package:

<dependency>packet</dependency>

Tables

The packet table can be nested to narrow down specific packets.

packet -- Represents all packets
packet.incoming -- Represents incoming packets
packet.outgoing -- Represents outgoing packets
packet.incoming[0x044] -- Represents packets with ID 0x044 (pet info)
packet.incoming[0x044][0x12] -- Represents packets with ID 0x044 for job 0x12 (pet info for PUP)

Each of those resulting tables provides the following entries:

"Matching packets" here mean any packet of the narrowed down category this function is applied to, depending on how far the table was nested:

 -- Will register a function to execute on every packet
packet:register(fn)
 -- Will register a function to execute on every incoming packet
packet.incoming:register(fn)
 -- Will register a function to execute on every incoming packet with ID 0x063
packet.incoming[0x063]:register(fn)
 -- Will register a function to execute on every incoming packet with ID 0x063 of type 0x09
packet.incoming[0x063][0x09]:register(fn)

In addition to that, if the nesting is deep enough to fully identify a packet, the following entries become available:

These will error since the nesting is not deep enough to fully identify a packet:

packet:inject(p)
packet.outgoing:inject(p)
-- There exist multiple types of this packet, so this is not nested deep enough
packet.outgoing[0x04E]:inject(p)

These will work, since they are enough to fully identify a packet:

packet.outgoing[0x04E][0x04]:inject(p)
-- Unlike 0x04E, 0x017 does not have multiple types, so this is nested deep enough
packet.incoming[0x017]:inject(p)

Whether or not a packet is nested deep enough depends on their definition in the types.lua file. For most packets the direction and ID is all that is required, but if a packet is defined with the multiple function it can be further specified by whatever name is given in the key field.

As an example, incoming packet 0x056 contains quest and mission information for a player. The structure in the file is defined as follows:

types.incoming[0x056] = multiple({
    base = struct({
        type            = {0x20, int16},
    }),
    key = 'type',
    lookups = {
        [0x0080] = --[[ ... ]],
        [0x00C0] = --[[ ... ]],
        --[[ ... ]]
    },
})

This means the different types of that packet share the same int16 (number) that indicates their type, but can otherwise be structured differently. So to get the actual packet you need to provide the correct type. For completed ToAU quests and assaults this ID would be 0x00C0, so if an addon wanted to get that data (and a proper library was not available to provide it) the code could look like this:

local check_assault = function(assault_id)
    local latest = packet.incoming[0x056][0x00C0]:last()
    if latest.completed_assaults[assault_id] then
        print('Assault completed!')
    else
        print('Assault missing.')
    end
end


packet:register

Registers a function to execute for a packet of the specified category.

Definition

function packet:register(fn : function)

Parameters

fn function

The function to execute. Will be called with the packet_object parsed according to the types.lua file as the first argument and packet_info metadata as the second argument.

Return

This function does not return any values.



packet:unregister

Unregisters a function for packets of the specified category.

Definition

function packet:unregister(fn : function)

Parameters

fn function

The function to unregister.

Return

This function does not return any values.



packet:register_init

Registers a table of functions to execute for packets of the specified categories. It also retrieves the last packet of each specified category and calls the respective function, in the order the packets were received in.

Definition

function packet:register_init(fn_table)

Parameters

fn_table table

A mapping of packet IDs (and further specifiers) to functions. The functions are registered in the same way as individual registration via packet:register and get passed the same arguments.

As an example, if we wanted to register functions to execute on login and logout we could use the following:

packet.incoming:register_init({
    [{0x00A}] = function(p) -- 0x00A is sent on every zone in, needs further logic to disambiguate a fresh login
        --[[ ... ]]
    end,
    [{0x00B, 0x01}] = function(p) -- 0x00B is sent on every zone out, but sub-type 0x01 is only used on full logout
        --[[ ... ]]
    end,
})

This code is roughly equivalent to this:

packet.incoming[0x00A]:register(--[[ ... ]])
packet.incoming[0x00B][0x01]:register(--[[ ... ]])

The difference is that this way would not invoke the given functions on the last received packets, in the received order.

Return

This function does not return any values.



packet:inject

Injects a packet object of the specified category.

Definition

function packet:inject(data : table)

Parameters

data table

A table with values to populate the packet with.

Return

This function does not return any values.



packet:last

Retrieves the last packet object and its metadata of the category.

Definition

function packet:last() : packet_object, packet_info

Parameters

This function does not take any parameters.

Return

packet packet_object

The packet object, parsed according to the types.lua file.

info packet_info

The packet metadata.

⚠️ **GitHub.com Fallback** ⚠️