Minecraft Forge Handshake

From wiki.vg
Revision as of 14:29, 30 October 2015 by Pokechu22 (talk | contribs) (Provide a list of headings for each individual packet)
Jump to navigation Jump to search
Work in progress!

This page is a work in progress, and may be missing a lot of information or may contain incorrect information. Feel free to edit it to add your own information.

This page will document the changes made in the Minecraft Forge protocol.

Largely based on my own attempts to document the protocol and allow connection to forge servers here.

Changes to Server List Ping

When forge is installed, the Server List Ping changes with an additional modinfo. Example:

{
    "description": "A Minecraft Server",
    "players": {
        "max": 20,
        "online": 0
    },
    "version": {
        "name": "1.8",
        "protocol": 47
    },
    "modinfo": {
        "type": "FML",
        "modList": [
            {
                "modid": "mcp",
                "version": "9.05"
            },
            {
                "modid": "FML",
                "version": "8.0.99.99"
            },
            {
                "modid": "Forge",
                "version": "11.14.3.1512"
            },
            {
                "modid": "rpcraft",
                "version": "Beta 1.3 - 1.8.0"
            }
        ]
    }
}

So, to test whether forge is installed, look for the modinfo key and then a type of FML

The modList contains each installed mod's version and ID.

Warning.png The key modList has a capital 'L', unlike any other key in the ping result!

This is injected in ServerStatusResponse by calling FMLNetworkHandler.enhanceStatusQuery().

Connection to a forge server

Attempting to connect to a forge server without making any changes results in getting immediately disconnected with the message "This server requires FML/Forge to be installed. Contact your server admin for more details.". This message is displayed in FMLCommonHandler and is injected in a modified 0x00 Handshake packet.

If \0FML\0 is added to the end of the server's address (again, in the 0x00 handshake packet), the server will not immediately reject you. However, you still will not complete the connection.

This occurs because Minecraft Forge has an additional set of handshakes (for determining mods and block IDs), that must be completed before the server allows logging in.

Forge handshake

Forge's handshake occurs in the middle of the normal login sequence, right after 0x02 Login Success is received by the client.

In addition to the normal packet debugging for the server, if -Dfml.debugNetworkHandshake=true is passed to the forge server, some more information about the current handshake status will be outputted.

Definitions

Minecraft Forge uses an additional type not covered in data types for some things -- a varshort. This is essentially the same as a regular short, except that if the top byte (what is normally sign) is set, it is followed by an additional byte. This allows forge to retain backwards compatibility but extend the length of certain numbers -- the varshort is only used in places where, in vanilla Minecraft, the sign bit would not have been set. It is implemented in ByteBufUtils.

Discriminator bytes are the way that Minecraft Forge allows sending multiple messages on one plugin channel. They aren't part of the original specification, but a similar concept is used with the MC|AdvCdm plugin channel (used for command blocks). That packet decides whether a block location is being sent or an entity ID (minecart command blocks) is being sent based off of the value of the first byte in the packet.

In the same way, forge uses the first byte of the plugin message to specify which packet to use. It uses FMLIndexedMessageToMessageCodec to automatically switch the value.

Discriminator bytes change depending on the channel: 0 for FML|HS means something different from 0 for FML.

FML|HS Packet structure

FML|HS is used to perform the handshake. Discriminator bytes are found in FMLHandshakeCodec.

ServerHello

ClientHello

ModList

RegistryData

HandshakeAck

HandshakeReset