Desarrollo11 min de lectura

Compilar un cliente Metin2 para Android y conectarlo a un servidor de prueba

Guía para compilar el cliente Metin2 Android de Cemre, preparar datos compatibles y conectarlo a un servidor de prueba en LAN.

Por METIN2.GG

Cliente elegido y alcance de la guía

Entre los proyectos públicos que hemos revisado, cemreefe/metin2-android es la base más completa para probar el cliente de Metin2 en Android. Incluye el cliente C++, un lanzador Android, controles táctiles, bibliotecas nativas e instrucciones para conectarse a un servidor compatible. Esta guía usa la revisión concreta 4ac33651d49000de95e520e6de4373213dc54405. No es un APK universal para cualquier servidor privado: el cliente, los datos y el servidor tienen que ser compatibles.

Una precisión sobre el término «open source»: a 25 de octubre de 2026, el repositorio principal no declaraba una licencia para todo el cliente. Que el código sea público no autoriza automáticamente su redistribución. El componente OpenGr2ndma tiene licencia MPL-2.0, pero los datos originales del juego tienen sus propios derechos. Por eso esta guía no incluye datos ni un APK que los contenga. Código fuente, licencia de OpenGr2ndma.

Guerrero de Metin2 con armadura azul y plateada en un teléfono conectado a un ordenador.

Ilustración: un personaje reconocible de Metin2 en un teléfono mientras se prepara un cliente personalizado. No es una captura de la compilación ni del juego.

Por qué este cliente y qué encontramos en los foros

En el hilo Metin2 Mobile & PC Cross Platform Source de Turkmmo se accede, tras iniciar sesión, a las variantes BGFX y OpenGL. El archivo opengl.zip revisado sí contiene un proyecto Android y código C++ del cliente. Sin embargo, faltan las bibliotecas Android .a/.so necesarias para compilarlo; la biblioteca Granny de Windows que incluye no las sustituye. No encontramos un APK, un wrapper Gradle completo ni una licencia para todo el cliente. Leímos los archivos sin ejecutar los programas incluidos.

Un hilo más reciente llamado «Mobile Source … Full» describe un prototipo Unity y deja los controles táctiles y Android/iOS como trabajos futuros. No hemos evaluado su gran archivo separado. El título del hilo por sí solo no demuestra que exista un cliente móvil terminado.

Proyecto Evidencia pública revisada Utilidad para esta guía
Port Android de Cemre C++/Java, bibliotecas para dos ABI, perfiles, instalación de datos, interfaz táctil y servidor local Mejor candidato de los examinados; licencia del cliente principal sin aclarar
Archivo OpenGL de Turkmmo Estructura Android y código de cliente, pero faltan bibliotecas Android Requiere más portabilidad y dependencias
Metin2ToUnity en M2Dev Herramientas y conversión de recursos Importador, no cliente de red completo
metin2-godot MIT para su código y etapas de desarrollo descritas Base interesante, no un port Android listo para jugar

El autor del port cuenta que probó el acceso, la entrada al mundo, el combate, el inventario y el guardado. Sus pruebas principales son de un emulador x86_64; hace falta comprobar un teléfono arm64 y sesiones largas por separado. Para el panorama general, consulta la guía sobre clientes móviles de Metin2.

Elige primero una combinación comprobable

El procedimiento principal conecta el cliente Android por LAN a tu propio servidor de prueba. El servidor funciona en un Linux separado o una máquina virtual, y el teléfono comparte el Wi-Fi. Al final se explica la variante con el servidor dentro del APK.

Componente Revisión / versión
Cliente Android 4ac33651d49000de95e520e6de4373213dc54405
m2dev-server-src 66068c1
m2dev-server: configuración, mapas, SQL y misiones ad30738
Estructura esperada de datos m2dev-client 98d2c1af; debes tener permiso para usar esos datos
Java / Gradle JDK 17 / Gradle 8.1.1
Herramientas Android plataforma 33, Build Tools 33.0.1, NDK 25.2.9519653, CMake 3.22.1
ABI de destino arm64-v8a para un teléfono compatible, x86_64 para su emulador

