move stuff around until circular dependencies go away

This commit is contained in:
Jill 2023-11-15 18:11:48 +03:00
parent 3fcfe5851b
commit 42d875a68f
Signed by: oat
GPG Key ID: 33489AA58A955108
7 changed files with 166 additions and 160 deletions

View File

@ -1,7 +1,8 @@
import { AutocompleteInteraction, GuildMember, Interaction, SlashCommandBuilder } from 'discord.js';
import { craftingStations, defaultRecipes } from '../lib/rpg/data';
import { canUseStation, formatItem, formatItems, formatItemsArray, formatRecipe, getItemQuantity, getMaxStack, getRecipe, getStation, giveItem } from '../lib/rpg/items';
import { CraftingStationCooldown, db } from '../lib/db';
import { getStation, canUseStation, craftingStations } from '../lib/rpg/craftingStations';
import { formatItem, getItemQuantity, formatItems, getMaxStack, giveItem, formatItemsArray } from '../lib/rpg/items';
import { getRecipe, defaultRecipes, formatRecipe } from '../lib/rpg/recipes';
module.exports = {
data: new SlashCommandBuilder()

View File

@ -1,7 +1,7 @@
import { AutocompleteInteraction, Interaction, SlashCommandBuilder } from 'discord.js';
import { CustomItem, db } from '../lib/db';
import { formatItems, getItem, giveItem, itemAutocomplete } from '../lib/rpg/items';
import { behaviors } from '../lib/rpg/data';
import { behaviors } from '../lib/rpg/behaviors';
//function extendOption(t: string) {
// return {name: t, value: t};

26
src/lib/rpg/behaviors.ts Normal file
View File

@ -0,0 +1,26 @@
import type { User } from 'discord.js';
import type { Item } from './items';
export interface Behavior {
name: string,
description: string,
itemType: 'plain' | 'weapon' | 'consumable',
// triggers upon use
// for 'weapons', this is on hit
// for 'consumable', this is on use
// for 'plain', ...??
// returns `true` upon success, `false` otherwise
action?: (item: Item, user: User) => Promise<boolean>
}
export const behaviors: Behavior[] = [
{
name: 'heal',
description: 'Heals the user by `behaviorValue`',
itemType: 'consumable',
action: async (item, user) => {
// todo
return false;
}
}
];

View File

@ -0,0 +1,50 @@
import { DefaultItems, Item, Items, formatItems, getDefaultItem, getItemQuantity } from './items';
export interface CraftingStation {
key: string,
name: string,
description: string,
emoji: string,
requires?: Item,
// in seconds
cooldown?: number,
formatRecipe?: (inputs: Items[], requirements: Items[], outputs: Items[]) => string,
manipulateResults?: (outputs: Items[]) => Items[]
}
export function getStation(key: string) {
return craftingStations.find(station => station.key === key);
}
export const craftingStations: CraftingStation[] = [
{
key: 'forage',
name: 'Forage',
description: 'Pick up various sticks and stones from the forest',
emoji: '🌲',
cooldown: 60 * 5,
formatRecipe: (_inputs, _requirements, outputs) => `${outputs.map(i => formatItems(i.item, i.quantity) + '?').join(' ')}`,
manipulateResults: (outputs) =>
outputs.map(o => ({item: o.item, quantity: Math.floor(o.quantity * Math.random())})).filter(o => o.quantity !== 0)
},
{
key: 'hand',
name: 'Hand',
description: 'You can use your hands to make a small assortment of things',
emoji: '✋'
},
{
key: 'workbench',
name: 'Workbench',
description: 'A place for you to work with tools, for simple things',
emoji: '🛠️',
requires: getDefaultItem(DefaultItems.WORKBENCH)
}
];
export async function canUseStation(user: string, station: CraftingStation) {
if (!station.requires) return true;
const inv = await getItemQuantity(user, station.requires.id);
return inv.quantity > 0;
}

View File

@ -1,97 +0,0 @@
import { Behavior, CraftingStation, DefaultItem, DefaultRecipe, formatItems, getDefaultItem } from './items';
export enum DefaultItems {
COIN = 1,
WORKBENCH = 2,
PEBBLE = 3
}
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
}
];
export const behaviors: Behavior[] = [
{
name: 'heal',
description: 'Heals the user by `behaviorValue`',
itemType: 'consumable',
action: async (item, user) => {
// todo
return false;
}
}
];
export const craftingStations: CraftingStation[] = [
{
key: 'forage',
name: 'Forage',
description: 'Pick up various sticks and stones from the forest',
emoji: '🌲',
cooldown: 60 * 5,
formatRecipe: (_inputs, _requirements, outputs) => `${outputs.map(i => formatItems(i.item, i.quantity) + '?').join(' ')}`,
manipulateResults: (outputs) =>
outputs.map(o => ({item: o.item, quantity: Math.floor(o.quantity * Math.random())})).filter(o => o.quantity !== 0)
},
{
key: 'hand',
name: 'Hand',
description: 'You can use your hands to make a small assortment of things',
emoji: '✋'
},
{
key: 'workbench',
name: 'Workbench',
description: 'A place for you to work with tools, for simple things',
emoji: '🛠️',
requires: getDefaultItem(DefaultItems.WORKBENCH)
}
];
export const defaultRecipes: DefaultRecipe[] = [
{
id: -1,
station: 'forage',
inputs: [],
requirements: [],
outputs: [
{ item: getDefaultItem(DefaultItems.PEBBLE), quantity: 2 }
]
},
{
id: -2,
station: 'workbench',
inputs: [
{ item: getDefaultItem(DefaultItems.PEBBLE), quantity: 2 }
],
requirements: [],
outputs: [
{ item: getDefaultItem(DefaultItems.WORKBENCH), quantity: 1 }
]
}
];

