resumen
- pregunta
- ¿Cómo compartir un mundo de Minecraft entre amigos sin dejar un servidor prendido y sin que existan dos versiones del mundo?
- método
- Un solo host a la vez, elegido al abrir el mundo; tokens con número de generación para resolver aperturas simultáneas; y el mundo que pasa al siguiente host como una foto con JGit, o a la nube si no queda nadie
- resultado
- Funciona de punta a punta, probado dentro del juego con una ida y vuelta A → B → A; la lógica difícil tiene 67 pruebas sin Minecraft
- límites
- Es para grupos chicos de amigos, no para servidores grandes; y las pruebas cubren la lógica y casos manuales, no redes reales a escala
jukz es un mod de Minecraft para jugar con amigos en el mismo mundo sin dejar un servidor prendido. El mundo vive en el PC de quien esté jugando. La regla que ordena todo el diseño es simple: no hay copias que sincronizar, el mundo vive en un solo lugar a la vez
El problema de fondo: dos líderes
En sistemas distribuidos esto se conoce como split-brain: dos nodos creen al mismo tiempo que son el líder, y cada uno acepta cambios por su lado. Cuando se vuelven a encontrar ya no hay una versión correcta, hay dos. En un mundo de Minecraft eso significa construcciones o inventarios que se pierden
jukz lo evita de dos formas: preguntando antes de abrir, y resolviendo con un número de generación el caso en que dos personas abren a la vez
Abrir un mundo es preguntar
Cada mundo tiene un UUID permanente y un código corto para compartir. Al abrirlo, jukz pregunta si alguien ya lo tiene abierto: en la misma red, por multicast; desde casas distintas, en un servidor rendezvous propio escrito en Rust (Axum). Si alguien lo tiene, entras en vivo al mundo de esa persona. Si no, se abre en tu PC y quedas anunciado como host
Al principio había planeado una DHT para encontrarse, pero quedó descartada: el rendezvous era más simple y más confiable
Nunca dos hosts
Cada anuncio lleva un token con un número de generación. Si dos personas abren el mismo mundo a la vez, gana la generación más nueva y la otra se entera: puede quedarse con su copia local o entrar como invitada a la partida en vivo
Nob abre el mundo → host, generación 7
Kai lo abre a la vez → host, generación 8
gana la 8
Nob se entera → se queda con su copia local
o entra como invitadoLa idea es la misma que Martin Kleppmann describe como fencing token: un número que solo crece y que acompaña a quien tiene el permiso. Lo que llega con un número viejo se reconoce como viejo, aunque su dueño todavía crea que manda
Atravesar el NAT de cada casa
Para que un amigo entre al mundo, su PC tiene que llegar al del host, y casi siempre hay un router con NAT en medio. jukz combina tres piezas:
UPnP ──► el host le pide a su router que abra un puerto STUN ──► cada PC averigua cuál es su dirección pública │ si no se puede abrir el puerto (por ejemplo, detrás de CGNAT) ▼ relay por WebSocket en el rendezvous: une las dos conexiones salientes
El último paso es la misma idea que estandariza TURN (RFC 8656): si dos equipos no pueden conectarse directo, los dos se conectan hacia afuera, a un tercero que pasa los datos. Cuesta un poco más de latencia, pero funciona aunque ninguno pueda recibir conexiones
Pasar el mundo
Cuando el host cierra con invitados conectados, guarda, toma una foto del mundo con JGit y se la pasa a un invitado, que la aplica y sigue como host. Si cierra sin nadie, la foto sube a la nube (R2) y el siguiente que abra el mundo la descarga y sigue desde ahí
Esto no salió bien a la primera. El 11 de junio el mundo se desincronizaba: al pasarlo al siguiente host se perdían cambios. La solución fue un relay por WebSocket en el rendezvous, por donde viaja la copia del mundo
Probarlo sin abrir el juego
La lógica difícil (elegir host, los tokens, el protocolo) vive en un módulo de Kotlin puro, sin Minecraft, con 67 pruebas que corren en segundos. El paso del mundo sí se probó dentro del juego, incluida una ida y vuelta A → B → A
ideaSeparar la lógica difícil del juego hizo posible probar los casos raros (dos aperturas a la vez, un host que se va) en segundos, sin abrir Minecraft cada vez
Límites
- Está pensado para grupos chicos de amigos: un solo host a la vez significa que el mundo depende del PC y la conexión de quien hostea en ese momento
- Las pruebas automáticas cubren la lógica; la red real se probó a mano, no con muchos jugadores ni en condiciones de red difíciles a escala
- El relay agrega un salto más: es la opción de último recurso, no la ideal
Preguntas frecuentes
¿Cómo jugar Minecraft con amigos sin servidor dedicado?
Una opción es que el mundo viva en el PC de quien esté jugando y pase al siguiente cuando esa persona se va. Es lo que hace jukz: un solo host a la vez, y el mundo se pasa como una foto o queda en la nube hasta que alguien lo vuelve a abrir
¿Qué es un split-brain?
Cuando dos nodos de un sistema creen al mismo tiempo que son el líder y aceptan cambios por separado. Al reencontrarse hay dos versiones y no una
¿Qué es un fencing token?
Un número que solo crece y que acompaña al permiso de ser líder. Si llega algo con un número más viejo que el último visto, se descarta, aunque quien lo manda todavía crea que tiene el permiso
¿Cómo se conecta un jugador que está detrás de CGNAT?
Si no se puede abrir un puerto (UPnP) ni encontrar un camino directo (STUN), los dos equipos se conectan hacia afuera a un relay que pasa los datos, la misma idea de TURN
¿Qué pasa con el mundo si el último jugador se va?
En jukz, el mundo se sube a la nube (R2) y el siguiente que lo abra lo descarga y sigue desde ahí
Referencias
- Martin Kleppmann · How to do distributed locking (2016) · fencing tokens · martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
- RFC 8489 · Session Traversal Utilities for NAT (STUN) · rfc-editor.org/rfc/rfc8489
- RFC 8656 · Traversal Using Relays around NAT (TURN) · rfc-editor.org/rfc/rfc8656
- JGit · Git implemented in Java · eclipse.org/jgit
- Nuulz/jukz · source code of the mod · github.com/Nuulz/jukz