Les hooks, rôle et utilité
#1
Explication de la problématique initiale
Sur le script lycanobot (Les loups-garous de Thiercelieux), je dois importer des profils de joueurs particuliers qui doivent déclencher des actions à certains moments, et ses profils sont chargés en fonction du mode de jeu et/ou du nombre de joueurs. J'ai pris le parti de créer des fichiers annexes chargés à la demande.
Il est donc assez complexe de prévoir dans le script initial quels seront les jobs chargés, d'autant plus que le but est de permettre facilement la création de nouveaux profils.

Mon idée est d'avoir une structure quasi identique pour chaque job, avec des procédures normées qui seraient appelées si besoin est, et sans avoir à gérer dans le script principal toute une palanquée de conditions ou de vérifications pour savoir si tel ou tel job est chargé.

Solution : le hook

Le hook, je le connais dans d'autres systèmes (et d'autres langages), c'est plus ou moins un système qui permet de raccrocher des fonctions à un déclencheur déterminé dans le programme principal. Et depuis tcl8.5, il y a un package hook.
(la suite part du principe que vous avez déjà fait package require hook)
Créer un hook (bind)
Le hook se définit par 4 argument :
tcl
hook bind subject hook observer binding


subject et hook sont des paramètres qui permettent plus ou moins de définir une arborescence, et observer permet de distinguer qui est le destinataire du hook. binding est la procédure qui sera appelée.
Dans mon cas, j'ai deux jobs (angel et thief), qui contiennent (dans leur propre namespace):
tcl
# angel.job
hook bind job start angel [namespace current]::start
proc start {} { putlog "Angel is loaded" }
#thief
hook bind job start thief [namespace current]::start
proc start {} { putlog "Thief is loaded" }


Lorsque les scripts sont chargés (depuis le namespace principal), il pourront être appelés avec la bonne commande (on verra ensuite) en passant les infos "job" et "start". Si je veux ajouter d'autres hooks, je garderai "job" comme sujet, et je mettrai un autre hook (par exemple end pour appeler une procédure qui doit se déclencher à la fin).
Code :
.tcl hook bind
Tcl: job
.tcl hook bind job
Tcl: start
.tcl hook bind job start
Tcl: angel thief
L'eggdrop voit donc les hooks propres à chaque sous-script, ce qui signifie que si un sous-script ne doit pas être appelé à un moment, il suffit qu'il n'ait pas son hook.

Déclencher le hook (call)

C'est la partie la plus simple: il vous suffit de faire:
tcl
hook call subject hook arguments


subject et hook sont donc dans mon cas "job" et "start", pour le hook de fin ce sera "job" et "end". Les arguments (s'ils existent) sont passés aux procédures déclarées en binding:
Code :
.tcl hook call job start
[16:38] Angel is loaded
[16:38] Thief is loaded

Je ferai dans les jours qui viennent la page wiki concernant ce package qui peut s'avérer fort utile.
Répondre
#2
Petite note suite à un échange avec thommey:
Il est possible d'obtenir à peu près la même chose en eggdrop sans le package hook en utilisant callevent et bind event.

Actuellement, aucun argument ne peut être passé à callevent (à part l'évènement lui-même) il faut donc utiliser des variables globales, mais dans la prochaine version, on pourra passer un argument (ou une liste pour en passer plusieurs).
Ma préférence va pour l'instant toujours aux hooks qui permettent de déclarer les arguments attendus.
Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)
Tchat 100% gratuit -Discutez en toute liberté