1. Lire un message

Bienvenue dans l'espace développeur. Un espace réservé aux plus curieux d'entre-vous qui vous permettra de faire ce que vous souhaitez avec vos trajets sans aucune limite !

Pour cette partie de la documentation vous devrez vous aider de la partie mode développeur dans le bot.

Exemple de lecture d'un message

Voici la valeur que nous souhaitons récupérer dans notre exemple :

Dans notre exemple nous souhaitons savoir si le bot peut actuellement se déplacer. Pour se faire nous remarquons que le paquet SetCharacterRestrictionsMessage contient une variable cantMove qui renvoie True si le personnage ne peut pas se déplacer. Voici comment je récupère cette valeur dans mon script :

function move()
	
end

function messagesRegistering()
	developer:registerMessage("SetCharacterRestrictionsMessage", setRestriction)
end

function setRestriction(message)
	global:printMessage(message.restrictions.cantMove)
end

Pour commencer, vous remarquez qu'une nouvelle fonction fait son apparition, la fonction messagesRegistering(). Cette fonction comme son nom l'indique est un "Enregistrement des messages" et permet de s'abonner a des messages. Dans notre exemple, on s'abonne au message SetCharacterRestrictionsMessage et on souhaite appeler la fonction setRestiction quand on reçoit ce message. Ensuite pour récupérer la donnée que l'on souhaite, il nous suffit de remonter jusqu’à la variable cantMove.

Remarque importante : Les fonctions enregistrées grâce à developer:registerMessage peuvent s'exécuter même si votre script est OFF.

Exécution en parallèle

Par défaut, l'interpréteur LUA n'autorise pas l'accès au même script par deux threads différents, supposons le script et le scénario suivant :

function move()
	global:delay(100000)
end

function messagesRegistering()
	developer:registerMessage("ChatServerMessage", _ChatServerMessage)
end

function _ChatServerMessage(message)
	global:printMessage("Un message de chat a été reçu !")
end
  • Si on lance le script, il sera bloqué dans la fonction move() pendant 100 seconds.

  • Donc un thread A a accès au script et sera occupé par l'exécution de cette fonction move().

  • Pendant cette durée, si vous recevez un ChatServerMessage, un autre thread B essayera d'exécuter la fonction _ChatServerMessage().

  • L'exécution de cette dernière va échouer, vu que le thread A est celui qui a accès au script pendant ce moment.

Pour remédier à ce problème, il suffit d'ajouter la ligne suivante au début de votre script :

DEVELOPER_MULTI_THREADING = true

Elle indiquera à AnkaBot d'autoriser l'exécution en parallèle de la fonction move() et la fonction _ChatServerMessage().

Cette manipulation comporte plusieurs risque si vous êtes un débutant en programmation, car vous allez devoir gérer par vous mêmes l'accès aux variables par plusieurs threads.

Exemple de risque du multi-threading

On va faire la tache suivante par deux scripts différents :

  • Envoyer un BasicWhoAmIRequestMessage (/whoami)

  • Récupérer l'ID du serveur où je me trouve lorsqu'on reçoit BasicWhoIsMessage

1. Script (avec DEVELOPER_MULTI_THREADING)

DEVELOPER_MULTI_THREADING = true

function move()
	local BasicWhoAmIRequestMessage = developer:createMessage("BasicWhoAmIRequestMessage")
	serverId = 0
	developer:sendMessage(BasicWhoAmIRequestMessage)

	-- J'attend jusqu'à ce que serverId n'est plus égale à 0
	-- Le message BasicWhoIsMessage qu'on va recevoir permet d'avoir cette valeur
	while serverId == 0 do
		global:delay(10)
	end
	global:printSuccess("Mon serverId est "..serverId)
end

function messagesRegistering()
	developer:registerMessage("BasicWhoIsMessage", _BasicWhoIsMessage)
end

function _BasicWhoIsMessage(message)
	serverId = message.serverId
end

2. Script (sans DEVELOPER_MULTI_THREADING)

function move()
	local BasicWhoAmIRequestMessage = developer:createMessage("BasicWhoAmIRequestMessage")
	serverId = 0
	developer:sendMessage(BasicWhoAmIRequestMessage)

	-- J'attend jusqu'à ce que serverId n'est plus égale à 0
	-- Le message BasicWhoIsMessage qu'on va recevoir permet d'avoir cette valeur
	-- Je bloque la fonction move ici, jsuqu'à la réception de BasicWhoIsMessage et l'exécution de la fonction _BasicWhoIsMessage
	developer:suspendScriptUntil("BasicWhoIsMessage", 10000000, false)
	global:printSuccess("Mon serverId est "..serverId)
end

function messagesRegistering()
	developer:registerMessage("BasicWhoIsMessage", _BasicWhoIsMessage)
end

function _BasicWhoIsMessage(message)
	serverId = message.serverId
end

Analyse des deux exemples

Si vous exécuter les deux scripts, vous aurez les memes résultats, cependant le premier script n'est pas totalement stable, y'a une chance qu'il va produire une erreur imprévisible.

Cela vient du fait que le script essai de faire deux opérations en même temps à la meme variable serverId

	while serverId == 0 do
		global:delay(10)
	end

Ici le script 1, tous les 10 milliseconds, il lis la valeur de la variable serverId, et lorsqu'il reçoit BasicWhoIsMessage il va écraser la valeur de la variable serverId, et si ces deux opérations de lecture et écriture coincident dans un même instant, cela peut provoquer une erreur.

Eviter l'utilisation de DEVELOPER_MULTI_THREADING = true sauf si vous n'avez pas une alternative à votre problème.

Dernière mise à jour