Aller au contenu

← Tous les projets

2016 → 2017 Architecte & développeur backend

Endariel — fondations distribuées d'un réseau Minecraft, chez Vidcraft

Le SDK fondateur de l'écosystème Minecraft Vidcraft : 2 133 commits sur 11 mois, 150+ classes Java sous `fr.endariel`, un bus Redis pub/sub typé et un accès NMS direct posés en 2016 quand BungeeCord n'était qu'un proxy TCP. C'est ce tronc qui deviendra Unitale en 2019.

  • Java 8
  • Spigot 1.10.2 (fork unispigot-server)
  • BungeeCord
  • Jedis 2.8
  • Apache HttpClient
  • Socket.io
  • Redis pub/sub
  • Netty
  • NMS reverse engineering
  • Maven multi-module
  • Systèmes distribués

Contexte

En 2016, l’écosystème Minecraft français regardait Mineplex et Hypixel et se demandait comment monter un réseau multi-modes à plusieurs dizaines de milliers de joueurs sans cluster monolithique bespoke. Vidcraft, studio derrière Endariel, voulait jouer dans cette cour : plusieurs modes de jeu, une économie partagée, des joueurs qui hopent d’un serveur à l’autre sans recharger leur identité. Au pic, le réseau a touché 100 000+ joueurs uniques et tenu 10 000+ connexions simultanées sur 50+ instances Spigot interconnectées.

Le problème : Mojang n’a jamais conçu son serveur pour ça. Le protocole, le moteur, l’état joueur, tout est pensé single-instance. Et Kubernetes en 2016 était encore confidentiel — il n’y avait pas d’orchestrateur tout fait pour ce genre de charge sur la JVM Bukkit. Il fallait poser les fondations distribuées soi-même.

Mon rôle

J’ai conçu et porté le SDK qui orchestrait l’écosystème — la fondation Java sur laquelle tous les modes de jeu se branchaient. Architecture distribuée, reverse engineering du serveur Minecraft officiel, bus de synchronisation inter-instance, intégration avec le proxy BungeeCord : ce périmètre était sous ma responsabilité.

La mission centrale chez Vidcraft, c’était précisément ça : développer un SDK propriétaire pour les mini-jeux. Le tronc fr.endariel est né dans ce cadre, pas après — LaserGame, premier commit le 21 novembre 2016, est le premier mini-jeu à tourner dessus.

Ce que j’ai construit

Le SDK — namespace fr.endariel, 2 133 commits sur 11 mois

Le premier commit du SDK est daté du 14 juillet 2016 : 138 fichiers d’un coup, qui migrent le projet de son nom de code “IceCube” vers “Endariel” dans la même journée. Onze mois plus tard, à fin mai 2017, le tronc Java compte 150+ classes réparties sur deux trees principaux.

fr.endariel.api.* héberge la couche distribuée :

  • 11+ subscribers Redis typés dérivant d’une abstraction SubJedisPubSubCommunPubSub, SDKPubSub, ServerPlayersPubSub, PlayerEliminatedSubscriber, ServerStatusSubscriber, etc. Pas de strings broadcastés en aveugle : chaque domaine a sa classe de souscription typée qui dispatche vers les bons handlers.
  • 14+ clients REST pour les opérations cross-instance qui supportent un peu de latence : Bag, Boost, Contact, Feature, Guild, Money, News, Player, Properties, Sanction, SearchPlayer, Session…
  • Des clients Redis dédiés pour le chaud : Feature, Modo, Party, Player, Sanction, Server, Settings.

fr.endariel.sdk.* héberge le cœur gameplay :

  • PlayersEndCraftPlayer, EndPlayer, PlayerInflator (lazy loading des données joueur depuis Redis et REST), PlayerContainer, SettingsHandler, EndCraftOfflinePlayer.
  • MorphsMorphAPI, MorphManager, MorphPacketHandler, NettyManager : accès Netty bas niveau pour injecter les paquets de morphing sans dépendre de ProtocolLib.
  • Features sociales et économiques : guildes, parties, groupes, gadgets, montures, pets, boîtes (loot), sacs (inventaire), BossBar custom.
  • Aura — une dizaine d’effets visuels composables : AngelAura, CloudAura, DrinkAura, ExplosionsAura, HelicopterAura, HellAura, MultiColorRingAura, RainAura, ScannerAura, TailAura.
  • Chat distribué via ChatPubSub Redis pour la diffusion cross-instance.
  • Advancement API custom qui rend compatible la sémantique 1.12+ tout en restant ancré sur le serveur 1.10.2.
  • PVP versionné avec des listeners séparés pour 1.8 et 1.10, parce que les hitbox et les paquets de combat changent entre versions.

