isaacscript-common 21.4.0 → 21.5.0

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.
Files changed (72) hide show
  1. package/dist/index.d.ts +186 -3766
  2. package/dist/isaacscript-common.lua +1055 -973
  3. package/dist/src/classes/ModFeature.d.ts +2 -2
  4. package/dist/src/classes/ModFeature.d.ts.map +1 -1
  5. package/dist/src/classes/{ModUpgradedBase.d.ts → ModUpgraded.d.ts} +20 -32
  6. package/dist/src/classes/ModUpgraded.d.ts.map +1 -0
  7. package/dist/src/classes/{ModUpgradedBase.lua → ModUpgraded.lua} +30 -29
  8. package/dist/src/classes/features/other/DebugDisplay.lua +2 -2
  9. package/dist/src/classes/features/other/ExtraConsoleCommands.lua +2 -2
  10. package/dist/src/classes/features/other/extraConsoleCommands/commands.d.ts.map +1 -1
  11. package/dist/src/classes/features/other/extraConsoleCommands/commands.lua +2 -1
  12. package/dist/src/classes/private/CustomCallback.d.ts +3 -1
  13. package/dist/src/classes/private/CustomCallback.d.ts.map +1 -1
  14. package/dist/src/classes/private/CustomCallback.lua +12 -4
  15. package/dist/src/core/upgradeMod.d.ts +0 -42
  16. package/dist/src/core/upgradeMod.d.ts.map +1 -1
  17. package/dist/src/core/upgradeMod.lua +46 -21
  18. package/dist/src/features.lua +2 -2
  19. package/dist/src/functions/console.d.ts +8 -0
  20. package/dist/src/functions/console.d.ts.map +1 -0
  21. package/dist/src/functions/console.lua +14 -0
  22. package/dist/src/functions/deepCopy.d.ts.map +1 -1
  23. package/dist/src/functions/deepCopy.lua +3 -2
  24. package/dist/src/functions/enums.d.ts +28 -0
  25. package/dist/src/functions/enums.d.ts.map +1 -1
  26. package/dist/src/functions/enums.lua +27 -0
  27. package/dist/src/functions/globals.lua +3 -3
  28. package/dist/src/functions/log.d.ts +5 -0
  29. package/dist/src/functions/log.d.ts.map +1 -1
  30. package/dist/src/functions/log.lua +6 -0
  31. package/dist/src/functions/mergeTests.lua +2 -2
  32. package/dist/src/functions/modFeatures.d.ts +1 -1
  33. package/dist/src/functions/modFeatures.d.ts.map +1 -1
  34. package/dist/src/functions/sort.d.ts +38 -0
  35. package/dist/src/functions/sort.d.ts.map +1 -0
  36. package/dist/src/functions/sort.lua +95 -0
  37. package/dist/src/functions/utils.d.ts +0 -54
  38. package/dist/src/functions/utils.d.ts.map +1 -1
  39. package/dist/src/functions/utils.lua +0 -91
  40. package/dist/src/index.d.ts +3 -2
  41. package/dist/src/index.d.ts.map +1 -1
  42. package/dist/src/index.lua +17 -1
  43. package/dist/src/interfaces/private/AddCallbackParametersCustom.lua +2 -2
  44. package/dist/src/interfaces/private/ModUpgradedInterface.d.ts +4 -2
  45. package/dist/src/interfaces/private/ModUpgradedInterface.d.ts.map +1 -1
  46. package/dist/src/types/{ModUpgraded.d.ts → private/ModUpgradedWithFeatures.d.ts} +13 -9
  47. package/dist/src/types/private/ModUpgradedWithFeatures.d.ts.map +1 -0
  48. package/dist/src/types/{ModUpgraded.lua → private/ModUpgradedWithFeatures.lua} +0 -0
  49. package/package.json +1 -1
  50. package/src/classes/ModFeature.ts +5 -5
  51. package/src/classes/{ModUpgradedBase.ts → ModUpgraded.ts} +33 -37
  52. package/src/classes/features/other/DebugDisplay.ts +1 -1
  53. package/src/classes/features/other/ExtraConsoleCommands.ts +1 -1
  54. package/src/classes/features/other/extraConsoleCommands/commands.ts +2 -1
  55. package/src/classes/private/CustomCallback.ts +17 -7
  56. package/src/core/upgradeMod.ts +55 -29
  57. package/src/features.ts +1 -1
  58. package/src/functions/console.ts +15 -0
  59. package/src/functions/deepCopy.ts +3 -2
  60. package/src/functions/enums.ts +33 -0
  61. package/src/functions/globals.ts +2 -2
  62. package/src/functions/log.ts +9 -0
  63. package/src/functions/mergeTests.ts +1 -1
  64. package/src/functions/modFeatures.ts +1 -1
  65. package/src/functions/sort.ts +128 -0
  66. package/src/functions/utils.ts +0 -124
  67. package/src/index.ts +3 -2
  68. package/src/interfaces/private/AddCallbackParametersCustom.ts +1 -1
  69. package/src/interfaces/private/ModUpgradedInterface.ts +4 -2
  70. package/src/types/{ModUpgraded.ts → private/ModUpgradedWithFeatures.ts} +13 -9
  71. package/dist/src/classes/ModUpgradedBase.d.ts.map +0 -1
  72. package/dist/src/types/ModUpgraded.d.ts.map +0 -1
