Compiler un client Metin2 Android et le relier à un serveur de test
Procédure pour compiler le client Metin2 Android Cemre, préparer des données compatibles et joindre un serveur de test en LAN.
Client retenu et portée du guide
Parmi les projets publics examinés, cemreefe/metin2-android offre la base la plus exploitable pour essayer le client complet de Metin2 sur Android. Il réunit le client C++, un lanceur Android, les commandes tactiles, des bibliothèques natives et une procédure de connexion à un serveur compatible. Ce guide suit la révision 4ac33651d49000de95e520e6de4373213dc54405. Ce n’est pas un APK universel pour les serveurs privés : le client, les données du jeu et le serveur doivent correspondre.
Réserve concernant le terme « open source » : au 25 octobre 2026, le dépôt principal ne déclarait pas de licence couvrant le client entier. Code public ne signifie pas redistribution autorisée. Le composant OpenGr2ndma est sous MPL-2.0, tandis que les données originales du jeu ont leurs propres droits. Ce guide ne fournit ni pack de données ni APK qui les contient. Code source, licence OpenGr2ndma.

Illustration : un personnage reconnaissable de Metin2 sur un téléphone pendant la préparation d’un client personnalisé. Ce n’est pas une capture du jeu ou de sa compilation.
Pourquoi ce client et ce que montrent les forums
Le fil Metin2 Mobile & PC Cross Platform Source sur Turkmmo donne accès aux variantes BGFX et OpenGL après connexion. L’archive opengl.zip examinée contient un projet Android et du code C++. Il lui manque les bibliothèques Android .a/.so nécessaires au build ; la bibliothèque Granny pour Windows ne les remplace pas. Nous n’y avons trouvé ni APK, ni wrapper Gradle complet, ni licence pour le client complet. Nous avons lu les fichiers sans exécuter les programmes de l’archive.
Le fil plus récent « Mobile Source … Full » décrit un prototype Unity et présente les commandes tactiles ainsi qu’Android/iOS comme des évolutions prévues. Nous n’évaluons pas sa grande archive distincte. Le titre seul ne confirme pas un client mobile achevé.
| Projet | Éléments publics relevés | Pertinence |
|---|---|---|
| Port Android Cemre | C++/Java, bibliothèques pour deux ABI, profils, installation des données, interface tactile, serveur local | Candidat le plus solide parmi ceux examinés ; licence du client principal non clarifiée |
| Archive OpenGL Turkmmo | Squelette Android et code client ; bibliothèques Android manquantes | Portage et dépendances supplémentaires nécessaires |
| Metin2ToUnity sur M2Dev | Outils et conversion des ressources | Importeur, pas client réseau complet |
| metin2-godot | MIT pour son code, étapes de développement décrites | Base de développement, pas port Android prêt à jouer |
L’auteur du port indique avoir testé la connexion, l’entrée dans le monde, le combat, l’inventaire et la sauvegarde. Ses principales preuves viennent d’un émulateur x86_64 ; il faut vérifier soi-même un téléphone arm64 et les longues sessions. Voir aussi notre panorama des clients mobiles Metin2.
Choisir une combinaison vérifiable
La procédure principale connecte un client Android en LAN à son propre serveur de test. Le serveur tourne sur un Linux distinct ou une VM, et le téléphone utilise le même Wi-Fi. La variante avec serveur dans l’APK est décrite à la fin.
| Élément | Révision / version |
|---|---|
| Client Android | 4ac33651d49000de95e520e6de4373213dc54405 |
| m2dev-server-src | 66068c1 |
| m2dev-server : configuration, cartes, SQL, quêtes | ad30738 |
| Structure des données m2dev-client | 98d2c1af ; vous devez être autorisé à utiliser ces données |
| Java / Gradle | JDK 17 / Gradle 8.1.1 |
| Outils Android | plateforme 33, Build Tools 33.0.1, NDK 25.2.9519653, CMake 3.22.1 |
| ABI cible | arm64-v8a pour un téléphone compatible, x86_64 pour l’émulateur adapté |
Build Tools 33.0.1 est indiqué dans app/build.gradle ; l’exemple amont indique un autre sous-numéro. Ne remplacez pas automatiquement les versions épinglées par les dernières.
1. Installer les outils et récupérer la révision exacte
Ces commandes sont prévues pour Bash sous Linux. Indiquez le vrai emplacement du SDK Android et de Gradle 8.1.1. Le JDK 17 doit être actif dans JAVA_HOME. Installez le SDK avec les outils officiels ; lisez et acceptez vous-même toute nouvelle licence. Documentation du SDK.
java -version
gradle --version
sdkmanager "platforms;android-33" "build-tools;33.0.1" \
"ndk;25.2.9519653" "cmake;3.22.1" "platform-tools"
mkdir -p "$HOME/metin2-lab"
cd "$HOME/metin2-lab"
git clone https://github.com/cemreefe/metin2-android.git
cd metin2-android
git checkout --detach 4ac33651d49000de95e520e6de4373213dc54405
git submodule update --init --recursive
git submodule status
export M2_REPO="$PWD"
export M2_ANDROID="$M2_REPO/r10dev.net OPENGL-ITJA/android"
export ANDROID_SDK_ROOT="$HOME/Android/Sdk"
export GRADLE="/opt/gradle-8.1.1/bin/gradle"
printf 'sdk.dir=%s\n' "$ANDROID_SDK_ROOT" > "$M2_ANDROID/local.properties"
Le sous-module OpenGr2ndma est fixé au commit 210f5c326531297495c24e7bb1e24dc1b1a77833. Sans lui, CMake échoue ; un ZIP téléchargé ne l’initialise pas. Gardez entre guillemets le chemin r10dev.net OPENGL-ITJA.
2. Créer son profil et désactiver le catalogue tiers
Placez le texte suivant dans profiles/home.properties. Remplacez 192.168.1.50 par l’adresse LAN de votre serveur Linux. Sur le téléphone, 127.0.0.1 désigne le téléphone, pas l’ordinateur serveur.
m2.abi=arm64-v8a
m2.serverMode=remote
m2.serverHost=192.168.1.50
m2.authPort=11000
m2.channelPort=11011
m2.gamePortOffset=0
m2.applicationIdSuffix=.lab
m2.appLabel=Metin2 Local Lab
m2.versionName=home
m2.dataBundled=false
m2.dataUrl=
m2.dataVersion=1
m2.serverListUrl=
m2.devUrl=
m2.updateChannel=
Dans servers/servers.json, ne gardez que votre serveur de test :
{
"version": 1,
"servers": [
{
"name": "Home Lab",
"host": "192.168.1.50",
"authPort": 11000,
"channelPort": 11011
}
]
}
Laisser m2.serverListUrl= vide est volontaire : sans cette propriété, le build utilise le catalogue distant par défaut de l’auteur. Laisser m2.devUrl= vide désactive l’envoi facultatif de diagnostics et la vérification des mises à jour. Le labo n’ajoutera donc pas un serveur de développement tiers. Voir ServerCatalog.java et DevReporter.java.
3. Compiler d’abord l’APK sans données
On sépare ainsi les erreurs d’outils et de bibliothèques natives des problèmes de données ou de serveur. La compilation seule ne prouve pas qu’on entre dans le monde.
cd "$M2_ANDROID"
"$GRADLE" --no-daemon --max-workers=4 assembleDebug \
-Pm2profile=home -Pm2abi=arm64-v8a
ls -lh app/build/outputs/apk/debug/app-debug.apk
Pour l’émulateur x86_64, utilisez -Pm2abi=x86_64. L’ABI doit correspondre à l’appareil. Le dépôt ne fournissait pas d’APK public prêt à installer lors de notre contrôle ; cette procédure crée une compilation debug.
Résultat vérifié de la compilation
Sous Windows, la révision intacte s’est arrêtée lors de la compilation C++ : UserInterface/Locale.h masquait l’en-tête système locale.h. Dans une copie de travail isolée, nous avons retiré le chemin UserInterface de la liste include_directories(...) dans clientsource/CMakeLists.txt, puis ajouté après cette liste :
add_compile_options("-iquote${CMAKE_CURRENT_SOURCE_DIR}/UserInterface")
Le dossier du jeu reste accessible pour ses inclusions entre guillemets, sans interférer avec la recherche des en-têtes système. Après cette modification, assembleDebug a réussi pour x86_64 et arm64-v8a, avec un APK commun. Ce résultat concerne notre copie de travail, pas le dépôt amont inchangé sur tous les Windows. Les étapes Linux sont tirées du code et du guide de l’auteur. Nous n’avons pas ainsi vérifié l’entrée en jeu, un téléphone physique, les performances ou le serveur hors ligne.
4. Préparer les données avec le script de staging
Placez dans ~/metin2-lab/client-data un checkout de données que vous êtes autorisé à utiliser, avec la structure compatible indiquée plus haut. Ce guide ne donne aucun droit sur les modèles, cartes ou musiques originaux. Un pack pris au hasard sur un autre serveur privé n’est pas un remplacement vérifié : protos, interface Python et formats peuvent varier.
sudo apt install rsync patch python3-pil libsodium23 liblzo2-2 zip imagemagick ninja-build
export M2_DATA="$HOME/metin2-lab/client-data"
export M2_STAGE="$HOME/metin2-lab/staged-data"
test -d "$M2_DATA/assets/root"
"$M2_ANDROID/tools/stage_client_data.sh" "$M2_DATA" "$M2_STAGE" en
stage_client_data.sh fusionne les packs dans l’ordre attendu, met root au-dessus, convertit item_proto/mob_proto et ajoute scripts de compatibilité, mise à l’échelle et HUD tactile. En cas de problème, contrôlez ce staging avant le moteur graphique. Ne renommez pas en masse les fichiers coréens en minuscules.
Le client attend aussi la bibliothèque standard Python 2.7.18 : son dossier Lib, pas le Python 3 de l’ordinateur. Téléchargez l’archive source officielle de Python 2.7.18, extrayez-la dans un répertoire de travail séparé et indiquez par exemple M2_PYLIB=~/metin2-lab/python-2.7.18/Lib. Python 2 n’est pas un environnement hôte actuel pour des services ordinaires ; il s’agit ici d’une dépendance de l’ancien client embarqué.
Pour empaqueter les données, passez m2.dataBundled=true dans home.properties, puis :
export M2_PYLIB="$HOME/metin2-lab/python-2.7.18/Lib"
test -f "$M2_PYLIB/os.py"
M2_CLIENT_DATA="$M2_STAGE" M2_PYLIB="$M2_PYLIB" \
M2_BUNDLE_OUT="$HOME/metin2-lab/bundle" GRADLE="$GRADLE" \
"$M2_ANDROID/tools/make_bundle.sh" home 1
Vous obtiendrez ~/metin2-lab/bundle/metin2-home-1.apk et un ZIP de données versionné. Prévoyez de l’espace pour les données extraites, le ZIP et l’APK. Lorsque vous modifiez les données, augmentez m2.dataVersion : supprimer seulement le ZIP ne forcera pas une application installée à réextraire cette même version. La version APK est indépendante. Voir make_bundle.sh.
5. Préparer un serveur compatible et adresser les cœurs
Cette partie suit le guide d’auto-hébergement de l’auteur. Utilisez une VM de test Linux dédiée, pas un serveur de production. La documentation indique Ubuntu 22.04, g++ 11, CMake 3.22 et MariaDB 10.6.
sudo apt install build-essential cmake git mariadb-server python3
cd "$HOME/metin2-lab"
git clone https://github.com/d1str4ught/m2dev-server-src.git
git -C m2dev-server-src checkout --detach 66068c1
git -C m2dev-server-src apply "$M2_REPO/server/m2dev-server-src-linux.patch"
cmake -S m2dev-server-src -B m2dev-server-src/build -DCMAKE_BUILD_TYPE=Release
cmake --build m2dev-server-src/build -j4
git clone https://github.com/d1str4ught/m2dev-server.git m2srv
git -C m2srv checkout --detach ad30738
cp m2dev-server-src/build/bin/{db,game,qc} m2srv/share/bin/
cp m2srv/share/bin/qc m2srv/share/locale/english/quest/qc
(cd m2srv/share/locale/english/quest && python3 make.py)
Avant le lancement, créez les bases et un utilisateur SQL limité. Ce SQL est pour une nouvelle VM isolée, sans bases existantes de ces noms. Dans sudo mariadb, remplacez les deux valeurs DOPLN_VLASTNI_HESLO par le même mot de passe robuste. Ne lancez pas ce SQL avec cette valeur littérale.
CREATE DATABASE account;
CREATE DATABASE common;
CREATE DATABASE player;
CREATE DATABASE log;
CREATE DATABASE hotbackup;
CREATE USER 'm2lab'@'127.0.0.1' IDENTIFIED BY 'DOPLN_VLASTNI_HESLO';
CREATE USER 'm2lab'@'localhost' IDENTIFIED BY 'DOPLN_VLASTNI_HESLO';
GRANT ALL ON account.* TO 'm2lab'@'127.0.0.1', 'm2lab'@'localhost';
GRANT ALL ON common.* TO 'm2lab'@'127.0.0.1', 'm2lab'@'localhost';
GRANT ALL ON player.* TO 'm2lab'@'127.0.0.1', 'm2lab'@'localhost';
GRANT ALL ON log.* TO 'm2lab'@'127.0.0.1', 'm2lab'@'localhost';
GRANT ALL ON hotbackup.* TO 'm2lab'@'127.0.0.1', 'm2lab'@'localhost';
Importez ensuite les quatre schémas ; le runtime prévoit que hotbackup reste vide au départ :
cd "$HOME/metin2-lab/m2srv"
for db in account common player log; do
sudo mariadb "$db" < "sql/$db.sql"
done
Dans share/conf/db.txt, remplacez utilisateur/mot de passe pour SQL_ACCOUNT, SQL_PLAYER, SQL_COMMON et SQL_HOTBACKUP par votre m2lab et votre mot de passe. Faites de même dans share/conf/game.txt pour ACCOUNT_SQL, PLAYER_SQL, COMMON_SQL et LOG_SQL. Gardez les autres valeurs et l’ordre particulier des champs. Ne mettez pas de vrais identifiants dans Git public. Configuration DB, configuration game.
MariaDB doit écouter seulement sur 127.0.0.1 ; le téléphone ne s’y connecte pas. Dans la VM, ajoutez le fichier séparé /etc/mysql/mariadb.conf.d/99-metin2-lab.cnf sous [mysqld] :
[mysqld]
bind-address=127.0.0.1
sql_mode=NO_ENGINE_SUBSTITUTION
Après sudo systemctl restart mariadb, vérifiez avec mariadb -h 127.0.0.1 -u m2lab -p account ; saisissez le mot de passe à l’invite. L’ancien runtime a besoin de ce mode SQL. Ne le reportez pas à une base partagée d’un autre projet.
Créez un nouveau compte de test du jeu ; le dump contient des comptes préparés. Après remplacement des deux exemples par vos propres valeurs :
INSERT INTO account.account (login, password, social_id, status)
VALUES ('VLASTNI_TEST_LOGIN', PASSWORD('VLASTNI_TEST_HESLO'), '1234567', 'OK');
Après préparation des bases, exécutez python3 install.py dans m2srv. Les configurations sont régénérées. Dans chaque channels/channel1/coreN/CONFIG, définissez l’adresse que peut joindre le téléphone :
BIND_IP: 192.168.1.50
La détection automatique peut ignorer l’adresse LAN. Chaque cœur annonce son adresse au client. Après tout nouvel install.py, vérifiez à nouveau la modification : les fichiers générés auront été réécrits.
| Connexion | Port TCP par défaut | Accès depuis le téléphone |
|---|---|---|
| Authentification | 11000 | Oui, LAN de test seulement |
| Cœurs du canal 1 | 11011, 11012, 11013 | Les trois, car un changement de carte peut rediriger le client |
| Processus DB | 9000 | Communication interne du serveur |
| P2P entre les cœurs | 12000 et suivants | Communication interne du serveur |
Dans m2srv, lancez le canal avec python3 start.py 1 et arrêtez-le avec python3 stop.py. Vérifiez les journaux auth et des trois cœurs. Si le login passe mais qu’après le choix du personnage vous revenez à la liste des serveurs, vérifiez d’abord l’adresse et le port du cœur qui héberge la carte. Le port auth seul ne suffit pas.
Ne mettez pas le serveur à jour à l’aveugle. À partir du commit serveur 0cc595bf097dcf89ddba60615e56fe790823cd22, le handshake passe à 0xf8 avec libsodium/XChaCha20. Le client retenu attend l’ancien 0xfb/0xfa. Pour un serveur récent, il faut porter le protocole dans le client ; changer l’IP ou le mot de passe ne suffit pas.
6. Installer sur le téléphone et diagnostiquer le premier lancement
adb devices
adb shell getprop ro.product.cpu.abilist
adb install -r "$HOME/metin2-lab/bundle/metin2-home-1.apk"
adb shell pm path com.metin2.client.lab
Lancez l’appli, choisissez votre Home Lab et connectez-vous uniquement avec le compte test de votre serveur. Le profil utilise le package com.metin2.client.lab ; les données externes sont généralement ici :
adb shell ls /sdcard/Android/data/com.metin2.client.lab/files/
adb shell cat /sdcard/Android/data/com.metin2.client.lab/files/syserr.txt
adb logcat -d > metin2-android-logcat.txt
Le paquet de base est com.metin2.client, le profil hors ligne amont com.metin2.client.offline. Ne confondez pas leurs chemins. Le code utilise getExternalFilesDir(null) : l’emplacement réel sur l’appareil fait foi. En cas de problème de mise à jour, vérifiez ABI, package ID et signature APK ; une désinstallation aveugle peut effacer les personnages hors ligne.
| Symptôme | Premier contrôle |
|---|---|
| CMake ne trouve pas OpenGr2ndma | Sous-module initialisé au commit attendu |
| APK incompatible avec l’appareil | Comparer ro.product.cpu.abilist et -Pm2abi |
| Déconnexion après login | Version exacte du handshake, puis journaux |
| Retour après sélection du personnage | IP redirigée, BIND_IP et ports des cœurs |
| UI absente ou écran noir | Staging, protos, Python Lib et syserr.txt |
| Données anciennes après mise à jour | m2.dataVersion, profil et ZIP |
Ce qu’ajoute un serveur embarqué dans l’APK
Le projet amont propose un profil bundled : il compile les processus du serveur pour Android, ajoute une couche SQLite au lieu de MySQL et emballe les données du serveur. Le téléphone n’a alors pas besoin d’un serveur distant. Cela nécessite une compilation supplémentaire et un pack dédié ; ce n’est pas automatique dans l’APK de l’étape 3.
Dans servers/servers.json, ajoutez l’entrée de serveur local suivante :
{
"version": 2,
"servers": [
{ "name": "Single Player", "embedded": true }
]
}
Dans profiles/bundled.properties, laisse vides m2.serverListUrl=, m2.devUrl= et m2.updateChannel=. Conserve m2.serverMode=embedded, m2.dataBundled=true et le suffixe .offline. Pour chaque nouveau pack de données, augmente m2.dataVersion.
Une fois les checkouts runtime et source préparés, le script de pack suit cette forme :
"$M2_REPO/r10dev.net OPENGL-ITJA/server/tools/make-server-pack.sh" \
"$HOME/metin2-lab/m2srv" \
"$HOME/metin2-lab/m2dev-server-src" \
"$HOME/metin2-lab/server-pack"
M2_SERVER_PACK="$HOME/metin2-lab/server-pack" \
M2_CLIENT_DATA="$M2_STAGE" M2_PYLIB="$M2_PYLIB" \
M2_BUNDLE_OUT="$HOME/metin2-lab/bundle" GRADLE="$GRADLE" \
"$M2_ANDROID/tools/make_bundle.sh" bundled 1
Avant ces commandes, vérifiez bundled.properties, le catalogue privé, dataVersion et le compte de test dans la base seed. make-server-pack.sh attend runtime, sources, puis dossier de sortie. N’utilisez pas l’exemple différent de la section Web de la documentation amont. La compilation Gradle du serveur embarqué contient un chemin NDK Linux ; nous ne la présentons pas comme une compilation Windows vérifiée.
Compilation, lancement, connexion et jeu continu sont des résultats distincts. Pour tester la configuration, créez un personnage, entrez sur une carte, combattez, changez de cœur, relancez le client et vérifiez la sauvegarde de l’inventaire. Sans ces étapes, on ne peut pas affirmer qu’un téléphone et un serveur précis sont validés ensemble.
Questions Fréquentes
Ce client fonctionnera-t-il sur mon serveur privé préféré ?
Ce guide fonctionne-t-il sur iPhone ?
Puis-je partager l’APK et ses données publiquement ?
Pages Associées
Trouve ton serveur parfait
Parcours les serveurs privés Metin2 les mieux classés sur METIN2.GG ou ajoute ton propre serveur au classement.

