Bonjour,
je vais vous présenter aujourd’hui EnderChest. EnderChest est un système de mise à jour comme S-Update, très utilisé pour les launchers.
Features
Si S-Update existe déjà, pourquoi recréer un système d’update ? Tout simplement parce que ce dernier est très vieux et utilise des mécaniques obsolètes (comme l’algorithme MD5 pour les checksums, une des causes de sa lenteur).
Après avoir parlé avec Litarvan, l’auteur du prédécesseur d’EC, j’en suis venu à créer mon propre système, avec le but qu’il soit rapide et performant.
EnderChest est donc né, et possède avec lui les fonctionnalités suivantes:
- Gestion de la concurrence et requêtes asynchrones, pour empêcher le blocage du thread d’exécution. Principalement faite grâce aux libraries
akka-stream
etakka-http
- Utilisation de l’algorithme xxHash32, environ 16.35x plus rapide que MD5.
- Chunking des données pour empêcher la taille des fichiers d’influer sur la consommation de mémoire vive.
- Installation du serveur simple, de la même manière que Spigot, SpongeVanilla ou Forge: lancer un jar.
- Configuration simple depuis un fichier YAML, créé lors du premier lancement
- Utilisation du langage Scala, parfaitement adapté à ce genre de systèmes.
Pourquoi Scala ?
J’ai choisi d’utiliser pour EnderChest le langage Scala pour EnderChest. Pouvez vous l’utiliser avec Java malgré tout ? Oui, mais je conseille cependant fortement de faire votre launcher, ou du moins d’utiliser cette lib en Scala car ce langage permet énormément de choses concernant la gestion de la concurrence et la clarté du code.
Installation
Pour l’installation du serveur, vous devez simplement télécharger dans l’onglet releases le server-xxxx-withDependencies.jar
et le lancer. Un fichier de config documenté sera généré. Plus d’informations ici.
Pour le client, vous pouvez installer la library de 2 manières différentes.
En utilisant un build tool
Le client d’EnderChest est disponible sur le Maven Central et indexé par Scaladex. Vous pouvez donc l’importer comme n’importe quelle lib avec votre build tool préféré:
Avec Gradle:
repositories {
mavenCentral()
}
dependencies {
implementation 'io.github.iltotore:ec-client_2.13:version'
}
Étant donné que le MDK utilise Gradle, je pense qu’il s’agit de la solution à laquelle le plus de monde est habitué ici.
Avec SBT:
libraryDependencies += "io.github.iltotore" %% "ec-client" % "version"
En utilisant le jar.
Rendez vous sur les releases Github et téléchargez le fichier client-xxx-withDependencies
. Vous pouvez ensuite l’importer dans votre IDE comme n’importe quelle autre library.
Noter que vous devrez probablement incorporer la library à votre jar final. Avec Gradle je vous recommande d’utiliser le plugin shadowJar
.
Les bases
Créer un FileAnalyzer
Commençons d’abord par créer une nouvelle instance de FileAnalyzer, qui servira à indexer les fichiers du client Minecraft:
val rootPath = Paths.get("blabla") //À noter que vous pouvez également résoudre le Path par rapport à la localisation de votre jar, ou le dossier utilisateur.
val analyzer = new FileAnalyzer(rootPath)
Si vous voulez exclure des fichiers ou augmenter le max depth, précisez le/les comme ceci:
val analyzer = new FileAnalyzer(
rootPath, //Le chemin vers le dossier racine des téléchargements.
exclude = _.startWith("shaderpacks/"), //Exclu tous les fichiers qui sont dans le dossier `shaderpacks`, à la racine des téléchargements.
maxDepth = Option(100) //La profondeur de recherche maximale est maintenant de 100.
) //Remarque: vous pouvez également déclarer les paramètres sur une ligne.
À noter que les fichiers exclus seront téléchargés si manquants mais ne seront pas modifiés/supprimés. Les fichiers inconnus ne seront pas non plus effacés si exclus.
Instancier le client
Maintenant que nous avons créé notre FileAnalyzer, nous pouvons maintenant créer notre EnderClient qui servira à mettre à jour le système. Nous allons utiliser la méthode apply
, qui utilise certaines valeurs par défaut. Notons que Foo.apply()
en Scala est la même chose que Foo()
.
val client = EnderChest("https://localhost:8080/" /*L'adresse vers le serveur d'update*/, analyzer)
Vous maintenant prêt à utiliser les fonctionnalités du client !
Indexer les fichiers
La première chose à faire est d’indexer les fichiers déjà existants de notre client Minecraft:
client.checkFiles()
Cette méthode a la particularité de renvoyer un Future[Int], qui va indexer les fichiers en parallèle. Le paramètre générique Int
est utilisé pour symboliser le nombre de fichiers indexés.
Utilisons maintenant une fonctionnalité de Scala qui vient tout droit de la programmation fonctionnelle: le Pattern Matching.
client.checkFiles.onComplete {
case Success(count) => println(count + " fichiers ont été indexés.")
case Failure(exception) => exception.printStacktrace().
} //Les paranthèses de la méthode ne sont pas obligatoires.
Une fois les fichiers analysés, nous pouvons lancer la requête de mise à jour (vous pouvez également indexer les fichiers avant au lieu de juste avant d’update). Nous allons simplement utiliser client.update()
et la méthode flatMap
des futures pour pouvoir lancer l’update dès que l’indexation est finie:
client.checkFiles.flatMap(_ => client.update()).onComplete {
case Success(done) => println("Mise à jour terminée !")
case Failure(exception) => exception.printStacktrace()
}
Voilà, vous avez maintenant les bases nécessaire (si tant est que vous avez appris le Scala =p) pour pouvoir utiliser EnderChest.
Voici quelques liens utiles:
- Github: https://github.com/Iltotore/EnderChest
- Scaladex: https://index.scala-lang.org/iltotore/enderchest/ec-client
- Discord: https://discord.gg/zX3A8Nb
Le projet est open-source et gratuit sous licence Apache 2.0. Si vous avez des questions/remarques, faites-moi savoir !
Et si le projet vous a été utile, libre à vous de mettre une star sur Github
PS: Je suis surtout actif sur Github et Discord.