@@ -1,10 +1,10 @@
1
- import { ModUpgradedBase } from "../classes/ModUpgradedBase";
2
- import { Feature } from "../classes/private/Feature";
3
- import { ISCFeature } from "../enums/ISCFeature";
4
- import { ISCFeatureToClass } from "../features";
5
- import { PublicInterface } from "./PublicInterface";
6
- import { TupleToIntersection } from "./TupleToIntersection";
7
- import { Writeable } from "./Writable";
1
+ import { ModUpgraded } from "../../classes/ModUpgraded";
2
+ import { Feature } from "../../classes/private/Feature";
3
+ import { ISCFeature } from "../../enums/ISCFeature";
4
+ import { ISCFeatureToClass } from "../../features";
5
+ import { PublicInterface } from "../PublicInterface";
6
+ import { TupleToIntersection } from "../TupleToIntersection";
7
+ import { Writeable } from "../Writable";
8
8
  /**
9
9
  * `isaacscript-common` has many custom callbacks that you can use in your mods. Instead of
10
10
  * hijacking the vanilla `Mod` object, we provide a `ModUpgraded` object for you to use, which
@@ -14,8 +14,12 @@ import { Writeable } from "./Writable";
14
14
  *
15
15
  * By specifying one or more optional features, end-users will get a version of `ModUpgraded` that
16
16
  * has extra methods corresponding to the features that were specified.
17
+ *
18
+ * This type is in the private directory because if it was exported, it would cause all of the
19
+ * internal feature classes to populate the auto-complete of end-user mods (which should never be
20
+ * directly imported by end-users).
17
21
  */
18
- export type ModUpgraded<T extends readonly ISCFeature[] = []> = ModUpgradedBase & ISCFeaturesToKeys<T>;
22
+ export type ModUpgradedWithFeatures<T extends readonly ISCFeature[] = []> = ModUpgraded & ISCFeaturesToKeys<T>;
19
23
  /**
20
24
  * We want to only extract the class public methods, so we omit the keys of the `Feature` base
21
25
  * class.
@@ -29,4 +33,4 @@ type ISCFeatureTupleToClassTuple<T extends ISCFeature[]> = {
29
33
  [Key in keyof T]: PublicInterface<ISCFeatureToClass[T[Key]]>;
30
34
  };
31
35
  export {};
32
- //# sourceMappingURL=ModUpgraded.d.ts.map
36
+ //# sourceMappingURL=ModUpgradedWithFeatures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModUpgradedWithFeatures.d.ts","sourceRoot":"","sources":["../../../../src/types/private/ModUpgradedWithFeatures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,SAAS,UAAU,EAAE,GAAG,EAAE,IACtE,WAAW,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAErC;;;GAGG;AACH,KAAK,iBAAiB,CAAC,CAAC,SAAS,SAAS,UAAU,EAAE,IAAI,IAAI,CAC5D,mBAAmB,CAAC,2BAA2B,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAC9D,MAAM,OAAO,CACd,CAAC;AAEF;;;GAGG;AACH,KAAK,2BAA2B,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI;KACxD,GAAG,IAAI,MAAM,CAAC,GAAG,eAAe,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "21.4.0",
3
+ "version": "21.5.0",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -8,7 +8,7 @@ import {
8
8
  import { isFunction, isNumber, isTable } from "../functions/types";
9
9
  import { TSTLClassMetatable } from "../interfaces/TSTLClassMetatable";
10
10
  import { AnyFunction } from "../types/AnyFunction";
11
- import { ModUpgradedBase } from "./ModUpgradedBase";
11
+ import { ModUpgraded } from "./ModUpgraded";
12
12
 
13
13
  export const MOD_FEATURE_CALLBACKS_KEY = "__callbacks";
14
14
  export const MOD_FEATURE_CUSTOM_CALLBACKS_KEY = "__customCallbacks";
@@ -62,7 +62,7 @@ type ModFeatureConstructor = TSTLClassMetatable["constructor"] & {
62
62
  */
