annihilation is the popular mini game from Minecraft
README
Red multi-servidor de Minecraft con el modo de juego Annihilation: equipos compiten por destruir el nexo enemigo mientras defienden el propio. Construido con Spigot/Paper 1.13+, BungeeCord, Redis y MongoDB.

Cada módulo tiene su propia documentación de referencia completa en la carpeta docs/:
| Módulo | Archivo | Descripción |
|---|---|---|
| annihilation-bungee | docs/bungee.md | Plugin BungeeCord: transferencia de jugadores, listeners Redis y visión general de la arquitectura de red |
| annihilation-commons | docs/commons.md | Librería compartida: modelos, Redis, MongoDB, sistema de mensajería, matchmaking e i18n |
| annihilation-game | docs/game.md | Plugin de partida: state machine, 21 kits, nexo, minas, combate, shop, listeners y comandos |
| annihilation-lobby | docs/lobby.md | Plugin de lobby: sesión, shop de cosméticos, matchmaking, scoreboard, holograms y comandos |
┌─────────────────────────────────────┐
│ BungeeCord Proxy │
│ annihilation-bungee.jar │
│ Escucha PLAYER_TRANSFER en Redis │
│ Mueve jugadores entre servidores │
└──────────┬──────────────┬───────────┘
│ │
┌─────────────▼──┐ ┌──────▼──────────┐
│ Lobby Server │ │ Game Server(s) │
│ lobby.jar │ │ game.jar x N │
└───────┬────────┘ └────────┬────────┘
│ │
┌───────▼──────────────────────▼───────┐
│ Redis │
│ Pub/Sub · Cola de matchmaking │
│ Leaderboard · Caché de sesiones │
└───────────────────┬──────────────────┘
│
┌───────────────────▼──────────────────┐
│ MongoDB │
│ Arenas · Stats · Cosméticos │
└──────────────────────────────────────┘
Los tres componentes nunca comparten memoria directamente. Toda la comunicación ocurre a través de Redis pub/sub (mensajes en tiempo real) y MongoDB (persistencia).
| Canal | Publicado por | Consumido por | Propósito |
|---|---|---|---|
| PLAYER_TRANSFER | Lobby (processor) | BungeeCord, Game | Transferir un jugador a un servidor concreto + registrar transferencia pendiente |
| MATCH_FOUND | Lobby (processor) | Lobby | Limpiar estado de cola local tras un match |
| ARENA_UPDATE | Game | Lobby | Estado de arenas en tiempo real (jugadores, fase, disponibilidad) |
| SERVER_REGISTER | Game | Lobby | Registro de un servidor Game al arrancar |
| CROSS_SERVER_CHAT | Game | Lobby | Chat global entre servidores (prefijo !) |
Lobby ──PLAYER_TRANSFER──► BungeeCord ──connect()──► Game Server
──PLAYER_TRANSFER──► Game Server (PendingTransferService)
──MATCH_FOUND──────► Lobby (limpieza de cola local)
El LobbyMatchmakingProcessor corre cada 5 segundos: selecciona la mejor arena disponible, desencola jugadores de Redis y publica un PLAYER_TRANSFER por cada uno. BungeeCord mueve al jugador; el servidor Game registra la transferencia pendiente y asigna al jugador a la arena correcta cuando se conecta.
| Componente | Versión mínima | |---|---| | Java | 11 | | BungeeCord / Waterfall | 1.20+ | | Spigot / Paper | 1.13+ | | Redis | 6.x | | MongoDB | 5.x |
git clone https://github.com/alexissdev/annihilation.git
cd annihilation
./gradlew shadowJar
Los JARs se generan en:
annihilation-bungee/build/libs/annihilation-bungee-1.0.0-all.jar
annihilation-lobby/build/libs/annihilation-lobby-1.0.0-all.jar
annihilation-game/build/libs/annihilation-game-1.0.0-all.jar
shadowJarempaqueta todas las dependencias (Guice, Lettuce, MongoDB driver) con reubicación de paquetes para evitar conflictos con otros plugins.
El repositorio incluye un docker-compose.yml que levanta Redis en localhost:6379. Los tres plugins ya traen esa dirección como credencial por defecto, así que no hace falta cambiar ningún config para empezar a probar.
Requisito: Docker y Docker Compose instalados.
# Levantar Redis
docker compose up -d
# Detener Redis
docker compose down
Con Redis corriendo ya puedes iniciar los servidores Spigot/BungeeCord normalmente. Los plugins se conectan solos al arrancar.
MongoDB no está incluido en el Compose. Si necesitas persistencia de stats y arenas, levanta una instancia aparte o usa MongoDB Atlas con la URI en
storage.mongodb.uri.
La red mínima requiere 3 servidores más el proxy:
proxy/ ← BungeeCord con annihilation-bungee.jar
lobby/ ← Spigot/Paper con annihilation-lobby.jar
game-1/ ← Spigot/Paper con annihilation-game.jar
game-2/ ← Spigot/Paper con annihilation-game.jar (opcional, escalable)
Cada servidor Game puede alojar múltiples arenas simultáneas. El ID configurado en server.id debe coincidir exactamente con el nombre del servidor en BungeeCord/config.yml.
Instalar el plugin:
BungeeCord/plugins/annihilation-bungee.jar
plugins/AnnihilationBungee/config.yml:
redis:
host: "localhost"
port: 6379
password: ""
database: 0
BungeeCord/config.yml — registrar todos los servidores:
servers:
lobby:
motd: Lobby
address: localhost:25566
restricted: false
game-1:
motd: Game 1
address: localhost:25567
restricted: false
game-2:
motd: Game 2
address: localhost:25568
restricted: false
listeners:
- priorities:
- lobby
Instalar el plugin:
lobby/plugins/annihilation-lobby.jar
plugins/AnnihilationLobby/config.yml:
storage:
mongodb:
uri: "mongodb://localhost:27017"
database: "annihilation"
pool-size: 10
redis:
host: "localhost"
port: 6379
password: ""
database: 0
pool-size: 8
server:
id: "lobby" # Debe coincidir con el nombre en BungeeCord config.yml
i18n:
default-language: en # Idioma por defecto (en, es, pt)
Instalar el plugin:
game-1/plugins/annihilation-game.jar
plugins/AnnihilationGame/config.yml:
server:
id: "game-1" # Debe coincidir con el nombre en BungeeCord config.yml
lobby-name: "lobby" # Nombre del servidor lobby al que regresar tras la partida
storage:
mongodb:
uri: "mongodb://localhost:27017"
database: "annihilation"
pool-size: 10
redis:
host: "localhost"
port: 6379
password: ""
database: 0
pool-size: 4
game:
min-players: 8 # Jugadores mínimos para iniciar
max-players-per-team: 10 # Máximo por equipo
starting-countdown: 30 # Segundos de cuenta atrás
phase-one-duration: 1200 # Duración fase I en segundos (20 min)
phase-two-duration: 600 # Duración fase II en segundos (10 min)
phase-three-duration: 300 # Duración fase III en segundos (5 min)
phase-four-duration: 300 # Duración fase IV en segundos (5 min)
phase-five-duration: 240 # Duración fase V en segundos (4 min)
phase-six-duration: 180 # Duración fase VI en segundos (3 min)
nexus-health: 100 # HP inicial del nexo
respawn-delay: 5 # Segundos hasta respawn
free-classes: # Clases disponibles sin desbloqueo
- miner
- swordsman
- builder
- archer
- knight
border:
phase-one-size: 500 # Radio del borde en fase 1
phase-two-size: 300 # Radio del borde en fase 2
phase-three-size: 150 # Radio del borde en fase 3
mines:
respawn-delay: 120 # Segundos para que reaparezca una mina
mid-diamond-interval: 180 # Segundos entre spawns de diamantes en mid
Repite esta configuración para game-2, game-3, etc. cambiando únicamente server.id.
Una vez que el servidor Game está corriendo, configura cada arena desde el propio servidor con comandos de admin.
/arenacreate <id> <world>
El world debe existir en el servidor. La arena se guarda en MongoDB y se carga automáticamente al reiniciar.
/arenacreate valley world_valley
Opción rápida — 4 equipos por defecto (rojo, verde, amarillo, azul):
/arenateamcreate <arenaId> default [maxPlayers]
/arenateamcreate valley default 10
Crea automáticamente los cuatro equipos (red, green, yellow, blue) con sus colores correspondientes. Si alguno ya existe, lo omite sin sobrescribirlo.
Opción manual — un equipo a la vez:
/arenateamcreate <arenaId> <teamId> <color> [maxPlayers]
/arenateamcreate valley red RED 10
/arenateamcreate valley blue BLUE 10
color es un nombre de ChatColor válido. maxPlayers es opcional (valor por defecto: 10).
Párate encima del bloque que será el nexo y ejecuta:
/arenasetnexus <arenaId> <teamId>
/arenasetnexus valley red
/arenasetnexus valley blue
/arenasetnexus valley green
/arenasetnexus valley yellow
Párate en el punto de spawn y ejecuta:
/arenasetspawn <arenaId> <teamId>
Puedes ejecutarlo varias veces por equipo para añadir múltiples puntos de spawn.
Las minas se configuran con un wand de selección de bloques. Para cada equipo:
/arenasetmine <arenaId> <teamId>
Repite el proceso por cada equipo y tipo de mineral:
/arenasetmine valley red ← selecciona Iron para la mina del equipo rojo
/arenasetmine valley blue ← selecciona Gold para la mina del equipo azul
Puedes volver a ejecutar el comando en cualquier momento para modificar los bloques de una mina existente. Los bloques previos se cargan automáticamente en la sesión.
Los spots de diamante del mid también se configuran con el mismo wand:
/arenasetmine <arenaId> mid
Los diamantes del mid solo spawnean a partir de la Fase 3. Durante las fases 1 y 2 no aparecen.
Para ajustar el intervalo de respawn del mid (en segundos):
/arenasetmid <arenaId> <respawnDelay>
/arenasetmid valley 180
Si la arena puede rotar entre varios mundos según el voto de los jugadores, cada mundo necesita su propia geometría (posiciones de nexos, spawns, minas, mid). Esto se configura con /mapsetup para cada mundo votable.
Párate en el mundo que quieres configurar y ejecuta:
# Spawn del equipo (posición actual del admin)
/mapsetup <worldName> setspawn <teamId>
# Nexo del equipo (clic derecho en el bloque con el wand)
/mapsetup <worldName> setnexus <teamId>
# Minas del equipo (abre GUI de mineral + wand de bloques)
/mapsetup <worldName> setmine <teamId>
# Spots de diamante del mid
/mapsetup <worldName> setmid
# Verificar configuración completa
/mapsetup <worldName> info
Repite para cada equipo y para cada mundo registrado en maps.yml. La configuración se guarda en plugins/AnnihilationGame/maps/<worldName>.yml.
Si un mundo no tiene
MapConfig(geometría propia), el sistema usa como fallback las coordenadas globales de la arena (ArenaConfig). Esto garantiza compatibilidad con configuraciones de un solo mapa.
Define una o varias ubicaciones donde aparecerá el boss al inicio de la Fase IV. Párate en cada punto y ejecuta:
/bosssetspawn <arenaId>
Puedes repetirlo tantas veces como ubicaciones quieras (aparecerá un boss en cada una simultáneamente).
Otros subcomandos:
/bosssetspawn <arenaId> list ← lista las coordenadas configuradas
/bosssetspawn <arenaId> clear ← elimina todos los spawns del boss para esa arena
La configuración se guarda en plugins/AnnihilationGame/boss_spawns.yml. Si no hay spawns configurados, la Fase IV transcurre normalmente sin boss.
Para que el mundo se restaure al estado original al terminar cada partida:
/arenasaveworld <arenaId>
Esto toma una copia del directorio del mundo como plantilla. Al terminar cada partida, la arena entra en estado RESETTING: elimina el mundo actual, restaura la plantilla y recarga el mundo automáticamente.
/arenainfo <arenaId> ← resumen: estado, equipos, nexos, minas, mid
/arenastart <arenaId> ← fuerza inicio (requiere mínimo de jugadores)
/arenaforcestart <arenaId> ← fuerza inicio con cualquier número de jugadores (mínimo 1)
/arenastop <arenaId> ← fuerza fin de partida
/arenajoin <arenaId> ← únete directamente a una arena (pruebas, requiere admin)
| Comando | Permiso | Descripción |
|---|---|---|
| /arenacreate <id> <world> | annihilation.admin | Crea una nueva arena |
| /arenadelete <id> | annihilation.admin | Elimina una arena |
| /arenalist | annihilation.admin | Lista todas las arenas cargadas |
| /arenainfo <id> | annihilation.admin | Información detallada de una arena |
| /arenastart <id> | annihilation.admin | Fuerza inicio (requiere mínimo de jugadores) |
| /arenastop <id> | annihilation.admin | Fuerza fin de arena |
| /arenaforcestart <id> | annihilation.admin | Fuerza inicio con cualquier número de jugadores (mínimo 1) |
| /arenajoin <id> | annihilation.admin | Únete directamente a una arena (para pruebas) |
| /arenateamcreate <id> default [max] | annihilation.admin | Crea los 4 equipos por defecto (red, green, yellow, blue) |
| /arenateamcreate <id> <teamId> <color> [max] | annihilation.admin | Añade un equipo individual a la configuración |
| /arenasetspawn <id> <teamId> | annihilation.admin | Establece un punto de spawn (repetible) |
| /arenasetnexus <id> <teamId> | annihilation.admin | Establece el nexo de un equipo (posición actual) |
| /arenasetmine <id> <teamId> | annihilation.admin | Abre GUI de mineral + wand para seleccionar bloques de mina |
| /arenasetmine <id> mid | annihilation.admin | Wand para seleccionar los spots de diamante del mid |
| /arenasetmid <id> <delay> | annihilation.admin | Configura el intervalo de respawn del mid (segundos) |
| /arenasaveworld <id> | annihilation.admin | Guarda la plantilla de mundo para el reset automático |
| /mapsetup <world> setnexus <teamId> | annihilation.admin | Wand para marcar el nexo de un equipo en un mapa específico |
| /mapsetup <world> setspawn <teamId> | annihilation.admin | Guarda la posición actual como spawn del equipo en el mapa |
| /mapsetup <world> setmine <teamId> | annihilation.admin | GUI + wand para configurar los bloques de mina del equipo en el mapa |
| /mapsetup <world> setmid | annihilation.admin | Wand para configurar los spots de diamante del mid en el mapa |
| /mapsetup <world> info | annihilation.admin | Muestra la geometría configurada para el mapa |
| | | Añade la posición actual como spawn de boss para la Fase IV |
| | | Lista todas las ubicaciones de boss configuradas para el arena |
| | | Elimina todos los spawns de boss del arena |
| Comando | Descripción |
|---|---|
| /arenateam | Abre la GUI para elegir equipo |
| /classselect [clase] | Abre la GUI de clases o selecciona directamente |
| /stats | Muestra tus estadísticas de la partida actual |
| /gamescore | Muestra la salud actual de los nexos |
| /shop | Abre la tienda de recursos in-game |
| /enderpearl | Obtiene un ender pearl (cooldown configurable) |
| /leaderboard [stat] | Leaderboard (KILLS, WINS, DEATHS) |
| /rank | Muestra tu posición en el leaderboard de kills |
| /top [stat] | Top 10 jugadores por estadística (kills, wins, deaths) |
| /report <jugador> <razón> | Reporta a un jugador |
Chat global entre servidores: escribe
!<mensaje>en el chat (fuera de una arena) para enviar un mensaje a todos los jugadores en el lobby.
| Comando | Permiso | Descripción |
|---|---|---|
| /addbalance <jugador> <cantidad> | annihilation.admin | Añade monedas al balance de un jugador |
| /refreshleaderboard | annihilation.admin | Recarga el leaderboard desde MongoDB |
| /lobbyreload | annihilation.admin | Recarga la configuración del lobby |
| /setholo <tipo> <stat> | annihilation.admin | Crea un holograma de leaderboard en tu posición |
| Comando | Descripción |
|---|---|
| /play | Entra a la cola de matchmaking |
| /quickjoin | Entra directamente a la arena más llena disponible |
| /leavequeue | Sale de la cola de matchmaking |
| /stats [jugador] | Muestra estadísticas totales |
| /leaderboard [stat] | Leaderboard global (kills, wins, deaths) |
| /shop | Abre la tienda de cosméticos y clases |
| /equip <tipo> <id> | Equipa un cosmético (killmessage, particle, deathsound) |
| /lang [código] | Cambia tu idioma (en, es, pt) |
Hay 21 clases disponibles. Las marcadas con 🔒 requieren desbloqueo en la tienda del lobby.
| Clase | Armadura | Especialidad | |---|---|---| | Archer | Cuero | Arco con Power II + 32 flechas | | Miner | Cuero | Pico eficiente para minas | | Swordsman | Hierro | Espada de hierro, DPS cuerpo a cuerpo | | Builder | Cuero | Bloques y herramientas de construcción | | Healer | Hierro | Regeneración pasiva + pociones | | Tank | Diamante | Máxima defensa, sin velocidad | | Speedster | Cuero | Speed II permanente | | Wizard | Cuero | Pociones de daño y slowness | | Assassin | Cuero | Invisibilidad al activar habilidad | | Necromancer | Cuero | Invoca esqueletos aliados | | Sniper 🔒 | Cuero | Arco con Punch II y Power IV | | Alchemist 🔒 | Cuero | Arsenal de pociones especiales | | Engineer 🔒 | Hierro | TNT y dispensadores | | Ranger 🔒 | Cuero | Arco + espada + rapidez | | Knight 🔒 | Hierro | Espada con Fire Aspect | | Trapper 🔒 | Cuero | Trampas de tela de araña y presión | | Vampire 🔒 | Cuero | Roba vida al atacar | | Paladin 🔒 | Diamante | Aura de curación para aliados cercanos | | Destroyer 🔒 | Hierro | Pico potente para destruir el nexo | | Scout 🔒 | Cuero | Speed III + Jump Boost | | Acrobat | Cuero | Arco con 15 flechas + doble salto hacia adelante (8 s cooldown) |
Las clases libres por defecto son miner, swordsman, builder, archer y knight (configurable en free-classes). Los jugadores eligen clase desde la GUI (/classselect) y pueden cambiarla en el spawn del equipo antes de que empiece la partida.
Además del shop general (/shop o clic derecho en cofre), los admins pueden colocar carteles de tienda especializada directamente en el mapa. Los jugadores los abren con clic derecho durante la partida.
Línea 1: [Shop]
Línea 2: Brewing ← para la tienda de ingredientes
Potions ← para la tienda de pociones
plugins/AnnihilationGame/sign_shops.yml.Solo jugadores con annihilation.admin pueden crear o romper carteles de tienda.
Vende ingredientes para elaborar pociones en el soporte de pociones:
| Item | Precio | |---|---| | Nether Wart ×4 | 5 monedas | | Blaze Powder ×2 | 8 monedas | | Spider Eye ×2 | 5 monedas | | Azúcar ×4 | 4 monedas | | Glistering Melon Slice ×2 | 10 monedas | | Water Bottle ×3 | 3 monedas |
Vende pociones listas para beber, más caras pero sin necesidad de soporte de pociones:
| Item | Precio | |---|---| | Potion of Strength | 25 monedas | | Potion of Speed II | 20 monedas | | Potion of Regeneration II | 30 monedas | | Potion of Invisibility | 35 monedas |
Accesible desde el lobby con /shop. Los jugadores gastan monedas (balance almacenado en MongoDB) para desbloquear:
| Categoría | Descripción | |---|---| | Kill Messages | Mensaje personalizado anunciado a toda la arena al eliminar a un enemigo | | Partículas | Efecto de partículas que estalla en la ubicación exacta donde murió el jugador | | Death Sounds | Sonido que se escucha en la ubicación del jugador al morir (ej. aullido de lobo) | | Clases | Desbloquear las clases premium (🔒) |
Los cosméticos activos se cachean en Redis (COSMETIC_CACHE:<uuid>) y se sincronizan con MongoDB. Se equipan con /equip <killmessage|particle|deathsound> <id> o desde la GUI de la tienda.
Kill messages disponibles: classic, brutal, clean, savage, silent, headshot, fire, ice, electric, poison, ninja, legendary.
Partículas de muerte disponibles: flame, hearts, smoke, explosion, witch, crit, note, portal, lava, snowball, slime, dragon_breath.
Death sounds disponibles: wolf, zombie, skeleton, creeper, ghast, enderman, blaze, spider, wither, villager, pig, horse.
Los tres catálogos se definen en shop.yml (lobby) y sus efectos reales en KillMessageRegistry / DeathParticleRegistry / DeathSoundRegistry (módulo de juego); los IDs deben coincidir entre ambos. Tanto la partícula como el sonido se reproducen en la ubicación exacta de la muerte y son audibles/visibles para los jugadores cercanos, no solo para la víctima.
Sistema i18n con soporte para 3 idiomas y caché en 3 capas:
JVM Cache (1 min) → Redis Cache (1 hr) → MongoDB → Fallback EN
| Código | Idioma |
|---|---|
| en | English (predeterminado) |
| es | Español |
| pt | Português |
El idioma preferido se guarda por UUID y se aplica a todos los mensajes del sistema.
1. Jugador se conecta al proxy BungeeCord
→ Aterriza en el servidor Lobby
2. Jugador ejecuta /play
→ QueueEntry se añade a la lista Redis MATCHMAKING_QUEUE:QUICK_JOIN
3. LobbyMatchmakingProcessor (cada 5 s) detecta jugadores en cola
→ Selecciona la mejor arena disponible (estado WAITING, con slots libres)
→ Por cada jugador desencola:
· Publica PLAYER_TRANSFER → BungeeCord transfiere al jugador
· Publica PLAYER_TRANSFER → Game Server registra transferencia pendiente
→ Publica MATCH_FOUND → Lobby limpia estado de cola local
4. BungeeCord recibe PLAYER_TRANSFER
→ ProxiedPlayer.connect("game-1")
5. Jugador llega al servidor Game
→ PendingTransferService.consumeTransfer() devuelve el arenaId
→ GameMatchmakingService.addToArena() añade al jugador a la arena
→ Estado de arena: WAITING
6. Jugador en sala de espera recibe 4 ítems en el hotbar:
· Slot 0 — Kit Selector (libro encantado): abre GUI de clases
· Slot 4 — Team Selector (brújula): abre GUI de equipos
· Slot 6 — Cosmetics (blaze powder): abre GUI de cosméticos activos
· Slot 8 — Return to Lobby (cama roja): vuelve al servidor lobby
7. Arena alcanza min-players → STARTING
→ Cuenta atrás de 30 s en scoreboard
8. Cuenta atrás llega a 0 → Fase I
→ Equipos auto-asignados si no eligieron uno
→ Ítems de espera eliminados, jugadores teleportados a sus spawns y kit aplicado
→ Minas de ores activadas
9. Duración de la Fase I agotada → Fase II
→ PvP habilitado
10. Duración de la Fase II agotada → Fase III
→ Diamantes del mid activados (spawnean en los spots configurados)
11. Duración de la Fase III agotada → Fase IV
→ Aparece un boss en cada ubicación configurada (Wither Skeleton o Iron Golem, aleatorio)
→ El boss muestra una BossBar en la parte superior de la pantalla a jugadores en un radio de 25 bloques
→ Todo daño al nexo sigue siendo 1 golpe = 1 HP
12. Duración de la Fase IV agotada → Fase V
→ El boss desaparece
→ El daño al nexo aumenta a x2 (1 golpe = 2 HP)
13. Duración de la Fase V agotada → Fase VI
→ Daño al nexo vuelve a 1 golpe = 1 HP
→ Minas y diamantes del mid siguen activos hasta el final
14. Nexo de un equipo llega a 0 HP → equipo eliminado, su bloque se reemplaza por bedrock
→ Cuando solo queda 1 equipo con nexo, o se agota la Fase VI → ENDING
15. ENDING (10 segundos)
→ Anuncio del equipo ganador con título
→ GameStatsService guarda kills/muertes/victorias/asistencias en MongoDB
→ LeaderboardService actualiza Redis sorted sets (KILLS, WINS, DEATHS)
→ Jugadores transferidos de vuelta al Lobby
16. RESETTING
→ Espectadores restaurados, equipos, jugadores y estado del mid limpiados
→ ArenaWorldManager elimina el mundo actual y restaura la plantilla
→ Mundo recargado en el servidor
→ Arena vuelve a WAITING lista para la siguiente partida
| Permiso | Descripción | Por defecto |
|---|---|---|
| annihilation.admin | Acceso a todos los comandos de administración | OP |
| annihilation.bypass | Saltar restricciones del juego | OP |
/bosssetspawn <arenaId>annihilation.admin/bosssetspawn <arenaId> listannihilation.admin/bosssetspawn <arenaId> clearannihilation.admin