Build Tools 33.0.1 aparece en app/build.gradle; el ejemplo upstream de instalación señala otro subnúmero. No sustituyas automáticamente las versiones fijadas por las más recientes.

1. Instala las herramientas y obtén la revisión exacta

Estos comandos son para Bash en Linux. Indica la ruta real del SDK de Android y de Gradle 8.1.1. JDK 17 debe estar activo en JAVA_HOME. Instala el SDK desde las herramientas oficiales de Android y lee y acepta tú mismo cualquier nueva licencia. Documentación del 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"

El submódulo OpenGr2ndma está fijado al commit 210f5c326531297495c24e7bb1e24dc1b1a77833. Si falta, CMake falla; descargar un ZIP de GitHub no lo inicializa. Mantén entre comillas la ruta r10dev.net OPENGL-ITJA.

2. Crea un perfil y desactiva el catálogo de terceros

Coloca esto en profiles/home.properties. Cambia 192.168.1.50 por la dirección LAN de tu servidor Linux. En el teléfono, 127.0.0.1 es el propio teléfono, no el PC servidor.

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=

En servers/servers.json deja solo tu servidor de pruebas:

{
  "version": 1,
  "servers": [
    {
      "name": "Home Lab",
      "host": "192.168.1.50",
      "authPort": 11000,
      "channelPort": 11011
    }
  ]
}

Dejar m2.serverListUrl= vacío es intencional: si falta esta propiedad, la compilación usa el catálogo remoto predeterminado del autor. Dejar m2.devUrl= vacío desactiva el envío opcional de diagnósticos y la comprobación de actualizaciones. El laboratorio no ofrecerá un servidor de desarrollo ajeno. Consulta ServerCatalog.java y DevReporter.java.

3. Compila primero el APK sin los datos del juego

Así separas los errores de las herramientas y bibliotecas nativas de los problemas de datos o servidor. Compilar no demuestra por sí solo que se pueda entrar al mundo.

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

Para el emulador x86_64 usa -Pm2abi=x86_64. La ABI debe coincidir con el dispositivo. Cuando lo revisamos, el repositorio no ofrecía un APK público listo para instalar; este proceso genera una compilación debug.

Resultado comprobado de la compilación

En Windows, la revisión sin cambios se detuvo al compilar C++: UserInterface/Locale.h ocultaba el encabezado del sistema locale.h. En una copia de trabajo aislada quitamos la ruta UserInterface de la lista include_directories(...) en clientsource/CMakeLists.txt y añadimos después de la lista:

add_compile_options("-iquote${CMAKE_CURRENT_SOURCE_DIR}/UserInterface")

La carpeta del juego sigue disponible para los include entre comillas, pero deja de interferir al buscar encabezados del sistema. Tras el cambio, assembleDebug terminó para x86_64 y arm64-v8a y produjo un APK común. Esto confirma la compilación de nuestra copia de trabajo, no del upstream sin modificar en todos los Windows. Los pasos Linux anteriores proceden del código y la guía del autor. No verificamos así la entrada al mundo, un teléfono físico, el rendimiento ni el servidor sin conexión.

4. Prepara los datos con el script de staging

Pon en ~/metin2-lab/client-data un checkout de datos que tengas permiso para usar y cuya estructura sea compatible con la descrita. Esta guía no otorga derechos sobre los modelos, mapas ni música originales. Un pack cualquiera de otro servidor privado no es un sustituto comprobado: pueden cambiar los protos, la interfaz Python y los formatos.

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 combina los packs en el orden previsto, coloca root encima, convierte item_proto/mob_proto y añade scripts de compatibilidad, escalado y HUD táctil. Ante un fallo, revisa esta preparación antes que el motor gráfico. No cambies masivamente a minúsculas los nombres coreanos.

El cliente también requiere la biblioteca estándar de Python 2.7.18, concretamente el directorio Lib, no el Python 3 del ordenador. Descarga el paquete fuente oficial de Python 2.7.18, extráelo en una carpeta de trabajo aparte y establece, por ejemplo, M2_PYLIB=~/metin2-lab/python-2.7.18/Lib. Python 2 no es un runtime actual para servicios normales; aquí es una dependencia del cliente antiguo embebido.

