Il ne s'agit ici en aucun cas d'une documentation complète, mais d'une explication de base qui peut permettre à quelqu'un sachant déjà un minimum programmer en php et ayant une persévérence certaine de pouvoir se lancer autrement qu'à l'aveuglette. C'est mal mis en page et un peu fouilli, mais si vous comptez vous lancez alors lisez tout sans rien sauter ! ;)
Si vous faites un plugin susceptible d'intéresser d'autres personnes, songez à les proposer sur le forum Dedimania/Fast, pour en informer et permettre un retour d'avis, infos et tests, ou simplement demander de l'aide. A terme je peux sans problème mettre des plugins finalisés au même endroit que Fast.
Je conseille d'utiliser un éditeur qui colorise le php, histoire de mieux voir les commentaires (au minimum), et aussi d'augmenter fortement la taille d'historique/buffer du terminal ou on lance fast.
En gros un plugin sera un fichier dans lequel on enregistre un nom, nom qui sera la base d'appel par fast de différentes fonctions callbacks liées à des évènements, provenant du serveur ou fabriqués par fast.
Se servir de plugin.98.howto.php comme base. Les plugins doivent avoir un nom de la forme plugin.NN.xxxxxx.php, sachant qu'ils seront lus dans l'ordre alphanumérique. Normalement on met le même nombre NN et meme xxxxxx que dans ce qui suit, mais en fait ya pas de vérification. Par contre xxxxxx doit être unique. A l'intérieur on va trouver :
registerPlugin('xxxxxx',NN);
A partir de là les fonctions xxxxxxEventname(...) seront automatiquement appelés lors des évènements correspondants, dans l'ordre des NN, donc ce nombre à une influence qui peut être importante pour certains évènements. La plupart de ceux ci sont assez explicites, sachant que la plupart des évènements proviennent directement des callbacks du serveur, d'autres sont purement fast, ou refabriqués par fast autant que possibles si c'est un serveur sans callback ; voir les commentaires de $_func_list dans fast_main.php (ceux qui ont un NeedChalSure sont éventuellement retardés jusqu'à ce que la map soit sure, car GetCurrentChallengeInfo peut être faux dans certains cas, et donc si le script est lancé en cours de map il y a une incertitude, qui a été source de faux records sur fast2 par exemple).
L'évenement xxxxxxInit() est appelé au démarrage de fast afin de permettre à tous les plugins de faire leur initialisation, à un moment où tous les plugins ont été inclus et dans leur ordre de priorité.
Pour mieux voir les différents évènements, décommenter le registerPlugin() de plugin.98.howto.php , puis lancer Fast à la main dans un term, et ainsi voir les différents évènements apparaitre pour mieux comprendre lequel dans quel cas. Eventuellement ajouter des affichages des paramètres reçus par chaque... Pour afficher utiliser plutot Console("...") ou debugPrint("....",$variable) qui affichent à la fois dans le term et dans le log. Observer aussi d'autres plugins (plutot la 2eme moitié à partir de records qui restent assez indépendants du reste de Fast et donc constituent de meilleurs exemples, tant qu'on cherche assez simple).
Note: si vous créez des variables globales dans votre plugin, essayez de les nommer sous la forme $xxxxxx_nom où xxxxxx est le nom du plugin, ceci afin d'éviter les risques d'interférences entre les différents plugins ! merci.
Note2: pour certains plugins évolués il peut être nécessaire de faire des modifs dans Fast parce que le plugin serait fortement compliqué sans, où simplement parce que le plugin à mis en évidence un bug ou disfonctionnement. N'hésitez pas à me contacter (en postant sur le forum Dedimania/Fast, ou MP dans le forum officiel, tm-forum ou le forum Traxico)
Pour envoyer des methodes au serveur (dédié ou non), utiliser la fonction :
addCall(action,'TMServerMethod',...)
'TMServerMethod' est une methode du serveur, voir méthodes pour un dédié TMU, méthodes pour un dédié TMS/TMO/TMN, ou générer les versions correspondant aux serveur ingame des différents jeu. Bien noter que invariablement les serveurs ingame ont des fonctionnalités plus ou moins réduites par rapport aux dédiés, d'ailleurs fast est je crois le seul script évolué qui gère encore les serveurs ingame.
Il y a d'autres versions de cette fonction (voir fast_general.php) : addCallArray(action,addcall_array) dont addcall_array est en fait array('TMServerMethod',...), et deux versions qui permettent d'ajouter un delai (en millisecondes!) avant envoi de la méthode au serveur : addCallDelay(delay,action,'TMServerMethod',...) et addCallDelayArray(delay,action,addcall_array).
Il existe diverses variables gobales disponibles et normalement tenues à jour par fast autant que possible. Les principales sont directement tirées des réponses aux méthodes du serveurs qui correspondent (exemple: http://kheops.unice.fr/slig/tmu/xmlrpc/TMU-dedicated-2007-01-09.html ) et pour certaines leur valeur précédante (servant a détecter les changements).
Un admin fast peut utiliser dans le chat la commande '/debug variable' pour provoquer un print_r de la variable/array dans le term et le log, pratique pour voir de plus près ce qui s'y trouve à un moment quelconque. A noter qu'il ne faut pas mettre le $ (exemple: /debug _players )
Il y a donc (voir // Init variables dans fast_main.php) :
$_Status , $_old_Status $_ChallengeInfo , $_old_ChallengeInfo , $_unsure_ChallengeInfo $_NetworkStats $_GameInfos $_NextGameInfos $_ServerOptions $_ChallengeList $_CurrentChallengeIndex $_players
L'utilisation directe de $_PlayerList, $_Ranking et $_PlayerInfo est à éviter : leur préférer $_players qui à l'avantage d'être un tableau associatif avec les logins comme index, de cumuler leurs contenus, et d'inclure pleins d'infos utilisés par fast et divers plugins (il est d'ailleurs créé et maintenu par le plugin plugin.01.players.php qui est obligatoire et doit être en 1er).
$_debug : niveau d'infos mises dans le log. ce n'est pas toujours super logique, disons que grossièrement le mettre à 3 convient pour avoir la plupart des infos utiles pour comprendre et débugger. $_use_cb : true si le dialogue serveur utilise les callback $_is_dedicated : true si c'est un dédié $_Game : 'TMU', 'TMS', 'TMO' ou 'TMN' $_currentTime : temps actuel en milliseconds $_players_round_current : num du round courrant (Rounds et Team modes) $_players_actives : nombre de joueurs actifs $_players_spec : nombre de specs $_players_finished : nombre de joueurs ayant fini (Rounds, Team and Laps modes) $_players_positions : tableau avec des infos live sur le joueur dans le round en cours
Il y a d'autres variables globales, soit spécifiques à des plugins, soit trop spécialisées pour chercher à les documenter : il faut fouiller un peu dans les plugins... :p
D'abord la structure des localisations : tous les fichiers locale.xxxxx.xml.txt sont lus et parsés, et doivent avoir une structure xml du type
<fast><locale><language><tag>sprintf like string text</tag></language></locale></fast>
sachant qu'il peut ou non y avoir plusieur langages, 'language' étant 'en', 'fr', etc. et doit correspondre au nom du langage dans la localisation du jeu. Il peut y avoir ou non plusiers 'tag', chacun étant le nom utilisé dans les fonctions ci dessous pour obtenir la traduction voulue, les paramètres passés dans ces fonctions après le tag seront passés en paramètres d'un sprintf, la string de traduction peut donc utiliser ces paramètres avec des %d, %f, %s etc. en tenant compte de leur ordre (c'est pour cela que dans le fichier xml de locale il faut préciser en commentaire les paramètres passés s'il y en a !)
localeText() et localeTextArray() renvoient une string, que l'ont peut donc envoyer à un joueur à l'aide d'un addCall('ChatSendToLogin','text','login') ou addCall('ChatSendServerMessageToLogin','text','login'). localeTextArray() sert à créer un texte localisé composé de plusieurs parties venant de tags traduits, simple strings, nombres etc. qui seront concaténés, ce qui est parfois plus clair/propre que de concaténer plusieurs localeText(). Les tags sont traduits en fonction du langage du joueur concerné, et si le tag n'est pas présent dans sa langue il est cherché dans la langue par défaut ('en' dans la config par défaut de fast).
// get localized string using login language // localeText($login,$tag,...) // set login to null if not related to a player // tag is the searched tag in the locale file // other params are sprintf like params localeText($login,$string) // get localized string using login language // localeTextArray($login,array($tag,...)) // set login to null if not related to a player // tag is the searched tag in the locale file // other params in the array are sprintf like params localeTextArray($login,$string_tag_array)
multiLocaleText() est un peu plus complexe et ne renvoit pas une string mais un tableau du format convenant aux méthodes ChatSendToLanguage() et ChatSendServerMessageToLanguage(), avec pour but d'envoyer le message à tous les joueurs, dans la langue de leur jeu quand la traduction des tags est présente. La forme des paramètres est du même type que localeTextArray() sauf que ce n'est pas une chaine à destination d'un login qui est fabriquée.
// get localized array for ChatSendToLanguage TM method for all used languages // multiLocaleText(mixed,mixed,...) // all mixed are concatenated, each mixed can be : // - an array($tag,...) , where tag is the searched tag in the locale file, and // other params in the array are sprintf like params // - any other value will just be concatenated multiLocaleText($string_tag_array,...)
Il faut noter que un seul manialink peut être affiché en même temps sur un client. Fast les utilise déjà et vous ne pouvez donc pas vous les accaparer, donc pas le choix il faut s'intégrer dans le système existant, géré par plugin.10.manialinks.php ! L'utilisation des manialinks nécessite d'abord de savoir écrire un xml de manialink. L'explication vise ici à son intégration dans Fast.
Le plugin plugin.10.manialinks.php s'occupe de la gestion de leur affichage, et s'occupera tout seul de refaire l'affichage lorsque l'état du joueur change si on le demande (en jeu ou non), ou de le garder permanent.
Ce plugin génère un "<manialinks>...</manialinks>" qui contiendra les différents "<manialink>...</manialink>", concaténés, qui composeront l'ensemble de l'affichage. La création de ceux ci passe par l'enregistrement d'une fonction callback/hook qui sera appelée lorsque nécessaire pour fabriquer la string complète. D'autres fonctions servent à simplifier la gestion des id (numériques) utilisés par le dédié et dont la valeur est renvoyée lorsque le texte correspondant est cliqué par le joueur. Ces id ont la nécessité d'être uniques pour éviter que les différents plugins n'utilisent les même valeurs.
Attention : les manialinks de Fast sont individuels, autrement dit calculés séparément pour chaque joueur. Cela implique que les callbacks devant retourner les infos à afficher sont appelés plus ou moins souvent, mais surtout pour chaque joueur : il faut donc veiller à ne pas y faire des choses consommant trop de ressources, sinon ça pourrait devenir catastrophique !
Il faut également être conscient que l'affichage de manialink provoque un petit lag graphique qui le rend quasi inutilisable en cours de jeu, donc à réserver exclusivement pour les moments où le joueur ne roule pas !
// add a hook/callback which will be called to build a manialink part // specify $login, or set it to true for all players, or false to set // it as default for new players. Set $force to 1 to get it visible // while playing, to 2 to force it visible. function manialinksAddManialinkHook($login,$id_name,$hook,$force=0) le $hook est le nom de la fonction callback qui sera appelée quand nécessaire et devra renvoyer une string contenant le manialink spécifique ("<manialink>...</manialink>"). $id_name est un nom qui doit être unique, typiquement le nom du plugin. La fonction $hook doit être définie ainsi : function $hook($login,&$pml){ return '<manialink>...</manialink>'; } où $login est le login du joueur dont le manialink est en cours de création, et $pml un référence sur $_players[$login]['ML']. // remove a hook added with manialinksAddManialinkHook function manialinksRemoveManialinkHook($login,$id_name) enleve le hook d'un manialink précédemment ajouté (s'il existe) // add a general action name and get its value manialinksAddAction($name) : sert à allouer un id pour les réponses quand on click mettre un nom contenant le nom du plugin, 'genre pluginname.xxx' l'id sera récupérable dans la array global $_ml_act[$name], typiquement dans des "<text action=\''.$_ml_act[$name].'\'>texte cliquable</text>", ou avec manialinksGetAction($name) // remove a general action name and value manialinksRemoveAction($name) // Get an base value of the specified size for manialink actions for custom use // (and so avoid having 2 plugins using the same values). // If login is specified then get it specifically for a user. // Player action values start at 20000, so if you get a general // value >20000 then it means that some plugin was too hungry manialinksGetActionBase($login=null,$size=100) si tu veux un group d'id : il te retourne l'id de base, tu peux ensuite utiliser de id retourné à id+size-1 // get a general action value manialinksGetAction($name) renvoie l'id du name (le meme que alloué par manialinksAddAction())
// ajout d'un callback d'affichage de temps (ou autres, zone des records) function ml_timesAddTimesMod($name,$hook,$data) // suppression d'un callback ajoute par ml_timesAddTimesMod() function ml_timesRemoveTimesMod($name)Le callback ($hook) est de la forme : callbackname($login,&$data,$num,$min){} , où $data est celui passé à la fonction ml_timesAddTimesMod(), $num le nombre d'entrées visibles sur l'écran du joueur, $min le nombre d'entrées minimum fournir. Il doit retourner un array (appelons le $table pour l'explication) qui contient :
La plupart des fonctions utiles sont dans fast_general.php, encore que beaucoup n'ont aucune raison d'être utilisées directement dans un plugin stabdard. Citons quelques unes plus ou moins utiles pas encore évoquées :
// formats a time: 1200000 -> 2:00.00 MwTimeToString($MwTime,$msec=true) // formats a time: -12340 -> -12.34 MwDiffTimeToString($DiffTime) // Remove colors from strings : $s$fffhello -> hello stripColors($str) // Remove links $h $l from strings. if not force then remove links only if game is known // and not TMU (ie which don't support the links) stripLinks($str,$force=false) // return a string with Player name, used for beginning of chat line authorChat($author) // verify if login is in admin list verifyAdmin($login) // Verify than 'Login' in given array is really of type string // because there are problems with pure numeric logins seen as int loginToString(&$response,$level)
Vous avez des outils xmlrpc pour php qui peuvent vous aider à faire des tests de commandes/méthodes du serveur, et pour TMU via un serveur dédié tester des manialinks ingame avant d'essayer de faire un plugin qui affiche.
Bon courage ;)
Slig