Add the src/lib/economy service (GM baselines, deterministic per-period demand drift, price modifier computation, event emission) and the economy-tick bin. Gated by GameRules economy.enabled; period-idempotent with a cold-start observation gate. Ultraworked with [Sisyphus](https://github.com/code-yeongju/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
/**
|
|
* Supply & demand economy — find/load helpers shared by the tick
|
|
* orchestrator. Kept out of `tick.ts` to respect the 250-line ceiling.
|
|
*/
|
|
|
|
import type { Payload } from "payload";
|
|
import type { Where } from "payload";
|
|
|
|
import type { EconomyItemType } from "./types";
|
|
|
|
export type ItemRef = { itemType: EconomyItemType; itemId: number };
|
|
|
|
export const FIND_LIMIT = 500;
|
|
|
|
export async function findItemIds(
|
|
payload: Payload,
|
|
itemType: EconomyItemType,
|
|
items: ItemRef[] | undefined,
|
|
): Promise<number[]> {
|
|
if (items) {
|
|
return items.filter((i) => i.itemType === itemType).map((i) => i.itemId);
|
|
}
|
|
const { docs } = await payload.find({
|
|
collection: itemType === "resource" ? "resources" : "assets",
|
|
where: { tradeable: { equals: true } },
|
|
limit: FIND_LIMIT,
|
|
depth: 0,
|
|
});
|
|
return docs.map((d) => d.id);
|
|
}
|
|
|
|
export async function loadItemDocs(
|
|
payload: Payload,
|
|
itemType: EconomyItemType,
|
|
itemIds: number[],
|
|
): Promise<Map<number, Record<string, unknown>>> {
|
|
const byId = new Map<number, Record<string, unknown>>();
|
|
const collection = itemType === "resource" ? "resources" : "assets";
|
|
for (let i = 0; i < itemIds.length; i += FIND_LIMIT) {
|
|
const chunk = itemIds.slice(i, i + FIND_LIMIT);
|
|
const { docs } = await payload.find({
|
|
collection,
|
|
where: { id: { in: chunk } },
|
|
limit: FIND_LIMIT,
|
|
depth: 0,
|
|
});
|
|
for (const doc of docs) {
|
|
byId.set(doc.id, doc as unknown as Record<string, unknown>);
|
|
}
|
|
}
|
|
return byId;
|
|
}
|
|
|
|
export function marketStateWhereFor(items: ItemRef[]): Where {
|
|
return {
|
|
or: items.map(
|
|
(i): Where => ({
|
|
and: [{ itemType: { equals: i.itemType } }, { itemId: { equals: i.itemId } }],
|
|
}),
|
|
),
|
|
};
|
|
}
|