Para incluir los datos en el paquete, cambia m2.dataBundled=true en home.properties y ejecuta:

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

El resultado será ~/metin2-lab/bundle/metin2-home-1.apk y un ZIP de datos versionado. Reserva espacio para los datos extraídos, el ZIP y el APK. Si después cambias los datos, incrementa m2.dataVersion: borrar solamente el ZIP no fuerza a una aplicación instalada a extraer de nuevo esa misma versión. La versión APK es independiente. Consulta make_bundle.sh.

5. Prepara un servidor compatible y las direcciones de los cores

Esta sección sigue la guía de autoalojamiento del autor. Usa una máquina virtual Linux de pruebas separada; no modifiques así un servidor de producción. El upstream indica Ubuntu 22.04, g++ 11, CMake 3.22 y 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)

Antes de arrancar, crea las bases de datos y un usuario SQL limitado. Este SQL es para una máquina virtual aislada y nueva, sin bases previas con esos nombres. En sudo mariadb sustituye las dos apariciones de DOPLN_VLASTNI_HESLO por la misma contraseña robusta. No ejecutes el SQL con ese texto literal.

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';

Después importa los cuatro esquemas incluidos; el runtime prevé que hotbackup empiece vacío:

cd "$HOME/metin2-lab/m2srv"
for db in account common player log; do
  sudo mariadb "$db" < "sql/$db.sql"
done

En share/conf/db.txt cambia el usuario y la contraseña de SQL_ACCOUNT, SQL_PLAYER, SQL_COMMON y SQL_HOTBACKUP por tu m2lab y la contraseña elegida. Haz lo mismo en share/conf/game.txt para ACCOUNT_SQL, PLAYER_SQL, COMMON_SQL y LOG_SQL. Conserva el resto de valores y el orden distinto de campos de esos archivos. No guardes credenciales reales en Git público. Configuración DB, configuración game.

MariaDB debe escuchar solo en 127.0.0.1; el teléfono no se conecta a ella. En esa máquina crea el archivo separado /etc/mysql/mariadb.conf.d/99-metin2-lab.cnf bajo [mysqld]:

[mysqld]
bind-address=127.0.0.1
sql_mode=NO_ENGINE_SUBSTITUTION

Después de sudo systemctl restart mariadb, comprueba con mariadb -h 127.0.0.1 -u m2lab -p account e introduce la contraseña cuando te la pida. El runtime antiguo necesita ese modo SQL. No lo extiendas a bases compartidas de otros proyectos.

Crea credenciales de prueba nuevas para la cuenta del juego; el volcado ya incluye cuentas preparadas. Tras sustituir los valores de ejemplo:

INSERT INTO account.account (login, password, social_id, status)
VALUES ('VLASTNI_TEST_LOGIN', PASSWORD('VLASTNI_TEST_HESLO'), '1234567', 'OK');

Cuando las bases estén preparadas, ejecuta python3 install.py en m2srv. Se regeneran las configuraciones. En cada channels/channel1/coreN/CONFIG del juego, asigna una dirección accesible desde el teléfono:

BIND_IP: 192.168.1.50

La detección automática puede saltarse la dirección LAN. Cada core anuncia su propia dirección al cliente. Si vuelves a ejecutar install.py, comprueba el cambio otra vez: los archivos generados se sobrescriben.

Conexión Puerto TCP predeterminado Acceso desde el teléfono
Autenticación 11000 Sí, solo en la LAN de pruebas
Cores del canal 1 11011, 11012, 11013 Los tres; el cambio de mapa puede redirigir al cliente
Proceso DB 9000 Comunicación interna del servidor
P2P entre cores 12000 y siguientes Comunicación interna del servidor

En m2srv, inicia el canal con python3 start.py 1 y detenlo con python3 stop.py. Revisa los logs de auth y de los tres cores. Si el login pasa pero vuelves a la lista tras elegir personaje, comprueba primero la IP y el puerto del core que aloja el mapa. El puerto auth no basta.

