isaacscript-common 15.3.0 → 15.3.2

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.
package/dist/index.d.ts CHANGED
@@ -10690,7 +10690,7 @@ declare class ModdedElementSets extends Feature {
10690
10690
  }
10691
10691
 
10692
10692
  /**
10693
- * Helper class for mods that wants to represent their individual features as classes. Extend your
10693
+ * Helper class for mods that want to represent their individual features as classes. Extend your
10694
10694
  * mod features from this class in order to enable the `@Callback` and `@CustomCallback` decorators
10695
10695
  * that automatically subscribe to callbacks.
10696
10696
  *
@@ -10715,18 +10715,31 @@ declare class ModdedElementSets extends Feature {
10715
10715
  * }
10716
10716
  * ```
10717
10717
  *
10718
+ * When instantiating a feature class, you must pass your upgraded mod as the first argument to the
10719
+ * constructor.
10720
+ *
10718
10721
  * In almost all cases, you will want the callback functions to be immediately subscribed after
10719
10722
  * instantiating the class. However, if this is not the case, you can pass `false` as the optional
10720
10723
  * second argument to the constructor.
10721
10724
  */
10722
10725
  export declare class ModFeature {
10723
10726
  private mod;
10727
+ private initialized;
10724
10728
  constructor(mod: ModUpgradedBase, init?: boolean);
10725
10729
  /**
10726
10730
  * Runs the `Mod.AddCallback` and `ModUpgraded.AddCallbackCustom` methods for all of the decorated
10727
10731
  * callbacks. Additionally, subscribes the `v` object to the save data manager, if present.
10732
+ *
10733
+ * @param init Optional. Whether to initialize or uninitialize. Default is true.
10728
10734
  */
10729
10735
  init(init?: boolean): void;
10736
+ /**
10737
+ * Runs the `Mod.RemoveCallback` and `ModUpgraded.RemoveCallbackCustom` methods for all of the
10738
+ * decorated callbacks. Additionally, unsubscribes the `v` object from the save data manager, if
10739
+ * present.
10740
+ *
10741
+ * This is just an alias for `ModFeature.init(false)`.
10742
+ */
10730
10743
  uninit(): void;
10731
10744
  }
10732
10745
 
@@ -12430,6 +12443,7 @@ export declare function round(num: float, numDecimalPlaces?: number): float;
12430
12443
  export declare function runDeepCopyTests(): void;
12431
12444
 
