Ankama patches Dofus regularly, and a patch can change the game's messages. Asterobot absorbs most of those changes before they reach scripts, but not all of them.
What a patch changes
Messages carry scrambled names on the wire, and those names change between game versions. Asterobot translates them into readable names, so as long as it knows the game version, a script that works with type and payload field names doesn't see the change.
A patch can also add messages, remove some, or change their fields. A new message has no readable name until Asterobot gives it one, and reaches scripts with an empty type until then.
Readable names can change too, with an Asterobot update, when a message gets a more accurate name. A script using the old name then stops matching the message, and sending under the old name fails. When a bot had the old name selected in its Network tool, Asterobot removes it from the selection the next time it loads the bot, such as when Asterobot starts.
While Asterobot doesn't know the new version
Right after a patch, Asterobot may not know the new version's names yet. When Dofus updates explains what to do from the player's side. Until Asterobot knows them, a message it can't name reaches scripts this way:
| In your script | What happens |
|---|---|
on("InventoryWeightEvent", handler) |
The handler never runs: the message arrives without its name. |
wait("InventoryWeightEvent", { timeout: 10000 }) |
The wait rejects with protocol wait timed out when its timeout runs out. |
onTraffic(handler) or on("*", handler) |
The handler receives the message with an empty type, unknown set to true, no payload, and a decodeError that starts with obfuscated protobuf wire name is not mapped:. |
Some messages arrive like this at any time, since only part of the protocol has readable names. After a patch, messages your script used to receive by name can join them. Traffic describes these messages in full.
Check a script after an update
- Update Asterobot when a new version is out, and download the new game version: see Updating and When Dofus updates.
- Open your package in the editor. The editor loads the message names of the Asterobot it's connected to, so a handler that reads the fields of a renamed message gets errors on the error badge.
- Run the package on a MITM bot (man-in-the-middle: the bot relays the game session of the Dofus client you play), and play through what the script handles.
- In the bot's Network tool, select the messages the script relies on and turn on Also mirror unrecovered messages. A message that lost its name appears in Traffic with its wire name in italics.
- Read the bot's console for the warnings your script writes when something it expects doesn't happen, as in the example below.
Write scripts that keep working
- Rely on
typeand on payload field names. Don't comparewireTypeortypeUrl, don't read fixed positions inrawAny, and don't use scrambled field names such asfzbl: all of those change with game versions. - Read every field with
?., and give defaults with??. A field that's gone reads asundefined, which doesn't throw. - Give every
wait()a timeout, and write something useful when it runs out: a message that lost its name never arrives. - Catch errors from
send().semantic protobuf message is not mapped:means the name you send doesn't exist in this version of Asterobot. - Say so on the console when expected messages stop coming, instead of failing silently.
- Game data can change too: its tables and columns come from the game files and follow the game version. See Game data overview.
This script puts two of those habits to work. On a Full socket bot, it warns when the game doesn't confirm the identification, for example because a message name no longer matches. On both kinds of bot, it writes one console line for each message it can't name.
import { session, botDebug, botWarn } from "asterobot:bot";
import { onTraffic, send, wait } from "asterobot:protocol";
export default async function behavior(launch) {
const unnamed = new Set();
onTraffic((traffic) => {
// One line per wire name is enough to see what lost its name.
if (!traffic.unknown || unnamed.has(traffic.wireType)) return;
unnamed.add(traffic.wireType);
botDebug(`No name for ${traffic.direction} message ${traffic.wireType}`);
});
if (launch.reason === "initial") {
// Started before identifying, so a quick answer can't be missed. The catch
// handles the timeout without holding up the rest of the script.
wait("AuthenticationTicketAcceptedEvent", { timeout: 10000 }).catch((error) => {
botWarn("The game didn't confirm the identification:", 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,
});
}
}
AuthenticationTicketAcceptedEvent is the message the game server sends once it has accepted the ticket.
compatibleVersion
A package can declare which Asterobot versions it works with, in the compatibleVersion field of its asterobot.json. Asterobot refuses to start a package whose compatibleVersion doesn't include the version it runs, and the editor shows Incompatible for it. It's about Asterobot versions, not Dofus versions, so it can't tell that the game changed. Use it when your script depends on something a given Asterobot version brought, such as a message's new name. Compatibility explains how to write it.
That's the end of the protocol chapter. The next one, Game data, covers reading items, monsters, maps and texts from a script.
Aucun avis à afficher.