essential-re/packets.md

4.0 KiB

Essential Packets

In Essential, packets are sent over WebSockets to wss://connect.essential.gg/v1. Both the server and client share the same simple structure:

  1. A single byte, representing the packet type sent as an integer.

The type ID is a number that is unique to the client and server and established by the sending party.

For example, if a client wants to send a ClientConnectionLoginPacket, they will have to send to the server a packet of ID 0, establishing that ClientConnectionLoginPacket is ID 1 (which looks something like {"a":"connection.ClientConnectionLoginPacket","b":1}), and then send a packet with the newly established ID 1. This packet will then be understood by the server as a ClientConnectionLoginPacket consequentially, and will not need to be redefined.

Both parties establish that a packet of ID 0 is a RegisterPacketTypeId packet upon connection.

  1. A single byte, representing the length of the packet UUID this packet is in reply to. Set to NUL and ignore next spot if this packet is not in reply to anything.
  2. The UUIDv4 of the packet this packet is in reply to. Usually either 0 or 36 bytes long, seperated by dashes.

It's unknown to me how the UUID of a packet is obtained. This UUID is not sent by the sending party, but it wasn't relevant to what I was doing so I discarded it.

  1. The length of the payload.
  2. The JSON-encoded payload.

The payload will be encoded using a custom GSON config which encodes simple JSON keys into single characters. For instance, a payload of {"className":"connection.ClientConnectionLoginPacket","packetId":1} will be converted into {"a":"connection.ClientConnectionLoginPacket","b":1}. This seems to be a networking optimization and obfuscation tactic. The keys will always stay consistent and seem to be based on definition order; if a constructor of a packet lists the properties id and type, then you can always know that a will mean id and b will mean type. It seems that both parties always maintain packet definitions for both sides to decode recieved packets.

Packets

Here are some note-worthy packets I've discovered:

connection.RegisterPacketTypeId

This is a packet that's always registered internally as 0 for both sides, which lets a party define the ID of a packet.

connection.ClientConnectionLoginPacket

This packet is sent by the client and is used for authentication. A username and sharedSecret are sent which are then processed by the server to authenticate the user. Afterwards, the server will consider the user authenticated, and proceed to send them various packets. All packets sent upon authentication from now on will be marked with "Sent on authentication".

response.ResponseActionPacket

This packet contains a single boolean and is used in responses to other packets to indicate whether something succeeded or failed.

cosmetic.ServerCosmeticsPopulatePacket

Sent on authentication

Server-exclusive

This packet sends every cosmetic registered on the server, along with the necessary assets and metadata. This is the only packet where information about a cosmetic is sent.

profile.trustedhosts.ServerProfileTrustedHostsPopulatePacket

Sent on authentication

Server-exclusive

This packet seems to provide the client with "trusted hosts". As of writing, this is what this packet looks like:

{
  "a": [
    {
      "a": "60cb24a50dc956941869312d",
      "b": "Discord",
      "c": [ "cdn.discordapp.com", "media.discordapp.net" ]
    },
    {
      "a": "60cb24a50dc956941869312e",
      "b": "BadLion",
      "c": [ "i.badlion.net" ]
    },
    {
      "a": "60cb24a50dc956941869312f",
      "b": "Imgur",
      "c": [ "i.imgur.com", "imgur.com" ]
    },
    {
      "a": "60cb24a50dc9569418693130",
      "b": "Reddit",
      "c": [ "i.redd.it" ]
    },
    {
      a: "60cb24a50dc9569418693131",
      b: "Twitter",
      c: [ "pbs.twimg.com" ]
    }
  ]
}

It is unknown what purpose these links serve. It may be a list of links that you are allowed to embed in private messages.