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.

Lookups

(0 notes)

Five functions of asterobot:gamedata cover most of what a script looks up: a text by its id, a record by its key, a whole table, the rows matching some values, and records by their name.

import { text, record, table, find, search } from "asterobot:gamedata";

What a row looks like

record(), table() and find() return rows as plain objects:

  • The keys are the table's column names, as the Game data tab shows them, such as name_id.
  • A column with no value is left out of the object, so reading it gives undefined.
  • Numbers are regular numbers, not BigInt, large ids included.
  • A column holding nested data comes as an array or an object, whose fields keep the game's own names.
  • In a derived table, a table whose name contains two underscores, each row points to its parent row with _parent_id.

Most tables key their rows with an _id column, and the others with their first column. That key is what record() looks up.

The key and the game's own id

_id is the key Asterobot gives each row. Some tables also have an id column that comes from the game, and an id you read in a message can refer to either one. The example queries of the SQL tab, for instance, find an item type with WHERE id = ... before using its _id. Check in the Game data tab which column your value matches, then use record() for the key, and find() for any other column:

const byKey = record("item_types", 48);
const [byGameId] = (await find("item_types", { id: 48 })) ?? [];

search() and the _names table give you keys directly, ready for record().

text()

text(key) returns one game text, or undefined.

Argument What it looks up
A whole number The text with that numeric id, such as the value of a name_id column
A string The text with that text key, such as ui.common.classic

It returns undefined when no text has that key, and for every key when the game's text file for the script's language is missing. Any other argument, such as a decimal number or a BigInt, throws TypeError: gamedata.text key must be a string or integer.

Texts come in the language the script was started with, which is fr for every start made from Asteroboard today.

record()

record(tableName, key) returns one row, or undefined when the table has no row with that key.

const monster = record("monsters", 147);
if (monster) {
  botInfo(text(monster.name_id));
}
Problem What it throws, right away
The table name is empty or isn't a string TypeError: gamedata.record table must be a non-empty string
The key isn't a whole number, a BigInt included TypeError: gamedata.record id must be an integer
This game version has no table with that name An error with the message datacenter: no such table: "monstres"

Ids in message payloads are often BigInt values. Convert one with Number() before looking it up, as in record("monsters", Number(id)).

table()

table(tableName, options) resolves to an array of rows, sorted by key.

Option Default What it does
limit 200 How many rows to return, 5,000 at most
offset 0 How many rows to skip first

A limit or an offset that isn't a positive whole number is ignored, and its default applies. Read a large table a page at a time:

for (let offset = 0; ; offset += 1000) {
  const rows = await table("items", { limit: 1000, offset });
  if (!rows || rows.length === 0) break;
  botInfo("Read", rows.length, "items starting at", offset);
}

table() resolves to undefined when the bot's game version has no game data. It rejects with gamedata.table name must be a non-empty string for an empty name, and with datacenter: no such table: "itmes" for a table that doesn't exist.

find()

find(tableName, filter, options) resolves to the rows whose columns hold every value in filter.

const spawns = await find("sub_areas__monsters", { value: 147 });

Each row found here links a sub-area, its _parent_id, to the monster whose key is 147. Derived tables like this one exist to answer such reverse questions.

Option Default What it does
limit 200 How many rows to return, 5,000 at most

find() has no offset. Pass numbers for columns that hold numbers, and strings for columns that hold text.

Problem The promise rejects with
The table name is empty or isn't a string gamedata.find table must be a non-empty string
filter is empty or isn't an object gamedata.find filter must be a non-empty object
The table doesn't exist datacenter: no such table: "sub_area_monsters"
The table has no column with that name datacenter: no such column: table "sub_areas__monsters" has no column "monster"

Like table(), find() resolves to undefined when there's no game data.

search(query, options) resolves to the records whose name matches the query, best matches first:

[
  { table: "monsters", id: 147, nameId: 7217, name: "Bouftou Royal" },
  // ...
]
Field What it holds
table The table of the record
id The record's key, ready for record(hit.table, hit.id)
nameId The id of the game text the name comes from
name The name, in the script's language
Option Default What it does
table Every table Only searches the records of this table
limit 200 How many results to return, 5,000 at most

Each word of the query matches as the start of a word, so bouftou roy finds Bouftou Royal, and shorter names come first. Without table, the results take turns between the tables that have a match, so the first results show the different kinds of things with that name. A very short query matches so many names that only the first 2,000 are ranked, and the one you want can be missed: add a letter, or a table.

Names are in the script's language, fr for a script started from Asteroboard today, so search for French names.

Problem The promise rejects with
The query is empty or isn't a string gamedata.search query must be a non-empty string
options.table isn't a string gamedata.search options.table must be a string
The table doesn't exist datacenter: no such table: "monstres"
The game data has no text in the script's language datacenter: no text for this language: "fr"

search() resolves to undefined when there's no game data.

A complete example

This package adds a button that looks monsters up by name and writes what it finds to the bot's console:

import { session, botInfo } from "asterobot:bot";
import { record, search } from "asterobot:gamedata";
import { send } from "asterobot:protocol";

export const actions = {
  findMonster: {
    label: "Find a monster",
    args: {
      name: { type: "string", label: "Name" },
    },
    async run({ name }) {
      const hits = await search(name, { table: "monsters", limit: 5 });
      // undefined rather than an empty array: this game version has no game data.
      if (hits === undefined) throw new Error("No game data for this bot's game version");

      for (const hit of hits) {
        const monster = record(hit.table, hit.id);
        botInfo(`${hit.name}: key ${hit.id}, race ${monster?.race}`);
      }
    },
  },
};

export default async function behavior(launch) {
  // 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,
    });
  }
}

Run the package on a bot, open the bot's Settings tab, and click Find a monster under Package settings. Type a name, in French for now, and click Run in the dialog. An error in run, such as a misspelled table name, shows as a toast and doesn't stop the script. Declare actions covers buttons in detail.

For questions these five functions can't answer, such as a join or a count, see SQL queries.

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.