Once your package declares settings, its script reads their current values from asterobot:parameters. It can also react the moment someone applies a change. asterobot:parameters is the reference for the module.
values
import { values } from "asterobot:parameters";
values has one property per setting your package declares, named by its key: values.maxAnswers for a setting declared as maxAnswers. Each value has the type of its setting: a boolean for bool, a string for string, a regular number for int and double, an array for array and an object for map.
The values are the ones saved for the bot, laid over the defaults of your declaration. A setting nobody changed reads as its default.
values is live. After someone applies new settings, the next read returns the new value, without restarting the script. So read a setting at the moment you need it, in a handler or at each turn of a loop, instead of copying it into a variable when the script starts. When a value has to stay the same for a whole exchange, copy it at the start of that exchange, as the chat script in Add a setting does with its reply.
A few more things about values:
Object.keys(values)lists the settings, and"delay" in valuestells whether one exists.- It's read-only. Assigning to one of its properties throws a
TypeError, and so does deleting one. asterobot:parameters quotes both texts. - It only holds your own package's settings. In a dependency,
valuesholds the dependency's settings: see Settings in dependencies. - When Asterobot can't read the declaration,
valuesis empty and every read givesundefined. Declare settings says when that happens. - An inline script can declare settings, but they never appear on the bot's Settings tab, so it always reads its defaults.
When new values arrive
Here is what happens when someone changes settings under Package settings on the bot's Settings tab, then clicks Apply:
- Asteroboard sends every setting of that package's card: the ones that changed and the ones that didn't.
- Asterobot checks each value against your declaration. If one doesn't fit, nothing is saved, and Couldn't apply the settings appears with the reason.
- Asterobot saves the values for the bot.
- If a script is running, Asterobot hands it the new values.
valuesreturns them from then on, then theonChange()handlers run for each setting whose value changed.
All the values of one Apply reach the script together, before any handler runs, so a script never sees half an edit.
When no script is running, the values are only saved, and the next start reads them. The same thing happens in the rare case where the running script already has 32 operations waiting when someone clicks Apply: see Limits.
React to a change
onChange() registers a function that runs when an applied value differs from the previous one. Use it when a change should do something right away. When the script only needs the current value the next time it looks, reading values is enough.
This script writes a warning on the bot's console when the character's pods go over a limit taken from the settings. When someone changes the limit, onChange() checks the last pods the game reported against the new limit at once, instead of waiting for the game to report them again:
import { session, botInfo, botWarn } from "asterobot:bot";
import { values, onChange } from "asterobot:parameters";
import { on, send } from "asterobot:protocol";
/** @type {BehaviorParameters} */
export const parameters = {
warnAt: {
type: "int",
label: "Warn when pods reach",
unit: "%",
default: 90,
min: 1,
max: 100,
},
};
// Kept so the pods can be checked again when the limit changes.
let lastWeight;
function checkWeight() {
if (!lastWeight || lastWeight.weightMax <= 0) return;
const percent = Math.floor((lastWeight.inventoryWeight * 100) / lastWeight.weightMax);
if (percent >= values.warnAt) {
botWarn(`Pods at ${percent}%, the limit is ${values.warnAt}%`);
}
}
export default async function behavior(launch) {
on("InventoryWeightEvent", (traffic) => {
// A message Asterobot couldn't decode has no payload, and an error
// thrown in a handler stops the whole script.
if (!traffic.payload) return;
lastWeight = traffic.payload;
checkWeight();
});
onChange(({ name, value }) => {
botInfo(`Setting ${name} is now ${value}`);
if (name === "warnAt") checkWeight();
});
// 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,
});
}
}
To try it, Run the package on a MITM bot (man-in-the-middle: the bot relays the game session of the Dofus client you play). On the bot's Settings tab, under Package settings, set Warn when pods reach to 1 and click Apply. The bot's Console shows Setting warnAt is now 1, and a warning as soon as the game has reported the character's pods since the script started.
The handler receives an object with the setting's name and its new value, of the setting's type. Some details:
- It runs once for each setting whose value changed, and only for your own package's settings.
- It doesn't run when the script starts, and an Apply that changes nothing doesn't call it. A list or a map counts as changed only when its content differs.
- With several handlers, the order they run in isn't fixed. Don't write one that depends on another having run first.
- A handler that throws stops the whole script, like a message handler. The Problems alert then starts with
parameters.onChange handler, or withunhandled Promise rejection:when anasynchandler's promise rejects. Put anything that can fail intry/catch.
onChange() returns a handle. Pass it to offChange() when the script no longer needs to hear about changes:
const handle = onChange(({ name }) => {
botInfo(`${name} changed`);
});
// Once the script doesn't need it any more.
offChange(handle);
A script can have up to 256 onChange() handlers registered at once, counted apart from its message handlers. See Limits.
Saved values
Settings are saved per bot, under the package's name, whatever its version. For you as the author, that means:
- Two bots playing your package each have their own values.
- A bot moved to another version of your package keeps its values.
- Asteroboard saves every setting of a package's card at once, the untouched ones included, when someone clicks Apply, and when a bot is added with your package picked in the Add a bot dialog. From then on, the bot has a saved value for each of those settings, and the defaults of your later versions don't change them.
- A saved value is used only while it fits the declaration of the version the bot plays. When it doesn't fit, the default applies, but the saved value isn't deleted: it comes back if the bot returns to a version where it fits, unless someone applied a new value to that setting in the meantime.
Here is what a bot sees after it moves to a new version of your package:
| In the new version, you | A bot with a saved value reads | A bot without one reads |
|---|---|---|
| Add a setting | Its default | Its default |
| Change a default | Its saved value | The new default |
| Rename a setting | The default, under the new name. The value saved under the old name isn't used. | The default |
| Change a setting's type | Its saved value if it still fits, such as a whole number saved for a setting now declared double, otherwise the default |
The default |
Remove a choice, or narrow min and max |
Its saved value if it's still allowed, otherwise the default | The default |
| Remove a setting | Nothing: the setting is gone | Nothing |
So once people use your package, keep the names of its settings. And when a setting should mean something else, give it a new name: an old value that still fits the type would otherwise be read with the new meaning.
The settings of a dependency are saved under the dependency's own name. Settings in dependencies explains what follows from that.
What a script can't do with settings
- Change a setting.
valuesis read-only, and the next Apply would send the values shown on the page anyway. - Read the settings of another package, whether it's the package that uses it or one of its dependencies.
- Keep data for its next run. Each start begins again from scratch: see Play, stop and reload.
Next, Declare actions.
Aucun avis à afficher.