12432
12445
  declare class RunInNFrames extends Feature {
12446
+ vConditionalFunc: () => boolean;
12433
12447
  private postUpdate;
12434
12448
  private postRender;
12435
12449
  /**
@@ -12667,6 +12681,8 @@ declare class SaveDataManager extends Feature {
12667
12681
  * manage them for you. (See below for an example.)
12668
12682
  *
12669
12683
  * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`.
12684
+ * (Upgrade your mod before registering any of your own callbacks so that the save data manager
12685
+ * will run before any of your code does.)
12670
12686
  *
12671
12687
  * The save data manager is meant to be called once for each feature of your mod. In other words,
12672
12688
  * you should not put all of the data for your mod on the same object. Instead, scope your
@@ -12723,10 +12739,6 @@ declare class SaveDataManager extends Feature {
12723
12739
  * supported. For the specific things that are supported, see the documentation for the `deepCopy`
12724
12740
  * helper function.
12725
12741
  *
12726
- * Note that before using the save data manager, you must call the `upgradeMod` function. (Upgrade
12727
- * your mod before registering any of your own callbacks so that the save data manager will run
12728
- * before any of your code does.)
12729
- *
12730
12742
  * If you want the save data manager to load data before the `POST_PLAYER_INIT` callback (i.e. in
12731
12743
  * the main menu), then you should explicitly call the `saveDataManagerLoad` function. (The save
12732
12744
  * data manager cannot do this on its own because it cannot know when your mod features are
@@ -1,6 +1,6 @@
1
1
  --[[
2
2
 
3
- isaacscript-common 15.3.0
3
+ isaacscript-common 15.3.2
4
4
 
5
5
  This is the "isaacscript-common" library, which was created with the IsaacScript tool.
6
6
 
@@ -30390,6 +30390,7 @@ __TS__ClassExtends(RunInNFrames, Feature)
30390
30390
  function RunInNFrames.prototype.____constructor(self)
30391
30391
  Feature.prototype.____constructor(self)
30392
30392
  self.v = {run = {queuedGameFunctionTuples = {}, queuedRenderFunctionTuples = {}, intervalGameFunctionTuples = {}, intervalRenderFunctionTuples = {}}}
30393
+ self.vConditionalFunc = function() return false end
30393
30394
  self.postUpdate = function()
30394
30395
  local gameFrameCount = game:GetFrameCount()
30395
30396
  checkExecuteQueuedFunctions(nil, gameFrameCount, self.v.run.queuedGameFunctionTuples)
@@ -48341,8 +48342,9 @@ return ____exports
48341
48342
  local ____lualib = require("lualib_bundle")
48342
48343
  local __TS__Class = ____lualib.__TS__Class
48343
48344
  local Map = ____lualib.Map
48345
+ local __TS__New = ____lualib.__TS__New
48344
48346
  local ____exports = {}
48345
- local initDecoratedCallbacks, initSaveDataManager, WRAPPED_CALLBACK_METHODS_KEY, WRAPPED_CUSTOM_CALLBACK_METHODS_KEY
48347
+ local initDecoratedCallbacks, addCallback, removeCallback, initSaveDataManager, WRAPPED_CALLBACK_METHODS_KEY, WRAPPED_CUSTOM_CALLBACK_METHODS_KEY
48346
48348
  local ____array = require("src.functions.array")
48347
48349
  local isArray = ____array.isArray
48348
48350
  local ____deepCopy = require("src.functions.deepCopy")
@@ -48351,6 +48353,8 @@ local ____tstlClass = require("src.functions.tstlClass")
48351
48353
  local getTSTLClassConstructor = ____tstlClass.getTSTLClassConstructor
48352
48354
  local getTSTLClassName = ____tstlClass.getTSTLClassName
48353
48355
  local ____types = require("src.functions.types")
48356
+ local isFunction = ____types.isFunction
48357
+ local isNumber = ____types.isNumber
48354
48358
  local isTable = ____types.isTable
48355
48359
  function initDecoratedCallbacks(self, modFeature, constructor, tstlClassName, vanilla, init)
48356
48360
  local modFeatureConstructor = constructor
@@ -48368,53 +48372,90 @@ function initDecoratedCallbacks(self, modFeature, constructor, tstlClassName, va
48368
48372
  end
48369
48373
  local parameters = deepCopy(nil, args)
48370
48374
  local modCallback = table.remove(parameters, 1)
48371
- if modCallback == nil then
48375
+ if not isNumber(nil, modCallback) then
48372
48376
  error("Failed to get the callback number from the parameters for class: " .. tstlClassName)
48373
48377
  end
48374
48378
  local callback = table.remove(parameters, 1)
48375
- if callback == nil then
48379
+ if not isFunction(nil, callback) then
48376
48380
  error("Failed to get the callback function from the parameters for class: " .. tstlClassName)
48377
48381
  end
48378
48382
  local mod = modFeature.mod
48379
48383
  if init then
48380
- local function wrappedCallback(____, ...)
48381
- callback(modFeature, ...)
48382
- end
48383
- if vanilla then
48384
- local modCallbackVanilla = modCallback
48385
- local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY]
48386
- wrappedMethodsMap:set(modCallbackVanilla, wrappedCallback)
48387
- else
48388
- local modCallbackCustom = modCallback
48389
- local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]
48390
- wrappedMethodsMap:set(modCallbackCustom, wrappedCallback)
48391
- end
48392
- if vanilla then
48393
- mod:AddCallback(
48394
- modCallback,
48395
- wrappedCallback,
48396
- table.unpack(parameters)
48397
- )
48398
- else
48399
- mod:AddCallbackCustom(
48400
- modCallback,
48401
- wrappedCallback,
48402
- table.unpack(parameters)
48403
- )
48404
- end
48405
- elseif vanilla then
48406
- local modCallbackVanilla = modCallback
48407
- local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY]
48408
- local wrappedCallback = wrappedMethodsMap:get(modCallbackVanilla)
48409
- mod:RemoveCallback(modCallback, wrappedCallback)
48384
+ addCallback(
48385
+ nil,
48386
+ modFeature,
48387
+ modFeatureConstructor,
48388
+ mod,
48389
+ modCallback,
48390
+ callback,
48391
+ parameters,
48392
+ vanilla
48393
+ )
48410
48394
  else
48411
- local modCallbackCustom = modCallback
48412
- local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]
48413
- local wrappedCallback = wrappedMethodsMap:get(modCallbackCustom)
48414
- mod:RemoveCallbackCustom(modCallback, wrappedCallback)
48395
+ removeCallback(
48396
+ nil,
48397
+ modFeatureConstructor,
48398
+ mod,
48399
+ modCallback,
48400
+ vanilla
48401
+ )
48415
48402
  end
48416
48403
  end
48417
48404
  end
48405
+ function addCallback(self, modFeature, modFeatureConstructor, mod, modCallback, callback, parameters, vanilla)
48406
+ local function wrappedCallback(____, ...)
48407
+ callback(nil, modFeature, ...)
48408
+ end
48409
+ if vanilla then
48410
+ local modCallbackVanilla = modCallback
48411
+ local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY]
48412
+ if wrappedMethodsMap == nil then
48413
+ wrappedMethodsMap = __TS__New(Map)
48414
+ modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY] = wrappedMethodsMap
48415
+ end
48416
+ wrappedMethodsMap:set(modCallbackVanilla, wrappedCallback)
48417
+ else
48418
+ local modCallbackCustom = modCallback
48419
+ local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]
48420
+ if wrappedMethodsMap == nil then
48421
+ wrappedMethodsMap = __TS__New(Map)
48422
+ modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY] = wrappedMethodsMap
48423
+ end
48424
+ wrappedMethodsMap:set(modCallbackCustom, wrappedCallback)
48425
+ end
48426
+ if vanilla then
48427
+ mod:AddCallback(
48428
+ modCallback,
48429
+ wrappedCallback,
48430
+ table.unpack(parameters)
48431
+ )
48432
+ else
48433
+ mod:AddCallbackCustom(
48434
+ modCallback,
48435
+ wrappedCallback,
48436
+ table.unpack(parameters)
48437
+ )
48438
+ end
48439
+ end
48440
+ function removeCallback(self, modFeatureConstructor, mod, modCallback, vanilla)
48441
+ if vanilla then
48442
+ local modCallbackVanilla = modCallback
48443
+ local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY]
48444
+ if wrappedMethodsMap == nil then
48445
+ return
48446
+ end
48447
+ local wrappedCallback = wrappedMethodsMap:get(modCallbackVanilla)
48448
+ mod:RemoveCallback(modCallback, wrappedCallback)
48449
+ else
48450
+ local modCallbackCustom = modCallback
48451
+ local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]
48452
+ if wrappedMethodsMap == nil then
48453
+ return
48454
+ end
48455
+ local wrappedCallback = wrappedMethodsMap:get(modCallbackCustom)
48456
+ mod:RemoveCallbackCustom(modCallback, wrappedCallback)
48457
+ end
48458
+ end
48418
48459
  function initSaveDataManager(self, modFeature, tstlClassName, init)
48419
48460
  local ____modFeature_0 = modFeature
48420
48461
  local v = ____modFeature_0.v
@@ -48450,6 +48491,7 @@ function ModFeature.prototype.____constructor(self, mod, init)
48450
48491
  if init == nil then
48451
48492
  init = true
48452
48493
  end
48494
+ self.initialized = false
48453
48495
  self.mod = mod
48454
48496
  if init then
48455
48497
  self:init()
@@ -48459,11 +48501,15 @@ function ModFeature.prototype.init(self, init)
48459
48501
  if init == nil then
48460
48502
  init = true
48461
48503
  end
48504
+ if self.initialized == init then
48505
+ return
48506
+ end
48507
+ self.initialized = init
48462
48508
  local constructor = getTSTLClassConstructor(nil, self)
48463
48509
  if constructor == nil then
48464
48510
  error("Failed to get the TSTL class constructor for a mod feature.")
48465
48511
  end
48466
- local tstlClassName = getTSTLClassName(nil, constructor)
48512
+ local tstlClassName = getTSTLClassName(nil, self)
48467
48513
  if tstlClassName == nil then
48468
48514
  error("Failed to get the TSTL class name for a mod feature.")
48469
48515
  end
@@ -2,7 +2,7 @@ import { ModUpgradedBase } from "./ModUpgradedBase";
2
2
  export declare const ADD_CALLBACK_ARGS_KEY = "__addCallbackArgs";
3
3
  export declare const ADD_CALLBACK_CUSTOM_ARGS_KEY = "__addCallbackCustomArgs";
4
4
  /**
5
- * Helper class for mods that wants to represent their individual features as classes. Extend your
5
+ * Helper class for mods that want to represent their individual features as classes. Extend your
6
6
  * mod features from this class in order to enable the `@Callback` and `@CustomCallback` decorators
7
7
  * that automatically subscribe to callbacks.
8
8
  *
@@ -27,18 +27,31 @@ export declare const ADD_CALLBACK_CUSTOM_ARGS_KEY = "__addCallbackCustomArgs";
27
27
  * }
28
28
  * ```
29
29
  *
30
+ * When instantiating a feature class, you must pass your upgraded mod as the first argument to the
31
+ * constructor.
32
+ *
30
33
  * In almost all cases, you will want the callback functions to be immediately subscribed after
31
34
  * instantiating the class. However, if this is not the case, you can pass `false` as the optional
32
35
  * second argument to the constructor.
33
36
  */
34
37
  export declare class ModFeature {
35
38
  private mod;
39
+ private initialized;
36
40
  constructor(mod: ModUpgradedBase, init?: boolean);
37
41
  /**
38
42
  * Runs the `Mod.AddCallback` and `ModUpgraded.AddCallbackCustom` methods for all of the decorated
39
43
  * callbacks. Additionally, subscribes the `v` object to the save data manager, if present.
44
+ *
45
+ * @param init Optional. Whether to initialize or uninitialize. Default is true.
40
46
  */
41
47
  init(init?: boolean): void;
48
+ /**
49
+ * Runs the `Mod.RemoveCallback` and `ModUpgraded.RemoveCallbackCustom` methods for all of the
50
+ * decorated callbacks. Additionally, unsubscribes the `v` object from the save data manager, if
51
+ * present.
52
+ *
53
+ * This is just an alias for `ModFeature.init(false)`.
54
+ */
42
55
  uninit(): void;
43
56
  }
44
57
  //# sourceMappingURL=ModFeature.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ModFeature.d.ts","sourceRoot":"","sources":["../../../src/classes/ModFeature.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AAWtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAkB;gBAEjB,GAAG,EAAE,eAAe,EAAE,IAAI,UAAO;IAQ7C;;;OAGG;IACI,IAAI,CAAC,IAAI,UAAO,GAAG,IAAI;IAgBvB,MAAM,IAAI,IAAI;CAGtB"}
1
+ {"version":3,"file":"ModFeature.d.ts","sourceRoot":"","sources":["../../../src/classes/ModFeature.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AAatE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,WAAW,CAAS;gBAEhB,GAAG,EAAE,eAAe,EAAE,IAAI,UAAO;IAQ7C;;;;;OAKG;IACI,IAAI,CAAC,IAAI,UAAO,GAAG,IAAI;IAqB9B;;;;;;OAMG;IACI,MAAM,IAAI,IAAI;CAGtB"}
@@ -1,8 +1,9 @@
1
1
  local ____lualib = require("lualib_bundle")
2
2
  local __TS__Class = ____lualib.__TS__Class
3
3
  local Map = ____lualib.Map
4
+ local __TS__New = ____lualib.__TS__New
4
5
  local ____exports = {}
5
- local initDecoratedCallbacks, initSaveDataManager, WRAPPED_CALLBACK_METHODS_KEY, WRAPPED_CUSTOM_CALLBACK_METHODS_KEY
6
+ local initDecoratedCallbacks, addCallback, removeCallback, initSaveDataManager, WRAPPED_CALLBACK_METHODS_KEY, WRAPPED_CUSTOM_CALLBACK_METHODS_KEY
6
7
  local ____array = require("src.functions.array")
7
8
  local isArray = ____array.isArray
8
9
  local ____deepCopy = require("src.functions.deepCopy")
@@ -11,6 +12,8 @@ local ____tstlClass = require("src.functions.tstlClass")
11
12
  local getTSTLClassConstructor = ____tstlClass.getTSTLClassConstructor
12
13
  local getTSTLClassName = ____tstlClass.getTSTLClassName
13
14
  local ____types = require("src.functions.types")
15
+ local isFunction = ____types.isFunction
16
+ local isNumber = ____types.isNumber
14
17
  local isTable = ____types.isTable
15
18
  function initDecoratedCallbacks(self, modFeature, constructor, tstlClassName, vanilla, init)
16
19
  local modFeatureConstructor = constructor
@@ -28,53 +31,90 @@ function initDecoratedCallbacks(self, modFeature, constructor, tstlClassName, va
28
31
  end
29
32
  local parameters = deepCopy(nil, args)
30
33
  local modCallback = table.remove(parameters, 1)
31
- if modCallback == nil then
34
+ if not isNumber(nil, modCallback) then
32
35
  error("Failed to get the callback number from the parameters for class: " .. tstlClassName)
33
36
  end
34
37
  local callback = table.remove(parameters, 1)
35
- if callback == nil then
38
+ if not isFunction(nil, callback) then
36
39
  error("Failed to get the callback function from the parameters for class: " .. tstlClassName)
37
40
  end
38
41
  local mod = modFeature.mod
39
42
  if init then
40
- local function wrappedCallback(____, ...)
41
- callback(modFeature, ...)
42
- end
43
- if vanilla then
44
- local modCallbackVanilla = modCallback
45
- local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY]
46
- wrappedMethodsMap:set(modCallbackVanilla, wrappedCallback)
47
- else
48
- local modCallbackCustom = modCallback
49
- local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]
50
- wrappedMethodsMap:set(modCallbackCustom, wrappedCallback)
51
- end
52
- if vanilla then
53
- mod:AddCallback(
54
- modCallback,
55
- wrappedCallback,
56
- table.unpack(parameters)
57
- )
58
- else
59
- mod:AddCallbackCustom(
60
- modCallback,
61
- wrappedCallback,
62
- table.unpack(parameters)
63
- )
64
- end
65
- elseif vanilla then
66
- local modCallbackVanilla = modCallback
67
- local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY]
68
- local wrappedCallback = wrappedMethodsMap:get(modCallbackVanilla)
69
- mod:RemoveCallback(modCallback, wrappedCallback)
43
+ addCallback(
44
+ nil,
45
+ modFeature,
46
+ modFeatureConstructor,
47
+ mod,
48
+ modCallback,
49
+ callback,
50
+ parameters,
51
+ vanilla
52
+ )
70
53
  else
