## Successfull full packet flow This describes the flow of packets and payloads between a client a server that completely implement the protocol. Examples would be NeoForge and Fabric. ```plantuml @startuml participant "Modded Client" as Client participant "Modded Server" as Server group Phase: configuration note over Server: The server sends an empty register packet. Server -> Client: minecraft:register Server -> Client: ping note over Client: The servers initial register packet is ignored. note over Client: The client answers with all known payload ids. Client -> Server: minecraft:register note over Client: The versions packet contains a string version per payload id. Client -> Server: c:version note over Client: The requirements packet contains a boolean required indicator per payload id. Client -> Server: c:required Client -> Server: pong note over Server: The server processes the clients payload ids. note over Server: The server answers with all accepted payloads. Server -> Client: minecraft:register note over Server: The server answers with a string version per payload id. Server -> Client: c:version note over Server: The server answers with a boolean required indicator per payload id. Server -> Client: c:required loop Configuration tasks run Server -> Client: mod_id:do_something Client -> Server: mod_id:did_something end note over Server: The server sends an unregister payload with all known payload ids Server -> Client: minecraft:unregister end group Phase: Play note over Server: The server sends an empty register packet. Server -> Client: minecraft:register Server -> Client: ping note over Client: The servers initial register packet is ignored. note over Client: The client answers with all known payload ids. Client -> Server: minecraft:register note over Client: The versions packet contains a string version per payload id. Client -> Server: c:version note over Client: The requirements packet contains a boolean required indicator per payload id. Client -> Server: c:required Client -> Server: pong note over Server: The server processes the clients payload ids. note over Server: The server answers with all accepted payloads. Server -> Client: minecraft:register note over Server: The server answers with a string version per payload id. Server -> Client: c:version note over Server: The server answers with a boolean required indicator per payload id. Server -> Client: c:required end @enduml ``` ## Sucessfull minimal packet flow In the case a server or proxy only speaks a "legacy"-flow then the client will not receive the "c" namespaced payloads, and the minecraft:register payloads will need to be differently processed. Given that we now do not have a way to differentiate between the phases, from a server side perspective (the old protocol simply did not allow it), we will need to assume that all known payloads are common. This means that the client will need to for example assume that the initial minecraft:register from the server are the payload ids the server supports: ```plantuml @startuml participant "Modded Client" as Client participant "Modded Server" as Server group Phase: configuration note over Server: The server sends a filled minecraft:register payload Server -> Client: minecraft:register Server -> Client: ping note over Client: The client answers with the payload ids it knows and that are a subset of the servers payload ids Client -> Server: minecraft:register Client -> Server: pong loop Configuration tasks run Server -> Client: mod_id:do_something Client -> Server: mod_id:did_something end end group Phase: Play Server -> Client: Normal start of play phase end @enduml ``` This variant of the protocol has significant brawbacks, there is for example no version information available and the sides do not know whether or not a payload is optional. However, it is compatible with even the oldest known protocol variations. ## Negotiation failure full packet flow Given that there might be situations where the client and the server can not agree to a common set of payloads and their versions, the case will arrise that the connection can not be setup based on this situation. ### Configuration phase If this happens in the configuration phase negotiation the packet flow will look as follows: ```plantuml @startuml participant "Modded Client" as Client participant "Modded Server" as Server group Phase: configuration note over Server: The server sends an empty register packet. Server -> Client: minecraft:register Server -> Client: ping note over Client: The servers initial register packet is ignored. note over Client: The client answers with all known payload ids. Client -> Server: minecraft:register note over Client: The versions packet contains a string version per payload id. Client -> Server: c:version note over Client: The requirements packet contains a boolean required indicator per payload id. Client -> Server: c:required Client -> Server: pong note over Server: The server processes the clients payload ids, and determines an incompatible setup Server -> Client: c:failure Server -> Client: disconnect end @enduml ``` There is another alternative route: If the server disregards the clients wishes when it comes to the versioning and compatibility of the channels, then the client is free to disconnect as soon as they realise it. For example when the initial information about the negotiated channels arrives: ```plantuml @startuml participant "Modded Client" as Client participant "Modded Server" as Server group Phase: configuration note over Server: The server sends an empty register packet. Server -> Client: minecraft:register Server -> Client: ping note over Client: The servers initial register packet is ignored. note over Client: The client answers with all known payload ids. Client -> Server: minecraft:register note over Client: The versions packet contains a string version per payload id. Client -> Server: c:version note over Client: The requirements packet contains a boolean required indicator per payload id. Client -> Server: c:required Client -> Server: pong note over Server: The server processes the clients payload ids. note over Server: The server answers with all accepted payloads. Server -> Client: minecraft:register note over Server: The server answers with a string version per payload id. Server -> Client: c:version note over Server: The server answers with a boolean required indicator per payload id. Server -> Client: c:required note over Client: The client realised that the agreed upon payloads are incompatible with its setup,\n and that the server violated the protocol. Client -> Server: disconnect end @enduml ``` Next to the client detecting that the server used incompatible logic for determining the payload compatibility the client is also free to disconnect at any time if it receives an invalid payload which was not agreed upon, either by this protocol directly, or via the negotiation: ```plantuml @startuml participant "Modded Client" as Client participant "Modded Server" as Server group Phase: configuration note over Server: The server sends an empty register packet. Server -> Client: minecraft:register Server -> Client: ping note over Client: The servers initial register packet is ignored. note over Client: The client answers with all known payload ids. Client -> Server: minecraft:register note over Client: The versions packet contains a string version per payload id. Client -> Server: c:version note over Client: The requirements packet contains a boolean required indicator per payload id. Client -> Server: c:required Client -> Server: pong note over Server: The server processes the clients payload ids. note over Server: The server answers with all accepted payloads. Server -> Client: minecraft:register note over Server: The server answers with a string version per payload id. Server -> Client: c:version note over Server: The server answers with a boolean required indicator per payload id. Server -> Client: c:required loop Configuration tasks run note over Server: The server sends an invalid payload Server -> Client: angry_mod:invalid_payload note over Client: The client detects the invalid payload Client -> Server: disconnect end end ``` ### Play phase The play phase flows would look similar as the configuration phase flows above. ### When using the minimal payload flow If the minimal payload flow is in effect, then there the only thing to agree or disagree on is the availability of all payload ids. In this case if a client does not have all the payload ids of the server the flow would look like follows: ```plantuml @startuml participant "Modded Client" as Client participant "Modded Server" as Server group Phase: configuration note over Server: The server sends a filled minecraft:register payload Server -> Client: minecraft:register Server -> Client: ping note over Client: The client detects that its payload ids are incompatible with the servers list and disconnects. Client -> Server: disconnect @enduml ``` ## A vanilla client connects to a modded server In the case that a vanilla client connects to a modded server, this can be detected by monitoring for the responses to the relevant minecraft:register payloads: ```plantuml @startuml participant "Vanilla Client" as Client participant "Modded Server" as Server group Phase: configuration note over Server: The server sends a filled minecraft:register payload Server -> Client: minecraft:register Server -> Client: ping note over Client: The client completly ignores the minecraft:register payload and only responds to the "ping" packet Client -> Server: pong @enduml ``` Now the server knows that the client does not support any modded protocol negotiation. Once this state of the connection has been determined, the server can check if it has any required protocol available. If so he will disconnect the client: ```plantuml @startuml participant "Vanilla Client" as Client participant "Modded Server" as Server group Phase: configuration note over Server: The server sends a filled minecraft:register payload Server -> Client: minecraft:register Server -> Client: ping note over Client: The client completly ignores the minecraft:register payload and only responds to the "ping" packet Client -> Server: pong note over Server: Server determines that required modded payloads are needed and disconnects the client Server -> Client: disconnect @enduml ``` ## A modded client connects to a vanilla server A vanilla server will never send the minecraft:register payload, and just starts the configuration phase. This can be used to detect that the modded client is connected to a vanilla server. Once this determination is made, the vanilla client can determine if it has any required payloads that are now not available: ```plantuml @startuml participant "Modded Client" as Client participant "Vanilla Server" as Server group Phase: configuration note over Server: The server immediatly starts with the brand payload (which is the first payload send during configuration) Server -> Client: minecraft:brand note over Client: Client detects the vanilla connection and determines elligibility. If compatible will continue to process incoming packets. Server -> Client: Registry packets Client -> Server: Acknowledgement packets loop Configuration tasks run Server -> Client: mod_id:do_something Client -> Server: mod_id:did_something end @enduml ``` If this client determines that it has required payloads the disconnect flow will look as follows: ```plantuml @startuml participant "Modded Client" as Client participant "Vanilla Server" as Server group Phase: configuration note over Server: The server immediatly starts with the brand payload (which is the first payload send during configuration) Server -> Client: minecraft:brand note over Client: Client detects the vanilla connection and determines that it is not compatible, then disconnects. Client -> Server: disconnect end @enduml ```