La stack 2016-2017

Maven multi-module, compilateur Eclipse via plexus-compiler-eclipse, packaging via Maven Shade. Côté serveur, un fork maison unispigot-server à partir de Spigot 1.10.2-R0.1-SNAPSHOT, distribué via Nexus privé sur git.endariel.fr. Redis attaqué via Jedis 2.8.1 + Apache commons-pool2 pour le pooling de connexions. Apache HttpClient 4.1.1 pour le REST. Socket.io 0.8.3 (client Java) pour les broadcasts temps réel vers les outils internes. org.json pour la sérialisation. Pas de Redisson, pas de Hazelcast, pas d’ORM, pas de MariaDB directement attachée au SDK : Redis-first, REST pour le reste. C’était la photo de la stack distribuée raisonnable en 2016 sur la JVM Bukkit.

Les premiers mini-jeux

  • LaserGame, premier commit le 21 novembre 2016 — cinq mois après le SDK, le premier mini-jeu sort et valide que le tronc tient.
  • Arena, prototype court démarré le 6 mai 2017.
  • GameSDK2, refonte du game engine entamée le 29 mai 2017 — c’est la pièce qui survivra et grandira sous Unitale en 2019.

Point dur

Synchroniser l’état joueur cross-serveur en temps réel, en 2016, sans orchestrateur moderne. À l’époque, Mineplex et Hypixel tournaient sur des clusters monolithiques avec leur middleware bespoke ; BungeeCord se résumait à un proxy TCP qui ne savait rien faire au-delà du routing. Le pari d’Endariel a été de poser, dès la première ligne du SDK, un dispatch Redis pub/sub typé en classes dédiées par domaine (CommunPubSub, SDKPubSub, ServerPlayersPubSub…), plutôt que des chaînes string à parser dans un switch géant. C’est une décision d’architecture pénible à tenir en 2016 — il faut écrire la sérialisation à la main, gérer les versions de schéma, baliser chaque nouveau canal — mais c’est elle qui rend possible le hop joueur sous la seconde, l’économie cohérente, l’anti-cheat cross-instance.

L’autre versant du point dur : les morphs et les inventaires custom sans ProtocolLib. La plupart des plugins de l’époque déléguaient à ProtocolLib pour intercepter les paquets ; ça mangeait du CPU sur le hot path et ça créait une dépendance lourde à un projet externe au cycle de release imprévisible. J’ai pris la voie du dessous : reverse engineering NMS CraftBukkit, mapping des entités et des paquets non documentés, et accès Netty direct via NettyManager et MorphPacketHandler. Plus rapide, plus autonome, et compatible avec le multi-version 1.8 / 1.10 / 1.12+ via un ReflectionManager qui rebranche les bons internals selon la version cible.

Résultats

  • 100 000+ joueurs uniques servis sur la durée de vie du réseau Vidcraft.
  • 10 000+ connexions simultanées en pic, sans dégradation visible côté client.
  • 50+ instances Spigot orchestrées comme un seul réseau cohérent via le bus Redis pub/sub typé.
  • 2 133 commits sous le namespace fr.endariel sur 11 mois (juillet 2016 → mai 2017), soit 94 % du tronc Java avant 2018 — la fondation distribuée a été posée vite et tenue serrée.

Et la suite, qui n’est pas un secret : ce tronc Java n’est pas mort à la fermeture de Vidcraft fin 2017, il a été repris. À partir de 2019, le namespace fr.endariel est migré en fr.unitale puis fr.hycube, avec une stack modernisée — Redisson pour la couche transient, exploration Hazelcast pour les caches partagés, backend Symfony 3.3 sorti du monolithe Java en 2020. Le case study Unitale raconte cette deuxième vie. Endariel est ce tronc en version originelle.

Cette mission est aussi la rampe de lancement qui m’a mené, dans la foulée, à écrire TyphoonMC — un moteur serveur Minecraft from scratch en Go (90+ stars OSS) — puis aux problématiques scale de Dofus Touch (millions de joueurs), aux opérations SaaS d’Authlete (banques japonaises, OAuth/OIDC) et aujourd’hui à la direction technique de Conexia Tahiti. Même métier — pub/sub, cache cohérent, lifecycle propre, résilience —, échelles différentes.