271 lines
6.1 KiB
TypeScript
271 lines
6.1 KiB
TypeScript
import { AutocompleteInteraction } from 'discord.js';
|
|
import { CustomItem, ItemInventory, db } from '../db';
|
|
|
|
export type DefaultItem = Omit<CustomItem, 'guild'>; // 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<Item | undefined> {
|
|
if (id >= 0) {
|
|
return await getCustomItem(id);
|
|
} else {
|
|
return getDefaultItem(id);
|
|
}
|
|
}
|
|
|
|
export async function getCustomItem(id: number) {
|
|
return await db<CustomItem>('customItems')
|
|
.where('id', id)
|
|
.first();
|
|
}
|
|
|
|
export async function getItemQuantity(user: string, itemID: number): Promise<ItemInventory> {
|
|
return (await db<ItemInventory>('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<ItemInventory>('itemInventories')
|
|
.where('user', user)
|
|
.where('item', item.id)
|
|
.first();
|
|
|
|
let inv;
|
|
if (storedItem) {
|
|
inv = await db<ItemInventory>('itemInventories')
|
|
.update({
|
|
quantity: db.raw('MIN(quantity + ?, ?)', [quantity, getMaxStack(item)])
|
|
})
|
|
.limit(1)
|
|
.where('user', user)
|
|
.where('item', item.id)
|
|
.returning('*');
|
|
} else {
|
|
inv = await db<ItemInventory>('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<CustomItem>('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() }))
|
|
);
|
|
} |