@casual-simulation/aux-runtime 3.5.3-alpha.16326443512 → 3.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12294,6 +12294,22 @@ export interface GeoJSONMapLayer extends MapLayerBase {
12294
12294
  data?: object;
12295
12295
  }
12296
12296
 
12297
+ /**
12298
+ * The function signature of a dynamic bot listener.
12299
+ *
12300
+ * That is, a listener that is registered at runtime by a user script instead of parsed from a tag.
12301
+ *
12302
+ * @dochash types/core
12303
+ * @docgroup 01-core
12304
+ * @docname Listener
12305
+ * @docid DynamicListener
12306
+ */
12307
+ export type DynamicListener = (
12308
+ that: any,
12309
+ bot: Bot,
12310
+ tagName: string
12311
+ ) => any;
12312
+
12297
12313
  interface Ai {
12298
12314
  /**
12299
12315
  * Sends a chat message to the AI.
@@ -12801,6 +12817,34 @@ interface Ai {
12801
12817
  }
12802
12818
 
12803
12819
  interface Os {
12820
+
12821
+ /**
12822
+ * Adds the given listener to the given bot for the given tag.
12823
+ *
12824
+ * @param bot The bot that the listener should be added to.
12825
+ * @param tagName The name of the tag that the listener should be added to.
12826
+ * @param listener The listener that should be added to the bot.
12827
+ *
12828
+ * @dochash actions/os/event
12829
+ * @docgroup 02-event-actions
12830
+ * @docname os.addBotListener
12831
+ * @docid os.addBotListener
12832
+ */
12833
+ addBotListener(bot: Bot, tagName: string, listener: DynamicListener): void;
12834
+
12835
+ /**
12836
+ * Removes the given listener from a bot for a specific tag.
12837
+ * @param bot The bot that the listener should be removed from.
12838
+ * @param tagName The name of the tag that the listener should be removed from.
12839
+ * @param listener The listener that should be removed from the bot.
12840
+ *
12841
+ * @dochash actions/os/event
12842
+ * @docgroup 02-event-actions
12843
+ * @docname os.removeBotListener
12844
+ * @docid os.removeBotListener
12845
+ */
12846
+ removeBotListener(bot: Bot, tagName: string, listener: DynamicListener): void;
12847
+
12804
12848
  /**
12805
12849
  * Sleeps for time in ms.
12806
12850
  * @param time Time in ms. 1 second is 1000ms.
@@ -1,4 +1,4 @@
1
- import type { StateUpdatedEvent, Bot, BotSpace, RuntimeBot, CompiledBotListener, BotModuleResult, ResolvedBotModule, ImportMetadata } from '@casual-simulation/aux-common/bots';
1
+ import type { StateUpdatedEvent, Bot, BotSpace, RuntimeBot, BotModuleResult, ResolvedBotModule, ImportMetadata, DynamicListener } from '@casual-simulation/aux-common/bots';
2
2
  import type { Observable, SubscriptionLike } from 'rxjs';
3
3
  import type { AuxGlobalContext } from './AuxGlobalContext';
4
4
  import type { AuxLibrary } from './AuxLibrary';
@@ -90,6 +90,7 @@ export declare class AuxRuntime implements RuntimeBotInterface, RuntimeBotFactor
90
90
  * The number of times that the runtime can call onError for an error from the same script.
91
91
  */
92
92
  repeatedErrorLimit: number;
93
+ get library(): AuxLibrary;
93
94
  get context(): AuxGlobalContext;
94
95
  get currentVersion(): RuntimeStateVersion;
95
96
  get globalObject(): any;
@@ -231,11 +232,16 @@ export declare class AuxRuntime implements RuntimeBotInterface, RuntimeBotFactor
231
232
  getRawValue(bot: CompiledBot, tag: string): any;
232
233
  updateTagMask(bot: CompiledBot, tag: string, spaces: string[], value: any): RealtimeEditConfig;
233
234
  getTagMask(bot: CompiledBot, tag: string): any;
234
- getListener(bot: CompiledBot, tag: string): CompiledBotListener;
235
+ getListener(bot: CompiledBot, tag: string): DynamicListener | null;
236
+ setListener(bot: CompiledBot, tag: string, listener: DynamicListener | null): void;
237
+ getDynamicListeners(bot: CompiledBot, tag: string): DynamicListener[] | null;
238
+ addDynamicListener(bot: CompiledBot, tag: string, listener: DynamicListener): void;
239
+ removeDynamicListener(bot: CompiledBot, tag: string, listener: DynamicListener): void;
235
240
  getTagLink(bot: CompiledBot, tag: string): RuntimeBot | RuntimeBot[];
236
241
  getSignature(bot: CompiledBot, signature: string): string;
237
242
  private _compileTagOrMask;
238
243
  private _compileTag;
244
+ private _updateListenerPresense;
239
245
  private _compileTagValue;
240
246
  private _compileValue;
241
247
  private _compileTagMaskValue;
@@ -72,6 +72,9 @@ async function _importInterpreterCore() {
72
72
  * This means taking state updates events, shouts and whispers, and emitting additional events to affect the future state.
73
73
  */
74
74
  export class AuxRuntime {
75
+ get library() {
76
+ return this._library;
77
+ }
75
78
  get context() {
76
79
  return this._globalContext;
77
80
  }
@@ -1702,6 +1705,7 @@ export class AuxRuntime {
1702
1705
  newBot.masks[space] = newMasks;
1703
1706
  }
1704
1707
  }
1708
+ newBot.dynamicListeners = existing.dynamicListeners;
1705
1709
  existing.script[REPLACE_BOT_SYMBOL](newBot.script);
1706
1710
  }
1707
1711
  let precalculated = {
@@ -2152,6 +2156,8 @@ export class AuxRuntime {
2152
2156
  precalculated: true,
2153
2157
  tags: fromFactory ? bot.tags : { ...bot.tags },
2154
2158
  listeners: {},
2159
+ listenerOverrides: {},
2160
+ dynamicListeners: {},
2155
2161
  modules: {},
2156
2162
  exports: {},
2157
2163
  values: {},
@@ -2345,12 +2351,50 @@ export class AuxRuntime {
2345
2351
  return undefined;
2346
2352
  }
2347
2353
  getListener(bot, tag) {
2348
- const listener = bot.listeners[tag];
2349
- if (listener) {
2350
- return listener;
2354
+ return bot.listenerOverrides[tag] || bot.listeners[tag] || null;
2355
+ }
2356
+ setListener(bot, tag, listener) {
2357
+ if (hasValue(listener)) {
2358
+ bot.listenerOverrides[tag] = listener;
2359
+ }
2360
+ else {
2361
+ delete bot.listenerOverrides[tag];
2362
+ }
2363
+ this._updateListenerPresense(bot, tag);
2364
+ }
2365
+ getDynamicListeners(bot, tag) {
2366
+ if (bot.dynamicListeners && bot.dynamicListeners[tag]) {
2367
+ return bot.dynamicListeners[tag];
2368
+ }
2369
+ return null;
2370
+ }
2371
+ addDynamicListener(bot, tag, listener) {
2372
+ if (!bot.dynamicListeners) {
2373
+ bot.dynamicListeners = {};
2374
+ }
2375
+ if (!bot.dynamicListeners[tag]) {
2376
+ bot.dynamicListeners[tag] = [];
2377
+ }
2378
+ const listeners = bot.dynamicListeners[tag];
2379
+ if (listeners.includes(listener)) {
2380
+ // If the listener already exists, do not add it again.
2381
+ return;
2382
+ }
2383
+ listeners.push(listener);
2384
+ this._updateListenerPresense(bot, tag);
2385
+ }
2386
+ removeDynamicListener(bot, tag, listener) {
2387
+ if (bot.dynamicListeners && bot.dynamicListeners[tag]) {
2388
+ const listeners = bot.dynamicListeners[tag];
2389
+ const index = listeners.indexOf(listener);
2390
+ if (index >= 0) {
2391
+ listeners.splice(index, 1);
2392
+ if (listeners.length <= 0) {
2393
+ delete bot.dynamicListeners[tag];
2394
+ }
2395
+ this._updateListenerPresense(bot, tag);
2396
+ }
2351
2397
  }
2352
- this.getValue(bot, tag);
2353
- return bot.listeners[tag] || null;
2354
2398
  }
2355
2399
  getTagLink(bot, tag) {
2356
2400
  const tagValue = bot.values[tag];
@@ -2443,15 +2487,20 @@ export class AuxRuntime {
2443
2487
  }
2444
2488
  this._compileTagValue(bot, tag, tagValue);
2445
2489
  }
2490
+ _updateListenerPresense(bot, tag) {
2491
+ this._globalContext.recordListenerPresense(bot.id, tag, !!bot.listenerOverrides[tag] ||
2492
+ !!bot.listeners[tag] ||
2493
+ !!bot.dynamicListeners[tag]);
2494
+ }
2446
2495
  _compileTagValue(bot, tag, tagValue) {
2447
2496
  let { value, listener, module } = this._compileValue(bot, tag, tagValue);
2448
2497
  if (listener) {
2449
2498
  bot.listeners[tag] = listener;
2450
- this._globalContext.recordListenerPresense(bot.id, tag, true);
2499
+ this._updateListenerPresense(bot, tag);
2451
2500
  }
2452
2501
  else if (!!bot.listeners[tag]) {
2453
2502
  delete bot.listeners[tag];
2454
- this._globalContext.recordListenerPresense(bot.id, tag, false);
2503
+ this._updateListenerPresense(bot, tag);
2455
2504
  }
2456
2505
  if (module) {
2457
2506
  bot.modules[tag] = module;
@@ -2713,7 +2762,13 @@ export class AuxRuntime {
2713
2762
  // Default import function
2714
2763
  [`_${IMPORT_FACTORY}`]: () => (module, meta) => this._importModule(module, meta),
2715
2764
  },
2716
- arguments: [['that', 'data'], IMPORT_FACTORY, EXPORT_FACTORY],
2765
+ arguments: [
2766
+ ['that', 'data'],
2767
+ '$__bot',
2768
+ '$__tag',
2769
+ IMPORT_FACTORY,
2770
+ EXPORT_FACTORY,
2771
+ ],
2717
2772
  });
2718
2773
  if (hasValue(bot)) {
2719
2774
  this._functionMap.set(functionName, func);
@@ -2727,7 +2782,10 @@ export class AuxRuntime {
2727
2782
  };
2728
2783
  const exportFunc = (valueOrSource, exp) => exports(valueOrSource, exp, meta);
2729
2784
  return this._wrapWithCurrentPromise(() => {
2730
- let result = func(null, importFunc, exportFunc);
2785
+ // Pass null for the argument, bot, and tag
2786
+ // because module functions do not accept arguments
2787
+ // and have the bot and tag injected automatically
2788
+ let result = func(null, null, null, importFunc, exportFunc);
2731
2789
  this._scheduleJobQueueCheck();
2732
2790
  return result;
2733
2791
  });