UNPKG

isaacscript-common

Version:

Helper functions and features for IsaacScript mods.

162 lines (161 loc) 6.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearTable = clearTable; exports.copyUserdataValuesToTable = copyUserdataValuesToTable; exports.getBooleansFromTable = getBooleansFromTable; exports.getNumbersFromTable = getNumbersFromTable; exports.getStringsFromTable = getStringsFromTable; exports.isTableEmpty = isTableEmpty; exports.iterateTableInOrder = iterateTableInOrder; exports.tableHasKeys = tableHasKeys; const types_1 = require("./types"); const utils_1 = require("./utils"); /** * In a `Map`, you can use the `clear` method to delete every element. However, in a `LuaMap`, the * `clear` method does not exist. Use this helper function as a drop-in replacement for this. */ function clearTable(luaMap) { for (const [key] of luaMap) { luaMap.delete(key); } } /** Helper function to copy specific values from a userdata object (e.g. `Vector`) to a table. */ function copyUserdataValuesToTable(object, keys, luaMap) { if (!(0, types_1.isUserdata)(object)) { error(`Failed to copy an object values to a table, since the object was of type: ${type(object)}`); } // We can access values on userdata objects similar to a normal table. const userdata = object; for (const key of keys) { const value = userdata.get(key); luaMap.set(key, value); } } /** * Helper function to safely get boolean values from a Lua table. Will throw an error if the * specific value does not exist on the table. * * This function is variadic, meaning that you can specify N arguments to get N values. */ function getBooleansFromTable(luaMap, objectName, ...keys) { const booleans = []; for (const key of keys) { const value = luaMap.get(key); (0, utils_1.assertDefined)(value, `Failed to find a value for "${key}" in a table representing a "${objectName}" object.`); if ((0, types_1.isBoolean)(value)) { booleans.push(value); } else { error(`Failed to get the boolean for the "${key}" value of a table representing a "${objectName}" object because the type was: ${typeof value}`); } } return booleans; } /** * Helper function to safely get number values from specific keys on a Lua table. If the values are * strings, they will be converted to numbers. Will throw an error if the specific value does not * exist on the table or if it cannot be converted to a number. * * This function is variadic, meaning that you can specify N arguments to get N values. */ function getNumbersFromTable(luaMap, objectName, ...keys) { const numbers = []; for (const key of keys) { const value = luaMap.get(key); (0, utils_1.assertDefined)(value, `Failed to find a value for "${key}" in a table representing a "${objectName}" object.`); if ((0, types_1.isNumber)(value)) { numbers.push(value); } else if ((0, types_1.isString)(value)) { const number = tonumber(value); (0, utils_1.assertDefined)(number, `Failed to convert the "${key}" value of a table representing a "${objectName}" object to a number: ${value}`); numbers.push(number); } else { error(`Failed to get the number for the "${key}" value of a table representing a "${objectName}" object because the type was: ${typeof value}`); } } return numbers; } /** * Helper function to safely get string values from a Lua table. Will throw an error if the specific * value does not exist on the table. * * This function is variadic, meaning that you can specify N arguments to get N values. */ function getStringsFromTable(luaMap, objectName, ...keys) { const strings = []; for (const key of keys) { const value = luaMap.get(key); (0, utils_1.assertDefined)(value, `Failed to find a value for "${key}" in a table representing a "${objectName}" object.`); if ((0, types_1.isString)(value)) { strings.push(value); } else { const string = tostring(value); strings.push(string); } } return strings; } /** Helper function to check if a Lua table has 0 keys. */ function isTableEmpty(luaMap) { // Using `next` does not seem to work properly, so we use `pairs` instead. // eslint-disable-next-line no-unreachable-loop for (const [_key, _value] of luaMap) { return false; } return true; } /** * Helper function to iterate over a table deterministically. This is useful because by default, the * `pairs` function will return the keys of a Lua table in a random order. * * This function will sort the table entries based on the value of the key. * * This function will only work on tables that have number keys or string keys. It will throw a * run-time error if it encounters a key of another type. * * @param luaMap The table to iterate over. * @param func The function to run for each iteration. * @param inOrder Optional. Whether to iterate in order. True by default. You can dynamically set to * false in situations where iterating randomly would not matter and you need the * extra performance. */ function iterateTableInOrder(luaMap, func, inOrder = true) { // First, handle the trivial case of a non-deterministic iteration. if (!inOrder) { for (const [key, value] of luaMap) { func(key, value); } return; } const keys = Object.keys(luaMap); const hasAllNumberKeys = keys.every((key) => (0, types_1.isNumber)(key)); const hasAllStringKeys = keys.every((key) => (0, types_1.isString)(key)); if (!hasAllNumberKeys && !hasAllStringKeys) { // Since the table has non-homogenous keys, we won't be able to sort it. Revert to // non-deterministic iteration in this case. for (const [key, value] of luaMap) { func(key, value); } return; } keys.sort(); // eslint-disable-line @typescript-eslint/require-array-sort-compare for (const key of keys) { const keyIndex = key; const value = luaMap.get(keyIndex); if (value !== undefined) { func(keyIndex, value); } } } /** * Helper function to check if a Lua table has all of the provided keys. * * This function is variadic, meaning that you can specify as many arguments as you want to check * for. */ function tableHasKeys(luaMap, ...keys) { return keys.every((key) => luaMap.has(key)); }