diff --git a/CHANGELOG.md b/CHANGELOG.md index bba293751e..1b8814503e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -113,6 +113,8 @@ Basic Authentication - username/password based login - uses bip39 for recovery phrases +/additem +- added ability to fuzzy search for matching name, or dbname ``` ## 5.0.0 diff --git a/src/core/plugins/core-commands/server/commands/moderator/item.ts b/src/core/plugins/core-commands/server/commands/moderator/item.ts index f29574acf0..214b28dec3 100644 --- a/src/core/plugins/core-commands/server/commands/moderator/item.ts +++ b/src/core/plugins/core-commands/server/commands/moderator/item.ts @@ -3,11 +3,11 @@ import * as Athena from '@AthenaServer/api'; Athena.commands.register( 'additem', - '/additem [dbName] [amount] [version?]', + '/additem [partialName] [amount] [version?]', ['admin'], - async (player: alt.Player, dbName: string, amount: string, version: string | undefined) => { - if (typeof dbName === 'undefined') { - Athena.player.emit.message(player, `Must specify a dbName to add an item.`); + async (player: alt.Player, partialName: string, amount: string, version: string | undefined) => { + if (typeof partialName === 'undefined') { + Athena.player.emit.message(player, `Must specify a partialName to add an item.`); return; } @@ -31,8 +31,14 @@ Athena.commands.register( } } + const baseItem = Athena.systems.inventory.factory.getBaseItemByFuzzySearch(partialName); + if (typeof baseItem === 'undefined') { + Athena.player.emit.message(player, `Item '${partialName}' does not exist!`); + return; + } + const result = await Athena.player.inventory.add(player, { - dbName, + dbName: baseItem.dbName, quantity: actualAmount, data: {}, version: actualVersion, diff --git a/src/core/server/systems/inventory/factory.ts b/src/core/server/systems/inventory/factory.ts index 71bf70026f..7c87253b83 100644 --- a/src/core/server/systems/inventory/factory.ts +++ b/src/core/server/systems/inventory/factory.ts @@ -445,6 +445,57 @@ export function getBaseItems(): Array { return databaseItems; } +/** + * Searches for a base item based on a fuzzy search. + * Specify either 'myitem', 'My_Item', or 'My Item'. + * + * Will try to find a match in the following order: + * - Exact dbname + * - Exact name + * - Partial name + * - Partial dbname + * + * @export + * @template CustomData + * @param {string} partialName + * @return {(BaseItem | undefined)} + */ +export function getBaseItemByFuzzySearch( + partialName: string, +): BaseItem | undefined { + partialName = partialName.replaceAll('_', ' '); + + const index = databaseItems.findIndex((item) => { + // 'myitem' -> 'myitem' + if (item.dbName === partialName) { + return true; + } + + // 'My_Item' -> 'My Item' + if (item.name === partialName) { + return true; + } + + // 'My_It' -> 'My Item' + if (item.name.includes(partialName)) { + return true; + } + + // 'myi' -> 'myitem' + if (item.dbName.includes(partialName)) { + return true; + } + + return false; + }); + + if (index <= -1) { + return undefined; + } + + return deepCloneObject>(databaseItems[index]); +} + interface FactoryFuncs { getBaseItemAsync: typeof getBaseItemAsync; upsertAsync: typeof upsertAsync; @@ -456,6 +507,7 @@ interface FactoryFuncs { fromBaseToStored: typeof fromBaseToStored; getBaseItemsAsync: typeof getBaseItemsAsync; getBaseItems: typeof getBaseItems; + getBaseItemByFuzzySearch: typeof getBaseItemByFuzzySearch; } const Overrides: Partial = {}; @@ -470,6 +522,7 @@ export function override(functionName: 'toStoredItem', callback: typeof toStored export function override(functionName: 'fromBaseToStored', callback: typeof fromBaseToStored); export function override(functionName: 'getBaseItems', callback: typeof getBaseItems); export function override(functionName: 'getBaseItemsAsync', callback: typeof getBaseItemsAsync); +export function override(functionName: 'getBaseItemByFuzzySearch', callback: typeof getBaseItemByFuzzySearch); /** * Used to override inventory item factory functionality *