Pantalla de estado para servidor casero de Minecraft 
A lo largo de esta entrada se describe cómo se ha montado una pantalla IPS auxiliar de 3.5 pulgadas conectada por USB a un servidor Minecraft casero. La pantalla permite visualizar la cantidad de usuarios online que hay en tiempo real en el servidor.

Introducción

Cuando se monta un servidor casero de Minecraft, lo habitual es que no se le conecte ninguna pantalla. En mi caso el servidor de Minecraft (launcher Fabric con mods) que tengo en ejecución (en un portátil reciclado en casa) está configurado para que cualquier jugador de Minecraft pueda conectarse desde fuera redirigiendo puertos en el router y usando DNS dinámica (cualquiera puede conectarse accediendo a hachero.ddns.net:25565). La forma de saber el estado del servidor, si hay alguien conectado, etc. es, habitualmente, mediante webs como https://mcstatus.io o similares, que te dicen el nombre del servidor, el icono y, lo que más necesita mi hijo saber: la cantidad de gente que está conectada en ese momento.

Por ejemplo en este enlace puede verse el estado de mi servidor casero.

Como mi hijo me preguntaba a cada rato decidí buscar una solución basada en algún tipo de pantalla auxiliar conectada al servidor (de unas poca pulgadas).

La pantalla

Pillé una pantalla de marca Turing (Turing Smart Screen) de 3.5 pulgadas a través de AliExpress. Esta pantalla de bajo costo usa conexión USB y crea un puerto serie sobre USB en el ordenador donde se conecta. No necesita drivers en Linux, al enchufarla aparece el dispositivo /dev/ttyACM0 que es un puerto serie por el que se le envían comandos para pintar. Como se puede intuir, la velocidad de refresco de este display es muy baja (no creo que llegue ni a 3 fps) pero para lo que es va genial y, al ser IPS, tiene mucho contraste y buen ángulo de visión.

El control de la pantalla

Para controlar la pantalla se creó una clase "turing_display_t" basada en los comandos documentados en el proyecto de python https://github.com/pilahito/turing-smart-screen-linux. Cogí un subconjunto de los comandos que necesitaba y sólo el código compatible con pantallas de 3.5 pulgadas (con otros tamaños de pantalla el protocolo cambia un poco).

Aparte de la clase "turing_display_t" también se crearon las clases "font_renderer_t" y "font_renderer_delegate_t":

- La clase "font_renderer_t" utiliza la librería header-only stb_truetype.h para cargar fuentes de tipo TrueType y poder renderizar texto con ellas.

- La clase "font_renderer_delegate_t" es una clase abstracta con un sólo método virtual puro "draw_symbol" al que le llega por parámetros ya la imagen de cada letra para pintarla.

- La clase "turing_display_t" comentada al principio hereda de "font_renderer_delegate_t" e implementa la función miembro "draw_symbol" para que dibuje en la pantalla usando el protocolo específico del fabricante.

Monitorización del servidor Minecraft

Los servidores Minecraft de tipo Java (no Bedrock) utilizan un protocolo de comunicaciones sobre TCP (normalmente el puerto 25565) muy bien documentado por la comunidad. El protocolo incluye un tipo de paquete de nominado "Handshake" que permite hacer un "ping" y solicitar a cualquier servidor Minecraft información en formato JSON de su versión, nombre, icono, cantidad de jugadores que están online, etc.

Partiendo de la especificación de este protocolo se desarrolla la clase "minecraft_server_status_client_t" con un método "read_status" que envía un paquete "ping" al servidor Minecraft y lee el JSON devuelto para extraer de él, por ahora, sólo la cantidad de jugadores que hay conectados al servidor.

Ejemplo de cadena JSON que devuelve un servidor de Minecraft:
{
  "version": {
    "name": "26.2",
    "protocol": 776
  },
  "players": {
    "max": 20,
    "online": 3
  },
  "description": {
    "text": "A Minecraft Server"
  },
  "favicon": "data:image/png;base64,..."
}

Usando la librería header-only MinJSONCpp se parsea el JSON devuelto por el servidor Minecraft para extraer la información.

Bucle principal

El bucle principal del programa es el siguiente:
int main(int argc, char *argv[]) {
    if (argc < 4) {
        cerr << "Syntax: " << argv[0] << " /dev/lcd_device minecraft_host minecraft_port" << endl;
        return 1;
    }
    try {
        minecraft_server_status_client_t mssc(argv[2], atoi(argv[3]));
        turing_display_t td(argv[1]);
        font_renderer_t fr("font.ttf", td);
        td.reset();
        td.set_orientation(turing_display_t::orientation_t::reverse_portrait);
        int64_t prev_value = -1;
        while (true) {
            minecraft_server_status_t mss;
            mss.num_online_players = 0;
            mssc.read_status(mss);
            if (mss.num_online_players > 9)
                mss.num_online_players = 9;
            else if (mss.num_online_players < 0)
                mss.num_online_players = 0;
            cout << mss.num_online_players << " players" << endl;
            if (mss.num_online_players != prev_value) {
                td.clear();
                fr.draw_text(L"jugadores", 70, 60, 0.02);
                fr.draw_text(L"conectados", 55, 110, 0.02);
                wostringstream woss;
                woss << mss.num_online_players;
                fr.draw_text(woss.str().c_str(), 87, 330, 0.12);
                prev_value = mss.num_online_players;
            }
            sleep(5);
        }
    }
    catch (const char *error) {
        cerr << "Error: " << error << endl;
    }
    return 0;
}

Cada 5 segundos se consulta el servidor Minecraft y si ha habido algún cambio en el número de jugadores online conectados, se actualiza la pantalla con el nuevo número. Sin complicaciones.



El software puede descargarse de la sección soft.

Comentarios 

Agregar comentario

Rellene los campos de abajo para dejar su comentario.









Extras (Negrita / Cursiva / URL / Imagen):