71
- local modCallbackCustom = modCallback
72
- local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]
73
- local wrappedCallback = wrappedMethodsMap:get(modCallbackCustom)
74
- mod:RemoveCallbackCustom(modCallback, wrappedCallback)
54
+ removeCallback(
55
+ nil,
56
+ modFeatureConstructor,
57
+ mod,
58
+ modCallback,
59
+ vanilla
60
+ )
75
61
  end
76
62
  end
77
63
  end
64
+ function addCallback(self, modFeature, modFeatureConstructor, mod, modCallback, callback, parameters, vanilla)
65
+ local function wrappedCallback(____, ...)
66
+ callback(nil, modFeature, ...)
67
+ end
68
+ if vanilla then
69
+ local modCallbackVanilla = modCallback
70
+ local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY]
71
+ if wrappedMethodsMap == nil then
72
+ wrappedMethodsMap = __TS__New(Map)
73
+ modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY] = wrappedMethodsMap
74
+ end
75
+ wrappedMethodsMap:set(modCallbackVanilla, wrappedCallback)
76
+ else
77
+ local modCallbackCustom = modCallback
78
+ local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]
79
+ if wrappedMethodsMap == nil then
80
+ wrappedMethodsMap = __TS__New(Map)
81
+ modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY] = wrappedMethodsMap
82
+ end
83
+ wrappedMethodsMap:set(modCallbackCustom, wrappedCallback)
84
+ end
85
+ if vanilla then
86
+ mod:AddCallback(
87
+ modCallback,
88
+ wrappedCallback,
89
+ table.unpack(parameters)
90
+ )
91
+ else
92
+ mod:AddCallbackCustom(
93
+ modCallback,
94
+ wrappedCallback,
95
+ table.unpack(parameters)
96
+ )
97
+ end
98
+ end
99
+ function removeCallback(self, modFeatureConstructor, mod, modCallback, vanilla)
100
+ if vanilla then
101
+ local modCallbackVanilla = modCallback
102
+ local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY]
103
+ if wrappedMethodsMap == nil then
104
+ return
105
+ end
106
+ local wrappedCallback = wrappedMethodsMap:get(modCallbackVanilla)
107
+ mod:RemoveCallback(modCallback, wrappedCallback)
108
+ else
109
+ local modCallbackCustom = modCallback
110
+ local wrappedMethodsMap = modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]
111
+ if wrappedMethodsMap == nil then
112
+ return
113
+ end
114
+ local wrappedCallback = wrappedMethodsMap:get(modCallbackCustom)
115
+ mod:RemoveCallbackCustom(modCallback, wrappedCallback)
116
+ end
117
+ end
78
118
  function initSaveDataManager(self, modFeature, tstlClassName, init)