View File

@ -1,64 +1,49 @@
import { AutocompleteInteraction, User } from 'discord.js';
import { AutocompleteInteraction } from 'discord.js';
import { CustomItem, ItemInventory, db } from '../db';
import { DefaultItems, craftingStations, defaultItems, defaultRecipes } from './data';
export type DefaultItem = Omit<CustomItem, 'guild'>; // uses negative IDs
export type Item = DefaultItem | CustomItem;
export interface Behavior {
name: string,
description: string,
itemType: 'plain' | 'weapon' | 'consumable',
// triggers upon use
// for 'weapons', this is on hit
// for 'consumable', this is on use
// for 'plain', ...??
// returns `true` upon success, `false` otherwise
action?: (item: Item, user: User) => Promise<boolean>
}
export interface Items {
item: Item,
quantity: number
}
const defaultFormatRecipe = (inputs: Items[], requirements: Items[], outputs: Items[]) =>
`${formatItemsArray(inputs)}${requirements.length === 0 ? '' : ` w/ ${formatItemsArray(requirements)}`} => ${formatItemsArray(outputs)}`;
export interface CraftingStation {
key: string,
name: string,
description: string,
emoji: string,
requires?: Item,
// in seconds
cooldown?: number,
formatRecipe?: (inputs: Items[], requirements: Items[], outputs: Items[]) => string,
manipulateResults?: (outputs: Items[]) => Items[]
export enum DefaultItems {
COIN = 1,
WORKBENCH = 2,
PEBBLE = 3
}
export function getStation(key: string) {
return craftingStations.find(station => station.key === key);
}
export function formatRecipe(recipe: DefaultRecipe) {
const station = getStation(recipe.station);
return (station?.formatRecipe || defaultFormatRecipe)(recipe.inputs, recipe.requirements, recipe.outputs);
}
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
}
];
export interface DefaultRecipe {
id: number,
station: string,
inputs: Items[],
requirements: Items[],
outputs: Items[]
}
export type Recipe = DefaultRecipe
export async function getCustomItem(id: number) {
return await db<CustomItem>('customItems')
.where('id', id)
.first();
}
export function getDefaultItem(id: DefaultItems): Item
export function getDefaultItem(id: number): Item | undefined {
@ -73,18 +58,10 @@ export async function getItem(id: number): Promise<Item | undefined> {
}
}
export function getDefaultRecipe(id: number): DefaultRecipe | undefined {
return defaultRecipes.find(recipe => recipe.id === id);
}
export function getRecipe(id: number): Recipe | undefined {
return getDefaultRecipe(id); // currently just a stub
}
export async function canUseStation(user: string, station: CraftingStation) {
if (!station.requires) return true;
const inv = await getItemQuantity(user, station.requires.id);
return inv.quantity > 0;
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> {

49
src/lib/rpg/recipes.ts Normal file
View File

@ -0,0 +1,49 @@
import { getStation } from './craftingStations';
import { DefaultItems, Items, formatItemsArray, getDefaultItem } from './items';
export interface DefaultRecipe {
id: number,
station: string,
inputs: Items[],
requirements: Items[],
outputs: Items[]
}
export type Recipe = DefaultRecipe
export const defaultRecipes: DefaultRecipe[] = [
{
id: -1,
station: 'forage',
inputs: [],
requirements: [],
outputs: [
{ item: getDefaultItem(DefaultItems.PEBBLE), quantity: 2 }
]
},
{
id: -2,
station: 'workbench',
inputs: [
{ item: getDefaultItem(DefaultItems.PEBBLE), quantity: 2 }
],
requirements: [],
outputs: [
{ item: getDefaultItem(DefaultItems.WORKBENCH), quantity: 1 }
]
}
];
export function getDefaultRecipe(id: number): DefaultRecipe | undefined {
return defaultRecipes.find(recipe => recipe.id === id);
}
export function getRecipe(id: number): Recipe | undefined {
return getDefaultRecipe(id); // currently just a stub
}
const defaultFormatRecipe = (inputs: Items[], requirements: Items[], outputs: Items[]) =>
`${formatItemsArray(inputs)}${requirements.length === 0 ? '' : ` w/ ${formatItemsArray(requirements)}`} => ${formatItemsArray(outputs)}`;
export function formatRecipe(recipe: DefaultRecipe) {
const station = getStation(recipe.station);
return (station?.formatRecipe || defaultFormatRecipe)(recipe.inputs, recipe.requirements, recipe.outputs);
}