Scripts Lua : API des props
Cette page couvre toutes les API disponibles dans les scripts de props de FreeMinecraftModels : context.prop, context.event, context.player, context.projectile, context.world, context.zones, context.scheduler, context.state, context.cooldowns et context.log. Si vous débutez avec les scripts, consultez d'abord Premiers pas.
context.prop
La table fournit des informations sur le prop et des méthodes pour contrôler ses animations. FMM conserve une table par prop pour les performances. Les champs tels que current_location consultent l'état actuel à chaque lecture.
Champs
| Champ | Type | Notes |
|---|---|---|
prop.model_id | string | Le nom de modèle blueprint (par ex. "torch_01") |
prop.current_location | table de position | La position actuelle du prop, consultée à chaque lecture. Ce n'est pas un instantané fixe. |
La table de location a les champs standard : x, y, z, world, yaw, pitch.
Exemple : lecture des infos du prop
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Prop spawned: " .. (context.prop.model_id or "unknown"))
local loc = context.prop.current_location
if loc then
context.log:info("Location: " .. loc.x .. ", " .. loc.y .. ", " .. loc.z)
end
end
}
prop:play_animation(name, blend, loop)
Joue une animation nommée sur le modèle du prop.
| Paramètre | Type | Défaut | Notes |
|---|---|---|---|
name | string | requis | Le nom de l'animation tel que défini dans le fichier de modèle |
blend | boolean | true | Avec true, programme le changement après le tick de l’état courant ; avec false, interrompt immédiatement. Aucun fondu entre les animations. |
loop | boolean | true | Indique si une animation personnalisée boucle ; les états intégrés suivent leurs propres règles |
Retourne true lorsque la demande est acceptée, même si la lecture est mise en attente ou ignorée ; false si elle ne peut pas être acceptée. L'état terminal death refuse toute lecture ultérieure. Une demande d'attaque pendant une animation personnalisée est acceptée sans l'interrompre. La file ne contient qu'une place : une nouvelle demande remplace la précédente. L'acceptation ne prouve pas qu'une image a été affichée ; voir Animations.
Exemple
return {
api_version = 1,
on_right_click = function(context)
local success = context.prop:play_animation("open", true, false)
if not success then
context.log:warn("Animation 'open' not found on this model!")
end
end
}
prop:stop_animation()
Efface les animations en attente et revient à idle si disponible ; sinon, arrête l'état partagé courant. L'état terminal death reste actif dans le moteur partagé, même si l'appel envoie aussi une demande d'arrêt au système Bedrock.
Ne prend aucun paramètre.
Exemple
return {
api_version = 1,
on_right_click = function(context)
context.prop:stop_animation()
end
}
prop:hurt_visual()
Joue l'animation visuelle de blessure (flash de teinte rouge) sur le prop sans lui infliger de dégâts réels.
Ne prend aucun paramètre.
Exemple
return {
api_version = 1,
on_left_click = function(context)
-- Flash red when punched, but don't actually take damage
if context.event then
context.event.cancel()
end
context.prop:hurt_visual()
end
}
prop:pickup()
Retire le prop du monde et laisse tomber un objet de placement en papier à sa position. Utilisez cet objet sur un bloc par clic droit pour replacer le prop.
Ne prend aucun paramètre et ne retourne rien. Le retrait et l'apparition de l'objet sont mis en attente sur le thread principal de Bukkit. La méthode ne vérifie pas les permissions et ne transfère pas l'inventaire ou le livre stockés dans l'objet de placement. Décidez de l'accès dans le hook appelant et gérez le contenu stocké avant de ramasser le prop. Ne programmez pas plusieurs ramassages du même prop.
Exemple
return {
api_version = 1,
on_right_click = function(context)
-- Let players pick up the prop by right-clicking it
context.prop:pickup()
end
}
prop:mount(player)
Monte un joueur sur le premier siège de point de monture disponible sur le prop. Le modèle doit avoir des os de point de monture définis.
| Paramètre | Type | Notes |
|---|---|---|
player | entity table | Une table d'entité joueur (par ex. depuis context.player ou context.event.player) |
Retourne true lorsque le joueur a été trouvé, que le prop possède des points de monture et que l'action de montée a été mise en file d'attente. Retourne false lorsque ces références de base ne sont pas valides. Un retour true ne prouve pas qu'un siège était finalement disponible au moment où l'action en file d'attente s'est exécutée.
Si un script gère les sièges au clic droit, annulez context.event pour empêcher le comportement par défaut de FMM d'essayer lui aussi d'asseoir le joueur.
Exemple
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player then
context.prop:mount(player)
end
end
}
prop:dismount(player)
Fait descendre un joueur de son siège sur le prop.
| Paramètre | Type | Notes |
|---|---|---|
player | entity table | Une table d'entité joueur |
Retourne true lorsque le joueur a été trouvé, que le prop possède un gestionnaire de montures et que la vérification de démontage a été mise en file d'attente. Retourne false lorsque ces références de base ne sont pas valides.
Exemple
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player then
-- Toggle mount/dismount
local passengers = context.prop:get_passengers()
for i = 1, #passengers do
if passengers[i].uuid == player.uuid then
context.prop:dismount(player)
return
end
end
context.prop:mount(player)
end
end
}
prop:get_passengers()
Retourne un tableau Lua de tables d'entité pour tous les passagers actuels du prop.
Ne prend aucun paramètre.
Exemple
return {
api_version = 1,
on_game_tick = function(context)
local passengers = context.prop:get_passengers()
if #passengers > 0 then
context.log:info("Prop has " .. #passengers .. " passenger(s)")
end
end
}
prop:has_mount_points()
Retourne si ce prop a des os de point de monture définis dans son modèle.
Ne prend aucun paramètre. Retourne true ou false.
Exemple
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player and context.prop:has_mount_points() then
context.prop:mount(player)
end
end
}
prop:spawn_elitemobs_boss(filename, x, y, z)
Fait apparaître un boss personnalisé EliteMobs à la position donnée. Nécessite qu'EliteMobs soit installé sur le serveur.
| Paramètre | Type | Notes |
|---|---|---|
filename | string | Le nom de fichier du boss personnalisé (par ex. "my_boss.yml") |
x | number | Coordonnée X |
y | number | Coordonnée Y |
z | number | Coordonnée Z |
Retourne une table d'entité vivante pour le boss créé, ou nil si l'intégration ne peut pas renvoyer de boss vivant, notamment si le plugin est indisponible, si la configuration manque ou si l'apparition échoue. nil ne précise pas la cause.
Exemple
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local boss = context.prop:spawn_elitemobs_boss("dungeon_guardian.yml", loc.x, loc.y + 1, loc.z)
if boss then
context.log:info("Spawned boss: " .. (boss.name or "unknown"))
else
context.log:warn("Could not spawn boss -- is EliteMobs installed?")
end
end
end
}
prop:open_inventory(player, title, rows)
Programme l'ouverture d'un inventaire de coffre pour le joueur. Chaque prop possède un seul inventaire partagé : la première ouverture le construit à partir du contenu enregistré dans le PersistentDataContainer du prop, et les ouvertures suivantes montrent ce même inventaire en direct à chaque utilisateur. FMM le réenregistre dans le prop lorsque le dernier utilisateur le ferme, lorsque le chunk du prop se décharge, et avant que drop_inventory() ne le lise.
| Paramètre | Type | Défaut | Notes |
|---|---|---|---|
player | entity table | requis | Le joueur à qui montrer l'inventaire |
title | string | requis | Le titre de l'inventaire (supporte les codes de couleur &) |
rows | int | 3 | Nombre de rangées (1-6, où 6 = 54 slots = double coffre) |
Retourne true si les références prop/joueur étaient valides et que l'action d'ouverture a été mise en file d'attente, false sinon. Le nombre de rangées est ramené dans l'intervalle 1-6 avant la création de l'inventaire.
La taille et le titre proviennent de l'appel qui construit l'inventaire ; tant qu'il est ouvert, les appels suivants le réutilisent tel quel. Lorsque le contenu enregistré occupe plus de cases que les rangées demandées, l'inventaire s'agrandit pour les contenir : une valeur rows plus petite ne supprime donc jamais d'objets stockés. Si les données enregistrées ne peuvent pas être lues, l'inventaire ne s'ouvre pas. L'action est ignorée si le prop a été retiré avant son exécution. La valeur de retour ne garantit pas que l'inventaire s'est ouvert.
prop:is_viewing_inventory(player)
Indique si le listener d'inventaire suit actuellement ce joueur comme utilisateur de l'inventaire de ce prop.
| Paramètre | Type | Notes |
|---|---|---|
player | entity table | Le joueur à vérifier |
Retourne true ou false.
Exemple : animation de fermeture lorsque l'inventaire est fermé
context.state["task_" .. player.uuid] = context.scheduler:run_repeating(5, 5, function(tick_context)
if not tick_context.prop:is_viewing_inventory(player) then
tick_context.prop:play_animation("close", true, false)
tick_context.scheduler:cancel(tick_context.state["task_" .. player.uuid])
end
end)
prop:place_book(player)
Prend le livre écrit ou inscriptible de la main principale du joueur et le stocke sur le prop.
| Paramètre | Type | Notes |
|---|---|---|
player | entity table | Le joueur tenant le livre |
Retourne true si les références prop/joueur étaient valides et que l'action a été mise en file d'attente. L'action différée sur le thread principal ne place un livre que si le joueur tient un livre inscriptible ou écrit et que le prop n'en possède pas déjà un.
prop:read_book(player)
Ouvre le livre stocké en lecture pour le joueur.
| Paramètre | Type | Notes |
|---|---|---|
player | entity table | Le joueur à qui montrer le livre |
Retourne true si les références prop/joueur étaient valides et si la lecture a été mise en attente. L'action différée exige un WRITTEN_BOOK stocké et désérialisable. Cette méthode n'ouvre pas un livre inscriptible stocké pour le lire.
prop:take_book(player)
Retourne le livre stocké dans l'inventaire du joueur et le retire du prop.
| Paramètre | Type | Notes |
|---|---|---|
player | entity table | Le joueur à qui donner le livre |
Retourne true si les références prop/joueur étaient valides et que l'action de récupération a été mise en file d'attente. Cela ne garantit pas qu'un livre était effectivement stocké.
Laissez de la place dans l'inventaire : l'entrée stockée est supprimée avant l'ajout du livre, et le surplus n'est pas déposé au sol. place_book sérialise la pile tenue avant de réduire sa quantité de un ; utilisez des livres individuels ordinaires.
prop:has_book()
Vérifie la présence de la clé PDC du livre stocké sur le porte-armure. Ne valide pas le livre sérialisé et ne prend aucun paramètre.
prop:drop_inventory()
Programme l'enregistrement de l'inventaire ouvert, s'il y en a un, et sa fermeture pour chaque utilisateur, puis lit le contenu enregistré, supprime son entrée PDC et dépose les objets au niveau du prop. Les modifications faites dans l'inventaire ouvert jusqu'à ce moment sont incluses. Un échec de décodage peut ne laisser aucun objet à déposer après la suppression de l'entrée.
Ne prend aucun paramètre. Retourne true si le prop possède un porte-armure de support valide et que l'action a été mise en attente. Cela ne garantit pas que des objets étaient effectivement stockés.
prop:drop_book()
Programme le dépôt du livre stocké à la position du prop. L'action supprime l'entrée avant de décoder le livre ; un échec de décodage peut donc ne laisser aucun livre à déposer.
Ne prend aucun paramètre. Retourne true si le prop possède un porte-armure de support valide et que l'action a été mise en attente. Cela ne garantit pas qu'un livre était effectivement stocké.
prop:set_persistent_data(key, value)
Stocke une chaîne dans le PersistentDataContainer du porte-armure du prop. Elle persiste avec ce porte-armure lors des sauvegardes normales du monde et des déchargements de chunks. La suppression définitive du prop ou son remplacement par un objet de placement ne transfère pas ces données.
| Paramètre | Type | Notes |
|---|---|---|
key | string | Suffixe de clé Bukkit unique utilisant des lettres minuscules, chiffres, ., _, - ou /, stocké sous fmm_lua_<key> en interne. Une clé invalide provoque une erreur |
value | string | La valeur à stocker. Utilisez tostring() pour les nombres et booléens. |
Retourne true en cas de succès, false si le prop n'a pas de porte-armure de support.
prop:get_persistent_data(key)
Récupère une valeur chaîne précédemment stockée avec set_persistent_data. Retourne nil si la clé n'a pas été définie.
| Paramètre | Type | Notes |
|---|---|---|
key | string | Le nom de clé utilisé dans set_persistent_data |
Exemple : état de bascule persistant
return {
api_version = 1,
on_spawn = function(context)
local saved = context.prop:get_persistent_data("active")
context.state.active = saved == "true"
end,
on_right_click = function(context)
context.state.active = not context.state.active
context.prop:set_persistent_data("active", tostring(context.state.active))
end
}
Effets d'objets
L'ancienne API context.item des objets équipés a été retirée. Définissez les effets avec des enchantements personnalisés et associez-les à l'objet via sa liste enchantments: utilisant des espaces de noms.
context.event
Données de l'événement du hook actuel. Disponibles dans les hooks de clic de props, d'impact de projectile et de zone génériques. Retourne nil dans les hooks sans événement associé ni acteur joueur (on_spawn, on_game_tick, on_destroy).
Les clics FMM utilisent un indicateur d'annulation du plugin pour le traitement par défaut des props. Le wrapper Lua n'expose que les champs et méthodes listés ici.
Champs et méthodes
| Champ ou méthode | Type | Notes |
|---|---|---|
event.player | player entity table | Le joueur qui a déclenché l'événement ou franchi la limite d'une zone générique surveillée. Disponible dans les hooks de props on_left_click, on_right_click, on_zone_enter et on_zone_leave. Dans on_projectile_hit, il s'agit de l'entité vivante qui a tiré le projectile, qui peut être un mob ; il est absent lorsque le tireur n'est pas une entité vivante. Voir Méthodes d'entité joueur pour tous les champs et méthodes. |
event.is_cancelled | boolean | L'état d'annulation au moment où le contexte a été construit. Ce champ n'est pas rafraîchi après un appel à cancel() ou uncancel(). |
event.cancel() | function | Annule l'événement (par ex. empêche les dégâts ou l'interaction) |
event.uncancel() | function | Dé-annule un événement précédemment annulé |
cancel et uncancel ignorent leurs arguments. context.event.cancel() et context.event:cancel() se comportent donc de façon identique. Cette page utilise le point ; les deux formes fonctionnent.
Les hooks de zone génériques fournissent un acteur joueur sans indicateur d'annulation : event.cancel() et event.uncancel() sont donc absents, et event.is_cancelled vaut false. Les hooks de clic de props fournissent l'indicateur d'annulation de FMM ; l'annuler empêche l'action par défaut correspondante du prop.
Considérez event.is_cancelled comme un instantané de l'état initial. Si votre propre script appelle event.cancel() ou event.uncancel(), conservez votre propre indicateur local si vous avez besoin de vous souvenir de ce changement plus loin dans le même hook.
La table d'événement actuelle de FMM n'expose pas les champs spécifiques à Bukkit tels que target, block, projectile ou item. Utilisez context.player, context.event.player, context.projectile (dans on_projectile_hit), player:get_target_entity(range), context.world:raycast(...) ou les requêtes d'entités proches lorsque vous avez besoin de contexte supplémentaire.
on_projectile_hit
Se déclenche lorsqu'un projectile touche la hitbox du prop, une fois par projectile.
| Valeur de contexte | Notes |
|---|---|
context.projectile | Table d'entité du projectile (flèche, trident, boule de neige, etc.). Définie uniquement dans ce hook |
context.event.player | L'entité vivante qui a tiré le projectile, le cas échéant |
context.player | Le tireur lorsqu'il s'agit d'un joueur, sinon nil |
Le hook s'exécute après que FMM a traité l'impact, et le traitement par défaut des projectiles de FMM ne fait rien pour les props. Appeler context.event.cancel() ici n'empêche pas un projectile non perforant d'être consommé par l'impact. Le hook ne se déclenche pas lorsqu'un autre plugin a déjà annulé l'impact.
return {
api_version = 1,
on_projectile_hit = function(context)
local shooter = context.player
if shooter then
shooter:send_message("&eYou hit the target!")
end
context.prop:play_animation("hit", false, false)
end
}
Exemple : annuler les dégâts de clic gauche
Exemple
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Exemple : vérification de l'état d'annulation
Exemple
return {
api_version = 1,
on_left_click = function(context)
if context.event and not context.event.is_cancelled then
context.event.cancel()
context.log:info("Damage cancelled!")
end
end
}
À l'intérieur des callbacks programmés (scheduler:run_later, scheduler:run_repeating), context.event est toujours nil. La modification d'événement ne peut se produire que pendant le hook d'événement lui-même.
context.world
Il s'agit de l'API world de FreeMinecraftModels/MagmaCore. Voir context.world pour la référence complète.
Toutes les méthodes documentées sur la page globale (get_block_at, set_block_at, spawn_particle, play_sound, strike_lightning, get_time, set_time, get_nearby_entities, get_nearby_players, spawn_entity, get_highest_block_y, raycast, place_temporary_block, drop_item, spawn_firework) sont disponibles dans FMM. Voir l'API world MagmaCore pour tous les détails sur world:raycast() (lance un rayon et détecte les entités/blocs touchés), world:place_temporary_block() (remplacement temporaire de bloc) et world:spawn_firework() (fait apparaître des fusées de feu d'artifice avec couleurs et formes personnalisées). Les pouvoirs de boss d'EliteMobs partent de la même base world et ajoutent des méthodes de table de location spécifiques aux boss pour faire apparaître des boss, des renforts, des blocs tombants, des blocs temporaires et plus encore ; voir EliteMobs Monde & Environnement.
Ajouts à world spécifiques à FMM
FreeMinecraftModels superpose trois aides de butin EliteMobs optionnelles à context.world. Elles sont toujours présentes, mais chacune retourne false et ne fait rien lorsqu'EliteMobs n'est pas installé :
| Méthode | Notes |
|---|---|
world:drop_elitemobs_procedural_loot(player, level, location?) | Génère un objet EliteMobs pour le joueur. Respecte le réglage de remise directe dans l'inventaire ; le surplus tombe auprès du joueur. Sinon, utilise la position choisie. Retourne false si les objets procéduraux sont désactivés |
world:drop_elitemobs_random_loot(player, level, location?) | Lance les tables de butin d'EliteMobs pour le joueur au niveau indiqué |
world:drop_elitemobs_custom_loot(player, file, level, location?) | Fait tomber un fichier d'objet personnalisé EliteMobs précis pour le joueur. Retourne false lorsque le fichier ne se résout pas |
Les signatures complètes se trouvent dans la Référence de l'API Lua. L'équivalent côté prop pour les boss est prop:spawn_elitemobs_boss(...), documenté ci-dessus.
Méthodes d'entité joueur
Les tables d'entité joueur sont retournées depuis context.player, context.event.player et context.world:get_nearby_players(). Les hooks MagmaCore génériques on_zone_enter / on_zone_leave définissent context.player et context.event.player sur le joueur qui entre ou qui sort.
Les tables d'entité, méthodes d'entité vivante, méthodes spécifiques aux joueurs et méthodes d'UI joueur documentées sur la page globale sont les tables MagmaCore utilisées par FMM. Les pouvoirs de boss d'EliteMobs exposent des tables d'entité similaires mais spécifiques aux boss, documentées dans Boss & Entités. Voir le moteur de scripting Lua MagmaCore pour la référence FMM complète couvrant les champs de base d'entité, les champs et méthodes d'entité vivante, les champs et méthodes spécifiques aux joueurs, et les méthodes d'UI joueur. Les nouvelles méthodes joueur incluent player:get_target_entity() (ciblage par raycast), player:get_eye_location(), player:get_look_direction(), player:send_block_change() (faux blocs par joueur) et player:reset_block() -- voir Méthodes spécifiques aux joueurs pour les détails.
Champs d'entité spécifiques à FMM
Chaque table d'entité construite à l'intérieur d'un script FMM obtient automatiquement ces champs supplémentaires (via le LuaEntityEnricher de FMM) :
| Champ | Type | Notes |
|---|---|---|
entity.is_modeled | boolean | true si cette entité Bukkit est l'entité sous-jacente d'un ModeledEntity |
entity.is_prop | boolean | true si cette entité est un armor stand supportant un PropEntity |
entity.model | table or nil | Renseigné uniquement lorsque is_modeled = true (voir ci-dessous) |
Ces indicateurs FMM et la référence du modèle sont capturés à la création de la table, sans mise à jour à chaque lecture. Obtenez une nouvelle table si le modèle attaché change. Les tables de joueur exposent aussi has_permission(node) et un instantané is_op ; has_permission vérifie la permission actuelle.
Lorsque entity.model est présent, il expose :
| Champ / Méthode | Notes |
|---|---|
model.model_id | Le nom de modèle blueprint (par ex. "dragon") |
model.is_dynamic | true s'il s'agit d'un DynamicEntity (attaché à une entité vivante) |
model:play_animation(name, blend, loop) | Demande une animation nommée. blend et loop valent false par défaut sur ce pont. true indique une acceptation, pas nécessairement un affichage |
model:stop_animations() | Efface les animations en attente et revient à idle si disponible ; n'interrompt pas la mort terminale |
model:remove() | Supprime immédiatement l'entité modélisée et tous ses os |
on_right_click = function(context)
local player = context.event and context.event.player
if not player then return end
local target = player:get_target_entity(8)
if target and target.is_modeled then
target.model:play_animation("hurt", true, false)
end
end
Champs d'entité EliteMobs
Lorsqu'EliteMobs est installé, FMM transfère à l'enricher d'EliteMobs afin que les mêmes tables d'entité exposent également :
| Champ | Type | Notes |
|---|---|---|
entity.is_elite | boolean | true si l'entité est suivie par EliteMobs |
entity.is_custom_boss | boolean | true s'il s'agit d'une configuration de boss personnalisé |
entity.is_significant_boss | boolean | true pour les boss personnalisés avec un healthMultiplier > 1 (filtre les mobs nommés sans importance) |
entity.elite | table or nil | Renseigné uniquement lorsque is_elite = true. Contient level, name, health, max_health, health_multiplier, damage_multiplier, is_custom_boss, plus elite:remove() |
Les indicateurs et la plupart des champs elite sont des instantanés ; health et max_health sont consultés à la lecture. Avec EliteMobs activé, entity:can_receive_hostile_effect(player_uuid) applique aussi l'autorisation des cibles magiques d'EliteMobs après la vérification partagée des cibles hostiles. Un adaptateur indisponible refuse la vérification au lieu de traiter les alliés comme des cibles sans intégration.
context.zones
Il s'agit de l'API zones de FreeMinecraftModels/MagmaCore. Voir context.zones pour la référence complète. Les pouvoirs de boss d'EliteMobs utilisent une table context.zones différente, avec des définitions de zone natives d'EliteMobs ; voir EliteMobs Zones & Ciblage.
context.scheduler
L'API scheduler documentée ici est le scheduler MagmaCore utilisé par les scripts de FreeMinecraftModels et les scripts de PNJ d'EliteMobs. Les noms de style EliteMobs (run_after, run_every et cancel_task) sont des alias sur le scheduler partagé : les deux conventions de nommage fonctionnent donc. Les pouvoirs de boss exposent les mêmes alias via leur contexte spécifique aux boss. Voir context.scheduler pour la référence FMM complète.
context.state
L'API state est partagée par les scripts de FreeMinecraftModels, les pouvoirs de boss d'EliteMobs et les scripts de PNJ d'EliteMobs. Voir context.state pour la référence complète.
context.log
L'API de logging documentée ici est le logger de FreeMinecraftModels/MagmaCore (info, warn, error). Les scripts de PNJ d'EliteMobs utilisent le même logger ; les pouvoirs de boss d'EliteMobs exposent info, warn et debug. Voir context.log pour la référence complète.
context.cooldowns
L'API de cooldown documentée ici suit l'ordre partagé MagmaCore/FMM utilisé par les scripts de FreeMinecraftModels et les scripts de PNJ d'EliteMobs : check_local(key?, duration). Les pouvoirs de boss d'EliteMobs utilisent le même ordre d'arguments avec des stores de sauvegarde spécifiques aux boss. Voir context.cooldowns pour la référence complète.
| Méthode | Notes |
|---|---|
local_ready(key?) | Vérifie si un cooldown local est prêt. |
local_remaining(key?) | Retourne le nombre de ticks restants du cooldown local, ou 0. |
check_local(key?, duration) | Vérifie et démarre un cooldown local de façon atomique. |
set_local(duration, key?) | Définit un cooldown local sans vérification. |
global_ready() | Vérifie le cooldown global partagé du propriétaire du script. |
set_global(duration) | Définit le cooldown global partagé du propriétaire du script. |
Utilisez context.cooldowns:check_local("my_key", 40) pour les temps de recharge des actions ordinaires de props.
Modèle d'exécution
Un environnement d'exécution par instance de script
Chaque entrée de la liste scripts: d'un prop obtient un environnement Lua indépendant. FMM découvre et valide le code lors de l'enregistrement du fournisseur, puis évalue le code mis en cache dans un nouvel environnement isolé pour chaque liaison. Modifier ou ajouter un fichier Lua exige un rechargement réussi avant que les nouvelles liaisons l'utilisent. Les scripts s'exécutent dans l'ordre de la liste configurée ; le champ priority est lu mais ne change pas cet ordre. Retirer le prop arrête ses instances de script.
Les enchantements d'objets ont un cycle de vie distinct ; ils ne créent pas d'instance de script de prop pour un objet équipé.
Cela signifie :
- Les variables locales déclarées à l'échelle du fichier sont privées à cette instance de script.
context.stateest complètement isolé entre les instances, même si elles partagent le même fichier de script.
Propriété des tâches programmées
Toutes les tâches créées via context.scheduler appartiennent au runtime qui les a créées. Lorsqu'un prop est retiré :
- Le runtime est arrêté.
- Toute tâche possédée -- à coup unique et répétitive -- est automatiquement annulée.
- Toutes les surveillances de zone sont effacées.
on_destroy ne s'exécute au préalable que lorsque le prop est retiré définitivement : ramassé, cassé, supprimé avec /fmm deleteall ou retiré par un plugin. Lorsque le chunk ou le monde du prop se décharge, ou que FMM recharge ou s'arrête, le runtime s'arrête sans appeler on_destroy. Le prop revient avec un nouveau runtime, et un nouvel on_spawn, lorsque son chunk se charge de nouveau.
Portée des temps de recharge
Le moteur de scripting partagé expose des utilitaires de cooldown local (local_ready, local_remaining, check_local, set_local) et des utilitaires de cooldown global (global_ready, set_global). FMM délimite ces stores comme suit :
| Type de script | Portée du store local | Portée du store global |
|---|---|---|
| Script de prop | Par ScriptInstance (prop + fichier de script) | Par PropEntity (partagé entre tous les scripts liés à ce prop) |
Les temps de recharge globaux sont effacés lorsque le prop est retiré du registre ou que le gestionnaire des scripts s'arrête lors d'un rechargement réussi ou d'une désactivation. Une préparation de rechargement rejetée conserve l'environnement actuel. Les durées suivent le temps écoulé monotone à raison de 50 ms par tick demandé, tandis que les délais du planificateur suivent les ticks serveur ; ils peuvent diverger lorsque le serveur ralentit.
Budget d'exécution
Chaque invocation de hook, chaque callback planifié et l'évaluation initiale du fichier de script lui-même s'exécutent sous un budget d'exécution strict. Le budget est appliqué à l'intérieur de la VM Lua, il s'applique donc pendant que votre code s'exécute encore plutôt que de se contenter de vérifier l'horloge après coup.
| Limite | Valeur |
|---|---|
| Temps CPU du thread courant | 50 millisecondes |
| Instructions Lua exécutées | 250 000 |
La première limite atteinte interrompt l'appel avec une erreur Lua et désactive l'instance de script. Les messages sont :
Lua instruction budget exceeded (250000 instruction limit)
Lua CPU-time budget exceeded (50ms current-thread CPU limit)
Le compteur d'instructions borne une boucle Lua pure comme while true do end. Le temps est vérifié toutes les 1024 instructions Lua et au retour de l'appel. Le mécanisme n'interrompt pas une méthode Java/Bukkit bloquante pendant son exécution.
La partie temporelle du budget est mesurée en temps CPU du thread courant, et non en temps réel : un script n'est donc pas facturé pour le temps pendant lequel le thread serveur a été déprogrammé. Sur une JVM où la mesure du temps CPU du thread courant n'est pas disponible, MagmaCore retombe sur une limite délibérément plus généreuse de 250 millisecondes de temps écoulé (Lua elapsed-time fallback budget exceeded (250ms fallback; current-thread CPU time unavailable)) tout en conservant le même plafond de 250 000 instructions, de sorte que les scripts qui ne terminent pas restent bornés dans les deux cas.
Les appels imbriqués partagent un seul budget : si un hook invoque un callback qui en invoque un autre, toute la chaîne est mesurée comme une unique allocation de 50 ms de CPU / 250 000 instructions, et non une allocation chacun.
L'évaluation lors de la découverte du fournisseur rejette une définition invalide avant son enregistrement. Le code en cache est évalué de nouveau pour chaque instance, avec les mêmes limites.
Pour rester dans le budget :
- Évitez les boucles non bornées à l'intérieur des hooks.
- Gardez les gestionnaires
on_game_ticklégers -- ils s'exécutent chaque tick unique. - Utilisez
context.scheduler:run_repeating(...)pour répartir le travail sur les ticks.
Référence complète des hooks
Cette table liste les hooks de props actifs.
La colonne context.event décrit l'indicateur d'annulation de FMM ou l'acteur de zone. Le wrapper Lua expose event.player, event.is_cancelled, event.cancel() et event.uncancel(), selon le cas.
Hooks de props actifs (8)
| Hook | Se déclenche quand | context.event |
|---|---|---|
on_spawn | Le prop apparaît dans le monde, ou se charge de nouveau avec son chunk | nil |
on_game_tick | Chaque tick serveur (50 ms à 20 TPS) | nil |
on_destroy | Le prop est retiré définitivement (pas lors d'un déchargement de chunk ni d'un rechargement) | nil |
on_left_click | Le joueur clique gauche sur le prop | indicateur d'annulation des dégâts par défaut |
on_right_click | Le joueur clique droit sur le prop | indicateur d'annulation de l'interaction par défaut |
on_zone_enter | Un joueur entre dans une zone surveillée | acteur joueur de zone (context.player / context.event.player ; non annulable) |
on_zone_leave | Un joueur quitte une zone surveillée | acteur joueur de zone (context.player / context.event.player ; non annulable) |
on_projectile_hit | Un projectile touche le prop | événement d'impact de projectile ; event.player est le tireur. Voir on_projectile_hit |
Effets d'objets
Utilisez les enchantements personnalisés pour les effets d'objets tenus. L'ancienne table de scripts d'objets à 22 hooks ne décrit plus un contrat d'exécution actuel.
Étapes suivantes
- Exemples et modèles -- scripts de props avec explications et notes de préparation
- Dépannage -- problèmes courants, conseils de débogage et checklist QC
- Premiers pas -- structure de fichier, hooks, première marche pas à pas
Transport EliteMobs
context.world:start_elitemobs_transport(player, route_id) lance un itinéraire EliteMobs enregistré pour un joueur dans le monde du contexte. La méthode retourne si la demande a été acceptée et nécessite EliteMobs avec cet itinéraire chargé. L'identifiant n'a pas d'extension .yml. Consultez les itinéraires de transport.