Query
Query (littéralement "requête") est un protocole UDP introduit dans l'édition Java Beta 1.9 Prerelease 4 pour récupérer des propriétés d'un serveur. Il est conçu pour être compatible avec le protocole Query UT3 (ou GameSpot).
Une alternative légèrement plus simple au protocole de requête consiste à se connecter au port TCP principal de Minecraft et à envoyer un paquet de "ping de la liste des serveurs", qui renvoie le MOTD, le nombre d'utilisateurs et le nombre d'emplacements.
Tous les types de données sont en big-endian, à l'exception du type short.
server.properties
[modifier | modifier le wikicode]Pour activer la RCON, il faut modifier le fichier server.properties :
enable-query=true
query.port=<1-65535>
Le port par défaut est celui défini dans server-port.
Format du paquet de base
[modifier | modifier le wikicode]Format du paquet client vers serveur
[modifier | modifier le wikicode]| Nom du champ | Type de champ | Notes |
|---|---|---|
| Magique | unsigned short | Toujours 65277 (0xFEFD) |
| Type | byte | 9 pour le handshake, 0 pour les statistiques
|
| ID de session | int32 | |
| Charge utile | Varie | Voir ci-dessous |
Format du paquet serveur vers client
[modifier | modifier le wikicode]| Nom du champ | Type de champ | Notes |
|---|---|---|
| Type | byte | 9 pour le handshake, 0 pour les statistiques
|
| ID de session | int32 | |
| Charge utile | Varie | Voir ci-dessous |
Handshake
[modifier | modifier le wikicode]Générer un ID de session
[modifier | modifier le wikicode]L'ID de session est utilisé pour identifier les requêtes. Les exemples suivants utilisent l'ID de session = 1 (encodé comme 00 00 00 01 sur les vidages hexadécimaux).
Seuls les 4 bits inférieurs de chaque octet de l'ID de session doivent être utilisés, car Minecraft ne traite pas les 4 bits supérieurs de chaque octet. Pour convertir n'importe quel ID de session de 4 octets en un ID de session de Minecraft valide, il faut simplement masquer les bits avec sessionId & 0x0F0F0F0F.
Requête
[modifier | modifier le wikicode]Envoyez une requête avec une charge utile vide.
| Nom du champ | Type de champ | Exemple |
|---|---|---|
| Magique | short | FE FD
|
| Type | byte | 09
|
| ID de session | int32 | 00 00 00 01
|
| Charge utile | (vide) |
Vidage :
FE FD 09 00 00 00 01
Réponse
[modifier | modifier le wikicode]La charge utile de la réponse sera un jeton de challenge encodé sous forme de chaîne de caractères terminée par un caractère nul. Vous devez le convertir en int32 et le stocker.
| Nom du champ | Type de champ | Exemple |
|---|---|---|
| Type | byte | 09
|
| ID de session | int32 | 00 00 00 01
|
| Chaîne de caractères du jeton de challenge | Chaîne de caractères terminée par un caractère nul | "9513307\0"
|
Dans cet exemple, après avoir analysé la chaîne de caractères "9513307\0" en tant qu'entier et l'avoir compressée en tant que int32 en big-endian, le résultat doit être 00 91 29 5B.
Vidage :
09 00 00 00 01 39 35 31 33 33 30 37 00 | .....9513307.
Expiration du token de challenge
[modifier | modifier le wikicode]Citation de la publication originale de Dinnerbone sur le protocole de requête de Minecraft :
Notez que le jeton de challenge est lié à votre IP et votre port (par opposition à l'[ID de session]) et dure jusqu'à 30 secondes. Vous avez bien lu, c'est à vous de décider ; ce n'est pas "votre jeton expirera après 30 secondes", c'est "chaque token" qui expire toutes les 30 secondes. Cela signifie qu'il est tout à fait possible que vous obteniez un jeton et que vous l'utilisiez dans la même seconde et qu'il expire.
De plus :
Vous devrez fournir votre jeton de challenge, sinon vous ne recevrez aucune réponse. Si vous fournissez un jeton et qu'il est invalide, vous ne recevrez toujours pas de réponse. Avec cela à l'esprit, si vous souhaitez stocker votre jeton de challenge et l'utiliser ultérieurement, vous souhaiterez peut-être appliquer un délai d'attente avant une réponse, au cas où le serveur redémarrerait et que votre jeton ne serait plus valide. Il est impossible de faire la différence entre un serveur hors ligne et un serveur qui a refusé votre challenge sans aucune requête supplémentaire, vous devrez donc essayer d'obtenir un autre jeton de challenge et, si cela est échoue, le signaler comme indisponible.
Statistiques basiques
[modifier | modifier le wikicode]Requête
[modifier | modifier le wikicode]La charge utile doit être le jeton de challenge, compressé sous forme d'un int32.
| Nom du champ | Type de champ | Exemple |
|---|---|---|
| Magique | short | FE FD
|
| Type | byte | 00
|
| ID de session | int32 | 00 00 00 01
|
| Jeton de challenge | int32 | 00 91 29 5B
|
Vidage :
FE FD 00 00 00 00 01 00 91 29 5B
Réponse
[modifier | modifier le wikicode]| Nom du champ | Type de champ | Exemple |
|---|---|---|
| Type | byte | 00
|
| ID de session | int32 | 00 00 00 01
|
| MOTD | Chaîne de caractères terminée par un caractère nul | "A Minecraft Server\0"
|
| Type de jeu | Chaîne de caractères terminée par un caractère nul | "SMP\0"
|
| Carte | Chaîne de caractères terminée par un caractère nul | "world\0"
|
| Nombre de joueurs | Chaîne de caractères terminée par un caractère nul | "2\0"
|
| Joueurs maximum | Chaîne de caractères terminée par un caractère nul | "20\0"
|
| Port hôte | Entier court en little-endian | DD 63 ( = 25565)
|
| IP hôte | Chaîne de caractères terminée par un caractère nul | "127.0.0.1\0"
|
Vidage :
00 00 00 00 01 41 20 4D 69 6E 65 63 72 61 66 74 | .....A Minecraft 20 53 65 72 76 65 72 00 53 4D 50 00 77 6F 72 6C | Server.SMP.worl 64 00 32 00 32 30 00 DD 63 31 32 37 2E 30 2E 30 | d.2.20.##127.0.0 2E 31 00 | .1.
Statistiques complètes
[modifier | modifier le wikicode]Cette méthode est mise en cache toutes les 5 secondes.
Requête
[modifier | modifier le wikicode]La requête est la même que pour les statistiques de base, sauf que la charge utile doit être remplie à 8 octets. L'envoi de 0x00 0x00 0x00 0x00 à la fin fonctionne.
| Nom du champ | Type de champ | Exemple |
|---|---|---|
| Magique | short | FE FD
|
| Type | byte | 00
|
| ID de session | int32 | 00 00 00 01
|
| Jeton de challenge | int32 | 00 91 29 5B
|
| Remplissage | 00 00 00 00
|
Vidage :
FE FD 00 00 00 00 01 00 91 29 5B 00 00 00 00
Réponse
[modifier | modifier le wikicode]La réponse est en deux parties. La première partie est une liste de chaînes de caractères terminées par un caractère nul, représentant (clé1, valeur1, clé2, valeur2...). La deuxième partie est une autre liste de chaînes de caractères terminées par un caractère nul, chacune représentant un joueur.
Une façon simple d'analyser la charge utile consiste à ignorer les 11 premiers octets, puis à diviser la réponse autour du jeton \x00\x01player_\x00\x00. À la toute fin, il y a un octet nul supplémentaire.
| Nom du champ | Type de champ | Exemple | Notes |
|---|---|---|---|
| Type | byte | 00
|
|
| ID de session | int32 | 00 00 00 01
|
|
| Remplissage | 11 octets, constant | 73 70 6C 69 74 6E 75 6D 00 80 00
|
Sans signification |
| Section K, V | Plusieurs paires de chaînes de caractères terminées par un caractère nul | hostname\0A Minecraft Server\0gametype\0SMP\0 ... hostip\0127.0.0.1\0\0
|
Terminé lorsque vous lisez une clé de longueur 0 (sortie de la boucle, ne lisez pas la valeur) |
| Remplissage | 10 octets, constant | 01 70 6C 61 79 65 72 5F 00 00
|
Sans signification |
| Section des joueurs | Plusieurs chaînes de caractères terminées par un caractère nul | "barneygale\0TkTech\0 ... sadimusi\0\0"
|
Terminé lorsque vous lisez un nom de joueur de longueur 0 |
Vidage :
00 00 00 00 01 73 70 6C 69 74 6E 75 6D 00 80 00 | .....splitnum... 68 6F 73 74 6E 61 6D 65 00 41 20 4D 69 6E 65 63 | hostname.A minec 72 61 66 74 20 53 65 72 76 65 72 00 67 61 6D 65 | raft Server.game 74 79 70 65 00 53 4D 50 00 67 61 6D 65 5F 69 64 | type.SMP.game_id 00 4D 49 4E 45 43 52 41 46 54 00 76 65 72 73 69 | .MINECRAFT.versi 6F 6E 00 42 65 74 61 20 31 2E 39 20 50 72 65 72 | on.Beta 1.9 Prer 65 6C 65 61 73 65 20 34 00 70 6C 75 67 69 6E 73 | elease 4.plugins 00 00 6D 61 70 00 77 6F 72 6C 64 00 6E 75 6D 70 | ..map.world.nump 6C 61 79 65 72 73 00 32 00 6D 61 78 70 6C 61 79 | layers.2.maxplay 65 72 73 00 32 30 00 68 6F 73 74 70 6F 72 74 00 | ers.20.hostport. 32 35 35 36 35 00 68 6F 73 74 69 70 00 31 32 37 | 25565.hostip.127 2E 30 2E 30 2E 31 00 00 01 70 6C 61 79 65 72 5F | .0.0.1...player_ 00 00 62 61 72 6E 65 79 67 61 6C 65 00 56 69 76 | ..barneygale.Viv 61 6C 61 68 65 6C 76 69 67 00 00 | alahelvig..
Section K, V
[modifier | modifier le wikicode]| Clé | Exemple de valeur | Description |
|---|---|---|
Nom d'hôtehostname
|
'A Minecraft Server' | Le MOTD du serveur actuel. |
Type de jeugametype
|
'SMP' | Codé en dur à SMP. |
ID de jeugame_id
|
'MINECRAFT' | Codé en dur à MINECRAFT. |
Versionversion
|
'1.2.5' | La version du serveur. |
Pluginsplugins
|
'CraftBukkit on Bukkit 1.2.5-R4.0:
WorldEdit 5.3; CommandBook 2.1' |
La liste des plugins, non utilisée par le serveur vanilla, où c'est une chaîne de caractères vide (mais toujours terminée par un caractère nul, voir le vidage hexadécimal ci-dessus).
C'est le format proposé par Dinnerbone et actuellement utilisé par Bukkit : |
Cartemap
|
'world' | Le nom de la carte actuelle. |
Nombre de joueursnumplayers
|
'1' | Le nombre de joueurs en ligne. La chaîne de caractères peut être convertie en nombre. |
Joueurs maximummaxplayers
|
'20' | Le nombre maximum de joueurs sur le serveur. La chaîne de caractères peut être convertie en nombre. |
Port hôtehostport
|
'25565' | Le port du serveur. La chaîne de caractères peut être convertie en nombre. |
IP hôtehostip
|
'127.0.0.1' | L'adresse IP sur laquelle le serveur écoute ou a été contacté. |
Exemples d'implémentation
[modifier | modifier le wikicode]- https://github.com/Sch8ill/MCClient-lib (python)
- https://github.com/MaxLevs/McQueryLib.Net (C#, .Net 5.0)
- https://github.com/A2PLab/minelib (scala)
- https://github.com/Dinnerbone/mcstatus (python)
- https://github.com/Erikvv/Minecraft-Query-cpp (c++)
- https://github.com/barneygale/MCQuery (python)
- https://github.com/coNQP/mcipc (python 3.8+)
- https://github.com/kmpm/node-mcquery (node.js)
- https://github.com/py-mine/PyMine/blob/main/pymine/logic/query.py (python 3.7.9+)
- https://github.com/ryanshawty/MCJQuery (java)
- https://github.com/xPaw/PHP-Minecraft-Query (php)
- https://github.com/PassTheMayo/minecraft-server-util (node.js)
- https://github.com/dreamscached/minequery (go)
- https://github.com/mcstatus-io/mcutil (go)
- https://github.com/H4kt/minecraft-query-kt (kotlin)
Navigation
[modifier | modifier le wikicode]Les œuvres dérivées doivent être concédées sous licence en utilisant la même licence ou une licence compatible.