Encantamientos personalizados
EliteMobs y FreeMinecraftModels proporcionan encantamientos personalizados mediante un sistema compartido de MagmaCore. Cada plugin mantiene sus definiciones y efectos Lua en su propia carpeta enchantments/. Los encantamientos nativos de Minecraft permanecen en el espacio de nombres minecraft:.
Actualizar las definiciones incluidas
El catálogo restaura los archivos YAML y Lua incluidos que falten y añade los campos predeterminados ausentes a las definiciones incluidas existentes. Conserva los valores ya configurados y el código Lua existente. Esto funciona incluso cuando la carpeta enchantments/ ya existe.
El plugin responsable puede archivar primero los archivos que coincidan con un formato retirado. Por ejemplo, EliteMobs conserva los YAML de encantamientos que contienen maxLevelV2 antes de generar los valores predeterminados actuales. EliteMobs también archiva las copias sin editar de scripts de encantamientos incluidos en versiones anteriores, como un antiguo grappling_hook.lua, para escribir en su lugar el valor predeterminado actual; un script que hayas editado se conserva. Revisa los ajustes personalizados en el archivo de configuraciones y vuelve a aplicarlos con los campos actuales. Un DLC actualizado o un efecto personalizado sigue necesitando su propia definición y código Lua correspondientes.
Referencias en objetos
Los efectos personalizados usan un ID en minúsculas con espacio de nombres y un nivel entero positivo. Este ejemplo es una definición de objeto de FMM:
enchantments:
- "minecraft:unbreaking,3"
- "elitemobs:critical_strikes,2"
Por ejemplo, critical_strikes.yml en el catálogo de encantamientos de EliteMobs define elitemobs:critical_strikes. Una definición de FMM usa freeminecraftmodels:. Las subcarpetas no forman parte del ID; asigna nombres de archivo únicos al contenido.
El YAML de objetos personalizados de EliteMobs conserva los nombres de Bukkit, como UNBREAKING,3, para encantamientos nativos, pero exige IDs con espacio de nombres para efectos personalizados. No copies la sintaxis de objetos nativos de FMM a otro plugin sin comprobar su formato de objetos.
El proveedor instalado debe reconocer el ID. La compatibilidad, el tipo de objeto, la ranura, los conflictos y las capacidades necesarias proceden de su definición. Eliminar un proveedor no convierte su efecto personalizado en un encantamiento nativo.
Formato de definición
Esta es la definición Ignition incluida en FMM, asociada a ignition.lua en el mismo catálogo de encantamientos:
isEnabled: true
name: Ignition
description: Sets surviving targets on fire after a staff fireball hits.
maxLevel: 3
curse: false
validSlots: [MAINHAND]
itemTypes: [STAFF]
attackKinds: [STAFF_FIREBALL]
requires: []
conflicts: []
stacking: source_item
script: ignition.lua
parameters:
base_ticks: 20
ticks_per_level: 20
return {
api_version = 1,
on_ignition_ticks = function(context)
return math.max(0, math.min(200, context.parameters.base_ticks
+ context.parameters.ticks_per_level * context.enchantment.level))
end
}
Esta consulta devuelve una duración de ignición a FMM. No se ejecuta como un script de prop ni de objeto equipado.
| Campo | Significado |
|---|---|
isEnabled | Por defecto true; las definiciones desactivadas no entran en el catálogo |
name | Nombre visible de texto simple, obligatorio |
description | Descripción opcional, vacía por defecto |
maxLevel | Límite positivo de nivel al encantar; los objetos definidos explícitamente pueden superarlo |
curse | Indica si el encantamiento es una maldición; por defecto false |
validSlots | Ranuras de equipo: HEAD, CHEST, LEGS, FEET, MAINHAND, OFFHAND |
itemTypes | Categorías admitidas: SWORD, AXE, PICKAXE, SHOVEL, HOE, BOW, CROSSBOW, TRIDENT, MACE, SPEAR, HELMET, CHESTPLATE, LEGGINGS, BOOTS, SHIELD, FISHING_ROD, SHEARS, ELYTRA, WAND, STAFF, OTHER |
attackKinds | Filtro opcional de ataque mágico: WAND_MISSILE, STAFF_MELEE, STAFF_FIREBALL |
requires | Capacidades exigidas al proveedor |
conflicts | Otros IDs de encantamientos en minúsculas con espacio de nombres |
stacking | source_item por defecto, o sum_equipped_levels |
script | Nombre de archivo .lua obligatorio, en minúsculas y sin directorio |
parameters | Valores escalares con nombre o listas de escalares por nivel |
set | Opcional. Convierte este encantamiento en un conjunto de objetos |
Una lista por nivel debe tener exactamente maxLevel entradas. Por encima de ese nivel se conserva el último valor de la lista, mientras que el script sigue recibiendo el nivel real del encantamiento. Los parámetros pertenecen al efecto concreto; añadir una clave arbitraria aquí no crea una mecánica nueva.
Los campos desconocidos de nivel superior, los IDs duplicados, los scripts ausentes y los hooks no admitidos provocan el rechazo del catálogo candidato. Corrige el archivo que indique el error antes de recargar. Un candidato fallido no sustituye al catálogo activo.
Responsabilidad de los efectos
Parte de un efecto incluido en el plugin al que pertenecerá la nueva definición. Sus hooks y operaciones de dominio admitidos determinan lo que puede hacer. Los hooks de consulta devuelven valores como el número de misiles, la probabilidad de crítico o la bonificación de amenaza. Los hooks de acción procesan entradas de objetos aceptadas y pueden mantener efectos temporizados.
La antigua API context.item de FMM y su ciclo de equipar/desequipar no se aplican aquí. Los scripts de encantamiento usan sus propios context.enchantment, context.parameters, datos del origen capturados y operaciones de acción. No renombres un antiguo script de objeto suponiendo que su contexto es compatible.
Libros y yunques
Los libros encantados personalizados usan las mismas definiciones de proveedor que los objetos equipados. Un yunque valida el objeto de origen, el libro y el resultado completo, incluidos los encantamientos nativos. Los niveles personalizados iguales se combinan para obtener el siguiente nivel; si son distintos, se conserva el mayor. Cada encantamiento personalizado modificado suma su nivel resultante al coste nativo de reparación. El nivel resultante debe superar las comprobaciones de límite de nivel en yunque, ranura, tipo, capacidades y conflictos de la definición.
Los libros mixtos deben transferir todas las entradas nativas que acepte el servidor, además de las personalizadas. Si el servidor rechaza una entrada nativa, se rechaza la operación personalizada en lugar de descartar silenciosamente esa parte del libro. Las definiciones no válidas o no disponibles también impiden la vista previa. Los materiales de entrada y el estado del proveedor se comprueban de nuevo al recoger el resultado; una vista previa visible no reserva un resultado que siga siendo válido tras cambiar el catálogo.
Referencia de consultas Lua
Las consultas numéricas ejecutan una instancia nueva del script y la cierran inmediatamente después del resultado. Devuelve un único número finito o nil para no aportar ningún valor. El estado y el trabajo programado no sobreviven a la consulta. Una definición fallida queda en cuarentena hasta que se recargue correctamente el catálogo; agotar el presupuesto restante del llamador no pone por sí solo la definición en cuarentena.
| Contexto | Contenido |
|---|---|
context.enchantment | id y level real |
context.parameters | Valores de esta definición resueltos para ese nivel |
context.input | Datos escalares proporcionados por la mecánica responsable; consulta el efecto incluido para conocer las claves exactas |
context.target | Tabla Entity o Living Entity del objetivo, o nil |
context.player | Jugador desencadenante cuando la consulta dispone de uno |
FMM proporciona on_missile_count, on_missile_damage_factor, on_blast_radius_factor y on_ignition_ticks. Otros proveedores exponen sus propios hooks numéricos. Una definición solo puede declarar hooks aceptados por su proveedor.
Referencia de acciones Lua
Los scripts de acción usan las tablas compartidas de planificador, tiempos de reutilización, mundo, zonas, jugador y eventos. Se ejecutan para una entrada o ataque aceptado y usan un origen capturado en las llamadas posteriores. El chat captura el mensaje durante el evento de chat y después captura el equipo cuando se despacha en el hilo del servidor. El parámetro opcional parameters.lifetime_ticks debe ser un entero positivo; sin él, la activación dura un tick. Los efectos programados necesitan una duración definida lo bastante larga para terminar.
Las activaciones se detienen al finalizar su duración, cuando el actor muere, se desconecta o cambia de mundo, cuando se descarga el mundo al que pertenecen, cuando se descarga un chunk que contiene alguna entidad que poseen, o cuando el proveedor se recarga o se desactiva. Pueden terminar antes si, tras la última entrada, no queda trabajo propio pendiente. parameters.stop_on_unequip: true también detiene una activación cuando su objeto capturado deja de estar equipado. Los tiempos de reutilización locales pertenecen al jugador y al ID de encantamiento; los globales pertenecen al jugador dentro del proveedor. Ambos sobreviven a los cambios de equipo, las activaciones finalizadas, los cambios de mundo y las recargas válidas, y se borran al desconectarse o al apagarse el proveedor.
| Hook | Entrada aceptada |
|---|---|
on_attack_entity | Daño cuerpo a cuerpo nativo, positivo y aplicado correctamente con el objeto de la mano principal, o un ataque explícito del plugin |
on_projectile_hit | Daño aplicado correctamente a un objetivo vivo por un proyectil de arco capturado, entregado una vez por proyectil y objetivo, o un impacto explícito del plugin |
on_take_damage | Daño positivo al jugador; se examinan las ranuras equipadas que sean elegibles |
on_right_click, on_left_click | Interacción de mano sin agacharse |
on_shift_right_click, on_shift_left_click | Interacción de mano mientras se está agachado; sustituyen al hook de clic ordinario correspondiente |
on_break_block | Rotura de bloque aceptada del jugador con el objeto de la mano principal |
on_chat | Chat aceptado, despachado en el hilo del servidor con la copia del mensaje |
on_sneak | Inicio de la postura agachada; las contribuciones del equipo se recopilan por definición |
on_projectile_launch | Munición encantada consumida que se lanza como flecha desde un evento de arco |
on_game_tick | Tick mientras esta activación sigue activa |
on_zone_enter, on_zone_leave | Jugadores que cruzan una zona vigilada por esta activación |
Estos hooks no crean un entorno de scripts de equipar/desequipar. Una definición que solo actúe en cada tick sigue necesitando un hook de entrada para iniciar su activación. Los hooks nativos de ataque, daño, chat y minería observan entradas ya aceptadas; no pueden cancelar el evento original. Los cuatro hooks de interacción exponen una marca de cancelación síncrona: context.event:cancel() impide la interacción asociada con el objeto y el bloque. Las llamadas programadas no pueden cancelar retroactivamente una entrada.
| Contexto | Contenido |
|---|---|
context.enchantment | id, level |
context.parameters | Parámetros de la definición resueltos para el nivel |
context.player | Tabla Player del actor actual |
context.target | Tabla Living Entity del objetivo afectado actual, o nil |
context.source | Datos capturados: item, slot, inventory_slot, equipment, attack_kind, providers; algunas entradas también proporcionan ammunition, projectile, message, block, drop_items, sneaking o equipped_levels |
context.item | Métodos de durabilidad y consumo de la ranura capturada, cuando aún se puede acceder al objeto del inventario; consulta los métodos de objeto |
context.action | id (UUID del ataque), instance (token de activación), actor (UUID), world (UUID del mundo) y los métodos siguientes |
context.set | Para un conjunto de objetos: id, name, level y pieces; nil en caso contrario |
Las copias de objetos contienen material, amount y enchantments. Son datos, no objetos vivos del inventario. Los UUID de los datos del origen son cadenas. En minería, source.block contiene x, y, z y material en minúsculas.
| Método de acción | Devuelve | Comportamiento |
|---|---|---|
stop() | nil | Detiene esta activación y limpia el trabajo que posee |
has_previous() | bool | Comprueba si existe otra instancia activa de este encantamiento para el mismo jugador |
replace_previous() | nil | Detiene esas instancias anteriores y conserva esta |
damage_target(target_uuid, amount) | bool | Solicita al proveedor que aplique daño finito positivo atribuido al origen capturado; false si se rechaza |
own_entity(uuid) | bool | Registra una entidad válida del mismo mundo que no sea un jugador para eliminarla durante la limpieza; úsalo después de crearla |
launch_projectile(location, direction, speed, range, ticks, impact, visual?, protected_path?=false) | bool | Lanza un proyectil de script propio; speed/range deben ser finitos y positivos, y ticks al menos 1 |
attribute_projectile(uuid, callback, protect?=false) | bool | Vincula el daño de un proyectil nativo propio a una función definida por el autor |
place_block(x, y, z, expected_material, block_data) | bool | Coloca un bloque mediante la validación de acciones de bloques del jugador, solo si coincide el material actual |
break_block(x, y, z, expected_material, drop_material?, amount?=1) | bool | Rompe mediante la validación de acciones de bloques del jugador, con un objeto soltado opcional definido por el autor |
break_naturally(x, y, z, expected_material) | bool | Rompe usando la herramienta capturada y la política de objetos soltados del evento de rotura original |
temporary_block(x, y, z, block_data, ticks?=0) | bool | Toma posesión temporal de un bloque cargado y lo restaura durante la limpieza o tras un número positivo de ticks; cero dura hasta la limpieza |
can_own_block(x, y, z) | bool | Comprueba que las coordenadas estén cargadas y se pueda tomar posesión temporal |
temporary_gravity(uuid, enabled) | bool | Modifica temporalmente la gravedad y la restaura durante la limpieza |
restore_gravity(uuid) | bool | Restaura antes de tiempo la gravedad modificada por esta activación |
temporary_scale(uuid, scale) | bool | Modifica temporalmente la escala de una entidad viva hasta la limpieza |
temporary_potion(uuid, type, ticks, amplifier) | bool | Aplica temporalmente un efecto de poción con ticks positivos y un amplificador no negativo |
restore_potion(uuid, type) | bool | Restaura antes de tiempo el efecto de poción modificado por esta activación |
ride_rails(speed) | bool | Sienta al jugador en una vagoneta que solo ven los clientes y la hace avanzar por los raíles conectados en el bloque del jugador, hacia el extremo al que mira, a speed bloques por tick (mayor que 0 y como máximo 2); false cuando no hay un raíl allí, el jugador ya va montado en algo o el adaptador NMS del servidor no está disponible |
Un viaje en raíles es trabajo que posee su activación. Agacharse, el final de la vía, un teletransporte, la muerte, desconectarse o cualquier otra cosa que aleje al jugador más de un bloque de la vagoneta termina el viaje y después la activación; el jugador queda donde se detuvo la vagoneta, salvo tras un teletransporte, la muerte o una desconexión. Detener la activación, también mediante replace_previous(), igualmente baja al jugador. El lifetime_ticks de la activación sigue aplicándose, así que dale tiempo suficiente para la vía más larga.
Las funciones de impacto de proyectil reciben (fresh_context, target_or_nil, location); las visuales reciben (fresh_context, location). Las funciones de daño de proyectiles nativos reciben (fresh_context, target, native_damage) en el siguiente tick. Sustituyen la aplicación nativa y deben aplicar explícitamente el daño deseado, normalmente mediante fresh_context.action:damage_target(target.uuid, amount). Con protect=true en proyectiles nativos, se filtran los bloques protegidos de explosiones y la ignición. En los proyectiles de script, protected_path=true absorbe los vuelos que cruzan posiciones protegidas o no cargadas.
La limpieza se limita a operaciones que registran la propiedad. Las operaciones ordinarias world:spawn_entity, entity:set_gravity y world:set_block_at no reciben automáticamente limpieza de la acción. Los métodos de estado temporal gestionan la restauración; no sustituyen la comprobación de si está permitido un efecto hostil o un cambio de bloques.
Conjuntos de objetos
Una sección set convierte un encantamiento en un conjunto de objetos. Pon el mismo encantamiento en cada pieza. El conjunto está completo mientras cada ranura indicada en pieces contiene un objeto que lo lleva. Un conjunto completo ejecuta sus hooks una vez por evento. Si falta alguna pieza, no se ejecuta nada.
name: Crooked's Full Set
maxLevel: 1
validSlots: [HEAD, CHEST, LEGS, FEET]
itemTypes: [HELMET, CHESTPLATE, LEGGINGS, BOOTS]
script: crooked_set.lua
parameters:
lifetime_ticks: 620
stop_on_unequip: true
set:
pieces:
HEAD: Crooked's Hex-Brim
CHEST: Crooked's Warded Wrap
LEGS: Crooked's Bent Hosen
FEET: Crooked's Wayward Soles
lore:
- "&5Crooked's Full Set &7($equippedPieces/$totalPieces)"
- "$setPieces"
- "&7When damaged, has a 5% chance to grant Regeneration I."
return {
api_version = 1,
on_take_damage = function(context)
-- Runs only while all four pieces are worn, once per hit.
context.action:temporary_potion(context.player.uuid, "REGENERATION", 100, 0)
end
}
| Campo del conjunto | Significado |
|---|---|
pieces | Obligatorio. Asocia ranuras de equipo con nombres de pieza. Cuando se define validSlots, debe incluir la ranura de cada pieza |
name | Nombre que usa $setName. Por defecto es el name del encantamiento y admite códigos de color & |
lore | Las líneas de lore del conjunto. Por defecto es el nombre del conjunto con su recuento de piezas, seguido de una línea por pieza |
equippedPiece | Línea para una pieza puesta. Por defecto &a✔ $pieceName |
missingPiece | Línea para una pieza que falta. Por defecto &c✘ $pieceName |
El lore del conjunto admite estos placeholders:
| Placeholder | Muestra |
|---|---|
$setName | El nombre del conjunto |
$equippedPieces | Cuántas piezas lleva puestas el jugador |
$totalPieces | Cuántas piezas tiene el conjunto |
$setPieces | Una línea por pieza en orden de ranura, tomada de equippedPiece o missingPiece. El texto que rodea al placeholder se repite en cada línea |
$pieceName, $pieceSlot | Dentro de equippedPiece y missingPiece, el nombre de la pieza y su ranura, como Head o Main Hand |
$ifSetComplete | Muestra la línea solo mientras todas las piezas están puestas |
$ifSetIncomplete | Muestra la línea solo mientras falta alguna pieza |
Los objetos de un conjunto muestran esta sección en lugar de una línea en la lista de encantamientos personalizados. En EliteMobs, pon $itemSet en itemLoreStructureV2 de ItemSettings.yml, o en el propio lore de un objeto personalizado. Sin ninguna de las dos cosas, el conjunto va después del lore personalizado del objeto. $ifItemSet muestra una línea de la estructura solo en los objetos de un conjunto. Los objetos personalizados de FMM muestran el conjunto en la línea de lore que contiene $itemSet, o después de su lore.
La sección muestra lo que lleva puesto el jugador que porta el objeto y se redibuja cuando se equipa o se quita una pieza. Un objeto guardado fuera del inventario de un jugador conserva el estado que mostraba al salir.
Los hooks de un conjunto se diferencian de los hooks de encantamientos ordinarios en varios aspectos:
- Todos los hooks de acción de la tabla anterior llegan a un conjunto completo, sean cuales sean las ranuras de sus piezas. Un conjunto de armadura puede responder a
on_attack_entityoon_break_block. - Si el conjunto está completo se comprueba en el momento del evento. Un proyectil comprueba los conjuntos que se llevan puestos cuando aterriza, y cuenta cualquier proyectil, no solo las flechas de arco.
on_take_damageestablececontext.targetcomo el atacante cuando lo hay.context.source.itemycontext.itemson la primera pieza en orden de ranura:HEAD,CHEST,LEGS,FEET,MAINHAND,OFFHAND. Leecontext.source.equipment.MAINHANDpara el arma o herramienta que se sostiene.context.set.leveles el nivel más bajo entre las piezas.context.set.piecesestá indexado por ranura, con elnamey elinventory_slotde cada pieza.stop_on_unequip: truedetiene la activación de un conjunto cuando se quita cualquier pieza.- Las consultas numéricas, como la amenaza y la probabilidad de crítico de EliteMobs o los modificadores de lanzamiento de FMM, cuentan un conjunto una sola vez y solo mientras está completo.
Actualizar contenido existente
FMM omite los objetos personalizados con scripts: no vacío o entradas de encantamiento retiradas sin espacio de nombres. Sustituye esas definiciones de objeto por encantamientos con espacio de nombres; los scripts de props siguen siendo compatibles.
Los efectos personalizados de EliteMobs ahora usan maxLevel y parameters específicos del efecto en el YAML del proveedor. La configuración de encantamientos nativos y de nivel élite tiene un formato distinto. Sigue la referencia de encantamientos de EliteMobs en lugar de copiar un archivo antiguo de maxLevelV2 a una definición de proveedor.