import { AutocompleteInteraction } from 'discord.js'; import { CustomItem, ItemInventory, db } from '../db'; export type DefaultItem = Omit; // uses negative IDs export type Item = DefaultItem | CustomItem; export interface Items { item: Item, quantity: number } export enum DefaultItems { COIN = 1, WORKBENCH = 2, PEBBLE = 3, TWIG = 4, APPLE = 5, BERRIES = 6, LOG = 7, AXE = 8, BLOOD = 9, BAIT = 10, FISHING_ROD = 11, CARP = 12, PUFFERFISH = 13, EXOTIC_FISH = 14, SHOVEL = 15, DIRT = 16, } export const defaultItems: DefaultItem[] = [ { id: -1, name: 'Coin', emoji: '🪙', type: 'plain', maxStack: 9999, untradable: false }, { id: -2, name: 'Workbench', description: 'A place for you to work with tools, for simple things', emoji: '🛠️', type: 'plain', maxStack: 1, untradable: false }, { id: -3, name: 'Pebble', description: 'If you get 5 of them you will instantly ! !!!', emoji: '🪨', type: 'plain', maxStack: 64, untradable: false }, { id: -4, name: 'Twig', description: 'Just a tiny bit of wood', emoji: '🌿', type: 'plain', maxStack: 64, untradable: false }, { id: -5, name: 'Apple', description: 'A forager\'s snack', emoji: '🍎', type: 'consumable', maxStack: 16, untradable: false }, { id: -6, name: 'Berries', description: 'A little treat for the road!', emoji: '🍓', type: 'consumable', maxStack: 16, untradable: false }, { id: -7, name: 'Log', description: '㏒', emoji: '🪵', type: 'plain', maxStack: 64, untradable: false }, { id: -8, name: 'Axe', description: 'You could chop trees with this. Or commit murder! The choice is up to you', emoji: '🪓', type: 'weapon', maxStack: 1, untradable: false }, { id: -9, name: 'Blood', description: 'ow', emoji: '🩸', type: 'plain', maxStack: 1024, untradable: false }, { id: -10, name: 'Bait', description: 'I guess you could eat this.', emoji: '🪱', type: 'consumable', maxStack: 128, untradable: false }, { id: -11, name: 'Fishing Rod', description: 'Give a man a fish, and he will eat for a day', emoji: '🎣', type: 'plain', maxStack: 1, untradable: false }, { id: -12, name: 'Carp', description: 'wow', emoji: '🐟️', type: 'plain', maxStack: 16, untradable: false }, { id: -13, name: 'Pufferfish', description: 'yummy!', emoji: '🐡', type: 'plain', maxStack: 16, untradable: false }, { id: -14, name: 'Exotic Fish', description: 'lucky!', emoji: '🐠', type: 'plain', maxStack: 16, untradable: false, }, { id: -15, name: 'Shovel', description: 'Did you know there\'s no shovel emoji', emoji: '♠️', type: 'plain', maxStack: 1, untradable: false, }, { id: -16, name: 'Dirt', description: 'https://media.discordapp.net/attachments/819472665291128873/1081454188325785650/ezgif-2-5ccc7dedf8.gif', emoji: '🟫', type: 'consumable', maxStack: 64, untradable: false, }, ]; export function getDefaultItem(id: DefaultItems): Item export function getDefaultItem(id: number): Item | undefined { return defaultItems.find(item => Math.abs(item.id) === Math.abs(id)); } export async function getItem(id: number): Promise { if (id >= 0) { return await getCustomItem(id); } else { return getDefaultItem(id); } } export async function getCustomItem(id: number) { return await db('customItems') .where('id', id) .first(); } export async function getItemQuantity(user: string, itemID: number): Promise { return (await db('itemInventories') .where('item', itemID) .where('user', user) .first()) || { user: user, item: itemID, quantity: 0 }; } export async function giveItem(user: string, item: Item, quantity = 1) { const storedItem = await db('itemInventories') .where('user', user) .where('item', item.id) .first(); let inv; if (storedItem) { inv = await db('itemInventories') .update({ quantity: db.raw('MIN(quantity + ?, ?)', [quantity, getMaxStack(item)]) }) .limit(1) .where('user', user) .where('item', item.id) .returning('*'); } else { inv = await db('itemInventories') .insert({ user: user, item: Math.min(item.id, getMaxStack(item)), quantity: quantity }) .returning('*'); } return inv[0]; } export function getMaxStack(item: Item) { return item.type === 'weapon' ? 1 : item.maxStack; } export function formatItem(item: Item | undefined, disableBold = false) { if (!item) return disableBold ? '? MISSINGNO' : '? **MISSINGNO**'; return disableBold ? `${item.emoji} ${item.name}` : `${item.emoji} **${item.name}**`; } export function formatItems(item: Item | undefined, quantity: number, disableBold = false) { return `${quantity}x ${formatItem(item, disableBold)}`; } export function formatItemsArray(items: Items[], disableBold = false) { if (items.length === 0) return disableBold ? 'nothing' : '**nothing**'; return items.map(i => formatItems(i.item, i.quantity, disableBold)).join(' '); } export async function itemAutocomplete(interaction: AutocompleteInteraction) { const focused = interaction.options.getFocused(); const customItems = await db('customItems') .select('emoji', 'name', 'id') // @ts-expect-error this LITERALLY works .whereLike(db.raw('UPPER(name)'), `%${focused.toUpperCase()}%`) .where('guild', interaction.guildId!) .limit(25); const foundDefaultItems = defaultItems.filter(item => item.name.toUpperCase().includes(focused.toUpperCase())); const items = [...foundDefaultItems, ...customItems]; await interaction.respond( items.map(choice => ({ name: `${choice.emoji} ${choice.name}`, value: choice.id.toString() })) ); }