Guía YAML dependencies

Dependencias

Las dependencias permiten crear cadenas de misiones y árboles de progresión. Un evento con dependencias solo estará disponible cuando el jugador haya completado todos los eventos listados.

Cómo funciona

El campo dependencies acepta una lista de IDs de otros eventos. Cuando un jugador intenta iniciar un evento con dependencias, el sistema verifica que cada uno de esos eventos tenga estado COMPLETED en su progreso. Si alguno no está completado, el evento aparece como bloqueado y no puede iniciarse.

Sintaxis básica
id: "mi-evento"
displayName: "Mi Evento"
description: "Solo disponible tras completar los anteriores."

dependencies:
  - "primer-evento"
  - "segundo-evento"

objectives:
  - id: "obj-1"
    type: KILL_ENTITY
    description: "Mata zombies"
    parameters:
      entity_type: "minecraft:zombie"
      target_amount: 10
La lógica actual es siempre AND — todos los eventos de la lista deben estar completados. Lógicas alternativas como OR (completar al menos uno de varios) o SEQUENCE (en orden específico) están planeadas para versiones futuras.

Ejemplo — cadena lineal

El caso más común: una cadena de misiones donde cada una desbloquea la siguiente.

events/cap-1-tutorial.yml
id: "cap-1-tutorial"
displayName: "§eCap. 1 — Tutorial"
description: "Aprende los básicos del servidor."

objectives:
  - id: "hablar-guia"
    type: INTERACT
    description: "Habla con el guía de bienvenida"
    parameters:
      target_type: "entity"
      target_id: "minecraft:villager"
      target_amount: 1

rewards:
  xp: 100
events/cap-2-supervivencia.yml
id: "cap-2-supervivencia"
displayName: "§eCap. 2 — Supervivencia"
description: "Reúne recursos básicos."

# Solo disponible si el cap. 1 está completado
dependencies:
  - "cap-1-tutorial"

objectives:
  - id: "recolectar-madera"
    type: MINE_BLOCK
    description: "Recolecta madera"
    parameters:
      block_id: "minecraft:oak_log"
      target_amount: 16

rewards:
  xp: 200
  items:
    - "minecraft:iron_pickaxe 1"
events/cap-3-mineria.yml
id: "cap-3-mineria"
displayName: "§eCap. 3 — Minería"
description: "Desciende y encuentra hierro."

# Requiere cap. 2 completado
dependencies:
  - "cap-2-supervivencia"

objectives:
  - id: "minar-hierro"
    type: MINE_BLOCK
    description: "Extrae hierro"
    parameters:
      block_id: "minecraft:iron_ore"
      target_amount: 10

rewards:
  xp: 400
  items:
    - "minecraft:diamond 1"

Ejemplo — árbol de progresión

Un evento que requiere completar múltiples ramas antes de desbloquearse.

Árbol con dos ramas que convergen
# Rama A
id: "rama-combate"
displayName: "Combatiente"
description: "Demuestra tus habilidades en combate."
objectives:
  - id: "matar-50-mobs"
    type: KILL_ENTITY
    description: "Mata 50 mobs"
    parameters:
      entity_type: "minecraft:zombie"
      target_amount: 50

---

# Rama B
id: "rama-construccion"
displayName: "Constructor"
description: "Construye tu primera base."
objectives:
  - id: "colocar-bloques"
    type: PLACE_BLOCK
    description: "Coloca 200 bloques"
    parameters:
      block_id: "minecraft:oak_planks"
      target_amount: 200

---

# Evento final — requiere ambas ramas
id: "maestro-supervivencia"
displayName: "§6Maestro de la Supervivencia"
description: "Has demostrado dominar el combate y la construcción."

dependencies:
  - "rama-combate"
  - "rama-construccion"

objectives:
  - id: "llegar-nivel"
    type: REACH_LEVEL
    description: "Alcanza el nivel 30"
    parameters:
      level: "30"
      target_amount: 1

rewards:
  xp: 2000
  items:
    - "minecraft:diamond_sword 1"
    - "minecraft:diamond_chestplate 1"
  commands:
    - "lp user {player} parent addtemp elite 30d"

Validación automática de ciclos

Al arrancar el servidor o ejecutar /eventui reload, EventUI valida automáticamente el grafo de dependencias usando un algoritmo DFS. Si detecta un ciclo — es decir, que un evento depende de sí mismo a través de una cadena — lanza un error con la ruta exacta del problema:

Error en consola al detectar ciclo
[EventUI] ERROR: Dependency cycle detected:
  evento-a → evento-b → evento-c → evento-a

Un ciclo significa que ninguno de los eventos involucrados podrá completarse nunca, ya que cada uno espera que el otro esté completado primero. EventUI lanza este error en el momento de carga para que lo detectes antes de que afecte a jugadores en producción.

Ejemplo de ciclo a evitar:

evento-a depende de evento-b, y evento-b depende de evento-a. Ninguno podrá iniciarse jamás. EventUI lo detecta y lanza error al cargar.

Dependencia con ID inexistente

Si defines una dependencia que apunta a un ID que no existe en ningún archivo de events/, el sistema no lanza un error — emite un warning en consola y trata el evento como si no tuviera esa dependencia:

Warning en consola
[EventUI] WARNING: Event 'evento-que-no-existe' referenced as dependency but not found

Esto significa que el evento quedará accesible inmediatamente, como si esa dependencia no existiera. Ten cuidado con errores tipográficos en los IDs.

Comportamiento en la UI

Los eventos bloqueados por dependencias aparecen con el estado LOCKED en la UI del cliente. El mod renderiza estos eventos con la textura locked_texture si está definida en el botón, o con la textura base con un overlay grisáceo por defecto.

Cuando el jugador intenta iniciar un evento bloqueado, recibe el mensaje configurado en config.yml:

Mensaje por defecto al intentar iniciar evento bloqueado
[EventUI] Este evento está bloqueado. Completa los anteriores primero.

Puedes personalizar este mensaje en config.yml bajo messages.event_locked.format.

Lógicas planeadas para versiones futuras

Actualmente el sistema solo soporta lógica AND — todos los eventos listados deben estar completados. Estas lógicas adicionales están planeadas para versiones futuras:

LógicaDescripciónEstado
AND Todos los eventos deben estar completados. Comportamiento actual. ✅ Disponible
OR Al menos uno de los eventos listados debe estar completado. 🔜 Planeado
SEQUENCE Los eventos deben completarse en el orden exacto en que están listados. 🔜 Planeado
WEIGHTED Completar un número mínimo de eventos de una lista mayor. 🔜 Planeado
Mientras tanto, puedes simular lógica OR creando un evento puente sin objetivos que se complete automáticamente al iniciar, y haciendo que los eventos finales dependan de ese puente en lugar de los individuales. Es un workaround, no una solución elegante, pero funciona con el sistema actual.