79
119
  local ____modFeature_0 = modFeature
80
120
  local v = ____modFeature_0.v
@@ -103,7 +143,7 @@ ____exports.ADD_CALLBACK_ARGS_KEY = "__addCallbackArgs"
103
143
  ____exports.ADD_CALLBACK_CUSTOM_ARGS_KEY = "__addCallbackCustomArgs"
104
144
  WRAPPED_CALLBACK_METHODS_KEY = "__wrappedCallbackMethods"
105
145
  WRAPPED_CUSTOM_CALLBACK_METHODS_KEY = "__wrappedCustomCallbacksMethods"
106
- --- Helper class for mods that wants to represent their individual features as classes. Extend your
146
+ --- Helper class for mods that want to represent their individual features as classes. Extend your
107
147
  -- mod features from this class in order to enable the `@Callback` and `@CustomCallback` decorators
108
148
  -- that automatically subscribe to callbacks.
109
149
  --
@@ -128,6 +168,9 @@ WRAPPED_CUSTOM_CALLBACK_METHODS_KEY = "__wrappedCustomCallbacksMethods"
128
168
  -- }
129
169
  -- ```
130
170
  --
171
+ -- When instantiating a feature class, you must pass your upgraded mod as the first argument to the
172
+ -- constructor.
173
+ --
131
174
  -- In almost all cases, you will want the callback functions to be immediately subscribed after
132
175
  -- instantiating the class. However, if this is not the case, you can pass `false` as the optional
133
176
  -- second argument to the constructor.
@@ -138,6 +181,7 @@ function ModFeature.prototype.____constructor(self, mod, init)
138
181
  if init == nil then
139
182
  init = true
140
183
  end
184
+ self.initialized = false
141
185
  self.mod = mod
142
186
  if init then
143
187
  self:init()
@@ -147,11 +191,15 @@ function ModFeature.prototype.init(self, init)
147
191
  if init == nil then
148
192
  init = true
149
193
  end
194
+ if self.initialized == init then
195
+ return
196
+ end
197
+ self.initialized = init
150
198
  local constructor = getTSTLClassConstructor(nil, self)
151
199
  if constructor == nil then
152
200
  error("Failed to get the TSTL class constructor for a mod feature.")
153
201
  end
154
- local tstlClassName = getTSTLClassName(nil, constructor)
202
+ local tstlClassName = getTSTLClassName(nil, self)
155
203
  if tstlClassName == nil then
156
204
  error("Failed to get the TSTL class name for a mod feature.")
157
205
  end
@@ -1,6 +1,7 @@
1
1
  import { PlayerType } from "isaac-typescript-definitions";
2
2
  import { Feature } from "../../private/Feature";
3
3
  export declare class RunInNFrames extends Feature {
4
+ vConditionalFunc: () => boolean;
4
5
  private postUpdate;
5
6
  private postRender;
6
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"RunInNFrames.d.ts","sourceRoot":"","sources":["../../../../../src/classes/features/other/RunInNFrames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAgBhD,qBAAa,YAAa,SAAQ,OAAO;IAuBvC,OAAO,CAAC,UAAU,CAWhB;IAGF,OAAO,CAAC,UAAU,CAWhB;IAEF;;;;;;;;OAQG;IAEI,sBAAsB,CAAC,SAAS,CAAC,EAAE,UAAU,GAAG,IAAI;IAM3D;;;;;;;;;;;OAWG;IAEI,gBAAgB,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,UAAU,EAAE,GAAG,GAAG,IAAI;IAOhE;;;;;;;;;;;OAWG;IAEI,kBAAkB,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,YAAY,EAAE,GAAG,GAAG,IAAI;IAOpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IAEI,gBAAgB,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI;IAI/C;;;;;;;;;OASG;IAEI,kBAAkB,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI;IAIjD;;;;;;;;;;;;;;;;;OAiBG;IAEI,qBAAqB,CAC1B,IAAI,EAAE,MAAM,OAAO,EACnB,UAAU,EAAE,GAAG,EACf,cAAc,EAAE,OAAO,GACtB,IAAI;IAWP;;;;;;;;;;;;;;;;;OAiBG;IAEI,uBAAuB,CAC5B,IAAI,EAAE,MAAM,OAAO,EACnB,YAAY,EAAE,GAAG,EACjB,cAAc,EAAE,OAAO,GACtB,IAAI;CAcR"}
1
+ {"version":3,"file":"RunInNFrames.d.ts","sourceRoot":"","sources":["../../../../../src/classes/features/other/RunInNFrames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAKvE,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAgBhD,qBAAa,YAAa,SAAQ,OAAO;IAavB,gBAAgB,QAAO,OAAO,CAAU;IAaxD,OAAO,CAAC,UAAU,CAWhB;IAGF,OAAO,CAAC,UAAU,CAWhB;IAEF;;;;;;;;OAQG;IAEI,sBAAsB,CAAC,SAAS,CAAC,EAAE,UAAU,GAAG,IAAI;IAM3D;;;;;;;;;;;OAWG;IAEI,gBAAgB,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,UAAU,EAAE,GAAG,GAAG,IAAI;IAOhE;;;;;;;;;;;OAWG;IAEI,kBAAkB,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,YAAY,EAAE,GAAG,GAAG,IAAI;IAOpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IAEI,gBAAgB,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI;IAI/C;;;;;;;;;OASG;IAEI,kBAAkB,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI;IAIjD;;;;;;;;;;;;;;;;;OAiBG;IAEI,qBAAqB,CAC1B,IAAI,EAAE,MAAM,OAAO,EACnB,UAAU,EAAE,GAAG,EACf,cAAc,EAAE,OAAO,GACtB,IAAI;IAWP;;;;;;;;;;;;;;;;;OAiBG;IAEI,uBAAuB,CAC5B,IAAI,EAAE,MAAM,OAAO,EACnB,YAAY,EAAE,GAAG,EACjB,cAAc,EAAE,OAAO,GACtB,IAAI;CAcR"}
@@ -59,6 +59,7 @@ __TS__ClassExtends(RunInNFrames, Feature)
59
59
  function RunInNFrames.prototype.____constructor(self)
60
60
  Feature.prototype.____constructor(self)
61
61
  self.v = {run = {queuedGameFunctionTuples = {}, queuedRenderFunctionTuples = {}, intervalGameFunctionTuples = {}, intervalRenderFunctionTuples = {}}}
62
+ self.vConditionalFunc = function() return false end
62
63
  self.postUpdate = function()
63
64
  local gameFrameCount = game:GetFrameCount()
64
65
  checkExecuteQueuedFunctions(nil, gameFrameCount, self.v.run.queuedGameFunctionTuples)
@@ -54,6 +54,8 @@ export declare class SaveDataManager extends Feature {
54
54
  * manage them for you. (See below for an example.)
55
55
  *
56
56
  * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`.
