isaacscript-common 27.5.2 → 27.6.1

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.
@@ -941,7 +941,7 @@ export declare function arrayRemoveInPlace<T>(array: T[], ...elementsToRemove: T
941
941
  /** Helper function to convert a set of flags to a single `BitFlags` object. */
942
942
  export declare function arrayToBitFlags<T extends BitFlag | BitFlag128>(array: T[] | readonly T[]): BitFlags<T>;
943
943
 
944
- export declare function arrayToString<T>(array: T[] | readonly T[]): string;
944
+ export declare function arrayToString(array: unknown[]): string;
945
945
 
946
946
  /**
947
947
  * Helper function to safely cast a `number` to a `CardType`. (This is better than using the `as`
@@ -7156,7 +7156,7 @@ export declare function inCrawlSpace(): boolean;
7156
7156
  *
7157
7157
  * From: https://stackoverflow.com/questions/54243431/typescript-increment-number-type
7158
7158
  */
7159
- export declare type Increment<N extends number> = [...Tuple<N>, unknown]["length"];
7159
+ export declare type Increment<N extends number> = [...Tuple<N>, unknown]["length"] & number;
7160
7160
 
7161
7161
  /**
7162
7162
  * Helper function to detect if the current room is one of the rooms in the Death Certificate area.
@@ -12073,7 +12073,7 @@ export declare type NaturalNumbersLessThan<N extends number, Acc extends number[
12073
12073
  * From:
12074
12074
  * https://stackoverflow.com/questions/39494689/is-it-possible-to-restrict-number-to-a-certain-range
12075
12075
  */
12076
- export declare type NaturalNumbersLessThanOrEqualTo<N extends number> = NaturalNumbersLessThan<Increment<N>>;
12076
+ export declare type NaturalNumbersLessThanOrEqualTo<N extends number, T extends number[] = []> = T extends [unknown, ...infer Tail] ? Tail["length"] extends N ? T[number] : NaturalNumbersLessThanOrEqualTo<N, [...T, T["length"]]> : NaturalNumbersLessThanOrEqualTo<N, [...T, T["length"]]>;
12077
12077
 
12078
12078
  /** This is near the top door. */
12079
12079
  export declare const NEW_FLOOR_STARTING_POSITION_GREED_MODE: Readonly<Vector>;
@@ -15394,6 +15394,15 @@ export declare function spawnWithSeed(entityType: EntityType, variant: int, subT
15394
15394
  */
15395
15395
  export declare function spriteEquals(sprite1: Sprite, sprite2: Sprite, layerID: int, xStart: int, xFinish: int, xIncrement: int, yStart: int, yFinish: int, yIncrement: int): boolean;
15396
15396
 
15397
+ /**
15398
+ * Helper function to sort an array in a stable way.
15399
+ *
15400
+ * This is useful because by default, the transpiled `Array.sort` method from TSTL is not stable.
15401
+ *
15402
+ * Under the hood, this uses the merge sort algorithm.
15403
+ */
15404
+ export declare function stableSort<T>(array: T[], sortFunc?: (a: T, b: T) => -1 | 0 | 1): T[];
15405
+
15397
15406
  declare class StageHistory extends Feature {
15398
15407
  private postNewLevelReordered;
15399
15408
  /**
@@ -1,6 +1,6 @@
1
1
  --[[
2
2
 
3
- isaacscript-common 27.5.2
3
+ isaacscript-common 27.6.1
4
4
 
5
5
  This is the "isaacscript-common" library, which was created with the IsaacScript tool.
6
6
 
@@ -15536,6 +15536,8 @@ end
15536
15536
  return ____exports
15537
15537
  end,
15538
15538
  ["src.functions.sort"] = function(...)
15539
+ local ____lualib = require("lualib_bundle")
15540
+ local __TS__ArraySlice = ____lualib.__TS__ArraySlice
15539
15541
  local ____exports = {}
15540
15542
  local ____types = require("src.functions.types")
15541
15543
  local isNumber = ____types.isNumber
@@ -15543,10 +15545,10 @@ local isString = ____types.isString
15543
15545
  local isTable = ____types.isTable
15544
15546
  local function sortNormal(self, a, b)
15545
15547
  if not isNumber(nil, a) and not isString(nil, a) then
15546
- error("Failed to sort since the first value was not a number or string.")
15548
+ error("Failed to normal sort since the first value was not a number or string and was instead: " .. type(a))
15547
15549
  end
15548
15550
  if not isNumber(nil, b) and not isString(nil, b) then
15549
- error("Failed to sort since the second value was not a number or string.")
15551
+ error("Failed to normal sort since the second value was not a number or string and was instead: " .. type(b))
15550
15552
  end
15551
15553
  if a < b then
15552
15554
  return -1
@@ -15559,10 +15561,10 @@ end
15559
15561
  function ____exports.sortObjectArrayByKey(self, key)
15560
15562
  return function(____, a, b)
15561
15563
  if not isTable(nil, a) then
15562
- error(("Failed to sort an object by the key of \"" .. key) .. "\" since the first element was not a table.")
15564
+ error((("Failed to sort an object array by the key of \"" .. key) .. "\" since the first element was not a table and was instead: ") .. type(a))
15563
15565
  end
15564
15566
  if not isTable(nil, b) then
15565
- error(("Failed to sort an object by the key of \"" .. key) .. "\" since the second element was not a table.")
15567
+ error(((("Failed to sort an object array by the key of \"" .. key) .. "\" since the second element was not a table and was instead: ") .. type(b)) .. ".")
15566
15568
  end
15567
15569
  local aValue = a[key]
15568
15570
  local bValue = b[key]
@@ -15599,6 +15601,45 @@ function ____exports.sortTwoDimensionalArray(self, a, b)
15599
15601
  end
15600
15602
  return sortNormal(nil, firstElement1, firstElement2)
15601
15603
  end
15604
+ function ____exports.stableSort(self, array, sortFunc)
15605
+ if sortFunc == nil then
15606
+ sortFunc = sortNormal
15607
+ end
15608
+ if #array <= 1 then
15609
+ return array
15610
+ end
15611
+ local middleIndex = math.floor(#array / 2)
15612
+ local leftArray = __TS__ArraySlice(array, 0, middleIndex)
15613
+ local rightArray = __TS__ArraySlice(array, middleIndex)
15614
+ local sortedLeftArray = ____exports.stableSort(nil, leftArray, sortFunc)
15615
+ local sortedRightArray = ____exports.stableSort(nil, rightArray, sortFunc)
15616
+ local mergedArray = {}
15617
+ local leftIndex = 0
15618
+ local rightIndex = 0
15619
+ while leftIndex < #sortedLeftArray and rightIndex < #sortedRightArray do
15620
+ local left = sortedLeftArray[leftIndex + 1]
15621
+ local right = sortedRightArray[rightIndex + 1]
15622
+ local sortResult = sortFunc(nil, left, right)
15623
+ if sortResult == -1 or sortResult == 0 then
15624
+ mergedArray[#mergedArray + 1] = left
15625
+ leftIndex = leftIndex + 1
15626
+ else
15627
+ mergedArray[#mergedArray + 1] = right
15628
+ rightIndex = rightIndex + 1
15629
+ end
15630
+ end
15631
+ while leftIndex < #sortedLeftArray do
15632
+ local left = sortedLeftArray[leftIndex + 1]
15633
+ mergedArray[#mergedArray + 1] = left
15634
+ leftIndex = leftIndex + 1
15635
+ end
15636
+ while rightIndex < #sortedRightArray do
15637
+ local right = sortedRightArray[rightIndex + 1]
15638
+ mergedArray[#mergedArray + 1] = right
15639
+ rightIndex = rightIndex + 1
15640
+ end
15641
+ return mergedArray
15642
+ end
15602
15643
  return ____exports
15603
15644
  end,
15604
15645
  ["src.classes.DefaultMap"] = function(...)
@@ -15803,6 +15844,9 @@ local __TS__StringSlice = ____lualib.__TS__StringSlice
15803
15844
  local __TS__StringEndsWith = ____lualib.__TS__StringEndsWith
15804
15845
  local ____exports = {}
15805
15846
  function ____exports.capitalizeFirstLetter(self, ____string)
15847
+ if ____string == "" then
15848
+ return ____string
15849
+ end
15806
15850
  local firstCharacter = string.sub(____string, 1, 1)
15807
15851
  local capitalizedFirstLetter = string.upper(firstCharacter)
15808
15852
  local restOfString = string.sub(____string, 2)
@@ -17918,7 +17962,6 @@ local ____lualib = require("lualib_bundle")
17918
17962
  local __TS__Class = ____lualib.__TS__Class
17919
17963
  local __TS__ClassExtends = ____lualib.__TS__ClassExtends
17920
17964
  local __TS__Spread = ____lualib.__TS__Spread
17921
- local __TS__ArraySort = ____lualib.__TS__ArraySort
17922
17965
  local __TS__ArrayFindIndex = ____lualib.__TS__ArrayFindIndex
17923
17966
  local __TS__ArraySplice = ____lualib.__TS__ArraySplice
17924
17967
  local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
@@ -17927,6 +17970,7 @@ local ____log = require("src.functions.log")
17927
17970
  local log = ____log.log
17928
17971
  local ____sort = require("src.functions.sort")
17929
17972
  local sortObjectArrayByKey = ____sort.sortObjectArrayByKey
17973
+ local stableSort = ____sort.stableSort
17930
17974
  local ____tstlClass = require("src.functions.tstlClass")
17931
17975
  local getTSTLClassName = ____tstlClass.getTSTLClassName
17932
17976
  local ____Feature = require("src.classes.private.Feature")
@@ -17962,7 +18006,8 @@ function CustomCallback.prototype.addSubscriber(self, priority, callbackFunc, ..
17962
18006
  local subscription = {priority = priority, callbackFunc = callbackFunc, optionalArgs = optionalArgs}
17963
18007
  local ____self_subscriptions_0 = self.subscriptions
17964
18008
  ____self_subscriptions_0[#____self_subscriptions_0 + 1] = subscription
17965
- __TS__ArraySort(
18009
+ self.subscriptions = stableSort(
18010
+ nil,
17966
18011
  self.subscriptions,
17967
18012
  sortObjectArrayByKey(nil, "priority")
17968
18013
  )
@@ -1 +1 @@
1
- {"version":3,"file":"CustomCallback.d.ts","sourceRoot":"","sources":["../../../../src/classes/private/CustomCallback.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAC;AAChG,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAIlE,OAAO,EAAE,2BAA2B,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,iBAAiB,IAAI,UAAU,CAC5D,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAClC,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,iBAAiB,IAAI,WAAW,CACjE,2BAA2B,CAAC,CAAC,CAAC,CAC/B,CAAC;AAQF;;;GAGG;AACH,8BAAsB,cAAc,CAClC,CAAC,SAAS,iBAAiB,CAC3B,SAAQ,OAAO;IACf,OAAO,CAAC,aAAa,CAA8B;IAE5C,aAAa,CAClB,QAAQ,EAAE,gBAAgB,GAAG,GAAG,EAChC,YAAY,EAAE,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC/C,GAAG,YAAY,EAAE,WAAW,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,GAC3D,IAAI;IAUP;;;OAGG;IACI,gBAAgB,CAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAYnE,IAAI,gBACI,SAAS,CAAC,CAAC,KACvB,WAAW,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAc9C;IAEF;;;OAGG;IACH,SAAS,CAAC,UAAU,EAAE,CACpB,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EACrB,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,KAC1B,OAAO,CAAc;IAEnB,gBAAgB,IAAI,IAAI;CAYhC"}
1
+ {"version":3,"file":"CustomCallback.d.ts","sourceRoot":"","sources":["../../../../src/classes/private/CustomCallback.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAC;AAChG,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAIlE,OAAO,EAAE,2BAA2B,EAAE,MAAM,sDAAsD,CAAC;AACnG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,iBAAiB,IAAI,UAAU,CAC5D,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAClC,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,iBAAiB,IAAI,WAAW,CACjE,2BAA2B,CAAC,CAAC,CAAC,CAC/B,CAAC;AAQF;;;GAGG;AACH,8BAAsB,cAAc,CAClC,CAAC,SAAS,iBAAiB,CAC3B,SAAQ,OAAO;IACf,OAAO,CAAC,aAAa,CAA8B;IAE5C,aAAa,CAClB,QAAQ,EAAE,gBAAgB,GAAG,GAAG,EAChC,YAAY,EAAE,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC/C,GAAG,YAAY,EAAE,WAAW,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,GAC3D,IAAI;IAaP;;;OAGG;IACI,gBAAgB,CAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAYnE,IAAI,gBACI,SAAS,CAAC,CAAC,KACvB,WAAW,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAc9C;IAEF;;;OAGG;IACH,SAAS,CAAC,UAAU,EAAE,CACpB,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EACrB,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,KAC1B,OAAO,CAAc;IAEnB,gBAAgB,IAAI,IAAI;CAYhC"}
@@ -2,7 +2,6 @@ local ____lualib = require("lualib_bundle")
2
2
  local __TS__Class = ____lualib.__TS__Class
3
3
  local __TS__ClassExtends = ____lualib.__TS__ClassExtends
4
4
  local __TS__Spread = ____lualib.__TS__Spread
5
- local __TS__ArraySort = ____lualib.__TS__ArraySort
6
5
  local __TS__ArrayFindIndex = ____lualib.__TS__ArrayFindIndex
7
6
  local __TS__ArraySplice = ____lualib.__TS__ArraySplice
8
7
  local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
@@ -11,6 +10,7 @@ local ____log = require("src.functions.log")
11
10
  local log = ____log.log
12
11
  local ____sort = require("src.functions.sort")
13
12
  local sortObjectArrayByKey = ____sort.sortObjectArrayByKey
13
+ local stableSort = ____sort.stableSort
14
14
  local ____tstlClass = require("src.functions.tstlClass")
15
15
  local getTSTLClassName = ____tstlClass.getTSTLClassName
16
16
  local ____Feature = require("src.classes.private.Feature")
@@ -48,7 +48,8 @@ function CustomCallback.prototype.addSubscriber(self, priority, callbackFunc, ..
48
48
  local subscription = {priority = priority, callbackFunc = callbackFunc, optionalArgs = optionalArgs}
49
49
  local ____self_subscriptions_0 = self.subscriptions
50
50
  ____self_subscriptions_0[#____self_subscriptions_0 + 1] = subscription
51
- __TS__ArraySort(
51
+ self.subscriptions = stableSort(
52
+ nil,
52
53
  self.subscriptions,
53
54
  sortObjectArrayByKey(nil, "priority")
54
55
  )
@@ -74,7 +74,7 @@ export declare function arrayRemoveIndex<T>(originalArray: T[] | readonly T[], .
74
74
  * @returns Whether or not any array elements were removed.
75
75
  */
76
76
  export declare function arrayRemoveIndexInPlace<T>(array: T[], ...indexesToRemove: int[]): boolean;
77
- export declare function arrayToString<T>(array: T[] | readonly T[]): string;
77
+ export declare function arrayToString(array: unknown[]): string;
78
78
  /**
79
79
  * Helper function to combine two or more arrays. Returns a new array that is the composition of all
80
80
  * of the specified arrays.
@@ -1 +1 @@
1
- {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../../src/functions/array.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../../src/functions/array.ts"],"names":[],"mappings":"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"}
@@ -35,4 +35,12 @@ export declare function sortObjectArrayByKey(key: string): (a: unknown, b: unkno
35
35
  * https://stackoverflow.com/questions/16096872/how-to-sort-2-dimensional-array-by-column-value
36
36
  */
37
37
  export declare function sortTwoDimensionalArray<T>(a: T[], b: T[]): -1 | 0 | 1;
38
+ /**
39
+ * Helper function to sort an array in a stable way.
40
+ *
41
+ * This is useful because by default, the transpiled `Array.sort` method from TSTL is not stable.
42
+ *
43
+ * Under the hood, this uses the merge sort algorithm.
44
+ */
45
+ export declare function stableSort<T>(array: T[], sortFunc?: (a: T, b: T) => -1 | 0 | 1): T[];
38
46
  //# sourceMappingURL=sort.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sort.d.ts","sourceRoot":"","sources":["../../../src/functions/sort.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,OACnC,OAAO,KAAK,OAAO,KAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAkB5C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAiDrE"}
1
+ {"version":3,"file":"sort.d.ts","sourceRoot":"","sources":["../../../src/functions/sort.ts"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,OACnC,OAAO,KAAK,OAAO,KAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAsB5C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAiDrE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,KAAK,EAAE,CAAC,EAAE,EACV,QAAQ,GAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAc,GAChD,CAAC,EAAE,CAuDL"}
@@ -1,3 +1,5 @@
1
+ local ____lualib = require("lualib_bundle")
2
+ local __TS__ArraySlice = ____lualib.__TS__ArraySlice
1
3
  local ____exports = {}
2
4
  local ____types = require("src.functions.types")
3
5
  local isNumber = ____types.isNumber
@@ -5,10 +7,10 @@ local isString = ____types.isString
5
7
  local isTable = ____types.isTable
6
8
  local function sortNormal(self, a, b)
7
9
  if not isNumber(nil, a) and not isString(nil, a) then
8
- error("Failed to sort since the first value was not a number or string.")
10
+ error("Failed to normal sort since the first value was not a number or string and was instead: " .. type(a))
9
11
  end
10
12
  if not isNumber(nil, b) and not isString(nil, b) then
11
- error("Failed to sort since the second value was not a number or string.")
13
+ error("Failed to normal sort since the second value was not a number or string and was instead: " .. type(b))
12
14
  end
13
15
  if a < b then
14
16
  return -1
@@ -38,10 +40,10 @@ end
38
40
  function ____exports.sortObjectArrayByKey(self, key)
39
41
  return function(____, a, b)
40
42
  if not isTable(nil, a) then
41
- error(("Failed to sort an object by the key of \"" .. key) .. "\" since the first element was not a table.")
43
+ error((("Failed to sort an object array by the key of \"" .. key) .. "\" since the first element was not a table and was instead: ") .. type(a))
42
44
  end
43
45
  if not isTable(nil, b) then
44
- error(("Failed to sort an object by the key of \"" .. key) .. "\" since the second element was not a table.")
46
+ error(((("Failed to sort an object array by the key of \"" .. key) .. "\" since the second element was not a table and was instead: ") .. type(b)) .. ".")
45
47
  end
46
48
  local aValue = a[key]
47
49
  local bValue = b[key]
@@ -92,4 +94,48 @@ function ____exports.sortTwoDimensionalArray(self, a, b)
92
94
  end
93
95
  return sortNormal(nil, firstElement1, firstElement2)
94
96
  end
97
+ --- Helper function to sort an array in a stable way.
98
+ --
99
+ -- This is useful because by default, the transpiled `Array.sort` method from TSTL is not stable.
100
+ --
101
+ -- Under the hood, this uses the merge sort algorithm.
102
+ function ____exports.stableSort(self, array, sortFunc)
103
+ if sortFunc == nil then
104
+ sortFunc = sortNormal
105
+ end
106
+ if #array <= 1 then
107
+ return array
108
+ end
109
+ local middleIndex = math.floor(#array / 2)
110
+ local leftArray = __TS__ArraySlice(array, 0, middleIndex)
111
+ local rightArray = __TS__ArraySlice(array, middleIndex)
112
+ local sortedLeftArray = ____exports.stableSort(nil, leftArray, sortFunc)
113
+ local sortedRightArray = ____exports.stableSort(nil, rightArray, sortFunc)
114
+ local mergedArray = {}
115
+ local leftIndex = 0
116
+ local rightIndex = 0
117
+ while leftIndex < #sortedLeftArray and rightIndex < #sortedRightArray do
118
+ local left = sortedLeftArray[leftIndex + 1]
119
+ local right = sortedRightArray[rightIndex + 1]
120
+ local sortResult = sortFunc(nil, left, right)
121
+ if sortResult == -1 or sortResult == 0 then
122
+ mergedArray[#mergedArray + 1] = left
123
+ leftIndex = leftIndex + 1
124
+ else
125
+ mergedArray[#mergedArray + 1] = right
126
+ rightIndex = rightIndex + 1
127
+ end
128
+ end
129
+ while leftIndex < #sortedLeftArray do
130
+ local left = sortedLeftArray[leftIndex + 1]
131
+ mergedArray[#mergedArray + 1] = left
132
+ leftIndex = leftIndex + 1
133
+ end
134
+ while rightIndex < #sortedRightArray do
135
+ local right = sortedRightArray[rightIndex + 1]
136
+ mergedArray[#mergedArray + 1] = right
137
+ rightIndex = rightIndex + 1
138
+ end
139
+ return mergedArray
140
+ end
95
141
  return ____exports
@@ -1 +1 @@
1
- {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../../src/functions/string.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAM5D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,GACd,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,MAAM,CAGR;AAED,8FAA8F;AAC9F,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,GAAG,UAAU,EAAE,MAAM,EAAE,GACtB,MAAM,CAMR;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAOjE"}
1
+ {"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../../src/functions/string.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAU5D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,GACd,MAAM,GAAG,SAAS,CAYpB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,MAAM,CAGR;AAED,8FAA8F;AAC9F,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,GAAG,UAAU,EAAE,MAAM,EAAE,GACtB,MAAM,CAMR;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAOjE"}
@@ -7,6 +7,9 @@ local __TS__StringSlice = ____lualib.__TS__StringSlice
7
7
  local __TS__StringEndsWith = ____lualib.__TS__StringEndsWith
8
8
  local ____exports = {}
9
9
  function ____exports.capitalizeFirstLetter(self, ____string)
10
+ if ____string == "" then
11
+ return ____string
12
+ end
10
13
  local firstCharacter = string.sub(____string, 1, 1)
11
14
  local capitalizedFirstLetter = string.upper(firstCharacter)
12
15
  local restOfString = string.sub(____string, 2)
@@ -4,5 +4,5 @@ import { Tuple } from "./Tuple";
4
4
  *
5
5
  * From: https://stackoverflow.com/questions/54243431/typescript-increment-number-type
6
6
  */
7
- export type Increment<N extends number> = [...Tuple<N>, unknown]["length"];
7
+ export type Increment<N extends number> = [...Tuple<N>, unknown]["length"] & number;
8
8
  //# sourceMappingURL=Increment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Increment.d.ts","sourceRoot":"","sources":["../../../src/types/Increment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC"}
1
+ {"version":3,"file":"Increment.d.ts","sourceRoot":"","sources":["../../../src/types/Increment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GACxE,MAAM,CAAC"}
@@ -1,10 +1,8 @@
1
- import { Increment } from "./Increment";
2
- import { NaturalNumbersLessThan } from "./NaturalNumbersLessThan";
3
1
  /**
4
2
  * Helper type to get a range of integers between 0 and N.
5
3
  *
6
4
  * From:
7
5
  * https://stackoverflow.com/questions/39494689/is-it-possible-to-restrict-number-to-a-certain-range
8
6
  */
9
- export type NaturalNumbersLessThanOrEqualTo<N extends number> = NaturalNumbersLessThan<Increment<N>>;
7
+ export type NaturalNumbersLessThanOrEqualTo<N extends number, T extends number[] = []> = T extends [unknown, ...infer Tail] ? Tail["length"] extends N ? T[number] : NaturalNumbersLessThanOrEqualTo<N, [...T, T["length"]]> : NaturalNumbersLessThanOrEqualTo<N, [...T, T["length"]]>;
10
8
  //# sourceMappingURL=NaturalNumbersLessThanOrEqualTo.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NaturalNumbersLessThanOrEqualTo.d.ts","sourceRoot":"","sources":["../../../src/types/NaturalNumbersLessThanOrEqualTo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;GAKG;AACH,MAAM,MAAM,+BAA+B,CAAC,CAAC,SAAS,MAAM,IAE1D,sBAAsB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"NaturalNumbersLessThanOrEqualTo.d.ts","sourceRoot":"","sources":["../../../src/types/NaturalNumbersLessThanOrEqualTo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,+BAA+B,CACzC,CAAC,SAAS,MAAM,EAChB,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,IACrB,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,GAClC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GACtB,CAAC,CAAC,MAAM,CAAC,GACT,+BAA+B,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GACzD,+BAA+B,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "27.5.2",
3
+ "version": "27.6.1",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -1,7 +1,7 @@
1
1
  import { CallbackPriority } from "isaac-typescript-definitions/dist/src/enums/CallbackPriority";
2
2
  import { ModCallbackCustom } from "../../enums/ModCallbackCustom";
3
3
  import { log } from "../../functions/log";
4
- import { sortObjectArrayByKey } from "../../functions/sort";
4
+ import { sortObjectArrayByKey, stableSort } from "../../functions/sort";
5
5
  import { getTSTLClassName } from "../../functions/tstlClass";
6
6
  import { AddCallbackParametersCustom } from "../../interfaces/private/AddCallbackParametersCustom";
7
7
  import { AllButFirst } from "../../types/AllButFirst";
@@ -42,7 +42,10 @@ export abstract class CustomCallback<
42
42
  optionalArgs,
43
43
  };
44
44
  this.subscriptions.push(subscription);
45
- this.subscriptions.sort(sortObjectArrayByKey("priority"));
45
+ this.subscriptions = stableSort(
46
+ this.subscriptions,
47
+ sortObjectArrayByKey("priority"),
48
+ );
46
49
  }
47
50
 
48
51
  /**
@@ -173,7 +173,7 @@ export function arrayRemoveIndexInPlace<T>(
173
173
  return true;
174
174
  }
175
175
 
176
- export function arrayToString<T>(array: T[] | readonly T[]): string {
176
+ export function arrayToString(array: unknown[]): string {
177
177
  if (array.length === 0) {
178
178
  return "[]";
179
179
  }
@@ -2,11 +2,19 @@ import { isNumber, isString, isTable } from "./types";
2
2
 
3
3
  function sortNormal(a: unknown, b: unknown): -1 | 0 | 1 {
4
4
  if (!isNumber(a) && !isString(a)) {
5
- error("Failed to sort since the first value was not a number or string.");
5
+ error(
6
+ `Failed to normal sort since the first value was not a number or string and was instead: ${type(
7
+ a,
8
+ )}`,
9
+ );
6
10
  }
7
11
 
8
12
  if (!isNumber(b) && !isString(b)) {
9
- error("Failed to sort since the second value was not a number or string.");
13
+ error(
14
+ `Failed to normal sort since the second value was not a number or string and was instead: ${type(
15
+ b,
16
+ )}`,
17
+ );
10
18
  }
11
19
 
12
20
  if (a < b) {
@@ -43,13 +51,17 @@ export function sortObjectArrayByKey(key: string) {
43
51
  return (a: unknown, b: unknown): -1 | 0 | 1 => {
44
52
  if (!isTable(a)) {
45
53
  error(
46
- `Failed to sort an object by the key of "${key}" since the first element was not a table.`,
54
+ `Failed to sort an object array by the key of "${key}" since the first element was not a table and was instead: ${type(
55
+ a,
56
+ )}`,
47
57
  );
48
58
  }
49
59
 
50
60
  if (!isTable(b)) {
51
61
  error(
52
- `Failed to sort an object by the key of "${key}" since the second element was not a table.`,
62
+ `Failed to sort an object array by the key of "${key}" since the second element was not a table and was instead: ${type(
63
+ b,
64
+ )}.`,
53
65
  );
54
66
  }
55
67
 
@@ -126,3 +138,70 @@ export function sortTwoDimensionalArray<T>(a: T[], b: T[]): -1 | 0 | 1 {
126
138
 
127
139
  return sortNormal(firstElement1, firstElement2);
128
140
  }
141
+
142
+ /**
143
+ * Helper function to sort an array in a stable way.
144
+ *
145
+ * This is useful because by default, the transpiled `Array.sort` method from TSTL is not stable.
146
+ *
147
+ * Under the hood, this uses the merge sort algorithm.
148
+ */
149
+ export function stableSort<T>(
150
+ array: T[],
151
+ sortFunc: (a: T, b: T) => -1 | 0 | 1 = sortNormal,
152
+ ): T[] {
153
+ // Base case: an array of zero or one elements is already sorted
154
+ if (array.length <= 1) {
155
+ return array;
156
+ }
157
+
158
+ // Split the array into two halves.
159
+ const middleIndex = Math.floor(array.length / 2);
160
+ const leftArray = array.slice(0, middleIndex);
161
+ const rightArray = array.slice(middleIndex);
162
+
163
+ // Recursively sort each half.
164
+ const sortedLeftArray = stableSort(leftArray, sortFunc);
165
+ const sortedRightArray = stableSort(rightArray, sortFunc);
166
+
167
+ // Merge the two sorted halves.
168
+ const mergedArray: T[] = [];
169
+ let leftIndex = 0;
170
+ let rightIndex = 0;
171
+ while (
172
+ leftIndex < sortedLeftArray.length &&
173
+ rightIndex < sortedRightArray.length
174
+ ) {
175
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
176
+ const left = sortedLeftArray[leftIndex]!;
177
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
178
+ const right = sortedRightArray[rightIndex]!;
179
+
180
+ const sortResult = sortFunc(left, right);
181
+ if (sortResult === -1 || sortResult === 0) {
182
+ mergedArray.push(left);
183
+ leftIndex++;
184
+ } else {
185
+ mergedArray.push(right);
186
+ rightIndex++;
187
+ }
188
+ }
189
+
190
+ // Add any remaining elements from the left array.
191
+ while (leftIndex < sortedLeftArray.length) {
192
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
193
+ const left = sortedLeftArray[leftIndex]!;
194
+ mergedArray.push(left);
195
+ leftIndex++;
196
+ }
197
+
198
+ // Add any remaining elements from the right array.
199
+ while (rightIndex < sortedRightArray.length) {
200
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
201
+ const right = sortedRightArray[rightIndex]!;
202
+ mergedArray.push(right);
203
+ rightIndex++;
204
+ }
205
+
206
+ return mergedArray;
207
+ }
@@ -1,4 +1,8 @@
1
1
  export function capitalizeFirstLetter(string: string): string {
2
+ if (string === "") {
3
+ return string;
4
+ }
5
+
2
6
  const firstCharacter = string.charAt(0);
3
7
  const capitalizedFirstLetter = firstCharacter.toUpperCase();
4
8
  const restOfString = string.slice(1);
@@ -5,4 +5,5 @@ import { Tuple } from "./Tuple";
5
5
  *
6
6
  * From: https://stackoverflow.com/questions/54243431/typescript-increment-number-type
7
7
  */
8
- export type Increment<N extends number> = [...Tuple<N>, unknown]["length"];
8
+ export type Increment<N extends number> = [...Tuple<N>, unknown]["length"] &
9
+ number;
@@ -1,12 +1,14 @@
1
- import { Increment } from "./Increment";
2
- import { NaturalNumbersLessThan } from "./NaturalNumbersLessThan";
3
-
4
1
  /**
5
2
  * Helper type to get a range of integers between 0 and N.
6
3
  *
7
4
  * From:
8
5
  * https://stackoverflow.com/questions/39494689/is-it-possible-to-restrict-number-to-a-certain-range
9
6
  */
10
- export type NaturalNumbersLessThanOrEqualTo<N extends number> =
11
- // @ts-expect-error The return value of increment is a number, but TypeScript gets confused.
12
- NaturalNumbersLessThan<Increment<N>>;
7
+ export type NaturalNumbersLessThanOrEqualTo<
8
+ N extends number,
9
+ T extends number[] = [],
10
+ > = T extends [unknown, ...infer Tail]
11
+ ? Tail["length"] extends N
12
+ ? T[number]
13
+ : NaturalNumbersLessThanOrEqualTo<N, [...T, T["length"]]>
14
+ : NaturalNumbersLessThanOrEqualTo<N, [...T, T["length"]]>;