Enchantements personnalisés
EliteMobs et FreeMinecraftModels fournissent des enchantements personnalisés via un système MagmaCore partagé. Chaque plugin gère ses définitions et effets Lua dans son propre dossier enchantments/. Les enchantements natifs de Minecraft restent dans l'espace de noms minecraft:.
Mise à jour des définitions fournies
Le catalogue restaure les fichiers YAML et Lua fournis qui manquent et ajoute les champs par défaut absents aux définitions fournies existantes. Il conserve les valeurs déjà configurées et le code Lua existant. Cela fonctionne même si le dossier enchantments/ existe déjà.
Le plugin concerné peut d'abord archiver les fichiers correspondant à un format abandonné. Par exemple, EliteMobs conserve les YAML d'enchantement contenant maxLevelV2 avant de générer les valeurs par défaut actuelles. EliteMobs archive aussi les copies non modifiées d'anciens scripts d'enchantement fournis, comme un ancien grappling_hook.lua, afin que la version par défaut actuelle soit écrite à leur place ; un script que vous avez modifié est conservé. Vérifiez vos paramètres personnalisés dans les archives de configuration et réappliquez-les avec les champs actuels. Un DLC mis à jour ou un effet personnalisé nécessite toujours sa propre définition et son code Lua correspondants.
Références dans les objets
Les effets personnalisés utilisent un identifiant avec espace de noms en minuscules et un niveau entier positif. Cet exemple est une définition d'objet FMM :
enchantments:
- "minecraft:unbreaking,3"
- "elitemobs:critical_strikes,2"
Par exemple, critical_strikes.yml dans le catalogue d'enchantements d'EliteMobs définit elitemobs:critical_strikes. Une définition FMM utilise freeminecraftmodels:. Les sous-dossiers ne font pas partie de l'identifiant ; donnez des noms uniques aux fichiers de contenu.
Le YAML des objets personnalisés EliteMobs conserve les noms Bukkit comme UNBREAKING,3 pour les enchantements natifs et exige des identifiants avec espace de noms pour les effets personnalisés. Ne copiez pas la syntaxe des enchantements natifs de FMM dans un autre plugin sans vérifier son format d'objet.
Le fournisseur installé doit reconnaître l'identifiant. La compatibilité, le type d'objet, l'emplacement, les conflits et les capacités requises proviennent de sa définition. Retirer un fournisseur ne transforme pas son effet personnalisé en enchantement natif.
Format de définition
Voici la définition Ignition fournie avec FMM, associée à ignition.lua dans le même catalogue d'enchantements :
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
}
Cette requête retourne une durée d'embrasement à FMM. Elle ne s'exécute pas comme un script de prop ou d'objet équipé.
| Champ | Signification |
|---|---|
isEnabled | Vaut true par défaut ; les définitions désactivées n'entrent pas dans le catalogue |
name | Nom d'affichage simple obligatoire |
description | Description facultative, vide par défaut |
maxLevel | Plafond positif du niveau d'enchantement ; les objets explicitement définis peuvent le dépasser |
curse | Indique si l'enchantement est une malédiction ; vaut false par défaut |
validSlots | Emplacements d'équipement : HEAD, CHEST, LEGS, FEET, MAINHAND, OFFHAND |
itemTypes | Catégories acceptées : SWORD, AXE, PICKAXE, SHOVEL, HOE, BOW, CROSSBOW, TRIDENT, MACE, SPEAR, HELMET, CHESTPLATE, LEGGINGS, BOOTS, SHIELD, FISHING_ROD, SHEARS, ELYTRA, WAND, STAFF, OTHER |
attackKinds | Filtre facultatif d'attaque magique : WAND_MISSILE, STAFF_MELEE, STAFF_FIREBALL |
requires | Capacités requises du fournisseur |
conflicts | Autres identifiants d'enchantement en minuscules avec espace de noms |
stacking | source_item par défaut, ou sum_equipped_levels |
script | Nom obligatoire de fichier .lua en minuscules, sans dossier |
parameters | Valeurs scalaires nommées ou listes de valeurs scalaires par niveau |
set | Facultatif. Fait de cet enchantement un ensemble d'objets |
Une liste par niveau doit contenir exactement maxLevel entrées. Au-delà de ce niveau, la dernière valeur de la liste est conservée tandis que le script reçoit toujours le niveau réel de l'enchantement. Les paramètres appartiennent à l'effet concerné ; ajouter ici une clé arbitraire ne crée pas de nouvelle mécanique.
Les champs de premier niveau inconnus, identifiants en double, scripts manquants et hooks non pris en charge font rejeter le catalogue candidat. Corrigez le fichier nommé dans l'erreur avant de recharger. Un candidat invalide ne remplace pas le catalogue actif.
Responsabilité des effets
Partez d'un effet fourni par le plugin qui gérera votre nouvelle définition. Ses hooks et opérations disponibles déterminent ce qu'il peut faire. Les hooks de requête retournent des valeurs comme le nombre de missiles, la probabilité de coup critique ou le bonus de menace. Les hooks d'action traitent les entrées d'objet acceptées et peuvent gérer des effets temporisés.
L'ancienne API FMM context.item et son cycle équipement/déséquipement ne s'appliquent pas ici. Les scripts d'enchantement utilisent leurs propres context.enchantment, context.parameters, informations de source capturées et opérations d'action. Ne renommez pas un ancien script d'objet en supposant que son contexte est compatible.
Livres et enclumes
Les livres enchantés personnalisés utilisent les mêmes définitions de fournisseur que les objets équipés. Une enclume valide l'objet source, le livre et le résultat complet, y compris les enchantements natifs. Deux niveaux personnalisés égaux se combinent au niveau suivant ; des niveaux inégaux conservent le plus élevé. Chaque enchantement personnalisé modifié ajoute son niveau résultant au coût de réparation natif. Le niveau obtenu doit respecter les contrôles de la définition pour la limite d'enclume, l'emplacement, le type, les capacités et les conflits.
Les livres mixtes doivent transférer chaque entrée native acceptée par le serveur ainsi que leurs entrées personnalisées. Si le serveur refuse une entrée native, l'opération personnalisée est refusée au lieu d'abandonner silencieusement cette partie du livre. Les définitions invalides ou indisponibles empêchent aussi l'aperçu. Les entrées et l'état du fournisseur sont revérifiés à la récupération ; un aperçu visible n'est pas une réservation qui survit à un changement de catalogue.
Référence des requêtes Lua
Les requêtes numériques exécutent une nouvelle instance de script et la ferment immédiatement après le résultat. Retournez un nombre fini ou nil pour ne rien apporter. L'état et les tâches programmées ne survivent pas à la requête. Une définition en échec est mise en quarantaine jusqu'à un rechargement réussi du catalogue ; épuiser le budget restant de l'appelant ne met pas à lui seul la définition en quarantaine.
| Contexte | Contenu |
|---|---|
context.enchantment | id et level réel |
context.parameters | Valeurs de cette définition résolues pour ce niveau |
context.input | Données scalaires fournies par la mécanique propriétaire ; consultez l'effet fourni pour les clés exactes |
context.target | Table Entity ou Living Entity de la cible, ou nil |
context.player | Joueur déclencheur lorsque la requête en possède un |
FMM fournit on_missile_count, on_missile_damage_factor, on_blast_radius_factor et on_ignition_ticks. Les autres fournisseurs exposent leurs propres hooks numériques. Une définition ne peut déclarer que des hooks acceptés par son fournisseur.
Référence des actions Lua
Les scripts d'action utilisent les tables partagées du planificateur, des temps de recharge, du monde, des zones, des joueurs et des événements. Ils s'exécutent pour une entrée ou une attaque acceptée et utilisent une source capturée pour les callbacks ultérieurs. Le chat capture le message pendant l'événement de chat, puis l'équipement lors de la distribution sur le thread serveur. Le paramètre facultatif parameters.lifetime_ticks doit être un entier positif ; sans lui, l'activation dure un tick. Les effets programmés nécessitent une durée définie assez longue pour se terminer.
Les activations s'arrêtent à l'expiration de leur durée, à la mort ou à la déconnexion de l'acteur, lorsqu'il change de monde, lorsque le monde propriétaire ou un chunk contenant une de leurs entités gérées est déchargé, ou lorsque le fournisseur est rechargé ou désactivé. Elles peuvent se terminer plus tôt une fois que la dernière entrée n'a plus de travail restant à sa charge. parameters.stop_on_unequip: true arrête également une activation lorsque son objet capturé n'est plus équipé. Les temps de recharge locaux appartiennent au joueur et à l'identifiant d'enchantement ; les temps de recharge globaux appartiennent au joueur au sein du fournisseur. Les deux survivent aux échanges d'équipement, aux activations terminées, aux changements de monde et aux rechargements valides, et sont effacés à la déconnexion ou à l'arrêt du fournisseur.
| Hook | Entrée acceptée |
|---|---|
on_attack_entity | Dégâts natifs de mêlée réussis et positifs avec l'objet en main principale, ou attaque explicitement gérée par un plugin |
on_projectile_hit | Dégâts réussis sur une cible vivante par un projectile d'arc capturé, transmis une fois par projectile et cible, ou impact explicitement géré par un plugin |
on_take_damage | Dégâts positifs au joueur ; les emplacements équipés admissibles sont inspectés |
on_right_click, on_left_click | Interaction de la main sans accroupissement |
on_shift_right_click, on_shift_left_click | Interaction de la main en étant accroupi ; remplace le hook de clic ordinaire correspondant |
on_break_block | Destruction de bloc acceptée par le joueur avec l'objet en main principale |
on_chat | Chat accepté, distribué sur le thread serveur avec le message capturé |
on_sneak | Début de l'accroupissement ; les contributions de l'équipement sont collectées par définition |
on_projectile_launch | Munition enchantée consommée et lancée comme flèche depuis un événement d'arc |
on_game_tick | Tick tant que cette activation reste active |
on_zone_enter, on_zone_leave | Joueurs traversant une zone surveillée par cette activation |
Ces hooks ne créent pas de moteur de scripts avec équipement/déséquipement. Une définition ne contenant qu'un hook de tick a toujours besoin d'un hook d'entrée pour démarrer son activation. Les hooks natifs d'attaque, de dégâts, de chat et de minage observent des entrées déjà acceptées ; ils ne peuvent pas annuler l'événement original. Les quatre hooks d'interaction exposent un indicateur d'annulation synchrone : context.event:cancel() refuse l'interaction associée avec l'objet et le bloc. Les callbacks programmés ne peuvent pas annuler rétroactivement une entrée.
| Contexte | Contenu |
|---|---|
context.enchantment | id, level |
context.parameters | Paramètres de définition résolus pour le niveau |
context.player | Table Player de l'acteur actuel |
context.target | Table Living Entity de la cible actuellement affectée, ou nil |
context.source | Données capturées : item, slot, inventory_slot, equipment, attack_kind, providers ; certaines entrées fournissent aussi ammunition, projectile, message, block, drop_items, sneaking ou equipped_levels |
context.item | Méthodes de durabilité et de consommation de l'emplacement capturé lorsqu'un objet d'inventaire reste accessible ; voir les méthodes d'objet |
context.action | id (UUID de l'attaque), instance (jeton d'activation), actor (UUID), world (UUID du monde) et méthodes ci-dessous |
context.set | Pour un ensemble d'objets : id, name, level et pieces ; nil sinon |
Les instantanés d'objet contiennent material, amount et enchantments. Ce sont des données, pas des objets d'inventaire actifs. Les UUID des données sources sont des chaînes. Pour le minage, source.block contient x, y, z et material en minuscules.
| Méthode d'action | Retour | Comportement |
|---|---|---|
stop() | nil | Arrête cette activation et nettoie le travail dont elle est responsable |
has_previous() | bool | Vérifie s'il existe une autre instance active de cet enchantement pour le même joueur |
replace_previous() | nil | Arrête ces instances antérieures en conservant celle-ci |
damage_target(target_uuid, amount) | bool | Demande au fournisseur d'appliquer des dégâts finis et positifs attribués à la source capturée ; false en cas de refus |
own_entity(uuid) | bool | Enregistre une entité valide du même monde, autre qu'un joueur, pour suppression au nettoyage ; à utiliser après son apparition |
launch_projectile(location, direction, speed, range, ticks, impact, visual?, protected_path?=false) | bool | Lance un projectile scripté géré ; speed/range doivent être finis et positifs, et ticks au moins égal à 1 |
attribute_projectile(uuid, callback, protect?=false) | bool | Associe les dégâts d'un projectile natif géré à un callback défini |
place_block(x, y, z, expected_material, block_data) | bool | Place un bloc après validation des actions de bloc du joueur, uniquement si le matériau actuel correspond |
break_block(x, y, z, expected_material, drop_material?, amount?=1) | bool | Casse un bloc après validation des actions de bloc du joueur, avec un objet lâché facultatif défini |
break_naturally(x, y, z, expected_material) | bool | Casse avec l'outil capturé et la règle de butin de l'événement de destruction source |
temporary_block(x, y, z, block_data, ticks?=0) | bool | Prend temporairement en charge un bloc chargé, restauré au nettoyage ou après un nombre positif de ticks ; zéro dure jusqu'au nettoyage |
can_own_block(x, y, z) | bool | Vérifie que les coordonnées sont chargées et que la prise en charge temporaire est disponible |
temporary_gravity(uuid, enabled) | bool | Modifie temporairement la gravité et la restaure au nettoyage |
restore_gravity(uuid) | bool | Restaure en avance la gravité modifiée par cette activation |
temporary_scale(uuid, scale) | bool | Modifie temporairement l'échelle d'une entité vivante jusqu'au nettoyage |
temporary_potion(uuid, type, ticks, amplifier) | bool | Applique temporairement un effet de potion avec une durée positive en ticks et un amplificateur non négatif |
restore_potion(uuid, type) | bool | Restaure en avance l'effet de potion modifié par cette activation |
ride_rails(speed) | bool | Installe le joueur dans un wagonnet que seuls les clients voient et le fait avancer sur les rails connectés du bloc où se trouve le joueur, vers l'extrémité qu'il regarde, à speed blocs par tick (supérieur à 0, au plus 2) ; false si aucun rail ne s'y trouve, si le joueur chevauche déjà quelque chose ou si l'adaptateur NMS du serveur est indisponible |
Un trajet sur rails fait partie du travail dont son activation est responsable. S'accroupir, la fin de la voie, une téléportation, la mort, une déconnexion ou tout ce qui éloigne le joueur de plus d'un bloc du wagonnet met fin au trajet, puis à l'activation ; le joueur est déposé là où le wagonnet s'est arrêté, sauf après une téléportation, une mort ou une déconnexion. Arrêter l'activation, notamment par replace_previous(), fait aussi descendre le joueur. Le lifetime_ticks de l'activation s'applique toujours : accordez-lui donc assez de temps pour la voie la plus longue.
Les callbacks d'impact de projectile reçoivent (fresh_context, target_or_nil, location) ; les callbacks visuels reçoivent (fresh_context, location). Les callbacks de dégâts de projectile natif reçoivent (fresh_context, target, native_damage) au tick suivant. Ils remplacent l'application native et doivent appliquer explicitement les dégâts voulus, normalement avec fresh_context.action:damage_target(target.uuid, amount). Avec protect=true sur un projectile natif, les blocs protégés sont filtrés pour les explosions et l'embrasement. Pour les projectiles scriptés, protected_path=true absorbe les trajectoires qui traversent des positions protégées ou non chargées.
Le nettoyage géré se limite aux opérations qui enregistrent cette responsabilité. Les opérations ordinaires world:spawn_entity, entity:set_gravity et world:set_block_at ne bénéficient pas automatiquement du nettoyage de l'action. Les méthodes d'état temporaire gèrent la restauration ; elles ne remplacent pas la vérification de l'autorisation d'un effet hostile ou d'une modification de bloc.
Ensembles d'objets
Une section set transforme un enchantement en ensemble d'objets. Placez le même enchantement sur chaque pièce. L'ensemble est complet tant que chaque emplacement listé sous pieces contient un objet qui le porte. Un ensemble complet exécute ses hooks une fois par événement. Si une pièce manque, rien ne s'exécute.
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
}
| Champ de l'ensemble | Signification |
|---|---|
pieces | Obligatoire. Associe les emplacements d'équipement aux noms des pièces. Lorsque validSlots est défini, il doit inclure l'emplacement de chaque pièce |
name | Nom utilisé par $setName. Reprend par défaut le name de l'enchantement et accepte les codes de couleur & |
lore | Les lignes de lore de l'ensemble. Par défaut, le nom de l'ensemble avec son nombre de pièces, puis une ligne par pièce |
equippedPiece | Ligne d'une pièce portée. Vaut &a✔ $pieceName par défaut |
missingPiece | Ligne d'une pièce manquante. Vaut &c✘ $pieceName par défaut |
Le lore de l'ensemble accepte ces espaces réservés :
| Espace réservé | Affiche |
|---|---|
$setName | Le nom de l'ensemble |
$equippedPieces | Le nombre de pièces que porte le joueur |
$totalPieces | Le nombre de pièces de l'ensemble |
$setPieces | Une ligne par pièce dans l'ordre des emplacements, tirée de equippedPiece ou missingPiece. Le texte autour de l'espace réservé est répété sur chaque ligne |
$pieceName, $pieceSlot | Dans equippedPiece et missingPiece, le nom de la pièce et son emplacement, comme Head ou Main Hand |
$ifSetComplete | N'affiche la ligne que tant que chaque pièce est portée |
$ifSetIncomplete | N'affiche la ligne que tant qu'une pièce manque |
Les objets d'ensemble affichent cette section à la place d'une ligne dans la liste des enchantements personnalisés. Dans EliteMobs, placez $itemSet dans itemLoreStructureV2 de ItemSettings.yml, ou dans le lore d'un objet personnalisé. Sans l'un ni l'autre, l'ensemble suit le lore personnalisé de l'objet. $ifItemSet n'affiche une ligne de la structure que sur les objets d'ensemble. Les objets personnalisés FMM affichent l'ensemble sur la ligne de lore qui contient $itemSet, ou à la suite de leur lore.
La section montre ce que porte le joueur qui détient l'objet et se redessine lorsqu'il équipe ou retire une pièce. Un objet rangé en dehors de l'inventaire d'un joueur garde l'état qu'il affichait en le quittant.
Les hooks d'ensemble diffèrent des hooks d'enchantement ordinaires sur quelques points :
- Chaque hook d'action du tableau ci-dessus atteint un ensemble complet, quels que soient les emplacements de ses pièces. Un ensemble d'armure peut répondre à
on_attack_entityouon_break_block. - L'état complet est vérifié au moment de l'événement. Un projectile vérifie les ensembles portés à son atterrissage, et tout projectile compte, pas seulement les flèches d'arc.
on_take_damagedéfinitcontext.targetsur l'attaquant lorsqu'il y en a un.context.source.itemetcontext.itemsont la première pièce dans l'ordre des emplacements :HEAD,CHEST,LEGS,FEET,MAINHAND,OFFHAND. Lisezcontext.source.equipment.MAINHANDpour l'arme ou l'outil tenu.context.set.levelest le niveau le plus bas parmi les pièces.context.set.piecesest indexé par emplacement, avec lenameet l'inventory_slotde chaque pièce.stop_on_unequip: truearrête une activation d'ensemble dès qu'une pièce est retirée.- Les requêtes numériques, comme la menace et le taux de coup critique d'EliteMobs ou les modificateurs de lancer de FMM, comptent un ensemble une seule fois et seulement tant qu'il est complet.
Mise à niveau du contenu existant
FMM ignore les objets personnalisés avec une liste scripts: non vide ou d'anciennes entrées d'enchantement sans espace de noms. Remplacez ces définitions d'objet par des enchantements avec espace de noms ; les scripts de props restent pris en charge.
Les effets personnalisés EliteMobs utilisent désormais maxLevel et des parameters propres à chaque effet dans le YAML du fournisseur. La configuration des enchantements natifs et de niveau élite suit un format distinct. Consultez la référence des enchantements EliteMobs plutôt que de copier un ancien fichier maxLevelV2 dans une définition de fournisseur.