57
+ * (Upgrade your mod before registering any of your own callbacks so that the save data manager
58
+ * will run before any of your code does.)
57
59
  *
58
60
  * The save data manager is meant to be called once for each feature of your mod. In other words,
59
61
  * you should not put all of the data for your mod on the same object. Instead, scope your
@@ -110,10 +112,6 @@ export declare class SaveDataManager extends Feature {
110
112
  * supported. For the specific things that are supported, see the documentation for the `deepCopy`
111
113
  * helper function.
112
114
  *
113
- * Note that before using the save data manager, you must call the `upgradeMod` function. (Upgrade
114
- * your mod before registering any of your own callbacks so that the save data manager will run
115
- * before any of your code does.)
116
- *
117
115
  * If you want the save data manager to load data before the `POST_PLAYER_INIT` callback (i.e. in
118
116
  * the main menu), then you should explicitly call the `saveDataManagerLoad` function. (The save
119
117
  * data manager cannot do this on its own because it cannot know when your mod features are
@@ -1 +1 @@
1
- {"version":3,"file":"SaveDataManager.d.ts","sourceRoot":"","sources":["../../../../../src/classes/features/other/SaveDataManager.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAMzD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAsBhD,qBAAa,eAAgB,SAAQ,OAAO;IAC1C;;;OAGG;IACH,OAAO,CAAC,GAAG,CAAM;IAEjB;;;;OAIG;IACH,OAAO,CAAC,WAAW,CAAkC;IAErD;;;OAGG;IACH,OAAO,CAAC,mBAAmB,CAAkC;IAE7D;;;OAGG;IACH,OAAO,CAAC,0BAA0B,CAAuC;IAEzE;;;;;;OAMG;IACH,OAAO,CAAC,2BAA2B,CAAkC;IAErE;;;OAGG;IACH,OAAO,CAAC,iBAAiB,CAAkC;IAG3D,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,qCAAqC,CAAS;IAyBtD,OAAO,CAAC,2BAA2B,CAUjC;IAGF,OAAO,CAAC,cAAc,CA0BpB;IAGF,OAAO,CAAC,WAAW,CAUjB;IAGF,OAAO,CAAC,YAAY,CAYlB;IAGF,OAAO,CAAC,gBAAgB,CAuBtB;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmGG;IACI,eAAe,CAAC,UAAU,EAAE,GAAG,EAAE,KAAK,EAC3C,GAAG,EAAE,MAAM,EAAE,qEAAqE;IAClF,CAAC,EAAE,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,KAAK,CAAC,EACnC,eAAe,CAAC,EAAE,MAAM,OAAO,GAC9B,IAAI;IACA,eAAe,CACpB,GAAG,EAAE,MAAM,EAAE,kEAAkE;IAC/E,CAAC,EAAE,QAAQ,EACX,eAAe,EAAE,KAAK,GACrB,IAAI;IAkDP;;OAEG;IACH,OAAO,CAAC,gCAAgC;IAgBxC;;;;;;;;;OASG;IAEI,mBAAmB,IAAI,IAAI;IAIlC;;;;;;OAMG;IAEI,mBAAmB,IAAI,IAAI;IAIlC;;;;;;;OAOG;IAEI,wBAAwB,IAAI,IAAI;IAIvC;;;;;;;;;;;OAWG;IAEI,4BAA4B,CAAC,GAAG,WAAW,EAAE,QAAQ,EAAE,GAAG,IAAI;IAcrE;;;;;OAKG;IAEI,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAoB/C;;;;;;;;;;;;;;;;;;;;;OAqBG;IAEI,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,GAAG,IAAI;CAqB5E"}
1
+ {"version":3,"file":"SaveDataManager.d.ts","sourceRoot":"","sources":["../../../../../src/classes/features/other/SaveDataManager.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAMzD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAsBhD,qBAAa,eAAgB,SAAQ,OAAO;IAC1C;;;OAGG;IACH,OAAO,CAAC,GAAG,CAAM;IAEjB;;;;OAIG;IACH,OAAO,CAAC,WAAW,CAAkC;IAErD;;;OAGG;IACH,OAAO,CAAC,mBAAmB,CAAkC;IAE7D;;;OAGG;IACH,OAAO,CAAC,0BAA0B,CAAuC;IAEzE;;;;;;OAMG;IACH,OAAO,CAAC,2BAA2B,CAAkC;IAErE;;;OAGG;IACH,OAAO,CAAC,iBAAiB,CAAkC;IAG3D,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,qCAAqC,CAAS;IAyBtD,OAAO,CAAC,2BAA2B,CAUjC;IAGF,OAAO,CAAC,cAAc,CA0BpB;IAGF,OAAO,CAAC,WAAW,CAUjB;IAGF,OAAO,CAAC,YAAY,CAYlB;IAGF,OAAO,CAAC,gBAAgB,CAuBtB;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiGG;IACI,eAAe,CAAC,UAAU,EAAE,GAAG,EAAE,KAAK,EAC3C,GAAG,EAAE,MAAM,EAAE,qEAAqE;IAClF,CAAC,EAAE,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,KAAK,CAAC,EACnC,eAAe,CAAC,EAAE,MAAM,OAAO,GAC9B,IAAI;IACA,eAAe,CACpB,GAAG,EAAE,MAAM,EAAE,kEAAkE;IAC/E,CAAC,EAAE,QAAQ,EACX,eAAe,EAAE,KAAK,GACrB,IAAI;IAkDP;;OAEG;IACH,OAAO,CAAC,gCAAgC;IAgBxC;;;;;;;;;OASG;IAEI,mBAAmB,IAAI,IAAI;IAIlC;;;;;;OAMG;IAEI,mBAAmB,IAAI,IAAI;IAIlC;;;;;;;OAOG;IAEI,wBAAwB,IAAI,IAAI;IAIvC;;;;;;;;;;;OAWG;IAEI,4BAA4B,CAAC,GAAG,WAAW,EAAE,QAAQ,EAAE,GAAG,IAAI;IAcrE;;;;;OAKG;IAEI,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAoB/C;;;;;;;;;;;;;;;;;;;;;OAqBG;IAEI,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,GAAG,IAAI;CAqB5E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "15.3.0",
3
+ "version": "15.3.2",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -22,6 +22,6 @@
22
22
  "main": "dist/src/index",
23
23
  "types": "dist/src/index.d.ts",
24
24
  "dependencies": {
25
- "isaac-typescript-definitions": "^9.0.3"
25
+ "isaac-typescript-definitions": "^9.0.4"
26
26
  }
27
27
  }
@@ -6,7 +6,7 @@ import {
6
6
  getTSTLClassConstructor,
7
7
  getTSTLClassName,
8
8
  } from "../functions/tstlClass";
9
- import { isTable } from "../functions/types";
9
+ import { isFunction, isNumber, isTable } from "../functions/types";
10
10
  import { TSTLClassMetatable } from "../interfaces/TSTLClassMetatable";
11
11
  import { AnyFunction } from "../types/AnyFunction";
12
12
  import { ModUpgradedBase } from "./ModUpgradedBase";
@@ -19,12 +19,14 @@ const WRAPPED_CUSTOM_CALLBACK_METHODS_KEY = "__wrappedCustomCallbacksMethods";
19
19
  type ModFeatureConstructor = TSTLClassMetatable["constructor"] & {
20
20
  [ADD_CALLBACK_ARGS_KEY]: unknown | undefined;
21
21
  [ADD_CALLBACK_CUSTOM_ARGS_KEY]: unknown | undefined;
22
- [WRAPPED_CALLBACK_METHODS_KEY]: Map<ModCallback, AnyFunction>;
23
- [WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]: Map<ModCallbackCustom, AnyFunction>;
22
+ [WRAPPED_CALLBACK_METHODS_KEY]: Map<ModCallback, AnyFunction> | undefined;
23
+ [WRAPPED_CUSTOM_CALLBACK_METHODS_KEY]:
24
+ | Map<ModCallbackCustom, AnyFunction>
25
+ | undefined;
24
26
  };
25
27
 
26
28
  /**
27
- * Helper class for mods that wants to represent their individual features as classes. Extend your
29
+ * Helper class for mods that want to represent their individual features as classes. Extend your
28
30
  * mod features from this class in order to enable the `@Callback` and `@CustomCallback` decorators
29
31
  * that automatically subscribe to callbacks.
30
32
  *
@@ -49,6 +51,9 @@ type ModFeatureConstructor = TSTLClassMetatable["constructor"] & {
49
51
  * }
50
52
  * ```
51
53
  *
54
+ * When instantiating a feature class, you must pass your upgraded mod as the first argument to the
55
+ * constructor.
56
+ *
52
57
  * In almost all cases, you will want the callback functions to be immediately subscribed after
53
58
  * instantiating the class. However, if this is not the case, you can pass `false` as the optional
54
59
  * second argument to the constructor.
@@ -56,6 +61,7 @@ type ModFeatureConstructor = TSTLClassMetatable["constructor"] & {
56
61
 
57
62
  export class ModFeature {
58
63
  private mod: ModUpgradedBase;
64
+ private initialized = false;
59
65
 
60
66
  constructor(mod: ModUpgradedBase, init = true) {
61
67
  this.mod = mod;
@@ -68,14 +74,21 @@ export class ModFeature {
68
74
  /**
69
75
  * Runs the `Mod.AddCallback` and `ModUpgraded.AddCallbackCustom` methods for all of the decorated
70
76
  * callbacks. Additionally, subscribes the `v` object to the save data manager, if present.
77
+ *
78
+ * @param init Optional. Whether to initialize or uninitialize. Default is true.
71
79
  */
72
80
  public init(init = true): void {
81
+ if (this.initialized === init) {
82
+ return;
83
+ }
84
+ this.initialized = init;
85
+
73
86
  const constructor = getTSTLClassConstructor(this);
74
87
  if (constructor === undefined) {
75
88
  error("Failed to get the TSTL class constructor for a mod feature.");
76
89
  }
77
90
 
78
- const tstlClassName = getTSTLClassName(constructor);
91
+ const tstlClassName = getTSTLClassName(this);
79
92
  if (tstlClassName === undefined) {
80
93
  error("Failed to get the TSTL class name for a mod feature.");
81
94
  }
@@ -85,6 +98,13 @@ export class ModFeature {
85
98
  initSaveDataManager(this, tstlClassName, init);
86
99
  }
87
100
 
101
+ /**
102
+ * Runs the `Mod.RemoveCallback` and `ModUpgraded.RemoveCallbackCustom` methods for all of the
103
+ * decorated callbacks. Additionally, unsubscribes the `v` object from the save data manager, if
104
+ * present.
105
+ *
106
+ * This is just an alias for `ModFeature.init(false)`.
107
+ */
88
108
  public uninit(): void {
89
109
  this.init(false);
90
110
  }
@@ -122,16 +142,14 @@ function initDecoratedCallbacks(
122
142
  const parameters = deepCopy(args);
123
143
 
124
144
  const modCallback = parameters.shift();
125
- if (modCallback === undefined) {
145
+ if (!isNumber(modCallback)) {
126
146
  error(
127
147
  `Failed to get the callback number from the parameters for class: ${tstlClassName}`,
128
148
  );
129
149
  }
130
150
 
131
- const callback = parameters.shift() as
132
- | ((this: void, ...callbackArgs: unknown[]) => void)
133
- | undefined;
134
- if (callback === undefined) {
151
+ const callback = parameters.shift();
152
+ if (!isFunction(callback)) {
135
153
  error(
136
154
  `Failed to get the callback function from the parameters for class: ${tstlClassName}`,
137
155
  );
@@ -141,51 +159,99 @@ function initDecoratedCallbacks(
141
159
  const mod = modFeature["mod"];
142
160
 
143
161
  if (init) {
144
- // We need to wrap the callback in a new function so that we can explicitly pass the class as
145
- // the first argument. (Otherwise, the method will not be able to properly access `this`.
146
- const wrappedCallback = (...callbackArgs: unknown[]) => {
147
- callback(modFeature, ...callbackArgs);
148
- };
149
-
150
- // We need to save the wrapped function for later (so we can unregister them).
151
- if (vanilla) {
152
- const modCallbackVanilla = modCallback as ModCallback;
153
- const wrappedMethodsMap =
154
- modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY];
155
- wrappedMethodsMap.set(modCallbackVanilla, wrappedCallback);
156
- } else {
157
- const modCallbackCustom = modCallback as ModCallbackCustom;
158
- const wrappedMethodsMap =
159
- modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY];
160
- wrappedMethodsMap.set(modCallbackCustom, wrappedCallback);
161
- }
162
-
163
- if (vanilla) {
164
- (mod.AddCallback as AnyFunction)(
165
- modCallback,
166
- wrappedCallback,
167
- ...parameters,
168
- );
169
- } else {
170
- (mod.AddCallbackCustom as AnyFunction)(
171
- modCallback,
172
- wrappedCallback,
173
- ...parameters,
174
- );
175
- }
176
- } else if (vanilla) {
177
- const modCallbackVanilla = modCallback as ModCallback;
178
- const wrappedMethodsMap =
179
- modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY];
180
- const wrappedCallback = wrappedMethodsMap.get(modCallbackVanilla);
181
- (mod.RemoveCallback as AnyFunction)(modCallback, wrappedCallback);
162
+ addCallback(
163
+ modFeature,
164
+ modFeatureConstructor,
165
+ mod,
166
+ modCallback,
167
+ callback,
168
+ parameters,
169
+ vanilla,
170
+ );
182
171
  } else {
183
- const modCallbackCustom = modCallback as ModCallbackCustom;
184
- const wrappedMethodsMap =
185
- modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY];
186
- const wrappedCallback = wrappedMethodsMap.get(modCallbackCustom);
187
- (mod.RemoveCallbackCustom as AnyFunction)(modCallback, wrappedCallback);
172
+ removeCallback(modFeatureConstructor, mod, modCallback, vanilla);
173
+ }
174
+ }
175
+ }
176
+
177
+ function addCallback(
178
+ modFeature: ModFeature,
179
+ modFeatureConstructor: ModFeatureConstructor,
180
+ mod: ModUpgradedBase,
181
+ modCallback: unknown,
182
+ // eslint-disable-next-line @typescript-eslint/ban-types
183
+ callback: Function,
184
+ parameters: unknown[],
185
+ vanilla: boolean,
186
+ ) {
187
+ // We need to wrap the callback in a new function so that we can explicitly pass the class as the
188
+ // first argument. (Otherwise, the method will not be able to properly access `this`.
189
+ const wrappedCallback = (...callbackArgs: unknown[]) => {
190
+ callback(modFeature, ...callbackArgs);
191
+ };
192
+
193
+ // We need to save the wrapped function for later (so we can unregister them).
194
+ if (vanilla) {
195
+ const modCallbackVanilla = modCallback as ModCallback;
196
+ let wrappedMethodsMap = modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY];
197
+ if (wrappedMethodsMap === undefined) {
198
+ wrappedMethodsMap = new Map();
199
+ modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY] = wrappedMethodsMap;
200
+ }
201
+ wrappedMethodsMap.set(modCallbackVanilla, wrappedCallback);
202
+ } else {
203
+ const modCallbackCustom = modCallback as ModCallbackCustom;
204
+ let wrappedMethodsMap =
205
+ modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY];
206
+ if (wrappedMethodsMap === undefined) {
207
+ wrappedMethodsMap = new Map();
208
+ modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY] =
209
+ wrappedMethodsMap;
188
210
  }
211
+ wrappedMethodsMap.set(modCallbackCustom, wrappedCallback);
212
+ }
213
+
214
+ if (vanilla) {
215
+ (mod.AddCallback as AnyFunction)(
216
+ modCallback,
217
+ wrappedCallback,
218
+ ...parameters,
219
+ );
220
+ } else {
221
+ (mod.AddCallbackCustom as AnyFunction)(
222
+ modCallback,
223
+ wrappedCallback,
224
+ ...parameters,
225
+ );
226
+ }
227
+ }
228
+
229
+ function removeCallback(
230
+ modFeatureConstructor: ModFeatureConstructor,
231
+ mod: ModUpgradedBase,
232
+ modCallback: unknown,
233
+ vanilla: boolean,
234
+ ) {
235
+ if (vanilla) {
236
+ const modCallbackVanilla = modCallback as ModCallback;
237
+ const wrappedMethodsMap =
238
+ modFeatureConstructor[WRAPPED_CALLBACK_METHODS_KEY];
239
+ if (wrappedMethodsMap === undefined) {
240
+ return;
241
+ }
242
+
243
+ const wrappedCallback = wrappedMethodsMap.get(modCallbackVanilla);
244
+ (mod.RemoveCallback as AnyFunction)(modCallback, wrappedCallback);
245
+ } else {
246
+ const modCallbackCustom = modCallback as ModCallbackCustom;
247
+ const wrappedMethodsMap =
248
+ modFeatureConstructor[WRAPPED_CUSTOM_CALLBACK_METHODS_KEY];
249
+ if (wrappedMethodsMap === undefined) {
250
+ return;
251
+ }
252
+
253
+ const wrappedCallback = wrappedMethodsMap.get(modCallbackCustom);
254
+ (mod.RemoveCallbackCustom as AnyFunction)(modCallback, wrappedCallback);
189
255
  }
190
256
  }
