# Networking rework ## Vanilla packet flow ### Status ```sequence Client->Server: ClientIntentionPacket(protocolVersion, hostName, port, intention = STATUS) Note over Client,Server: Start Status phase Client->Server: ServerboundStatusRequestPacket Server->Client: ClientboundStatusResponsePacket(status) ``` ### Ping ```sequence Client->Server: ClientIntentionPacket(protocolVersion, hostName, port, intention = STATUS) Note over Client,Server: Start Status phase Client->Server: ServerboundPingRequestPacket(time) Server->Client: ClientboundPongResponsePacket(time) ``` ### Login ```sequence Client->Server: ClientIntentionPacket(protocolVersion, hostName, port, intention = LOGIN) Note over Client,Server: Start Login phase Client->Server: ServerboundHelloPacket(name, profileId) Note over Server: Set state to KEY Server->Client: ClientboundHelloPacket(serverId, publicKey, challenge) Note over Client: Set state to AUTHORIZING Note over Client: Set state to ENCRYPTING Client->Server: ServerboundKeyPacket(keybytes, encryptedChallenge) Note over Server: Set state to AUTHENTICATING Note over Server: Set state to VERIFYING Server->Client: ClientboundLoginCompressionPacket(compressionThreshold) Note over Server: Set state to WAITING_FOR_DUPE_DISCONNECT Note over Server: Set state to PROTOCOL_SWITCHING Server->Client: ClientboundGameProfilePacket(gameProfile) Note over Client: Set state to JOINING Client->Server: ServerboundLoginAcknowledgedPacket Note over Server: Set state to ACCEPTED Note over Client,Server: Start Configuration phase Client->Server: ServerboundCustomPayloadPacket(minecraft:brand) Client->Server: ServerboundClientInformationPacket(information) Server->Client: ClientboundCustomPayloadPacket(minecraft:brand) Server->Client: ClientboundUpdateEnabledFeaturesPacket(features) Server->Client: ClientboundRegistryDataPacket(registries) Server->Client: ClientboundUpdateTagsPacket(tags) Server-->Client: ClientboundResourcePackPacket(url, hash, required, prompt) Server->Client: ClientboundFinishConfigurationPacket Note over Client,Server: Start Play phase ``` ## New implementation - Underlying system relies solely on `CustomQueryPacket` and `CustomPayloadPacket` - If a mod registers at least one of these, and does not mark it as optional, then the server is considered not compatible with vanilla - An event is fired from the mod bus to collect a mods packets and their listeners, it is up to a mod to ensure that these are compatible with each other. ### Server status pinging - ServerStatus now holds only an indicator if the server the client is requesting status of is modded or not. - A vanilla client ignores this information because it is encoded in a not read part of the JSON structure - A modded client can then send additional packets to the modded server, requesting additional information, like the mods list, or the custom packet list. #### Modded Client <-> Modded Server connection ```sequence Client->Server: ServerboundStatusRequestPacket Server->Client: ClientboundStatusResponsePacket(serverStatus.isModdedConnection = true) Client->Server: ServerboundCustomPayloadPacket(minecraft:register, customPacketIds) Server->Client: ClientboundCustomPayloadPacket(minecraft:network, acceptedPacketsConfigPhase, acceptedPacketsPlayPhase) ``` The connection is basically upgraded from one that does not support custom packet payloads to one that does support them, because both sides know that they are modded. #### Vanilla Client <-> Modded Server connection ```sequence Client->Server: ServerboundStatusRequestPacket Server->Client: ClientboundStatusResponsePacket(serverStatus.isModdedConnection = true) ``` The vanilla client ignores the additional field on the JSON that is send for the server status, and the server notices that no additional packets get returned and gets an indication that the client is unsupported. #### Modded Client <-> Vanilla Server connection ```sequence Client->Server: ServerboundStatusRequestPacket Server->Client: ClientboundStatusResponsePacket ``` The client detects that the isModdedConnection field is missing, and does not try to upgrade the connection but will locally validate that his network setup works with a vanilla connection. ### Configuration phase - An event is fired during the configuration phase, that allows mods to send additional packets to sync custom configuration data - This is implemented via the custom task queue that exists in vanilla ```sequence Client->Server: ClientIntentionPacket(protocolVersion, hostName, port, intention = LOGIN) Note over Client,Server: Start Login phase Client->Server: ServerboundHelloPacket(name, profileId) Note over Server: Set state to KEY Server->Client: ClientboundHelloPacket(serverId, publicKey, challenge) Note over Client: Set state to AUTHORIZING Note over Client: Set state to ENCRYPTING Client->Server: ServerboundKeyPacket(keybytes, encryptedChallenge) Note over Server: Set state to AUTHENTICATING Note over Server: Set state to VERIFYING Server->Client: ClientboundLoginCompressionPacket(compressionThreshold) Note over Server: Set state to WAITING_FOR_DUPE_DISCONNECT Note over Server: Set state to PROTOCOL_SWITCHING Server->Client: ClientboundGameProfilePacket(gameProfile) Note over Client: Set state to JOINING Client->Server: ServerboundLoginAcknowledgedPacket Note over Server: Set state to ACCEPTED Note over Client,Server: Start Configuration phase Client->Server: ServerboundCustomPayloadPacket(minecraft:brand) Client->Server: ServerboundClientInformationPacket(information) Note over Client,Server: Start of Configuration Phase execution Server->Client: ClientboundCustomPayloadPacket(minecraft:register) Server->Client: ClientboundPingPacket(0) Client->Server: ServerboundCustomPayloadPacket(minecraft:register, customPacketIds) Client->Server: ServerboundPongPacket(0) Server->Client: ClientboundCustomPayloadPacket(minecraft:network, acceptedPacketsConfigPhase, acceptedPacketsPlayPhase) Note over Server: Actual start of configuration task processing Server->Client: ClientboundCustomPayloadPacket(minecraft:brand) Server->Client: ClientboundUpdateEnabledFeaturesPacket(features) Server->Client: ClientboundRegistryDataPacket(registries) Server->Client: ClientboundUpdateTagsPacket(tags) Server-->Client: ClientboundResourcePackPacket(url, hash, required, prompt) Note over Client,Server: Mod configuration tasks here Server->Client: ClientboundFinishConfigurationPacket Note over Client,Server: Start Play phase ```