Retn "Written"
Retn est une plateforme permettant d'interagir de manière autonome avec les serveurs d'un MMORPG majeur. Développé en solo sur 10 mois entre 2023 et 2024, ce projet est né d'un défi technique de taille : se passer du client officiel en reconstituant intégralement son protocole réseau binaire.
| Langage | C# / .NET 8 | Interface | WPF MVVM |
| Durée | 10 mois | Base de données | MongoDB |
| Architecture | 3 niveaux, sockets TCP | Commercialisation | Discord, 150+ membres |
Rétro-ingénierie
Le cœur du projet repose sur la reconstruction complète d'un protocole binaire
propriétaire, réalisée par analyse du code source décompilé du client officiel.
Ce travail a permis d'identifier les classes responsables de la constitution
des packets, de reconstituer les structures de données champ par champ,
de comprendre l'encodage Big Endian variable, et de reconstruire le système
de types réseau via un ProtocolTypeManager.
La couche d'authentification a nécessité la reconstruction complète du système cryptographique RSA/AES utilisé pour sécuriser les identifiants lors de la connexion au serveur de login. Chaque mise à jour du jeu pouvait modifier le protocole, nécessitant une nouvelle phase d'analyse.
Architecture
Retn repose sur une architecture distribuée en trois couches : un serveur central gérant licences, mises à jour, données de jeu... un client orchestrant des dizaines d'agents isolés, et chaque agent maintenant sa propre connexion TCP avec les serveurs du jeu.
Chaque agent gère de manière autonome le cycle d'authentification complet : connexion au serveur de login, résolution du challenge cryptographique RSA/AES, récupération du ticket de session, puis transition vers le serveur de jeu final pour l'interaction en temps réel.
Pour supporter cette concurrence réseau intensive sans bloquer l'interface ni
saturer la mémoire, le pipeline TCP de chaque agent est architecturé autour de
System.IO.Pipelines avec une approche zéro-allocation via Span<T>Memory<T>
ArrayBufferWriterBinaryPrimitives.
Scripting
Pour fournir des instructions aux agents, un moteur de scripting utilisant Roslyn a été implémenté. L'utilisateur écrit ses scripts en C# standard, que le client compile et injecte en mémoire à la volée, sans redémarrage. Il est possible à tout moment de démarrer ou mettre en pause son script depuis l'interface.
L'API est exposée via des
interfaces métier : IScriptMapIScriptFightIScriptBank...
masquant la complexité de la couche réseau.
Le routage des événements repose sur la réflexion : l'utilisateur décore ses méthodes
avec l'attribut [Handler] et le moteur se charge de les abonner
automatiquement aux événements correspondants du jeu. Par exemple, l'événement OnMoveAsync est
appelé à chaque fois que l'agent change de carte ou lorsque le script est démarré.
// Exemple de script utilisateur compilé à la volée
[Handler]
public async Task OnMoveAsync(int count)
{
var move = new Dictionary<(short, short), List<Func<Task>>>
{
[(-48, 15)] =
[
async () => { await Map.GatherAsync([257]); await Map.ChangeToAsync(ChangeMapSide.Left); },
async () => { await Map.GatherAsync([257]); await Map.ChangeToAsync(ChangeMapSide.Up); }
],
};
if (move.TryGetValue(Map.Coords, out var actions))
await actions[(count - 1) % actions.Count]();
}
[Handler]
public async Task OnFightTurnAsync()
{
await Fight.ExecuteAsync([
new FightActionMove(FightMove.Nearest),
new FightActionCast(13055, CastTarget.Enemy),
new FightActionFinishTurn()
]);
}
Rendu isométrique & Pathfinding
Le client affiche en temps réel une représentation isométrique de la carte, construite entièrement en WPF sans moteur graphique externe. Le système de coordonnées isométrique a été rétro-ingénié pour convertir les identifiants de cellules linéaires en coordonnées X / Y affichables. L'algorithme de pathfinding A* a été adapté à cette grille en tenant compte des coûts de déplacement, des zones de mouvement et des lignes de vue entre entités.