191
257
 
@@ -31,6 +31,9 @@ export class RunInNFrames extends Feature {
31
31
  },
32
32
  };
33
33
 
34
+ // eslint-disable-next-line class-methods-use-this
35
+ public override vConditionalFunc = (): boolean => false;
36
+
34
37
  /** @internal */
35
38
  constructor() {
36
39
  super();
@@ -210,6 +210,8 @@ export class SaveDataManager extends Feature {
210
210
  * manage them for you. (See below for an example.)
211
211
  *
212
212
  * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`.
213
+ * (Upgrade your mod before registering any of your own callbacks so that the save data manager
214
+ * will run before any of your code does.)
213
215
  *
214
216
  * The save data manager is meant to be called once for each feature of your mod. In other words,
215
217
  * you should not put all of the data for your mod on the same object. Instead, scope your
@@ -266,10 +268,6 @@ export class SaveDataManager extends Feature {
266
268
  * supported. For the specific things that are supported, see the documentation for the `deepCopy`
267
269
  * helper function.
268
270
  *
269
- * Note that before using the save data manager, you must call the `upgradeMod` function. (Upgrade
270
- * your mod before registering any of your own callbacks so that the save data manager will run
271
- * before any of your code does.)
272
- *
273
271
  * If you want the save data manager to load data before the `POST_PLAYER_INIT` callback (i.e. in
274
272
  * the main menu), then you should explicitly call the `saveDataManagerLoad` function. (The save
275
273
  * data manager cannot do this on its own because it cannot know when your mod features are