Mise en forme de code: pensez à utiliser les balises [ tcl ] et [ /tcl ] (sans les espaces bien sûr) autour de vos codes tcl afin d'avoir un meilleur rendu et une coloration syntaxique. x


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.
zeolia: tchat gratuit, sans inscription ni publicité
Merci de ne pas demander d'aide en MP
Away
  Reply
#2
Super intéressant. Je ne connaissais pas ce package. Merci Crazycat :)
  Reply
#3
Question 
En effet sa semble méga intéressant a connaitre et me semble très utile , vivement l explication en Français complet. merci pour ce post j'ai juste un passage que je n ais pas compris
Quote:subject et hook sont donc dans mon cas "job" et "start", pour le hook de fin ce sera "job" et "end".
le "end" je vois nulle part , ca serais pas ceci :

tcl
hook forget job


ou tu as fais fait un hook end ?
Retrouvez les dernières modifications de mes scripts TCL (versions Alpha/Bêta) ainsi que d'autres de mes réalisations sur ma page GitHub et les versions stables dans la section scripts de ce site  8-)
  Reply
#4
La commande trace add execution ne permet-elle pas de faire la même chose ?
Sinon quelque chose m'échappe et je relirai ça à tête reposée.

Trace command
Toute l'actualité de mes scripts ici     (dernière mise à jour le 22/04/2020)

Tout programme comporte au moins un bug et pourrait être raccourci d'au moins une instruction, de quoi l'on peut déduire que tout programme peut être réduit à une seule instruction qui ne fonctionne pas.
  Reply
#5
(10/03/2022, 00:37)ZarTek Wrote: ou tu as fais fait un hook end ?
"end" était juste un exemple de nom d'un autre hook que j'aurais pu créer, j'aurai aussi bien pu dire que je créais un hook "toto"

(10/03/2022, 01:12)MenzAgitat Wrote: La commande trace add execution ne permet-elle pas de faire la même chose ?
Sinon quelque chose m'échappe et je relirai ça à tête reposée.

Ca s'en rapproche, mais c'est moins précis car c'est déclenché à une exécution de procédure alors que le hook call est placé exactement où on veut, ça me semble plus pratique. Et je ne suis pas certain que trace permette de déclencher plusieurs procédures en même temps.
zeolia: tchat gratuit, sans inscription ni publicité
Merci de ne pas demander d'aide en MP
Away
  Reply
#6
Petit rajout pour ZarTek:
J'ai ajouté une procédure de nettoyage pour réinitialiser le jeu en fin de partie, les jobs étant dépendants du nombre de joueurs dans la partie en cours.

Voici à quoi ressemble le début d'un job:

tcl
namespace eval angel {
 
	hook bind job start angel ::lycan::angel::start
	proc start {} {
		putlog "Angel is loaded"
	}
 
	hook bind job clean angel ::lycan::angel::clean
	proc clean {} {
		namespace forget angel
		putlog "Angel unloaded"
	}
 
	putlog "angel.job loaded ([namespace current])"
}


Dans mon code principal, il y a des procédures d'initialisation et de fin de jeu

tcl
proc initJob {job} {
   # des checks et tout
   source jobs/$job.job
}
proc init {}
   foreach j $jobs {
      initjob $j
   }
   hook call job start
}
proc endgame {} {
   hook call job clean
   hook forget job
}

Et donc oui, là il y a bien un forget car je ne veux pas qu'au prochain lancement du jeu les anciens hooks soient appelés
zeolia: tchat gratuit, sans inscription ni publicité
Merci de ne pas demander d'aide en MP
Away
  Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)