No actualices el servidor a ciegas. Desde el commit de servidor 0cc595bf097dcf89ddba60615e56fe790823cd22, el handshake pasa a 0xf8 con libsodium/XChaCha20. El cliente elegido espera el antiguo 0xfb/0xfa. Para un servidor más nuevo hay que adaptar el protocolo en el cliente; cambiar IP o contraseña no lo arregla.

6. Instala en el teléfono y diagnostica el primer inicio

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

Abre la app, selecciona tu Home Lab e inicia sesión solo con una cuenta de prueba de tu servidor. Este perfil usa el package com.metin2.client.lab; sus datos externos suelen estar aquí:

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

El package base es com.metin2.client y el perfil offline upstream usa com.metin2.client.offline. No confundas sus rutas. El código obtiene la ubicación con getExternalFilesDir(null), por lo que manda el almacenamiento real de esa app en el dispositivo. Si falla la actualización, revisa ABI, package ID y firma APK; desinstalar a ciegas puede borrar personajes offline.

Síntoma Primer control
CMake no encuentra OpenGr2ndma Submódulo y commit esperado
APK incompatible con ABI Comparar ro.product.cpu.abilist con -Pm2abi
Desconexión tras login Versión exacta del handshake y luego los logs
Vuelta tras seleccionar personaje IP redirigida, BIND_IP y puertos de los cores
Interfaz ausente o pantalla negra Staging, protos, Python Lib y syserr.txt
Datos antiguos tras actualizar m2.dataVersion, perfil y ZIP

Servidor integrado en el APK

El proyecto upstream también tiene un perfil bundled: compila procesos del servidor para Android, agrega una capa SQLite en lugar de MySQL e incluye datos del servidor. El teléfono no necesita entonces un servidor remoto. Hace falta otra compilación y un paquete de datos; no viene activado automáticamente en el APK del paso 3.

En servers/servers.json, registra la instancia integrada:

{
  "version": 2,
  "servers": [
    { "name": "Single Player", "embedded": true }
  ]
}

En profiles/bundled.properties deja vacíos m2.serverListUrl=, m2.devUrl= y m2.updateChannel=. Conserva m2.serverMode=embedded, m2.dataBundled=true y el sufijo .offline. Para cada paquete de datos nuevo, incrementa m2.dataVersion.

Con los checkouts del runtime y del código fuente preparados, el empaquetado queda así:

"$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

Antes de ejecutar, comprueba bundled.properties, el catálogo privado, dataVersion y la cuenta de prueba de la base seed. make-server-pack.sh espera primero el checkout runtime, luego el de fuentes y finalmente la carpeta de salida. No uses en su lugar el ejemplo diferente de la sección Web de la documentación upstream. El Gradle del servidor integrado incluye una ruta NDK específica para Linux; no lo presentamos como compilación offline Windows verificada.

Compilar, iniciar la aplicación, conectarse y jugar una sesión completa son resultados distintos. Para probar tu instalación, crea un personaje, entra en un mapa, lucha, cambia de core, reinicia el cliente y comprueba que el inventario se guarda. Sin estos pasos no se puede afirmar que se hayan validado un teléfono y un servidor concretos.

Preguntas Frecuentes

¿Funcionará este cliente con mi servidor privado favorito?

Solo si el operador ofrece protocolo y datos compatibles y autoriza este cliente. Esta guía cubre la combinación Cemre/m2dev indicada, no los cambios propios de otros servidores. El APK no sustituye universalmente sus launchers.

¿También sirve para iPhone?

No. El proyecto y las herramientas descritas aquí son para Android. Que otro hilo mencione iOS no demuestra que exista una versión iOS de este cliente.

¿Puedo compartir públicamente el APK y sus datos?

El código público y la licencia de una sola biblioteca no resuelven los derechos del cliente completo ni de los datos originales. Antes de distribuir, comprueba los derechos de cada parte incluida. Este artículo no concede ningún permiso.

Páginas Relacionadas

Encuentra tu servidor perfecto

Explora los servidores privados Metin2 mejor clasificados en METIN2.GG o envía tu propio servidor al ranking.