63
63
 
64
64
  export class ModFeature {
65
- private mod: ModUpgradedBase;
65
+ private mod: ModUpgraded;
66
66
 
67
67
  /**
68
68
  * An optional method that allows for conditional callback execution. If specified, any class
@@ -105,7 +105,7 @@ export class ModFeature {
105
105
  */
106
106
  public initialized = false;
107
107
 
108
- constructor(mod: ModUpgradedBase, init = true) {
108
+ constructor(mod: ModUpgraded, init = true) {
109
109
  this.mod = mod;
110
110
 
111
111
  if (init) {
@@ -234,7 +234,7 @@ function initDecoratedCallbacks(
234
234
  function addCallback(
235
235
  modFeature: ModFeature,
236
236
  modFeatureConstructor: ModFeatureConstructor,
237
- mod: ModUpgradedBase,
237
+ mod: ModUpgraded,
238
238
  modCallback: ModCallback | ModCallbackCustom,
239
239
  callback: Function, // eslint-disable-line @typescript-eslint/ban-types
240
240
  parameters: unknown[],
@@ -297,7 +297,7 @@ function addCallback(
297
297
 
298
298
  function removeCallback(
299
299
  modFeatureConstructor: ModFeatureConstructor,
300
- mod: ModUpgradedBase,
300
+ mod: ModUpgraded,
301
301
  modCallback: ModCallback | ModCallbackCustom,
302
302
  vanilla: boolean,
303
303
  ) {
@@ -24,10 +24,11 @@ import { Feature } from "./private/Feature";
24
24
  *
25
25
  * To upgrade your mod, use the `upgradeMod` helper function.
26
26
  *
27
- * `ModUpgradedBase` provides the core functionality of the `ModUpgraded` class. (It does not
28
- * include the methods for the individual ISC features.)
27
+ * By specifying one or more optional features when upgrading your mod, you will get a version of
28
+ * `ModUpgraded` that has extra methods corresponding to the features that were specified. (This
29
+ * corresponds to the internal-type `ModUpgradedWithFeatures` type, which extends `ModUpgraded`.)
29
30
  */
30
- export class ModUpgradedBase implements Mod {
31
+ export class ModUpgraded implements Mod {
31
32
  // -----------------
32
33
  // Vanilla variables
33
34
  // -----------------
@@ -69,11 +70,6 @@ export class ModUpgradedBase implements Mod {
69
70
  // Vanilla methods
70
71
  // ---------------
71
72
 
72
- /**
73
- * Registers a function to be executed when an in-game event happens. For example, the
74
- * `ModCallback.POST_UPDATE` event corresponds to being executed once at the end of every game
75
- * logic frame.
76
- */
77
73
  public AddCallback<T extends ModCallback | string>(
78
74
  modCallback: T,
79
75
  ...args: T extends ModCallback ? AddCallbackParameters[T] : unknown[]
@@ -141,25 +137,14 @@ export class ModUpgradedBase implements Mod {
141
137
  }
142
138
  }
143
139
 
144
- /** Returns whether or not a corresponding "save#.dat" file exists for the current mod. */
145
140
  public HasData(): boolean {
146
141
  return this.mod.HasData();
147
142
  }
148
143
 
149
- /**
150
- * Returns a string containing all of the data inside of the corresponding "save#.dat" file for
151
- * this mod.
152
- */
153
144
  public LoadData(): string {
154
145
  return this.mod.LoadData();
155
146
  }
156
147
 
157
- /**
158
- * Unregisters a function that was previously registered with the `AddCallback` method.
159
- *
160
- * This method does not care about the tertiary argument. In other words, regardless of the
161
- * conditions of how you registered the callback, it will be removed.
162
- */
163
148
  public RemoveCallback<T extends ModCallback>(
164
149
  modCallback: T,
165
150
  callback: AddCallbackParameters[T][0],
@@ -167,14 +152,10 @@ export class ModUpgradedBase implements Mod {
167
152
  this.mod.RemoveCallback(modCallback, callback);
168
153
  }
169
154
 
170
- /** Deletes the corresponding "save#.dat" file for this mod, if it exists. */
171
155
  public RemoveData(): void {
172
156
  this.mod.RemoveData();
173
157
  }
174
158
 
175
- /**
176
- * Creates or updates the corresponding "save#.dat" file for this mod with the provided string.
177
- */
178
159
  public SaveData(data: string): void {
179
160
  this.mod.SaveData(data);
180
161
  }
@@ -184,23 +165,46 @@ export class ModUpgradedBase implements Mod {
184
165
  // ---------------------
185
166
 
186
167
  /**
187
- * Registers a function to be executed when an in-game event happens. This method is specifically
188
- * for events that are provided by the IsaacScript standard library. For example, the
189
- * `ModCallbackCustom.POST_BOMB_EXPLODE` event corresponds to when a bomb explodes.
168
+ * Registers a function to be executed when an in-game event happens.
169
+ *
170
+ * This method is specifically for events that are provided by the IsaacScript standard library.
171
+ * For example, the `ModCallbackCustom.POST_BOMB_EXPLODE` event corresponds to when a bomb
172
+ * explodes.
190
173
  */
191
174
  public AddCallbackCustom<T extends ModCallbackCustom>(
192
175
  modCallbackCustom: T,
193
176
  ...args: AddCallbackParametersCustom[T]
177
+ ): void {
178
+ this.AddPriorityCallbackCustom(
179
+ modCallbackCustom,
180
+ CallbackPriority.DEFAULT,
181
+ ...args,
182
+ );
183
+ }
184
+
185
+ /**
186
+ * The same as the `ModUpgraded.AddCallbackCustom` method, but allows setting a custom priority.
187
+ * By default, callbacks are added with a priority of 0, so this allows you to add early or late
188
+ * callbacks as necessary. See the `CallbackPriority` enum.
189
+ */
190
+ public AddPriorityCallbackCustom<T extends ModCallbackCustom>(
191
+ modCallbackCustom: T,
192
+ priority: CallbackPriority | int,
193
+ ...args: AddCallbackParametersCustom[T]
194
194
  ): void {
195
195
  const callbackClass = this.callbacks[modCallbackCustom];
196
196
  // @ts-expect-error The compiler is not smart enough to figure out that the parameters match.
197
- callbackClass.addSubscriber(...args);
197
+ callbackClass.addSubscriber(priority, ...args);
198
198
  this.initFeature(callbackClass);
199
199
  }
200
200
 
201
201
  /**
202
202
  * Unregisters a function that was previously registered with the `AddCallbackCustom` method.
203
203
  *
204
+ * This method is specifically for events that are provided by the IsaacScript standard library.
205
+ * For example, the `ModCallbackCustom.POST_BOMB_EXPLODE` event corresponds to when a bomb
206
+ * explodes.
207
+ *
204
208
  * This method does not care about the tertiary argument. In other words, regardless of the
205
209
  * conditions of how you registered the callback, it will be removed.
206
210
  */
@@ -294,8 +298,9 @@ export class ModUpgradedBase implements Mod {
294
298
  for (const callbackTuple of feature.callbacksUsed) {
295
299
  const [modCallback, callbackFunc, optionalArgs] = callbackTuple;
296
300
  // TypeScript is not smart enough to know that the arguments match the function.
297
- (this.AddCallback as AnyFunction)(
301
+ (this.AddPriorityCallback as AnyFunction)(
298
302
  modCallback,
303
+ CallbackPriority.IMPORTANT,
299
304
  callbackFunc,
300
305
  ...(optionalArgs ?? []),
301
306
  );
@@ -398,15 +403,6 @@ export class ModUpgradedBase implements Mod {
398
403
 
399
404
  return getExportedMethodsFromFeature(featureClass);
400
405
  }
401
-
402
- /**
403
- * This is mostly the same as the `AddCustomCallback` method, but we initialize the custom
404
- * callback without actually registering a subscription.
405
- */
406
- private initCustomCallbackEarly(modCallbackCustom: ModCallbackCustom) {
407
- const callbackClass = this.callbacks[modCallbackCustom];
408
- this.initFeature(callbackClass);
409
- }
410
406
  }
411
407
 
412
408
  /**
@@ -1,5 +1,5 @@
1
1
  import { Exported } from "../../../decorators";
2
- import { printEnabled } from "../../../functions/utils";
2
+ import { printEnabled } from "../../../functions/console";
3
3
  import { ModUpgradedInterface } from "../../../interfaces/private/ModUpgradedInterface";
4
4
  import { Feature } from "../../private/Feature";
5
5
  import { DebugDisplayBomb } from "./debugDisplay/DebugDisplayBomb";
@@ -8,9 +8,9 @@ import {
8
8
  } from "isaac-typescript-definitions";
9
9
  import { Exported } from "../../../decorators";
10
10
  import { ModCallbackCustom } from "../../../enums/ModCallbackCustom";
11
+ import { isVanillaConsoleCommand } from "../../../functions/console";
11
12
  import { addFlag, bitFlags } from "../../../functions/flag";
12
13
  import { getMapPartialMatch } from "../../../functions/map";
13
- import { isVanillaConsoleCommand } from "../../../functions/utils";
14
14
  import { Feature } from "../../private/Feature";
15
15
  import * as commands from "./extraConsoleCommands/commands";
16
16
  import { v } from "./extraConsoleCommands/v";
@@ -75,6 +75,7 @@ import { getCardName } from "../../../../functions/cards";
75
75
  import { getCharacterName } from "../../../../functions/characters";
76
76
  import { addCharge, getTotalCharge } from "../../../../functions/charge";
77
77
  import { isValidCollectibleType } from "../../../../functions/collectibles";
78
+ import { printEnabled } from "../../../../functions/console";
78
79
  import { runDeepCopyTests } from "../../../../functions/deepCopyTests";
79
80
  import { getNPCs } from "../../../../functions/entitiesSpecific";
80
81
  import { addFlag } from "../../../../functions/flag";
@@ -114,7 +115,7 @@ import {
114
115
  asCollectibleType,
115
116
  asTrinketType,
116
117
  } from "../../../../functions/types";
117
- import { iRange, printEnabled } from "../../../../functions/utils";
118
+ import { iRange } from "../../../../functions/utils";
118
119
  import { CARD_NAME_TO_TYPE_MAP } from "../../../../maps/cardNameToTypeMap";
119
120
  import { CHARACTER_NAME_TO_TYPE_MAP } from "../../../../maps/characterNameToTypeMap";
120
121
  import { COLLECTIBLE_NAME_TO_TYPE_MAP } from "../../../../maps/collectibleNameToTypeMap";
@@ -1,4 +1,6 @@
1
+ import { CallbackPriority } from "isaac-typescript-definitions/dist/src/enums/CallbackPriority";
1
2
  import { ModCallbackCustom } from "../../enums/ModCallbackCustom";
3
+ import { sortObjectArrayByKey } from "../../functions/sort";
2
4
  import { AddCallbackParametersCustom } from "../../interfaces/private/AddCallbackParametersCustom";
3
5
  import { AllButFirst } from "../../types/AllButFirst";
4
6
  import { AnyFunction } from "../../types/AnyFunction";
@@ -7,14 +9,16 @@ import { Feature } from "./Feature";
7
9
  export type FireArgs<T extends ModCallbackCustom> = Parameters<
8
10
  AddCallbackParametersCustom[T][0]
9
11
  >;
12
+
10
13
  export type OptionalArgs<T extends ModCallbackCustom> = AllButFirst<
11
14
  AddCallbackParametersCustom[T]
12
15
  >;
13
16
 
14
- type Subscription<T extends ModCallbackCustom> = [
15
- callbackFunc: AddCallbackParametersCustom[T][0],
16
- optionalArgs: AllButFirst<AddCallbackParametersCustom[T]>,
17
- ];
17
+ interface Subscription<T extends ModCallbackCustom> {
18
+ priority: CallbackPriority | int;
19
+ callbackFunc: AddCallbackParametersCustom[T][0];
20
+ optionalArgs: AllButFirst<AddCallbackParametersCustom[T]>;
21
+ }
18
22
 
19
23
  /**
20
24
  * The base class for a custom callback. Individual custom callbacks (and validation callbacks) will
@@ -26,11 +30,17 @@ export abstract class CustomCallback<
26
30
  private subscriptions: Array<Subscription<T>> = [];
27
31
 
28
32
  public addSubscriber(
33
+ priority: CallbackPriority | int,
29
34
  callbackFunc: AddCallbackParametersCustom[T][0],
30
35
  ...optionalArgs: AllButFirst<AddCallbackParametersCustom[T]>
31
36
  ): void {
32
- const subscription: Subscription<T> = [callbackFunc, optionalArgs];
37
+ const subscription: Subscription<T> = {
38
+ priority,
39
+ callbackFunc,
40
+ optionalArgs,
41
+ };
33
42
  this.subscriptions.push(subscription);
43
+ this.subscriptions.sort(sortObjectArrayByKey("priority"));
34
44
  }
35
45
 
36
46
  /**
@@ -40,7 +50,7 @@ export abstract class CustomCallback<
40
50
  public removeSubscriber(callback: AddCallbackParametersCustom[T][0]): void {
41
51
  const subscriptionIndexMatchingCallback = this.subscriptions.findIndex(
42
52
  (subscription) => {
43
- const subscriptionCallback = subscription[0];
53
+ const subscriptionCallback = subscription.callbackFunc;
44
54
  return callback === subscriptionCallback;
45
55
  },
46
56
  );
@@ -53,7 +63,7 @@ export abstract class CustomCallback<
53
63
  ...fireArgs: FireArgs<T>
54
64
  ): ReturnType<AddCallbackParametersCustom[T][0]> => {
55
65
  for (const subscription of this.subscriptions) {
56
- const [callbackFunc, optionalArgs] = subscription;
66
+ const { callbackFunc, optionalArgs } = subscription;
57
67
 
58
68
  if (this.shouldFire(fireArgs, optionalArgs)) {
59
69
  // TypeScript is not smart enough to know that the arguments match the function.
@@ -1,10 +1,9 @@
1
- import { ModUpgradedBase } from "../classes/ModUpgradedBase";
1
+ import { ModUpgraded } from "../classes/ModUpgraded";
2
2
  import { ISCFeature } from "../enums/ISCFeature";
3
- import { ModCallbackCustom } from "../enums/ModCallbackCustom";
4
3
  import { patchErrorFunction } from "../patchErrorFunctions";
5
4
  import { applyShaderCrashFix } from "../shaderCrashFix";
6
5
  import { AnyFunction } from "../types/AnyFunction";
7
- import { ModUpgraded } from "../types/ModUpgraded";
6
+ import { ModUpgradedWithFeatures } from "../types/private/ModUpgradedWithFeatures";
8
7
 
9
8
  type ISCFeatureTuple<T extends readonly ISCFeature[]> =
10
9
  ISCFeature extends T["length"]
@@ -31,28 +30,68 @@ type ISCFeatureTuple<T extends readonly ISCFeature[]> =
31
30
  * @param modVanilla The mod object returned by the `RegisterMod` function.
32
31
  * @param features Optional. An array containing the optional standard library features that you
33
32
  * want to enable, if any. Default is an empty array.
34
- * @param customCallbacksUsed Optional. An array containing the custom callbacks that you will be
35
- * subscribing to after you upgrade your mod. Specifying this will
36
- * immediately initialize the callbacks (as opposed to lazy-initializing
37
- * them when you first subscribe to the callback). This is only necessary
38
- * if you the order of callback firing is important for your mod. (For
39
- * example, you may want the `POST_NEW_ROOM` part of the
40
- * `POST_GRID_ENTITY_INIT` callback to fire before your own
41
- * `POST_NEW_ROOM` callbacks.)
42
33
  * @param debug Optional. Whether to log additional output when a callback is fired. Default is
43
34
  * false.
44
35
  * @param timeThreshold Optional. If provided, will only log callbacks that take longer than the
45
36
  * specified number of seconds (if the "--luadebug" launch flag is turned on)
46
37
  * or milliseconds (if the "--luadebug" launch flag is turned off).
47
38
  * @returns The upgraded mod object.
39
+ * @notExported
40
+ * @rename upgradeMod
48
41
  */
42
+ // We duplicate the definition for `upgradeMod` because the original one has to be marked internal.
43
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
44
+ function upgradeModDocumentation(
45
+ modVanilla: Mod,
46
+ features: ISCFeature[] = [],
47
+ debug = false,
48
+ timeThreshold?: float,
49
+ ): ModUpgraded {
50
+ print(modVanilla);
51
+ print(features);
52
+ print(debug);
53
+ print(timeThreshold);
54
+
55
+ const mod = RegisterMod("", 1);
56
+ return new ModUpgraded(mod, false);
57
+ }
58
+
59
+ /**
60
+ * Use this function to enable the custom callbacks and other optional features provided by
61
+ * `isaacscript-common`.
62
+ *
63
+ * For example:
64
+ *
65
+ * ```ts
66
+ * const modVanilla = RegisterMod("My Mod", 1);
67
+ * const mod = upgradeMod(modVanilla);
68
+ *
69
+ * // Subscribe to vanilla callbacks.
70
+ * mod.AddCallback(ModCallback.POST_UPDATE, postUpdate);
71
+ *
72
+ * // Subscribe to custom callbacks.
73
+ * mod.AddCallbackCustom(ModCallbackCustom.POST_ITEM_PICKUP, postItemPickup);
74
+ * ```
75
+ *
76
+ * @param modVanilla The mod object returned by the `RegisterMod` function.
77
+ * @param features Optional. An array containing the optional standard library features that you
78
+ * want to enable, if any. Default is an empty array.
79
+ * @param debug Optional. Whether to log additional output when a callback is fired. Default is
80
+ * false.
81
+ * @param timeThreshold Optional. If provided, will only log callbacks that take longer than the
82
+ * specified number of seconds (if the "--luadebug" launch flag is turned on)
83
+ * or milliseconds (if the "--luadebug" launch flag is turned off).
84
+ * @returns The upgraded mod object.
85
+ * @internal
86
+ */
87
+ // This has to be marked internal or else it will cause all of the feature classes to be included in
88
+ // the output of `api-extractor`.
49
89
  export function upgradeMod<T extends readonly ISCFeature[] = never[]>(
50
90
  modVanilla: Mod,
51
91
  features: ISCFeatureTuple<T> = [] as unknown as ISCFeatureTuple<T>,
52
- customCallbacksUsed: ModCallbackCustom[] | readonly ModCallbackCustom[] = [],
53
92
  debug = false,
54
93
  timeThreshold?: float,
55
- ): ModUpgraded<T> {
94
+ ): ModUpgradedWithFeatures<T> {
56
95
  // First, validate that all of the features exist (for Lua users who don't have type-safety).
57
96
  for (const feature of features) {
58
97
  const featureType = type(feature);
@@ -65,16 +104,15 @@ export function upgradeMod<T extends readonly ISCFeature[] = never[]>(
65
104
 
66
105
  patchErrorFunction();
67
106
 
68
- const mod = new ModUpgradedBase(modVanilla, debug, timeThreshold);
107
+ const mod = new ModUpgraded(modVanilla, debug, timeThreshold);
69
108
  applyShaderCrashFix(mod);
70
109
  initOptionalFeatures(mod, features as ISCFeature[]);
71
- initCallbacksEarly(mod, customCallbacksUsed);
72
110
 
73
- return mod as ModUpgraded<T>;
111
+ return mod as ModUpgradedWithFeatures<T>;
74
112
  }
75
113
 
76
114
  /** Initialize every optional feature that the end-user specified. */
77
- function initOptionalFeatures(mod: ModUpgradedBase, features: ISCFeature[]) {
115
+ function initOptionalFeatures(mod: ModUpgraded, features: ISCFeature[]) {
78
116
  for (const feature of features) {
79
117
  // We intentionally access the private method here, so we use the string index escape hatch:
80
118
  // https://github.com/microsoft/TypeScript/issues/19335
@@ -89,15 +127,3 @@ function initOptionalFeatures(mod: ModUpgradedBase, features: ISCFeature[]) {
89
127
  }
90
128
  }
91
129
  }
92
-
93
- function initCallbacksEarly(
94
- mod: ModUpgradedBase,
95
- callbacks: ModCallbackCustom[] | readonly ModCallbackCustom[],
96
- ) {
97
- for (const modCallbackCustom of callbacks) {
98
- // We intentionally access the private method here, so we use the string index escape hatch:
99
- // https://github.com/microsoft/TypeScript/issues/19335
100
- // eslint-disable-next-line @typescript-eslint/dot-notation
101
- mod["initCustomCallbackEarly"](modCallbackCustom);
102
- }
103
- }
package/src/features.ts CHANGED
@@ -56,7 +56,7 @@ import { TaintedLazarusPlayers } from "./classes/features/other/TaintedLazarusPl
56
56
  import { Feature } from "./classes/private/Feature";
57
57
  import { ISCFeature } from "./enums/ISCFeature";
58
58
  import { ModCallbackCustom } from "./enums/ModCallbackCustom";
59
- import { validateInterfaceMatchesEnum } from "./functions/utils";
59
+ import { validateInterfaceMatchesEnum } from "./functions/enums";
60
60
  import { ModUpgradedInterface } from "./interfaces/private/ModUpgradedInterface";
61
61
 
62
62
  export interface ISCFeatureToClass {
@@ -0,0 +1,15 @@
1
+ import { CONSOLE_COMMANDS_SET } from "../sets/consoleCommandsSet";
2
+
3
+ /**
4
+ * Helper function to see if a particular command is a vanilla console command. This is useful
5
+ * because the `EXECUTE_CMD` callback will not fire for any vanilla commands.
6
+ */
7
+ export function isVanillaConsoleCommand(commandName: string): boolean {
8
+ return CONSOLE_COMMANDS_SET.has(commandName);
9
+ }
10
+
11
+ /** Helper function to print whether something was enabled or disabled to the in-game console. */
12
+ export function printEnabled(enabled: boolean, description: string): void {
13
+ const enabledText = enabled ? "Enabled" : "Disabled";
14
+ print(`${enabledText} ${description}.`);
15
+ }
@@ -15,6 +15,7 @@ import {
15
15
  isSerializedIsaacAPIClass,
16
16
  serializeIsaacAPIClass,
17
17
  } from "./serialization";
18
+ import { sortTwoDimensionalArray } from "./sort";
18
19
  import {
19
20
  getTSTLClassName,
20
21
  isDefaultMap,
@@ -23,7 +24,7 @@ import {
23
24
  newTSTLClass,
24
25
  } from "./tstlClass";
25
26
  import { asString, isNumber, isPrimitive } from "./types";
26
- import { getTraversalDescription, twoDimensionalSort } from "./utils";
27
+ import { getTraversalDescription } from "./utils";
27
28
 
28
29
  /**
29
30
  * `deepCopy` is a semi-generic deep cloner. It will recursively copy all of the values so that none
@@ -642,7 +643,7 @@ function getCopiedEntries(
642
643
  }
643
644
 
644
645
  if (SAVE_DATA_MANAGER_DEBUG) {
645
- entries.sort(twoDimensionalSort);
646
+ entries.sort(sortTwoDimensionalArray);
646
647
  }
647
648
 
648
649
  // During serialization, we brand some Lua tables with a special identifier to signify that it has
@@ -186,3 +186,36 @@ export function validateEnumContiguous<T>(
186
186
  }
187
187
  }
188
188
  }
189
+
190
+ /**
191
+ * Helper function to validate that an interface contains all of the keys of an enum. You must
192
+ * specify both generic parameters in order for this to work properly (i.e. the interface and then
193
+ * the enum).
194
+ *
195
+ * For example:
196
+ *
197
+ * ```ts
198
+ * enum MyEnum {
199
+ * Value1,
200
+ * Value2,
201
+ * Value3,
202
+ * }
203
+ *
204
+ * interface MyEnumToType {
205
+ * [MyEnum.Value1]: boolean;
206
+ * [MyEnum.Value2]: number;
207
+ * [MyEnum.Value3]: string;
208
+ * }
209
+ *
210
+ * validateInterfaceMatchesEnum<MyEnumToType, MyEnum>();
211
+ * ```
212
+ *
213
+ * This function is only meant to be used with interfaces (i.e. types that will not exist at
214
+ * run-time). If you are generating an object that will contain all of the keys of an enum, use the
215
+ * `satisfies` operator with the `Record` type instead.
216
+ */
217
+ export function validateInterfaceMatchesEnum<
218
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
219
+ T extends Record<Enum, unknown>,
220
+ Enum extends string | number,
221
+ >(): void {}
@@ -5,7 +5,7 @@ import { log } from "./log";
5
5
  import * as logEntitiesExports from "./logEntities";
6
6
  import * as logMiscExports from "./logMisc";
7
7
  import { addSetsToSet, copySet } from "./set";
8
- import { twoDimensionalSort } from "./utils";
8
+ import { sortTwoDimensionalArray } from "./sort";
9
9
 
10
10
  const DEFAULT_GLOBALS = new ReadonlySet<string>([
11
11
  "ActionTriggers",
@@ -226,7 +226,7 @@ export function getNewGlobals(): ReadonlyArray<[AnyNotNil, unknown]> {
226
226
  }
227
227
  }
228
228
 
229
- newGlobals.sort(twoDimensionalSort);
229
+ newGlobals.sort(sortTwoDimensionalArray);
230
230
 
231
231
  return newGlobals;
232
232
  }
@@ -65,3 +65,12 @@ export function log(
65
65
  : `${parentFunctionDescription} - ${msg}`;
66
66
  Isaac.DebugString(debugMsg);
67
67
  }
68
+
69
+ /**
70
+ * Helper function to log a message to the "log.txt" file and to print it to the screen at the same
71
+ * time.
72
+ */
73
+ export function logAndPrint(msg: string): void {
74
+ log(msg);
75
+ print(msg);
76
+ }
@@ -1,10 +1,10 @@
1
1
  import { DefaultMap } from "../classes/DefaultMap";
2
2
  import { SerializationType } from "../enums/SerializationType";
3
3
  import { deepCopy } from "./deepCopy";
4
+ import { logAndPrint } from "./log";
4
5
  import { merge } from "./merge";
5
6
  import { isRNG, newRNG } from "./rng";
6
7
  import { isSerializedIsaacAPIClass } from "./serialization";
7
- import { logAndPrint } from "./utils";
8
8
  import { isVector, serializeVector } from "./vector";
9
9
 
10
10
  /**
@@ -1,5 +1,5 @@
1
1
  import { ModFeature } from "../classes/ModFeature";
2
- import { ModUpgraded } from "../types/ModUpgraded";
2
+ import { ModUpgraded } from "../classes/ModUpgraded";
3
3
 
4
4
  /**
5
5
  * Helper function to instantiate an array of mod features all at once. Use this function if your