Ceci est la traduction française, faite pour ce site, du guide livré dans le produit : le fichier README.md de votre archive, en anglais. L’anglais fait référence : en cas de doute, c’est lui qui compte. Lire l’original en anglais
1. Installer
- Téléchargez
PracticeCore.jardepuis votre espace client sur boteramc.com/licence. Cette copie est - Déposez
PracticeCore.jardansplugins/. - Démarrez le serveur.
- Lisez les deux lignes qu’il affiche. Sur une installation neuve, elles disent ce qui manque et ce qu’il faut taper :
construite pour vous et porte votre identifiant d’acheteur — téléchargez-la de nouveau plutôt que de faire circuler une copie, car un fichier partagé nomme le compte dont il vient. Elle tourne sur tout serveur que votre licence couvre.
[PracticeCore] No arenas.yml file: no arena is defined. Use /practice arena create <id> in game to make one.
[PracticeCore] No kits.yml file: no kit is defined. Run /practice kit preset all in game for the
bundled kits, or gear up and run /practice kit save <id> to make your own.
[PracticeCore] Practice Core 1.0.0 on v1_8_R3: 0 arena(s), 0 kit(s), 0 rating(s) loaded.
Le plugin refuse de démarrer plutôt que de tourner à moitié configuré : une valeur erronée dans config.yml, un nom de son inconnu, un fichier de langue qui n’existe pas. Il dit toujours quelle clé, ce qu’il a lu et ce qu’il attendait — et il signale tous les problèmes d’un coup, pour que vous les corrigiez en une passe plutôt qu’avec un redémarrage par erreur.
Il refuse aussi de démarrer sur un serveur qui n’est pas en 1.8.8/1.8.9, et le dit. Rien n’est chargé et aucun fichier n’est touché.
1b. Votre licence
Collez la clé de votre espace client sur boteramc.com/licence dans la configuration du plugin :
licence: "BOTERA1.xxxxxxxx.xxxxxxxx"
Elle peut être collée avec ou sans retours à la ligne — une clé copiée depuis un e-mail fonctionne telle quelle.
Le plugin contacte une seule adresse, et voici exactement ce qui se passe. Au démarrage puis toutes les douze heures, il demande à boteramc.com si la licence est toujours valide. Il envoie la clé, un nombre aléatoire, la version du plugin, et des empreintes hachées de la machine. Les valeurs brutes ne quittent jamais votre serveur : elles sont hachées en HMAC-SHA256 avant tout envoi. Aucune adresse IP, aucun nom de serveur, aucune donnée de joueur, rien sur votre jeu.
Si ce serveur ne répond pas, il ne se passe rien pendant quinze jours. Votre licence est signée et se vérifie hors ligne : une panne de notre côté n’arrête donc pas un serveur qui a payé. Dès la première vérification manquée, la console le dit et décompte les jours restants, et rien d’autre ne change.
Après quinze jours de silence, le plugin refuse de s’activer, et le message dit clairement que votre licence est valide et que c’est nous qu’il n’a pas pu joindre. Cette fenêtre existe pour qu’une machine derrière un pare-feu ou longtemps hors ligne soit prévenue tôt plutôt que coupée sans avertissement — si vous en exploitez une, autorisez boteramc.com ou contactez-nous et nous arrangerons cela.
Rien n’est jamais coupé en plein match. Si nous révoquons une licence pendant que votre serveur tourne, le plugin le dit dans la console et continue de fonctionner jusqu’au prochain redémarrage.
Combien de machines. Votre licence couvre un certain nombre de machines, affiché dans votre espace client — au moins deux par défaut, car presque tout le monde fait tourner un serveur de test à côté du serveur en ligne. Une machine est reconnue malgré les changements de matériel ordinaires : remplacer une carte réseau ne consomme pas un nouvel emplacement. Si vous changez d’hébergeur, libérez l’ancienne machine dans votre espace client ; la nouvelle s’enregistre toute seule au démarrage suivant.
S’il refuse. Le message dit lequel de ces cas c’est, et que faire : pas de clé, une clé d’un autre produit, une licence expirée, une licence révoquée, trop de machines, ou notre serveur injoignable au-delà de la période de grâce. Ce n’est jamais simplement « licence invalide ».
2. Vos cinq premières minutes
En jeu, en tant qu’opérateur :
/practice kit preset all # les 16 kits fournis, prêts à jouer
/practice arena preset all # les quatre arènes dont ces kits ont besoin, construites pour vous
/practice arena create ring # votre propre arène : placez-vous sur le départ 1, relancez-la sur le départ 2
/practice arena bounds ring # un coin, puis l’autre (ou donnez les six nombres)
/practice # le menu : clic gauche = non classé, clic droit = classé
Les deux premières lignes sont toute l’installation. Tout le reste est facultatif.
Pourquoi la deuxième ligne existe. Sumo et Stick Fight ont besoin d’air libre autour d’une plate-forme pour pousser quelqu’un dehors ; Spleef et Fireball en ont besoin aussi, cassable ; Bridge a besoin d’un but à chaque bout ; MLG Rush a besoin d’un lit dans chacun ; Build UHC a seulement besoin d’une arène où l’on peut poser des blocs. En tout, sept kits fournis ont besoin d’une forme d’arène qu’une simple paire de départs ne donne pas. Posez les kits et rien d’autre, et l’autodiagnostic vous dit — à raison — que sept des seize que vous venez d’installer ne peuvent être accueillis par rien de ce que vous possédez.
/practice arena preset all construit ces quatre formes à côté de l’endroit où vous vous tenez, blocs compris, les enregistre, puis repose au serveur sa propre question : la réponse se termine par le nombre de kits fournis qui n’ont toujours aucune arène. Sur une installation neuve, ce nombre passe de sept à zéro. Les formes se construisent aussi une à une -- /practice arena preset sumo, spleef, bridge, mlgrush, parkour -- et vous pouvez nommer l’arène vous-même avec un second mot.
Il n’écrit jamais par-dessus quoi que ce soit. Chaque bloc qu’il s’apprête à poser est d’abord lu, et un seul bloc qui n’est pas de l’air annule toute la pose avant que le premier soit écrit -- il passe donc à l’emplacement suivant au lieu de percer un trou dans ce que vous avez construit. Il se tient aussi à l’écart des arènes que vous avez déjà, et construit au-dessus du sol plutôt que sur lui, parce que la moitié de ces formes se gagnent en tombant.
Il y a un bouton pour cela. /practice arena ouvre la fenêtre des arènes, et son carré Construire les arènes de départ fait la même chose -- il vous dit combien de kits fournis n’ont pas d’arène, où il va construire, et que rien n’est écrit par-dessus, avant même que vous cliquiez.
Retirer l’une d’elles emporte ses blocs. /practice arena remove <id> sur une arène de départ que personne n’a touchée efface les blocs qu’elle a posés et vous dit combien. Si un seul bloc a changé -- vous avez construit sur la plate-forme, ou cassé un coin -- les blocs restent en place et l’arène est simplement désenregistrée : retirer le sol sous votre ouvrage serait pire que laisser une plate-forme debout.
Ce sont des arènes de départ : une plate-forme, deux îles, un lit. Elles sont jouables le jour de l’installation, et un serveur qui grandit les remplacera par les siennes -- /practice arena clone sert à multiplier celles que vous construisez. Ce qu’elles suppriment, ce n’est pas le travail d’une belle carte, c’est le mur du premier jour.
Faire la vôtre, sans rien taper. /practice arena → NEW ARENA en crée une là où vous vous tenez et ouvre son constructeur. Cette fenêtre a une ligne par chose que porte une arène — départ 1, départ 2, limites, but 1, but 2, chaque zone nommée, et si l’on peut poser des blocs — et chaque ligne dit ce qu’elle contient en ce moment : rien encore, un premier coin retenu en x y z, ou la zone définie avec ses trois dimensions. Cliquer sur une ligne enregistre l’endroit où vous vous tenez. Une zone prend deux clics, à des coins opposés ; vous ne tapez jamais une coordonnée.
Vous accédez à la même fenêtre depuis la liste des arènes par un clic droit sur n’importe quelle arène, y compris l’une qui accueille un match — poser un but ne dérange pas la manche en cours, ce qui explique pourquoi le clic droit y est permis alors que le clic gauche (qui vous téléporte) ne l’est pas.
La fenêtre ne fait que créer et placer. Nommer une nouvelle zone demande encore la commande, car un inventaire 1.8 n’a pas de zone de texte, et la fenêtre le dit plutôt que de vous laisser le chercher.
Faire la vôtre, par commande. create se lance deux fois exprès : le premier appel enregistre le premier départ et dit que l’arène n’est pas encore utilisable, le second enregistre le second départ. bounds n’est nécessaire que pour les kits qui autorisent la construction (Bridge, MLG Rush, Build UHC, Spleef) — il dit au plugin ce qu’il doit remettre après une manche. La restauration se fait par différence de blocs, sans WorldEdit. Chacune de ces commandes accepte aussi les six nombres explicitement, ce que vous voulez quand les coordonnées sont déjà sous vos yeux — une sélection WorldEdit, un plan, ou un script.
Rien de ce que vous retirez n’est perdu. Retirer une arène est un geste confirmé dans la fenêtre du constructeur, et /practice arena remove <id> en commande. Dans les deux cas l’arène est gardée, entière — départs, limites, buts et zones nommées. /practice arena removed liste ce que vous pouvez remettre et /practice arena restore <id> le fait ; la fenêtre des arènes gagne un carré PUT ONE BACK dès qu’il y a quelque chose à remettre. Il en va de même pour les kits : /practice kit removed et /practice kit restore <id>. Les cinquante dernières suppressions de chaque sorte sont conservées. Restaurer n’écrit jamais par-dessus ce qui existe maintenant — si vous avez entre-temps fait une nouvelle arène sous ce nom, la restauration est refusée plutôt que de remplacer silencieusement votre travail.
Plusieurs rangements par kit. /practice layout nodebuff range le kit ; /practice layout save le garde comme celui que vous jouez. save <name> le garde sous un nom et bascule dessus, names <kit> liste ce que vous avez, et use <kit> <name> bascule de l’un à l’autre entre deux manches — un rangement offensif et un rangement défensif sur le même kit.
Mettre à jour un serveur existant conserve tous les rangements déjà enregistrés : ils deviennent celui nommé default, toujours sélectionné. Rien à renommer, rien à refaire.
Chaque match ne voit que lui-même. Deux copies d’arène sont espacées de 16 blocs et une distance d’affichage vaut typiquement 64 : sans cela, un duel verrait les sept duels autour de lui — des silhouettes qui traversent l’écran, des flèches qui le croisent, et, sur un kit Sumo, aucun moyen de savoir lequel est votre adversaire. Les joueurs d’un match ne voient que les gens de ce match ; le lobby ne voit que le lobby. Réglez hud.hide-other-matches: false si vous préférez laisser les gens regarder les arènes depuis le lobby.
Plus d’arènes, et quand les faire. /practice arena clone ring 8 copie une arène terminée huit fois et enregistre chaque copie comme sa propre arène, de sorte que huit duels peuvent tourner en même temps dessus. La copie se fait une tranche de blocs par tick : le serveur reste jouable pendant qu’elle tourne. Mesuré sur huit copies d’une arène de 2 574 blocs : la pire tranche a pris 10 ms, contre les 50 ms d’un tick. Vous pouvez le constater vous-même avec /practice perf, sous arena.clone.
Le seul coût qu’elle ne peut pas fractionner, c’est le terrain lui-même. Sur un sol qu’aucun joueur n’a jamais visité, dans un monde au terrain normal, générer un seul chunk coûte 9 ms en moyenne et jusqu’à 36 ms — presque un tick — et rien ne peut le diviser par deux. Le clonage en paie un par tick, ce qui est le mieux que puisse promettre un plugin. /practice arena prepare ring 8 le déplace : lancez-le avec les mêmes nombres que ceux du clonage, à une heure creuse, et le terrain est généré à ce moment-là. Mesuré sur un monde à terrain normal, le clonage qui suit coûte 0,03 ms par chunk au lieu de 9,1 — 304 fois moins. Il n’écrit aucun bloc et ne crée aucune arène ; lancez-le deux fois et la seconde ne coûte rien.
Si votre monde d’arène est superplat ou vide, un chunk coûte bien moins d’une milliseconde et cette commande ne vous apporte presque rien. Mieux vaut le savoir avant de la programmer : le gain est réel, et il appartient aux mondes qui ont du terrain.
Une seule tâche de terrain à la fois : un prepare lancé pendant qu’un clone tourne est refusé, et inversement, car les deux ensemble mettraient deux générations de chunks dans le même tick. C’est aussi pourquoi /practice arena prepare stop existe — une préparation ne dérange jamais personne, mais elle occupe cette place, si bien qu’un mauvais nombre vous empêcherait de cloner jusqu’à sa fin. L’arrêter garde tous les chunks déjà générés. Il n’y a pas d’équivalent pour arrêter un clonage volontairement : un clonage interrompu à mi-chemin laisserait une arène qui a l’air prête et ne l’est pas.
Événements : neuf formats sur tous les kits. /practice event open sans kit ouvre une fenêtre — choisissez un format, puis un kit. Ou tapez-le : event open sumo lms.
| format | ce qui change | nécessite |
|---|---|---|
bracket | un tournoi à élimination directe en 1v1 | — |
lms | tout le monde dans une seule arène, le dernier en vie gagne | — |
oitc | un seul coup élimine ; la santé ne vous sauve pas | — |
tnt | la bombe circule et explose après event.tnt-fuse-seconds — frappez quelqu’un pour la passer, et il ne peut pas vous la repasser aussitôt | — |
juggernaut | un joueur met event.juggernaut-hits coups à tomber et élimine en un ; celui qui l’abat prend le titre | — |
koth | tenez la colline, seul, pendant event.koth-seconds secondes. Les secondes sont cumulées : être poussé dehors vous coûte le temps passé dehors, rien de plus | une région hill |
thimble | sautez dans le bassin ; la case sur laquelle vous atterrissez se remplit. Ratez le bassin, ou atterrissez sur une case prise, et vous êtes éliminé | une région pool |
parkour | le premier à l’arrivée gagne. Tomber vous renvoie au départ au lieu de vous éliminer | une région finish |
corners | quatre coins, dont l’un disparaît toutes les event.corners-round-seconds secondes. Ne restez pas dessus | corner1…corner4 |
Les quatre derniers ont besoin d’une région nommée, que vous tracez comme un but — placez-vous à un coin, tapez la commande, marchez jusqu’à l’autre, tapez-la de nouveau :
/practice arena region ring hill
/practice arena region ring (liste ce que cette arène a déjà)
/practice arena region ring hill clear (la retire)
Tracez la région là où les joueurs se tiennent, pas seulement le sol. Une région est une boîte, et un joueur est dedans quand le bloc où se trouvent ses pieds est dedans. Un coin tracé comme une seule couche plate de sol n’a personne dedans — ils se tiennent un bloc au-dessus. Prenez le coin bas au niveau du sol et le coin haut deux ou trois blocs plus haut, et cela se comporte comme vous l’attendez.
Un format dont la région manque le dit au début de la manche et nomme celle qu’il veut, plutôt que de dérouler cinq minutes que personne ne peut gagner. Les blocs qu’un mode retire — un coin qui s’en va, une case du bassin qui se remplit — sont remis à la fin de la manche, exactement comme les blocs qu’un joueur pose.
Neuf formats. bracket tourne sur n’importe lequel des seize kits fournis ; les huit autres prennent les treize qui se gagnent à la mort ou en sortant de l’arène, les mêmes que prend un chacun-pour-soi — plus d’une centaine de combinaisons, toutes jouées par du code déjà éprouvé, au lieu de modes de jeu écrits à la main, chacun avec son propre cycle de vie de match à entretenir et à rater.
Ce que les quatre derniers demandent de vous : une région nommée, tracée une fois, puis réutilisée par chaque événement que vous lancez sur cette arène. C’est tout le coût. Le parkour n’a pas de points de contrôle — un parcours à points de contrôle demande une liste ordonnée de régions, et une arène contient une table nommée, pas une liste ; ajouter un ordre pour un seul mode serait exactement la promesse qui ne peut pas être tenue, ce qui est le reproche contre lequel ce plugin a été écrit.
Où les joueurs se retrouvent ensuite. Exactement où ils étaient avant le match — même position, même santé, même mode de jeu, même inventaire, au bloc près. Ce plugin ne possède pas de lobby, ne téléporte personne vers un point d’apparition qui lui soit propre, et n’a aucun réglage de lobby : le hub ou le plugin de spawn que vous utilisez déjà continue de fonctionner, et les deux ne se contredisent jamais sur l’endroit où un joueur doit être. Un match ici est un aller-retour.
Revoir la dernière manche. /practice replay remet dans l’arène des silhouettes portant les skins des joueurs et leur fait rejouer la manche que vous venez de jouer, pour vous seul. C’est le mouvement seulement — ni les coups, ni les objets, ni les effets. C’est ce dont on discute après une manche (« où étais-tu quand je t’ai touché »), et l’appeler autrement serait promettre un enregistrement vidéo qui n’existe pas.
Une manche est conservée par joueur, la dernière, plafonnée et abandonnée à sa déconnexion. Une fonction de rediffusion qui enregistre sans limite ne se voit pas aux tests ; elle se voit trois jours plus tard, quand le tas est plein.
Duels seulement — les chacun-pour-soi et les événements ne sont pas enregistrés. Six silhouettes qui refont une mêlée seraient illisibles, et le dire coûte moins cher que de laisser un joueur le découvrir en tapant la commande après coup.
Un classement que l’on lit sans rien taper. /practice hologram add nodebuff, là où vous voulez le placer, met le top dix de ce kit dans les airs à vos pieds — nom, rating et palier, rafraîchis chaque minute. remove l’enlève et list montre ce que vous avez posé.
Ce qui est écrit sur le disque, c’est le point, jamais les entités. Les lignes flottantes sont posées au démarrage et effacées à l’arrêt, et chaque pose commence par balayer la zone à la recherche de lignes à nous. C’est voulu : un plugin qui enregistre des identifiants d’entités s’éloigne du monde au premier arrêt brutal, et six mois plus tard le spawn porte une centaine de porte-armures invisibles que personne ne sait retirer.
Des groupes qui n’ont pas besoin d’un second groupe. party split tire deux équipes du groupe et les fait jouer l’une contre l’autre — il faut un nombre pair. party ffa n’exige rien : trois joueurs, cinq, huit, chacun se bat pour soi et le dernier debout gagne. Chacun apprend sa place, pas seulement le nom du vainqueur, et le groupe n’est pas dissous — les mêmes joueurs recommencent avec une commande.
Un chacun-pour-soi prend les kits qui se gagnent à la mort ou en sortant de l’arène (Sumo, Spleef, Stick Fight, Fireball, et tous les kits ordinaires). Les kits qui se gagnent aux coups, aux buts ou aux lits sont refusés par leur nom : compter les coups entre six joueurs ne désigne personne, et un but appartient à un camp quand on est six. Les chacun-pour-soi ne sont pas classés, exprès — un classement se calcule entre deux camps, et un mauvais classement est pire que pas de classement.
Kits. kit save <id> enregistre votre inventaire actuel — équipez-vous, testez, enregistrez. C’est le déroulement que tout serveur 1.8 utilise vraiment. Réenregistrer un kit garde son profil de recul et sa condition de victoire : on passe des heures à régler un profil et une seconde à refaire un inventaire.
Annuler. kit remove <id> et arena remove <id> suppriment ce que vous avez fait, fichier compris — pour une faute de frappe, un test, ou un kit que vous ne proposez plus. Ils refusent tant que la chose est utilisée : une arène qui accueille un match, un kit qui est joué, un kit avec quelqu’un qui attend dans sa file (désactivez-le, laissez-les partir, puis supprimez-le). Les classements et l’historique des matchs gardent le nom du kit : un kit recréé sous ce nom retrouve son classement. Si vous voulez seulement sortir un kit de la rotation, kit disable <id> garde tout.
Identifiants. L’identifiant d’un kit ou d’une arène fait de 1 à 32 caractères parmi a-z, 0-9, - et _. Tout le reste est refusé avec la raison, parce qu’un identifiant devient une clé dans un fichier .yml et qu’un point, une espace ou un code couleur ne se relit pas comme il a été écrit.
3. Commandes
Tout vit sous /practice (alias /pr, /duel). /practice help les liste en jeu — les lignes que vous pouvez réellement utiliser, pour qu’un joueur ne se voie pas remettre les vingt commandes d’administration qu’il ne peut pas lancer. Appuyez sur TAB : chaque verbe, puis les kits, arènes, langues, modes, rangements, formats de tournoi et paramètres de recul que chacun accepte.
Seule la file d’attente est classée, et c’est voulu. Un défi, une manche de tournoi, un chacun-pour-soi de groupe et un bot d’entraînement laissent tous votre rating exactement où il était ; la file — et la file commune d’un réseau — est le seul endroit où il bouge. Un classement n’a de sens que si personne ne choisit son adversaire. Tout ici repose là-dessus : la file apparie à l’intérieur d’une fenêtre de rating, la surveillance d’intégrité compte les paires qui se rencontrent trop souvent, et le n-ième duel contre la même personne compte moins, pour que le boost soit inutile plutôt que puni. Laissez deux joueurs se désigner l’un l’autre pour un match noté et tout cela devient de la décoration — ils s’échangeraient des victoires en deux commandes.
Défiez donc qui vous voulez, quand vous voulez, sur le kit que vous voulez : le classement reste le registre des matchs que personne n’a choisis. La ligne qui arrive dit unranked pour que la personne qui accepte le sache avant d’accepter, pas après.
/duel <player> [kit] [bo3] [arena] fonctionne comme commande à part entière, comme partout ailleurs. Si un autre plugin de votre serveur possède déjà /duel, Bukkit le donne à celui qui se charge le premier — /practicecore:duel atteint toujours celle-ci, et /practice duel fonctionne toujours.
| commande | qui | quoi |
|---|---|---|
/practice | tout le monde | ouvre le menu — même si tout est déjà à un clic dans la barre d’objets |
/practice settings | tout le monde | visibilité, demandes de duel, invitations de groupe, spectateurs, tableau latéral, sons, plage de ping, langue |
/practice profile | tout le monde | votre rating, votre bilan et votre série, kit par kit, avec vos derniers matchs |
/practice queue <kit> [ranked] | tout le monde | rejoindre une file |
/practice leave | tout le monde | quitter une file, un duel, ou le mode spectateur |
/practice duel <player> [kit] [bo3] [arena] | tout le monde | défier quelqu’un directement, éventuellement sur une arène nommée. Jamais classé — voir plus haut |
/practice accept <player> | tout le monde | accepter un défi |
/practice rematch [bo3] | tout le monde | rejouer le dernier adversaire, même kit |
/practice party [invite|accept|kick|leave|disband] | tout le monde | groupes, pour du 2v2 et du 3v3 |
/practice party chat <message> | tout le monde | dire quelque chose à votre groupe seulement |
/practice party split [kit] | tout le monde | le groupe joue contre lui-même, équipes tirées au hasard |
/practice party ffa [kit] | tout le monde | chacun pour soi : tout le monde contre tout le monde, le dernier debout gagne |
/practice spectate <player> | tout le monde | regarder un duel |
/practice bot <kit> [easy|normal|hard] | tout le monde | s’entraîner contre un bot, sur place. Non classé |
/practice bot stop | tout le monde | terminer l’entraînement et récupérer son inventaire |
/practice layout <kit> | tout le monde | ranger un kit à sa façon |
/practice layout save <name>|use <kit> <name>|names <kit>|forget <kit> <name>|reset <kit>|cancel | tout le monde | plusieurs rangements par kit, pour passer de l’un à l’autre |
/practice inv [player] | tout le monde | les inventaires à la fin de la dernière manche |
/practice history | tout le monde | vos derniers matchs classés |
/practice replay [stop] | tout le monde | revoir votre dernière manche — le mouvement seulement |
/practice top [kit] | tout le monde | les classements — dans une fenêtre, ou en texte pour un kit |
/practice kit preview <kit> | tout le monde | voir ce que donne un kit avant de s’y mettre en file |
/practice kit | tout le monde | la grille des kits, où un clic droit affiche l’aperçu. Un admin obtient à la place la liste d’administration des kits |
/practice stats [player] | tout le monde | rating, palier, victoires, défaites et séries, par kit |
/practice lang <code> | tout le monde | choisir sa langue |
/practice status | practice.admin | arènes, kits, duels, ratings, et les serveurs derrière le proxy |
/practice arena preset <sumo|spleef|bridge|mlgrush|parkour|all> [id] | practice.admin | construit une arène de départ, blocs compris, à côté de vous |
/practice arena create|bounds|goal|region|tp|clone|prepare|rescan | practice.admin | construire et vérifier des arènes ; sans sous-commande, la liste des arènes s’ouvre |
/practice hologram <add|remove|list> [kit] | practice.admin | un classement posé dans le monde |
/practice kit save|preset|win|mode|pearl|hitdelay|enable|disable | practice.admin | créer et régler des kits. preset remplace : un kit qui existe déjà est remis à son contenu fourni, son recul, sa condition de victoire et son nom |
/practice kb <kit> [set …|reset] | practice.admin | profil de recul, mesurable |
/practice season [reset <name>] | tout le monde / practice.admin | la saison classée, et l’ouverture d’une nouvelle |
/practice config [section|all] | practice.admin | chaque réglage réellement en vigueur, et d’où vient chaque valeur : votre fichier, le preset, ou le plugin. Sans argument, il liste les sections — la réponse complète fait environ cent dix lignes et un chat 1.8 en garde cent |
/practice perf [reset] | practice.admin | coût par opération, sur le fil principal |
/practice selftest [full] | practice.admin | autodiagnostic : ce qui est cassé et pourquoi |
/practice integrity [pairs] | practice.admin | ce que la surveillance compétitive a vu |
/practice admin | practice.admin | le menu d’administration |
/practice setspawn | practice.admin | poser le spawn du lobby là où vous vous tenez — c’est ce qui confie le lobby au plugin |
/practice event open [kit] [format] | practice.event | un tournoi ou un mini-jeu — les neuf formats sont à la section 2 ; sans kit, une fenêtre s’ouvre |
/practice event [start|cancel|join|leave|info] | practice.event | le lancer, l’arrêter et le rejoindre. Les manches de tournoi ne sont pas classées non plus |
Les verbes français fonctionnent aussi (/practice langue, /practice revanche, /practice tournoi…).
Permissions
| nœud | par défaut | accorde |
|---|---|---|
practice.admin | op | créer des arènes, enregistrer des kits, réglages, diagnostic |
practice.event | op | ouvrir et annuler un tournoi |
practice.priority | false | servi avant les autres joueurs à temps d’attente égal ; ne fausse jamais les règles de rating ni de ping |
Tout le reste est ouvert à chaque joueur. Un joueur sans practice.admin est refusé sur les treize chemins d’administration, et rien ne change quand il essaie — c’est vérifié en jeu à chaque version, en connectant un joueur ordinaire et en relisant les nombres d’arènes et de kits avant et après.
3b. S’entraîner contre un bot
/practice bot nodebuff hard
/practice bot stop
Un partenaire d’entraînement qui ne se lasse jamais. Il apparaît à trois blocs devant vous, avec le même kit que le vôtre, et il se bat là où vous vous tenez -- pas de file d’attente, pas d’arène réservée. Ce dernier point compte sur un serveur chargé : vous pouvez travailler un kit alors que les huit arènes sont prises, et votre entraînement ne prend jamais une place qu’un vrai duel attendait.
C’est un joueur, pas un monstre. Le bot est une vraie entité joueur pour le serveur : il a donc la boîte de collision et la portée d’un joueur. C’est voulu : un partenaire d’entraînement avec la boîte de collision d’un mob enseigne des réflexes qui ne se transfèrent pas, ce qui est pire que pas de bot du tout.
Et il est poussé comme l’est un joueur. Frapper le bot le déplace. Il subit le profil de recul du kit, écrit par le même code qui pousse un humain en duel, et il a un corps : la gravité, les frottements et les collisions du moteur lui-même. Poussez-le d’une corniche et il tombe ; poussez-le sur de la glace et il glisse plus loin.
Cela n’était pas vrai avant la 1.1.0, et l’ampleur de l’écart mérite d’être dite simplement. Une entité joueur sans client derrière elle n’est jamais mise à jour, de sorte que le recul que le moteur écrivait pour le bot n’était jamais converti en mouvement : le frapper le déplaçait de zéro bloc, sur les seize kits. Mesuré sur un vrai client, sept coups portés, la hauteur du bot est passée de 4.0000 à 4.0000 — alors que tout recul 1.8 soulève sa victime de 0,4. Combo, un mode dont tout l’intérêt est de garder l’adversaire en l’air, s’entraînait contre une statue. Après la correction : dix coups, dix déplacements en s’éloignant de l’attaquant (de +0.06 à +0.62 bloc) et une hauteur qui monte à 4.8125 puis retombe.
Vous voyez ce qu’il porte, et ce que vous lui lancez touche. Le bot montre l’arme qu’il a en main et l’armure qu’il porte, comme tout joueur -- c’est ainsi que vous savez qu’il vient de passer à une pomme. Et tout ce qu’un kit vous permet de mettre sur un adversaire marche désormais sur lui : le poison fait baisser sa santé, la faiblesse retire quatre points à ses coups, la lenteur le ralentit -- et vous voyez l’effet tourbillonner sur lui, comme sur un joueur. Cela compte surtout sur Debuff, qui est du poison, de la lenteur et de la faiblesse, et très peu d’autre chose.
Et il se soigne tout seul, de trois façons -- avec ce que le kit lui a réellement donné.
| ce que le kit lui donne | ce qu’il fait | ce que vous voyez |
|---|---|---|
| des potions de soin jetables | en jette une à ses propres pieds, comme une vraie potion lancée, et recule pendant ce temps | la potion qui vole |
| un bol de soupe | en boit un, instantanément, et remet aussitôt son épée en main | sa santé saute, et vous l’entendez |
| des pommes d’or | lève le bras et mange, pendant les 32 ticks complets, la pomme tenue là où vous la voyez | la pomme dans sa main, le bras levé, la mastication |
Il ne fait que se soigner : le poison et la faiblesse d’un kit restent dans son inventaire. Quand il a plus d’un moyen, il choisit le moins cher d’abord -- une potion ne lui coûte rien, un bol est un stock à gérer, une pomme coûte une seconde et demie sans se battre. C’est l’arbitrage que fait un joueur.
La pomme est celle que l’on peut punir, et c’est tout l’intérêt de la montrer. Pendant 32 ticks, le bot n’attaque pas et tout le monde le voit : cette fenêtre est toute la leçon qu’enseigne la pomme d’or, et un bot qui se soignerait sans la montrer vous retirerait cette leçon.
Les trois difficultés diffèrent par quand et combien de fois -- hard commence à sept cœurs et demi et peut se soigner toutes les 1,25 s, easy attend d’être à quatre cœurs et met trois secondes -- et aucune ne se soigne plus vite qu’une personne ne le peut, parce qu’un bot qu’on ne peut pas punir n’est pas un entraînement.
C’est ce qui rend ces kits dignes d’être combattus. Un duel NoDebuff se décide à la gestion des potions, Soup à la gestion du stock, et le kit Gapple est une épée et 128 pommes d’or -- contre un adversaire dont la santé ne fait que baisser, vous travailleriez la moitié du jeu qui ne décide de rien.
Perdre contre lui ne vous coûte rien. Un coup mortel termine la session au lieu de vous tuer : votre inventaire, votre santé et votre position reviennent exactement comme ils étaient, de la même façon que le dernier coup d’un duel ne vous tue pas non plus.
Il joue la règle du kit, et il vous dit la partie qu’il ne peut pas jouer. Neuf des seize kits fournis se gagnent en tuant l’adversaire ; les sept autres non, et l’entraînement les jouait tous les seize comme un combat à mort, sans un mot. Il joue maintenant la condition de victoire propre au kit, et le dit dès la première ligne :
| le kit se gagne | ce que fait l’entraînement | ce qu’il dit |
|---|---|---|
| en tuant (9 kits) | comme avant | rien — c’est le comportement par défaut |
| aux touches — Boxing | personne ne subit de dégâts, le premier à 100 touches gagne, le score remplace la ligne de santé | « Se gagne aux touches : premier à 100. » |
| en poussant dehors — Sumo, Stick Fight, Spleef, Fireball | personne ne subit de dégâts ; descendre de 5 blocs sous votre hauteur de départ fait perdre, pour vous comme pour le bot | « …entraîne-toi au bord, sinon personne ne peut tomber. » |
| aux buts — Bridge, MLG Rush | personne ne meurt : un coup mortel ou une chute vous remet à votre point de départ, kit rempli | « un but demande une arène construite pour. L’entraînement te donne le combat. » |
Les deux réserves sont dans les messages eux-mêmes, parce que le combat a lieu là où vous vous tenez plutôt que dans une arène : un kit à pousser exige que vous trouviez un bord, et un kit à buts n’a pas de but où marquer. Les deux entraînent quand même le combat, qui est la part qu’un bot peut vous donner.
Ce qu’un match dit de lui-même. À la fin d’une manche, chaque joueur reçoit sa propre ligne et celle de son adversaire : touches, plus longue combo, précision aux potions — le chiffre dont dépend un NoDebuff — et précision aux flèches sur les quatre kits qui portent un arc. Chaque partie n’est écrite que quand il y a quelque chose à dire : sur un kit sans potions, ou sans arc, la ligne ne les mentionne tout simplement pas plutôt que d’afficher un « 0 % » qui ferait paraître tout le monde maladroit.
Une touche est une touche, quoi qu’il l’ait portée — une épée, une flèche ou une boule de feu. Cela compte sur Fireball Fight, où la charge est toute l’arme et où le kit ne porte volontairement aucune épée : une manche y finissait sur « 0 touche », muette sur la seule chose qui venait d’être jouée. La fiole de soin est la seule exception, pour une raison qui lui est propre : elle a déjà son propre décompte, et un soin n’est pas une touche portée.
Et il tire. Quatre kits fournis portent un arc -- Archer, Classic, HCF et Bridge -- et sur Archer l’arc est le premier emplacement, c’est-à-dire l’arme du mode. Le bot l’utilise désormais : au-delà de la portée de mêlée, il bande l’arc, pendant les vingt ticks du jeu, l’arc visiblement plié à l’écran et son pas ralenti à une allure d’escargot, puis décoche une vraie flèche. Une vraie -- une entité qui vole, met du temps à arriver, peut être esquivée et peut manquer. Tout ce qu’un joueur apprend contre un archer tient dans ces quatre propriétés, et aucune ne survit à des dégâts appliqués à la main.
Il tire ce que le kit lui a donné : chaque flèche est prise dans le carquois, et un carquois vide le remet aussitôt à réduire la distance, exactement comme le fait un joueur. Les dégâts sont ceux du moteur, calculés d’après la vitesse de la flèche : il n’y a donc pas de seconde table de nombres qui dérive de celle du jeu.
Ce qu’il ne fait toujours pas : lancer des perles de l’Ender. Nommé ici plutôt que découvert plus tard. Aucun kit fourni ne porte de perles, donc rien de ce qui est livré n’est touché ; un kit personnalisé qui en ajoute constatera que le bot les ignore simplement.
Trois difficultés, et ce sont trois adversaires plutôt qu’un seul cadran :
| difficulté | frappe toutes les | esquive latéralement en frappant | entre dans votre ouverture | pare quand il est acculé | flèches qui touchent | dégâts |
|---|---|---|---|---|---|---|
easy | 20 ticks (1 coup/s) | non | non | non | 15 % | 85 % |
normal | 12 ticks (1,7 coup/s) | un peu | oui | non | 39 % | 100 % |
hard | 10 ticks (2 coups/s) | deux fois plus | oui | oui | 50 % | 100 % |
La colonne des flèches est mesurée, pas configurée. Les dégâts d’une flèche viennent du moteur, calculés d’après sa vitesse : le multiplicateur de dégâts de la dernière colonne ne la touche donc pas — sans autre chose, un archer easy et un archer hard tireraient de façon identique, c’est-à-dire de nouveau la plainte des « trois difficultés qui sont un seul cadran », dans le seul mode qui l’avait déjà payée. Ce qui les sépare, c’est la visée : un archer débutant ne devance pas une cible mobile. Mesuré sur un vrai client, trois essais chacun contre un joueur qui recule : 11 touches sur 75 flèches en easy, 9 sur 23 en normal, 9 sur 18 en hard.
Pourquoi hard ne frappe pas plus fort. Il le faisait : les trois niveaux valaient 70 %, 100 % et 145 % de l’arme, et c’était l’essentiel de ce qui les séparait. Un bot qui frappe plus fort n’est pas un meilleur joueur, c’est un joueur plus fort -- on apprend à lui survivre, pas à le battre. Au-dessus de easy, les dégâts sont ceux du kit, et la difficulté est dans le jeu.
Et pourquoi la cadence s’arrête à 10 ticks. Un joueur qui prend un coup en 1.8 est invulnérable pendant dix ticks : deux coups par seconde passent, et aucun serveur n’y change rien. Une édition antérieure de ce guide promettait 3,3 coups par seconde pour hard. C’est impossible sur n’importe quel serveur 1.8 — et sur un vrai client le bot hard portait en fait moins de coups que le bot easy, parce qu’il dépensait la différence à se soigner. hard frappe maintenant aussi vite que le jeu le permet, et les nombres ci-dessus sont ceux que vous verrez.
Les trois choses qu’il fait avec cette vitesse :
- Il esquive latéralement en frappant. Une cible qui glisse sur le côté est difficile à viser ;
easyreste - Il entre dans votre ouverture. Quand votre main est levée -- manger, boire, parer -- il cesse de
- Il pare quand il est acculé. À court de potions et bas, il tient son épée levée entre deux coups :
immobile exprès, pour qu’un débutant ait quelque chose à toucher.
tourner autour et s’engage. C’est la fenêtre autour de laquelle tout le 1.8 se joue, et c’est la même fenêtre que le bot ouvre quand il mange sa propre pomme. Elle est maintenant des deux côtés du combat.
moitié des dégâts, moitié de la vitesse, exactement l’échange que propose le jeu. Vous apprenez à l’attendre plutôt qu’à frapper dedans.
Il recule aussi quand il est bas au lieu de marcher dans votre épée, et il tourne autour de vous entre deux coups au lieu de rester immobile.
Rien n’est enregistré. Aucun ELO ne bouge, aucun match n’est archivé, aucun classement ne change. Un rating gagné contre une machine ne dirait rien de personne. Votre inventaire revient par le même instantané que celui d’un duel -- pas par un chemin à part -- si bien que terminer un entraînement, mourir, se déconnecter ou un redémarrage du serveur vous rendent tous vos objets.
4. Configuration
config.yml est commenté clé par clé. /practice config montre ce qui est réellement en vigueur — /practice config duel pour une section, /practice config all pour tout d’un coup.
Ou modifiez-la sans ouvrir de fichier. /practice admin → Configuration liste les sections, et chaque réglage à l’intérieur montre la valeur utilisée en ce moment et d’où elle vient : votre fichier, votre preset, ou la valeur par défaut du plugin. Sur les 89 réglages, 67 sont des nombres ou des interrupteurs et se changent d’un clic — clic gauche pour augmenter, clic droit pour diminuer, et un carré règle de combien bouge un clic. Les 22 restants sont du texte (adresses, mots de passe, formats du tableau latéral, sons) : un inventaire 1.8 n’a pas de zone de texte, la fenêtre les affiche donc et vous dit de les modifier dans le fichier.
Trois choses que cette fenêtre fait exprès :
- Elle réécrit une seule ligne. Pas le fichier. Les 340 lignes de commentaire qui expliquent chaque réglage sont
- Elle ne peut pas écrire une configuration que le serveur refuserait ensuite. Avant d’écrire, elle construit les
- Elle ne fait pas croire qu’un changement est actif. Les réglages sont lus une seule fois, au démarrage. Un carré que vous avez
toujours là ensuite, à leur place, avec la note de fin de ligne propre à la valeur sur ce que chaque preset écrirait à la place. (La façon évidente d’enregistrer un réglage depuis le jeu les détruit toutes d’un coup, sans erreur et sans qu’aucune valeur devienne fausse.)
réglages que vous proposez et demande au plugin s’il les accepterait au démarrage. Sinon, rien n’est écrit et on vous montre l’objection du plugin lui-même.
modifié montre à la fois la valeur en service et celle que lira le prochain démarrage, pour que les deux ne soient jamais confondues.
Rien d’autre n’écrit dans config.yml : modifiez-le à la main quand vous préférez, lancez /reload ou redémarrez.
Les parties que touchent la plupart des serveurs :
preset—competitive,casualoutournament: un ensemble de réglages qui tiennent ensemble, choisi
en un mot.
Les douze clés qu’un preset décide sont livrées avec le mot preset à la place d’un nombre (countdown-seconds: preset). Écrivez-y une valeur et votre valeur l’emporte — cette règle n’a aucune exception dans ce fichier. Remettez le mot et le preset décide de nouveau. /practice config marque chaque ligne décidée par le preset, si bien que vous n’avez jamais à ouvrir le fichier pour savoir laquelle est laquelle.
competitive | casual | tournament | |
|---|---|---|---|
duel.countdown-seconds | 5 | 3 | 10 |
duel.max-duration-seconds | 300 | 240 | 600 |
duel.between-rounds-seconds | 5 | 5 | 10 |
matchmaking.initial-elo-window | 50 | 200 | 50 |
matchmaking.max-elo-window | 400 | 2000 | 400 |
matchmaking.ping-difference-limit | 120 | 250 | 120 |
event.registration-seconds | 45 | 45 | 120 |
event.min-entrants | 2 | 2 | 4 |
integrity.abandon-threshold | 3 | 5 | 2 |
integrity.abandon-cooldown-seconds | 300 | 120 | 600 |
integrity.abandon-max-cooldown-seconds | 1200 | 300 | 1200 |
integrity.repeat-decay | 0.7 | 0.7 | 1.0 (désactivé) |
Vous mettez à jour depuis une ancienne version ? Votre config.yml n’est jamais réécrit : il contient donc encore des nombres sur ces douze clés et ils continuent de l’emporter — ce qui est correct, ce sont vos valeurs. Changer preset ne ferait alors rien, et le serveur le dit au démarrage en nommant chaque clé. Écrivez preset à la place d’un nombre pour rendre la main sur cette clé.
duel.countdown-seconds,duel.max-duration-seconds— les deux qui changent la sensation d’une manche.matchmaking.*— la fenêtre de rating, la vitesse à laquelle elle s’élargit, et l’écart de ping refusé entre deuxfeedback.*— les sons, les titres et la bande de la liste des joueurs. Chaque son tient en une lignehud.duel-lines,hud.queue-lines,hud.lobby-lines— **quelles lignes le tableau latéral affiche, et dansranking.divisions— les paliers, sur une ligne, du plus bas au plus hautarchive.max-matchesetarchive.keep-days— combien de manches restent en mémoire (avec leursintegrity.*— limites d’invitations, l’attente après des abandons répétés, et le rapport. **Rien dans
adversaires. Ce dernier compte en 1.8.
("NOTE_PLING 1.0 2.0", ou "none") ; un nom inconnu arrête le serveur et propose les plus proches plutôt que de jouer en silence.
quel ordre**. Écrivez les identifiants voulus, blank pour une ligne vide. Un identifiant que ce tableau ne connaît pas arrête le serveur et liste ceux qui existent. Une ligne qui n’a rien à dire pour le moment disparaît toute seule.
(Bronze:0, Silver:1050, ...). Renommez-les, ajoutez-en, retirez-en : un rating est un nombre que personne ne dit à voix haute, un palier est une identité.
inventaires de fin de manche) et combien de jours de résultats restent sur le disque. Le résultat de chaque manche est écrit dans la base : les matchs d’un joueur survivent donc à un redémarrage et ne sont jamais chassés par ceux des autres ; 0 jour garde tout.
cette section ne bannit, ne retire de points ni ne marque un compte** : le plugin empêche ce qui est certainement nuisible, rend le boost inutile plutôt que de le punir, et ne fait que montrer ce qu’il ne peut pas prouver.
Les fichiers de langue (messages_en.yml, messages_fr.yml) sont créés au premier démarrage et jamais réécrits. Traduisez-les librement ; une clé que vous supprimez retombe sur celle qui est dans le jar. Déposez un messages_es.yml à côté et il est chargé au démarrage et proposé dans /practice lang. Une traduction partielle est acceptée — ce qui manque s’affiche en anglais et le journal vous dit combien.
Les deux façons d’utiliser une langue ajoutée sont testées contre un vrai client 1.8.9 avant la publication : un joueur qui la choisit avec /practice lang es sur un serveur anglais, et le serveur lui-même tournant dans cette langue (language: es dans config.yml). Dans les deux cas, les phrases traduites arrivent traduites avec leurs paramètres substitués, tout le reste revient en anglais, et aucun nom de clé ni aucun {0} non substitué n’atteint jamais le joueur. Le journal dit combien il en manque -- « Added language 'es' loaded from messages_es.yml (3/944 texts; the rest falls back to en) » -- parce qu’une traduction faite à 0,4 % et crue terminée est le seul moyen d’envoyer de l’anglais à des joueurs qui ne s’y attendent pas.
4b. Stockage : SQLite, MySQL, MariaDB ou PostgreSQL
La valeur par défaut n’a besoin de rien d’installé. Telle quelle, le plugin garde les ratings, les inventaires dus et les rangements de kits enregistrés dans un unique fichier SQLite, dans son propre dossier. Pas de base à mettre en place, pas de mot de passe à garder, pas de service à surveiller, aucune exigence de système. C’est voulu, et c’est la forme de la promesse : aucune dépendance externe obligatoire.
Les trois autres moteurs sont un choix, jamais une obligation. Prenez-en un si vous exploitez déjà une base et préférez que les données de practice y vivent -- pour les sauvegardes que vous faites déjà, ou le tableau de bord que vous avez déjà.
storage:
type: sqlite # sqlite | mysql | mariadb | postgresql
host: localhost
port: 0 # 0 = la valeur par défaut du moteur (3306 / 5432)
database: practice
user: practice
password: ""
ssl: false
Des pilotes mesurés plutôt que supposés. Le jar de Spigot 1.8.8 a été ouvert et son contenu compté :
| Moteur | Pilote | Ce que vous devez faire |
|---|---|---|
sqlite | livré par Spigot | rien |
mysql | livré par Spigot (Connector/J 5.1) | rien |
mariadb | le même pilote -- MariaDB parle le protocole MySQL | rien |
postgresql | non livré | mettez le jar du pilote dans plugins/PracticeCore/drivers/ |
Ce plugin ne télécharge jamais rien. Le seul appel réseau qu’il fait est la vérification de licence décrite à la section 1b, vers une seule adresse et nulle part ailleurs. Si un pilote manque, il le dit, nomme le dossier, et refuse de démarrer plutôt que de tourner sans persistance.
Une réserve, écrite plutôt que laissée à découvrir. Le pilote que livre Spigot est Connector/J 5.1, qui ne peut pas s’authentifier auprès d’un compte MySQL 8 utilisant caching_sha2_password -- le réglage par défaut de MySQL 8. Créez le compte avec mysql_native_password, ou déposez un jar Connector/J 8 dans ce même dossier drivers/.
Et le refus le dit, avec ces mots. Cela a été vérifié contre un vrai MySQL 8 plutôt que supposé, et la première tentative a trouvé le guide faux : le plugin affichait le message de surface du pilote et vous envoyait vérifier l’hôte, le port, la base et le compte -- les quatre étaient corrects. Ce qu’il affiche maintenant, c’est :
> the account uses an authentication method the driver cannot negotiate. The driver that ships with > Spigot 1.8.8 is Connector/J 5.1, and MySQL 8 creates accounts with caching_sha2_password by > default. Two ways out, either is fine: run ALTER USER 'you'@'your-host' IDENTIFIED WITH > mysql_native_password BY '<password>'; on your database, or put a Connector/J 8 jar in > plugins/PracticeCore/drivers/. Nothing else is misconfigured: the host, the port, the > database and the password are being accepted up to this point.
(Traduction libre du message ci-dessus : le compte utilise une méthode d’authentification que le pilote ne sait pas négocier ; le pilote livré avec Spigot 1.8.8 est Connector/J 5.1 et MySQL 8 crée ses comptes avec caching_sha2_password par défaut ; deux issues, au choix : lancer ALTER USER pour passer le compte en mysql_native_password, ou déposer un jar Connector/J 8 dans plugins/PracticeCore/drivers/ ; rien d’autre n’est mal configuré : l’hôte, le port, la base et le mot de passe sont acceptés jusqu’ici.)
Le même traitement couvre un mot de passe erroné, une base qui n’existe pas et un serveur qui ne répond pas -- chacun dit lequel des quatre c’est, pour que vous ne vérifiiez pas les trois autres.
Ce qui est vérifié, et ce qui ne l’est pas. Trois niveaux, et il vaut la peine de savoir lequel est lequel.
| Moteur | Vérifié comment |
|---|---|
sqlite | chaque campagne de tests tourne dessus, plus l’installation en salle blanche |
postgresql | un vrai serveur PostgreSQL 16.15 : l’archive livrée décompressée sur un serveur vide, le pilote déposé dans drivers/, les seize kits créés, une arène construite, un duel classé joué et décidé, le classement écrit et relu |
mariadb | deux vrais serveurs adossés à MariaDB derrière un proxy Velocity : un duel classé inter-serveurs, le classement partagé relu depuis l’autre serveur (voir 4c) |
mysql | un vrai serveur MySQL 8.0.46, dans les deux sens : un compte en mysql_native_password (tout le parcours de l’acheteur, sept contrôles, aucun échec) et un compte en caching_sha2_password (le refus ci-dessous, vérifié mot pour mot) |
L’essai PostgreSQL a utilisé pgjdbc 42.7.2 ; l’essai MySQL a utilisé le pilote que livre Spigot. Les quatre moteurs ont maintenant porté un vrai duel classé. Aucune affirmation de ce document ne repose sur un moteur que personne n’a fait tourner.
Changer de moteur ne déplace pas vos données : le plugin crée son schéma dans la base que vous lui indiquez, et y repart vide. L’export et l’import sont le travail de votre base de données, pas celui de ce plugin.
4c. Plusieurs serveurs, une seule pratique
Désactivé par défaut. Un serveur seul ne lit rien de tout cela et n’y perd rien -- pas d’interrogation périodique, pas de signal de vie, aucune table touchée.
Une fois activé, les ratings, les rangements de kits et les inventaires dus suivent déjà le joueur d’un serveur à l’autre : ils vivent dans la base partagée, et c’est tout ce qu’il faut. Ce que cela ajoute, c’est une file commune. Un joueur sur arena-1 est apparié à un joueur sur arena-2, et l’un des deux est envoyé de l’autre côté par votre proxy.
Le combat ne traverse jamais. Les deux joueurs se retrouvent sur un serveur et le duel s’y déroule exactement comme un duel local -- même code, mêmes tests, même coût. Faire se battre deux joueurs à travers un réseau voudrait dire synchroniser les positions tick par tick ; c’est un autre produit, et il serait injouable en 1.8.
network:
enabled: true
server-id: "arena-1" # exactement le nom sous lequel votre proxy connaît ce serveur
poll-seconds: 2
ladder-refresh-seconds: 20
ladder-refresh-seconds est la fréquence à laquelle ce serveur relit le classement écrit par les autres, pour que les classements et /practice stats montrent ce qui s’est passé ailleurs sans redémarrage. Cela n’affecte que ce qui est affiché : les points d’un duel sont toujours calculés depuis la base partagée au moment où le duel se termine, jamais depuis un instantané local. Baissez-le si vous voulez des classements plus frais, augmentez-le si votre base est loin.
Deux choses sont refusées au démarrage, avec la raison, plutôt que laissées à découvrir :
server-idvide. C’est le nom utilisé pour envoyer les joueurs de l’autre côté : un mauvais nom les envoie nulle part.storage.type: sqlite. Une base SQLite est un fichier local : deux serveurs ne peuvent pas la partager, il n’y
aurait donc aucune file commune -- et rien n’aurait l’air cassé, la file resterait simplement vide pour toujours.
Rien d’autre à installer. Pas de Redis, pas de bus de messages, pas de plugin sur le proxy. La coordination passe par la base que vous avez déjà configurée, et le transfert utilise le canal BungeeCord que BungeeCord et Velocity écoutent tous deux d’office.
Ce que coûte la coordination, mesuré. La file commune est une interrogation périodique : chaque serveur lit la même table toutes les poll-seconds, relit le classement toutes les ladder-refresh-seconds, et écrit son propre signal de vie. Quatre vrais serveurs derrière un proxy Velocity, sur une même MariaDB, au repos et sans personne de connecté :
201 queries in 20 s -> 10,05 /s for the network -> 2,51 /s per server
C’est ce que vous payez en permanence, et cela croît avec le nombre de serveurs, pas plus vite : dix serveurs font environ vingt-cinq requêtes par seconde, ce que n’importe quelle base gère sans s’en apercevoir. Avec quatre joueurs en file en même temps sur quatre serveurs différents, deux duels inter-serveurs ont démarré, deux joueurs ont été réellement déplacés par le proxy — lu dans le propre journal de connexion de Spigot, pas dans celui du plugin — personne n’a été réclamé par deux serveurs à la fois, et la base est montée à 10,5 requêtes par seconde pendant les duels.
Reproduisez-le vous-même : NET_ARENAS=4 qa/network/run-network-test.sh <jar>.
Ce qui se passe quand quelque chose tombe -- sur un réseau, c’est le cas normal, pas l’exception :
| ce qui casse | ce qui se passe |
|---|---|
| le joueur en déplacement n’arrive jamais | son rendez-vous expire ; l’hôte cesse d’attendre |
| le serveur hôte meurt en plein appariement | la réclamation expire ; les deux joueurs retournent dans la file |
| un serveur disparaît | il cesse de se signaler, et les autres cessent de le compter |
Rien de tout cela n’exige une intervention. /practice status liste chaque serveur en vie, combien de joueurs il porte et depuis combien de temps il s’est signalé pour la dernière fois -- ce que vous voulez quand une file ne produit pas de matchs.
Cela a été exécuté, pas seulement écrit. Deux serveurs Spigot avec des server-id distincts, une MariaDB partagée, un proxy Velocity en mode de transfert hérité. Un joueur s’est mis en file sur arena-2 tandis que son adversaire se mettait en file sur arena-1 ; celui qui avait le moins attendu a été informé de sa destination, le proxy l’a déplacé -- confirmé dans le journal de connexion du serveur, pas sur la parole du plugin -- le duel a commencé sur arena-1, a été disputé et décidé, et le résultat a ensuite été relu depuis le classement d’arena-2. Le script qui construit ce banc est livré dans qa/network/.
Les limites, simplement. L’inter-serveurs couvre les files 1v1. Les groupes, les files par équipes (2v2, 3v3) et les événements restent sur un seul serveur : ils ne sont pas partagés, et un groupe ne peut pas s’étendre sur plusieurs serveurs. Deux joueurs qui se mettent en file sur le même serveur y sont appariés sans que personne ne voyage.
5. PlaceholderAPI (facultatif)
Si PlaceholderAPI est installé, Practice Core enregistre une extension practice au démarrage et les placeholders ci-dessous se résolvent partout où PlaceholderAPI est lu — liste des joueurs, format du chat, hologrammes, tableaux latéraux d’un autre plugin. S’il n’est pas installé, rien ne change et rien n’est journalisé : Practice Core n’en dépend pas, n’embarque aucune de ses classes, et ne le demande jamais. Un serveur sans PlaceholderAPI est le cas normal.
/papi info practice les liste en jeu. Chaque jeton ci-dessous est vérifié par un test qui demande au plugin de le résoudre : cette liste ne peut donc pas s’écarter de ce qui répond réellement.
À propos du joueur
| Placeholder | Répond |
|---|---|
%practice_state% | lobby, queue, duel, melee, spectating, editing, training ou event. Traitez un mot que vous ne connaissez pas comme lobby : une version ultérieure peut en ajouter un |
%practice_in_match% | true pendant un duel ou une mêlée, false sinon |
%practice_kit% | le kit joué ou en file d’attente, tel qu’affiché (NoDebuff) |
%practice_kit_id% | le même kit comme identifiant (nodebuff), pour construire un autre placeholder |
%practice_opponent% | le nom de l’adversaire dans un 1v1, vide sinon |
%practice_rating% | le rating global, pondéré par les matchs joués par kit |
%practice_wins% / %practice_losses% / %practice_matches% | totaux sur tous les kits joués |
%practice_rating_<kit>% | le rating sur ce kit |
%practice_wins_<kit>% / %practice_losses_<kit>% | victoires et défaites sur ce kit |
%practice_matches_<kit>% | matchs joués sur ce kit |
%practice_streak_<kit>% / %practice_beststreak_<kit>% | série de victoires actuelle et meilleure série |
À propos du serveur
| Placeholder | Répond |
|---|---|
%practice_online% | joueurs connectés |
%practice_ongoing% | matchs en cours, duels et mêlées confondus |
%practice_queued% | joueurs en attente, toutes files confondues |
%practice_queued_<kit>% | joueurs en attente sur ce kit, classés et non classés, toutes tailles d’équipe |
%practice_topname_<rank>_<kit>% | le nom à ce rang dans le classement de ce kit, de 1 à 10 |
%practice_toprating_<rank>_<kit>% | le rating à ce rang |
Trois choses à savoir avant de les écrire dans votre liste des joueurs :
%practice_state%répond un mot stable, pas une phrase. C’est un identifiant fait pour être lu- Un jeton mal orthographié reste visible.
%practice_ratign%se résout en lui-même plutôt qu’en chaîne - Le classement a au plus une seconde de retard. Trier tous les joueurs classés d’un kit est la seule
par votre configuration, pas affiché tel quel à un joueur — écrivez la phrase autour, dans votre propre langue et vos propres couleurs. Ces cinq mots sont stables ; un nouveau type de match, s’il en est jamais ajouté, ajouterait un sixième plutôt que de renommer l’un d’eux. Utilisez %practice_in_match% plutôt que de comparer le mot vous-même, et votre configuration continue de fonctionner.
vide : une faute de frappe se voit au lieu de vider silencieusement la ligne.
réponse coûteuse ici : elle est donc gardée une seconde puis retriée. Tout le reste est une consultation de table ou un compteur que le plugin tient déjà — ces placeholders peuvent être rafraîchis à chaque tick sans risque.
Les rangs au-delà du dixième ne sont pas publiés, et un rang que personne ne tient encore répond vide pour que votre ligne garde sa forme sur un serveur neuf.
6. Ce qu’il ne fait pas
Écrit ici plutôt que découvert plus tard :
- 1.8.8 / 1.8.9 seulement. Pas 1.9+, et ViaVersion n’est pas requis (ni pris en charge comme cible).
- Pas de Bedrock.
- L’inter-serveurs ne couvre que les files 1v1 (voir la section 4c), et seulement quand vous l’activez. Les groupes,
- Pas d’anti-triche. La portée, l’autoclic et le reste sont le travail de quelqu’un d’autre.
- La surveillance compétitive signale, elle ne sanctionne jamais -- à l’exception de l’unique mesure qui agit
- Les attentes après abandon et les limites de débit d’invitations ne sont pas conservées d’un redémarrage à l’autre. Leurs fenêtres sont
les files par équipes et les événements restent sur un seul serveur. Un groupe ne peut pas s’étendre sur plusieurs serveurs.
sans accuser personne : les rencontres répétées entre les deux mêmes joueurs comptent moins dans le classement. Cette fenêtre survit à un redémarrage (elle est rejouée depuis votre historique au démarrage) ; les rapports eux-mêmes sont lus, jamais appliqués.
de trente minutes et d’une minute : un redémarrage tombe rarement dans l’une d’elles, et les deux sont des pénalités, que nous préférons pardonner plutôt que reconstruire.
7. D’où viennent les chiffres
Chaque affirmation de performance sur ce plugin est mesurée sur un vrai serveur avec de vrais clients 1.8, et re-mesurée sur l’artefact effectivement publié — pas héritée d’une ancienne version.
La charge, mesurée sur cette version :
| connectés | coût du plugin, 95e centile | pire tick | TPS |
|---|---|---|---|
| 1 | 0,486 ms | 1,993 ms | 20 |
| 51 | 0,307 ms | 0,451 ms | 20 |
| 101 | 0,314 ms | 0,901 ms | 20 |
| 151 | 0,292 ms | 1,807 ms | 20 |
| 201 | 0,363 ms | 1,252 ms | 20 |
C’est moins d’un pour cent d’un tick de 50 ms à deux cents joueurs, et -- c’est la partie qui mérite d’être lue deux fois -- le coût ne croît pas de façon mesurable avec la population dans cette plage. La droite ajustée est plate aux erreurs de mesure près (0,405 ms + -0,0005 ms par joueur), ce qui revient à dire que le tableau latéral coûte ce qu’il coûte par joueur et rien de plus parce qu’il a des voisins.
Ces chiffres remplacent ceux publiés auparavant (1,34 ms à 200 joueurs), et la raison n’est pas un changement du plugin : l’ancien banc était lui-même le goulot d’étranglement. Il tenait les deux cents clients dans un seul processus, et un processus client à la peine, c’est du temps que le serveur dépense en entrées-sorties réseau. Réparti sur quatre processus, le même build mesure trois fois moins. Un nombre mesuré à travers un instrument saturé n’est pas un nombre, et il n’est pas reporté.
Des matchs réellement disputés -- le chiffre sur lequel un serveur de practice est vraiment jugé. Des joueurs connectés dans un lobby ne coûtent presque rien ; vingt duels joués en même temps, c’est la vraie charge, et c’est le chiffre que ce guide n’avait pas. De vrais clients 1.8 bruts sont mis en file, appariés, puis se frappent les uns les autres au plafond du jeu, deux coups portés par seconde, pendant trente secondes par palier, sur l’artefact publié :
| duels simultanés | joueurs au combat | tableau latéral, moyenne | tableau latéral, 95e | échantillonnage du replay, 95e | règles du mode, 95e |
|---|---|---|---|---|---|
| 1 | 2 | 0,044 ms | 0,299 ms | 0,042 ms | 0,033 ms |
| 5 | 10 | 0,153 ms | 0,337 ms | 0,076 ms | 0,061 ms |
| 10 | 20 | 0,213 ms | 0,490 ms | 0,110 ms | 0,042 ms |
| 20 | 40 | 0,316 ms | 0,565 ms | 0,123 ms | 0,124 ms |
Le tableau latéral tourne à chaque tick, l’échantillonneur de replay dix fois par seconde, la règle de mode une fois. À vingt duels simultanés, cela fait environ six dixièmes de milliseconde dans un tick de 50 ms, soit un et demi pour cent, avec 2 400 coups portés pendant la mesure.
Le plafond ici, c’est le banc, pas le plugin. Un palier de trente duels a été tenté et seuls vingt se sont formés : un seul processus qui tient soixante clients de protocole et frappe pour tous est ce qui lâche, ce qui est le même piège que celui du banc de population à deux cents joueurs, réglé en répartissant sur quatre processus. Le banc de combat n’a pas encore été réparti : vingt duels, c’est donc ce qui est mesuré et par conséquent tout ce qui est revendiqué.
Deux cents joueurs, tous en file en même temps -- maintenant mesuré. C’était le seul nombre que ce guide disait ne pas avoir. Le banc tenait les deux cents clients dans un seul processus, et ce processus -- pas le serveur -- lâchait pendant la rafale. Il les répartit maintenant sur quatre processus, et la mesure existe :
| quoi | mesuré |
|---|---|
| joueurs connectés | 201 (200 plus un opérateur), comptés par le banc plutôt que supposés |
| ils se mettent tous en file au même instant | 25 duels démarrés, dans les trois essais |
| coût d’un démarrage de duel | 10,1 / 12,0 / 13,6 ms en moyenne sur trois essais consécutifs (15,0 / 19,9 / 22,1 au 95e ; 33 / 35 / 41 au pire) |
| le tableau latéral pendant cette rafale | 0,55 / 0,52 / 0,60 ms en moyenne, 0,79 / 0,83 / 1,17 au 95e |
| le tableau latéral au repos, 201 connectés | 0,324 ms en moyenne, 0,445 au 95e, 0,543 au pire |
| TPS | 20, descendant à 19,97 à partir de cent joueurs |
Trois nombres et non un seul, exprès. Les trois essais sont le même artefact, la même machine, à quelques minutes d’écart -- et le coût de démarrage d’un duel augmente à chacun. Cette dérive appartient à la machine (un VPS partagé qui fait aussi tourner un serveur de production), pas au plugin, et imprimer le plus joli des trois comme s’il était le chiffre serait le genre de mesure que ce document refuse ailleurs. Une édition antérieure de ce guide imprimait 8,4 ms d’un autre jour ; il n’est pas reporté, parce qu’il n’a pas été mesuré sur l’artefact que vous recevez.
Un démarrage de duel est devenu quatre millisecondes moins cher, et le tick a récupéré sa base. La copie de votre inventaire qui est gardée pour qu’un plantage puisse vous le rendre était écrite dans le tick, deux fois par démarrage de duel -- 2,023 ms en moyenne et jusqu’à 10,190 ms chacune, mesuré sur quarante matchs. Transformer l’inventaire en texte en faisait les deux tiers, et c’est du calcul pur sur une copie que personne d’autre ne peut toucher. Les deux sont passés au fil d’écriture qui portait déjà les ratings, l’historique et les réglages ; la même mesure donne maintenant 0,021 ms, et le compteur du plugin des requêtes de base sur le fil du serveur est passé de 40 à zéro. Sur SQLite, cela rend quatre millisecondes à chaque match ; sur un MySQL distant, où chacune de ces écritures était un aller-retour réseau dans le tick, c’est davantage, et cela croît avec la latence de votre base plutôt qu’avec le nombre de vos joueurs.
Pourquoi 25 duels et pas 100, et pourquoi c’est voulu. L’appariement tourne sur un budget -- matchmaking.queue-start-budget-ms, 8 ms par défaut -- et un démarrage de duel coûte de 10 à 14 ms à cette population. Une passe démarre donc un duel, et une file de deux cents joueurs se vide en une quarantaine de secondes plutôt que de saisir le serveur pendant une seconde. C’est l’échange que ce plugin fait délibérément : la file est plus lente qu’elle ne pourrait l’être pour que le jeu de personne ne saccade. Augmentez cette clé si vous préférez vider plus vite, et surveillez duel.start dans /practice perf pendant ce temps.
Le tableau latéral ne croît pas avec la population, et c’est le chiffre qui vaut d’être gardé. Mesuré sur cinq paliers sur l’artefact publié : 0,561 ms au 95e avec un joueur, 0,412 à cinquante et un, 0,339 à cent un, 0,336 à cent cinquante et un, 0,445 à deux cent un. Un ajustement par moindres carrés sur ces cinq points a une pente négative -- le coût par joueur n’est pas mesurable au-dessus du bruit. (Le banc tourne sur quatre processus pour cette raison : un seul était le goulot d’étranglement et se mesurait lui-même. Une ancienne édition imprimait 1,344 ms à 200 joueurs ; c’était un banc à la peine autant qu’un serveur, et il n’est pas reporté non plus.)
La campagne fonctionnelle exécute 250 contrôles qui lui sont propres, pilotés par de vrais clients 1.8.9, sur l’artefact exact qui est publié, et dans la même passe elle exécute 37 bancs de parcours complets -- le lobby, le tableau latéral, le parcours d’un spectateur dans un match, le chat de groupe, un tournoi de l’inscription au podium, les premières minutes d’un administrateur, et l’entraînement contre le bot sur chacun des kits fournis. Ceux-ci étaient exécutés à la main, ce qui veut dire qu’ils l’étaient quand quelqu’un s’en souvenait.
Sur la dernière version, cela a fait 874 contrôles en une passe : 250 dans les sections propres à la campagne et 624 sur les bancs de parcours, aucun en échec. La campagne imprime elle-même les deux nombres, pour que personne n’ait à les recopier : un chiffre publié ici disait 488 parce que quelqu’un avait compté des lignes dans un journal, et la vérité était 471.
Ces deux nombres sont ceux que calcule la campagne, et ils sous-comptent : les bancs qu’elle lance par leur nom plutôt que par le balayage -- l’entraînement sur chaque kit fourni, la couverture des kits, les formats d’événements, les permissions -- rapportent leurs propres totaux dans le journal et ne sont pas ajoutés. Le chiffre ci-dessus est donc un plancher, pas un plafond. Il est publié ainsi exprès : un nombre produit vaut plus qu’un nombre complet et recopié.
Viennent ensuite les bancs qui demandent plus d’une machine ou une machine cassée, exécutés seuls : quinze sur deux serveurs derrière un proxy, sept sur une installation PostgreSQL réelle, sept sur une langue ajoutée, huit sur la licence -- de dix jours de silence à une clé manquante -- six sur une base volontairement corrompue, et vingt-deux contre un Spigot 1.8.8 nu, sans aucun plugin. Ce dernier est la seule référence qui puisse dire si le recul et la fenêtre de coup de ce plugin sont ceux de 1.8, parce que tous les autres bancs comparent le plugin à lui-même.
Le plafond du banc de charge est son propre max-players, pas le plugin et pas la mémoire. La méthode et les chiffres sont publiés avec la version. Si un nombre n’a pas été mesuré, il n’est pas revendiqué.
Vous pouvez reproduire l’essentiel sur votre propre serveur : /practice perf montre le coût de chaque opération sur le fil principal, et /practice selftest full dit ce qui est mal configuré et pourquoi.
Pour les auteurs de modules complémentaires, le contrat public — quatre événements et l’API des modes — se trouve dans docs/API.md.