Aller au contenu
Afficher dans l'application

Une meilleure façon de naviguer. En savoir plus.

Asterobot

Une application plein écran sur votre écran d'accueil avec notifications push, badges et plus encore.

Pour installer cette application sur iOS et iPadOS
  1. Appuyez sur Icône de partage dans Safari
  2. Faites défiler le menu et appuyez sur Ajouter à l'écran d'accueil.
  3. Appuyez sur Ajouter dans le coin supérieur droit.
Pour installer cette application sur Android
  1. Appuyez sur le menu à trois points (⋮) dans le coin supérieur droit du navigateur.
  2. Appuyez sur Ajouter à l'écran d'accueil ou Installer l'application.
  3. Confirmez en appuyant sur Installer.

Send messages

(0 notes)

Reading the game is half of what a script does. Here the chat script learns to answer: when someone says !hello, the bot replies in chat and checks that its reply went through.

Warning

On a MITM bot (man-in-the-middle: the bot relays the game session of the Dofus client you play), everything the script sends goes out as your character. The reply on this page is a real chat message that other players can see.

Try the message by hand first

Before writing code, send the message from the Network tool. If it works there, you know the payload is right.

  1. On the bot's page, open Tools > Network > Send a game message.
  2. Keep To the server selected, and pick ChatChannelMessageRequest in the list of messages.
  3. Type some text in content and leave the other fields as they are. Empty fields aren't sent, and a channel left out means GLOBAL, the general channel.
  4. Check the payload under This is what will be sent., then click Send ChatChannelMessageRequest.

Your line appears in the game. If ChatChannelMessageEvent is selected in Settings, Traffic also shows your request going Out and your line coming back In.

send()

await send("ChatChannelMessageRequest", { channel: "GLOBAL", content: "Hello" });

send() takes a message name and a payload holding the message's fields. It builds the message and sends it to the game server, and its promise resolves as soon as the message is sent: it doesn't wait for an answer.

The promise rejects when the message can't be built or sent:

Problem Error
A field the message doesn't have ChatChannelMessageRequest.contnt: unknown protobuf field
A value of the wrong type ChatChannelMessageRequest.content: expected string
A channel name that doesn't exist ChatChannelMessageRequest.channel: unknown enum symbol "GENERAL"
A message name Asterobot can't send semantic protobuf message is not mapped: MyMessageRequest
Sending takes longer than the timeout The promise rejects after 30 seconds, or after the timeout you pass

channel takes a channel's name as a string, such as "GLOBAL", "GUILD" or "PARTY", or the channel's number. The Dofus protocol reference lists every channel.

Wait for the answer

The game doesn't answer a chat line with a response. It sends the line to everyone on the channel as a ChatChannelMessageEvent, you included. To know your line went through, wait for that event.

A wait only sees messages that arrive after wait() is called, and nothing guarantees that send() resolves before the game's answer comes in. So start the wait first, then send, and await both together:

await Promise.all([
  wait(
    (traffic) => traffic.type === "ChatChannelMessageEvent" && traffic.payload?.content === "Hello",
    { timeout: 5000 },
  ),
  send("ChatChannelMessageRequest", { channel: "GLOBAL", content: "Hello" }),
]);

wait() is called first, so it's already listening when the line goes out. Promise.all resolves once both have succeeded, and rejects as soon as either one fails. Two other ways of writing this look fine and aren't: a wait started after await send() can miss an answer that came quickly, and a wait kept in a variable to await after send() is left behind when send() fails. Waiting explains both.

wait() resolves with the next inbound message that matches, and you choose what matches: a message name, or a function that returns true for the message you want. The function above checks the name and the text, so another player's line doesn't count.

wait() has no timeout of its own. A wait that never matches stays open until the script stops, so always pass { timeout }, in milliseconds. When the time runs out, the promise rejects with protocol wait timed out.

request()

request() sends a message and resolves with the game's response to it. Only a handful of Dofus requests get a response, matched to them by uid, and none of them is something a first script needs to send. For every other message nothing comes back: request() waits until its timeout, 30 seconds unless you pass another one, and then rejects with context deadline exceeded.

So for almost everything, wait for the event the game answers with while you send(), as this page does. Sending covers request(), and the to option that sends a message to the Dofus client instead of the server.

Timeouts

Function Default timeout To change it
send() 30 seconds { timeout: milliseconds } as the third argument
request() 30 seconds { timeout: milliseconds } as the third argument
wait() None: it waits until the script stops { timeout: milliseconds } as the second argument

A timeout must be a positive number of milliseconds. Anything else rejects with timeout/milliseconds must be a finite positive Number.

The complete script

import { session, botInfo, botWarn } from "asterobot:bot";
import { on, send, wait } from "asterobot:protocol";

const TRIGGER = "!hello";
const REPLY = "Hello from my first script";

export default async function behavior(launch) {
  on("ChatChannelMessageEvent", async (traffic) => {
    // Only the exact trigger: the game also sends our own reply back to us,
    // and answering that echo would start a loop.
    if (traffic.payload?.content !== TRIGGER) return;

    try {
      // The wait starts before the reply goes out, so a quick echo isn't missed.
      await Promise.all([
        wait(
          (echo) => echo.type === "ChatChannelMessageEvent" && echo.payload?.content === REPLY,
          { timeout: 5000 },
        ),
        send("ChatChannelMessageRequest", { channel: "GLOBAL", content: REPLY }),
      ]);
      botInfo("Reply delivered");
    } catch (error) {
      // An error that escapes a handler stops the whole script.
      botWarn("Reply not delivered:", String(error));
    }
  });

  // A new game connection starts with this message. MITM bots never launch
  // with "initial": the Dofus client has already identified their session.
  if (launch.reason === "initial") {
    await send("IdentificationRequest", {
      ticketKey: session.gameToken,
      languageCode: session.language,
    });
  }
}

The handler is async so that it can await. Handlers don't wait for each other: while this one waits for the echo, the bot keeps handling other messages, the echo included, which is how wait() gets to see it.

The try/catch keeps a failed reply from ending the script, and String(error) turns the error into text the console can print.

Anyone who says !hello on a channel your character receives gets an answer in the general channel, so stop the script when you're done testing.

Test it

  1. Run the package on your MITM bot.
  2. Say !hello in the Dofus chat.
  3. The bot answers in the general channel, and its Console shows Reply delivered.

If the console shows Reply not delivered: followed by a reason, select ChatChannelMessageRequest and ChatChannelMessageEvent in the Network tool's Settings, try again, and check in Traffic whether the request went out and whether the line came back.

Next, Add a setting lets people change the trigger and the reply without editing your code. Waiting covers every way to wait for a message.

Commentaires des utilisateurs

Aucun avis à afficher.

Compte

Navigation

Recherche

Recherche

Configurer les notifications push du navigateur

Chrome (Android)
  1. Appuyez sur l'icône de cadenas à côté de la barre d'adresse.
  2. Tap Autorisations → Notifications.
  3. Ajustez vos préférences.
Chrome (Desktop)
  1. Cliquez sur l'icône représentant un cadenas dans la barre d'adresse..
  2. Select Paramètres du site.
  3. Find Notifications et ajustez vos préférences.