refactor: bunch of reorg updates
This commit is contained in:
parent
b28ec823a7
commit
f7b59a1790
|
|
@ -0,0 +1,2 @@
|
||||||
|
# 《背包爬塔》肉鸽
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import type { EffectDesert } from "../data/effectDesert.csv";
|
import type { EffectDesert } from "../data/effectDesert.csv";
|
||||||
import type { StatusCardDesert } from "../data/statusCardDesert.csv";
|
import type { CardDesert } from "../data/cardDesert.csv";
|
||||||
import { effectDesertData, statusCardDesertData } from "../data";
|
import { effectDesertData, cardDesertData } from "../data";
|
||||||
import { createStatusCard } from "../deck/factory";
|
import { createStatusCard } from "../deck/factory";
|
||||||
import type { PlayerDeck, GameCard } from "../deck/types";
|
import type { PlayerDeck, GameCard } from "../deck/types";
|
||||||
import type {
|
import type {
|
||||||
|
|
@ -321,7 +321,7 @@ function resolveInstantEffect(
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStatusCardToDiscard(state: CombatState, effectId: string, count: number): void {
|
function addStatusCardToDiscard(state: CombatState, effectId: string, count: number): void {
|
||||||
const cardDef = statusCardDesertData.find(c => c.id === effectId);
|
const cardDef = cardDesertData.find(c => c.id === effectId);
|
||||||
if (!cardDef) return;
|
if (!cardDef) return;
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
|
|
@ -333,7 +333,7 @@ function addStatusCardToDiscard(state: CombatState, effectId: string, count: num
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStatusCardToDrawPile(state: CombatState, effectId: string, count: number): void {
|
function addStatusCardToDrawPile(state: CombatState, effectId: string, count: number): void {
|
||||||
const cardDef = statusCardDesertData.find(c => c.id === effectId);
|
const cardDef = cardDesertData.find(c => c.id === effectId);
|
||||||
if (!cardDef) return;
|
if (!cardDef) return;
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
|
|
@ -345,7 +345,7 @@ function addStatusCardToDrawPile(state: CombatState, effectId: string, count: nu
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStatusCardToHand(state: CombatState, effectId: string, count: number): void {
|
function addStatusCardToHand(state: CombatState, effectId: string, count: number): void {
|
||||||
const cardDef = statusCardDesertData.find(c => c.id === effectId);
|
const cardDef = cardDesertData.find(c => c.id === effectId);
|
||||||
if (!cardDef) return;
|
if (!cardDef) return;
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
|
|
@ -411,7 +411,7 @@ export function resolveCardEffects(
|
||||||
|
|
||||||
const sourceKey: "player" | string = "player";
|
const sourceKey: "player" | string = "player";
|
||||||
|
|
||||||
const effects = card.itemData.effects as unknown as CombatEffectEntry[];
|
const effects = card.itemData.onPlay as unknown as CombatEffectEntry[];
|
||||||
for (const entry of effects) {
|
for (const entry of effects) {
|
||||||
const [target, effect, stacks] = entry;
|
const [target, effect, stacks] = entry;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ export async function runCombat(
|
||||||
): Promise<CombatResult> {
|
): Promise<CombatResult> {
|
||||||
const triggerRegistry = createCombatTriggerRegistry();
|
const triggerRegistry = createCombatTriggerRegistry();
|
||||||
|
|
||||||
|
// TODO prefer await game.produceAsync over game.produce since produceAsync can await ui animations
|
||||||
game.produce(state => {
|
game.produce(state => {
|
||||||
state.phase = "playerTurn";
|
state.phase = "playerTurn";
|
||||||
state.player.energy = state.player.maxEnergy;
|
state.player.energy = state.player.maxEnergy;
|
||||||
|
|
@ -93,6 +94,7 @@ async function runPlayerTurn(
|
||||||
state.player.damagedThisTurn = false;
|
state.player.damagedThisTurn = false;
|
||||||
state.player.cardsDiscardedThisTurn = 0;
|
state.player.cardsDiscardedThisTurn = 0;
|
||||||
|
|
||||||
|
// TODO avoid hardcoding here, prefer handling these in either the onTurnStart trigger or the onBuffUpdate trigger
|
||||||
if (state.player.buffs["energyNext"]) {
|
if (state.player.buffs["energyNext"]) {
|
||||||
state.player.energy += state.player.buffs["energyNext"];
|
state.player.energy += state.player.buffs["energyNext"];
|
||||||
}
|
}
|
||||||
|
|
@ -150,6 +152,7 @@ async function runPlayerTurn(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO end is an alternative action to be taken by the player.
|
||||||
const endAction = await game.prompt<{ action: "end" }>(
|
const endAction = await game.prompt<{ action: "end" }>(
|
||||||
prompts.endTurn,
|
prompts.endTurn,
|
||||||
() => {
|
() => {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@ import type { GridInventory } from "../grid-inventory/types";
|
||||||
import type { GameItemMeta, PlayerState } from "../progress/types";
|
import type { GameItemMeta, PlayerState } from "../progress/types";
|
||||||
import type { PlayerDeck } from "../deck/types";
|
import type { PlayerDeck } from "../deck/types";
|
||||||
import type { EnemyDesert } from "../data/enemyDesert.csv";
|
import type { EnemyDesert } from "../data/enemyDesert.csv";
|
||||||
import type { EnemyIntentDesert } from "../data/enemyIntentDesert.csv";
|
|
||||||
import type { EncounterDesert } from "../data/encounterDesert.csv";
|
|
||||||
import type { EffectDesert } from "../data/effectDesert.csv";
|
import type { EffectDesert } from "../data/effectDesert.csv";
|
||||||
|
import type { EncounterDesert } from "../data/encounterDesert.csv";
|
||||||
import { generateDeckFromInventory, createStatusCard } from "../deck/factory";
|
import { generateDeckFromInventory, createStatusCard } from "../deck/factory";
|
||||||
import { enemyDesertData, enemyIntentDesertData, effectDesertData } from "../data";
|
import { enemyDesertData, effectDesertData } from "../data";
|
||||||
import type {
|
import type {
|
||||||
BuffTable,
|
BuffTable,
|
||||||
CombatState,
|
CombatState,
|
||||||
|
|
@ -23,40 +22,50 @@ const FATIGUE_CARDS_PER_SHUFFLE = 2;
|
||||||
|
|
||||||
export function createEnemyInstance(
|
export function createEnemyInstance(
|
||||||
templateId: string,
|
templateId: string,
|
||||||
enemyData: EnemyDesert,
|
hp: number,
|
||||||
bonusHp: number,
|
initBuffs: [EffectDesert, number][],
|
||||||
idCounter: { value: number },
|
idCounter: { value: number },
|
||||||
): EnemyState {
|
): EnemyState {
|
||||||
idCounter.value++;
|
idCounter.value++;
|
||||||
const id = `enemy-${idCounter.value}`;
|
const id = `enemy-${idCounter.value}`;
|
||||||
const maxHp = enemyData.initHp + bonusHp;
|
const maxHp = hp;
|
||||||
const hp = maxHp;
|
const currentHp = hp;
|
||||||
|
|
||||||
const buffs: BuffTable = {};
|
const buffs: BuffTable = {};
|
||||||
for (const [effect, stacks] of enemyData.initBuffs) {
|
for (const [effect, stacks] of initBuffs) {
|
||||||
buffs[effect.id] = (buffs[effect.id] ?? 0) + stacks;
|
buffs[effect.id] = (buffs[effect.id] ?? 0) + stacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
const intentData = buildIntentLookup(templateId);
|
const intentData = buildIntentLookup(templateId);
|
||||||
|
const initialIntent = findInitialIntent(templateId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
templateId,
|
templateId,
|
||||||
hp,
|
hp: currentHp,
|
||||||
maxHp,
|
maxHp,
|
||||||
buffs,
|
buffs,
|
||||||
currentIntentId: enemyData.initialIntent,
|
currentIntentId: initialIntent ?? "",
|
||||||
intentData,
|
intentData,
|
||||||
isAlive: true,
|
isAlive: true,
|
||||||
hadDefendBroken: false,
|
hadDefendBroken: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildIntentLookup(enemyTemplateId: string): Record<string, EnemyIntentDesert> {
|
function findInitialIntent(enemyTemplateId: string): string | undefined {
|
||||||
const lookup: Record<string, EnemyIntentDesert> = {};
|
for (const row of enemyDesertData) {
|
||||||
for (const intent of enemyIntentDesertData) {
|
if (row.enemy === enemyTemplateId && row.initialIntent) {
|
||||||
if (intent.enemy.id === enemyTemplateId) {
|
return row.intentId;
|
||||||
lookup[intent.id] = intent;
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildIntentLookup(enemyTemplateId: string): Record<string, EnemyDesert> {
|
||||||
|
const lookup: Record<string, EnemyDesert> = {};
|
||||||
|
for (const row of enemyDesertData) {
|
||||||
|
if (row.enemy === enemyTemplateId) {
|
||||||
|
lookup[row.intentId] = row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lookup;
|
return lookup;
|
||||||
|
|
@ -92,16 +101,26 @@ export function createCombatState(
|
||||||
const enemyOrder: string[] = [];
|
const enemyOrder: string[] = [];
|
||||||
const enemyTemplateData: Record<string, EnemyDesert> = {};
|
const enemyTemplateData: Record<string, EnemyDesert> = {};
|
||||||
|
|
||||||
for (const [enemyRef, bonusHp] of encounter.enemies) {
|
for (const [enemyId, hp, bonusHp] of encounter.enemies) {
|
||||||
|
// Find initBuffs from enemyDesert (first row for this enemy type)
|
||||||
|
const enemyRow = enemyDesertData.find(e => e.enemy === enemyId);
|
||||||
|
const initBuffs: [EffectDesert, number][] = [];
|
||||||
|
if (enemyRow) {
|
||||||
|
for (const [effect, stacks] of enemyRow.initBuffs) {
|
||||||
|
initBuffs.push([effect, stacks]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalHp = hp + bonusHp;
|
||||||
const enemyInstance = createEnemyInstance(
|
const enemyInstance = createEnemyInstance(
|
||||||
enemyRef.id,
|
enemyId,
|
||||||
enemyRef,
|
totalHp,
|
||||||
bonusHp,
|
initBuffs,
|
||||||
idCounter,
|
idCounter,
|
||||||
);
|
);
|
||||||
enemies[enemyInstance.id] = enemyInstance;
|
enemies[enemyInstance.id] = enemyInstance;
|
||||||
enemyOrder.push(enemyInstance.id);
|
enemyOrder.push(enemyInstance.id);
|
||||||
enemyTemplateData[enemyInstance.templateId] = enemyRef;
|
enemyTemplateData[enemyInstance.templateId] = enemyRow!;
|
||||||
}
|
}
|
||||||
|
|
||||||
shuffleDeck(player.deck.drawPile, buildSimpleRNG(0));
|
shuffleDeck(player.deck.drawPile, buildSimpleRNG(0));
|
||||||
|
|
@ -126,6 +145,7 @@ export function drawCardsToHand(deck: PlayerDeck, count: number): string[] {
|
||||||
const drawn: string[] = [];
|
const drawn: string[] = [];
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
if (deck.drawPile.length === 0) {
|
if (deck.drawPile.length === 0) {
|
||||||
|
// TODO think we should shuffle Fatigue into the deck here.
|
||||||
reshuffleDiscardIntoDraw(deck);
|
reshuffleDiscardIntoDraw(deck);
|
||||||
}
|
}
|
||||||
if (deck.drawPile.length === 0) break;
|
if (deck.drawPile.length === 0) break;
|
||||||
|
|
@ -153,6 +173,7 @@ export function addFatigueCards(deck: PlayerDeck, count: number, fatigueCounter:
|
||||||
let added = 0;
|
let added = 0;
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
fatigueCounter.value++;
|
fatigueCounter.value++;
|
||||||
|
// TODO avoid hard coding, expect a fatigue card to be in the CSV with a specific id.
|
||||||
const card = createStatusCard(
|
const card = createStatusCard(
|
||||||
`fatigue-${fatigueCounter.value}`,
|
`fatigue-${fatigueCounter.value}`,
|
||||||
"疲劳",
|
"疲劳",
|
||||||
|
|
@ -187,7 +208,7 @@ export function exhaustCard(deck: PlayerDeck, cardId: string): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEnemyCurrentIntent(enemy: EnemyState): EnemyIntentDesert | undefined {
|
export function getEnemyCurrentIntent(enemy: EnemyState): EnemyDesert | undefined {
|
||||||
return enemy.intentData[enemy.currentIntentId];
|
return enemy.intentData[enemy.currentIntentId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,18 +218,18 @@ export function advanceEnemyIntent(enemy: EnemyState): void {
|
||||||
|
|
||||||
if (enemy.hadDefendBroken && current.brokenIntent.length > 0) {
|
if (enemy.hadDefendBroken && current.brokenIntent.length > 0) {
|
||||||
const idx = Math.floor(Math.random() * current.brokenIntent.length);
|
const idx = Math.floor(Math.random() * current.brokenIntent.length);
|
||||||
enemy.currentIntentId = current.brokenIntent[idx].id;
|
enemy.currentIntentId = current.brokenIntent[idx];
|
||||||
enemy.hadDefendBroken = false;
|
enemy.hadDefendBroken = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current.nextIntents.length > 0) {
|
if (current.nextIntents.length > 0) {
|
||||||
const idx = Math.floor(Math.random() * current.nextIntents.length);
|
const idx = Math.floor(Math.random() * current.nextIntents.length);
|
||||||
enemy.currentIntentId = current.nextIntents[idx].id;
|
enemy.currentIntentId = current.nextIntents[idx];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
enemy.currentIntentId = current.id;
|
enemy.currentIntentId = current.intentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shuffleDeck(drawPile: string[], rng: { nextInt: (n: number) => number }): void {
|
function shuffleDeck(drawPile: string[], rng: { nextInt: (n: number) => number }): void {
|
||||||
|
|
@ -218,6 +239,7 @@ function shuffleDeck(drawPile: string[], rng: { nextInt: (n: number) => number }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO why? use @/utils/rng.ts instead?
|
||||||
function buildSimpleRNG(seed: number) {
|
function buildSimpleRNG(seed: number) {
|
||||||
let s = seed;
|
let s = seed;
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { EffectDesert } from "../data/effectDesert.csv";
|
import type { EffectDesert } from "../data/effectDesert.csv";
|
||||||
import { statusCardDesertData } from "../data";
|
import { cardDesertData } from "../data";
|
||||||
import { createStatusCard } from "../deck/factory";
|
import { createStatusCard } from "../deck/factory";
|
||||||
import type { BuffTable, CombatEffectEntry, CombatState } from "./types";
|
import type { BuffTable, CombatEffectEntry, CombatState } from "./types";
|
||||||
import { applyDamage, removeBuff } from "./effects";
|
import { applyDamage, removeBuff } from "./effects";
|
||||||
|
|
@ -197,7 +197,7 @@ export function createCombatTriggerRegistry(): CombatTriggerRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStatusCardToHand(state: CombatState, effectId: string, count: number): void {
|
function addStatusCardToHand(state: CombatState, effectId: string, count: number): void {
|
||||||
const cardDef = statusCardDesertData.find(c => c.id === effectId);
|
const cardDef = cardDesertData.find(c => c.id === effectId);
|
||||||
if (!cardDef) return;
|
if (!cardDef) return;
|
||||||
|
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
// TODO shouldn't rely on csv types. Use interfaces and expect csv types to match.
|
// TODO shouldn't rely on csv types. Use interfaces and expect csv types to match.
|
||||||
import type { EnemyDesert } from "../data/enemyDesert.csv";
|
import type { EnemyDesert } from "../data/enemyDesert.csv";
|
||||||
import type { EnemyIntentDesert } from "../data/enemyIntentDesert.csv";
|
|
||||||
import type { EffectDesert } from "../data/effectDesert.csv";
|
import type { EffectDesert } from "../data/effectDesert.csv";
|
||||||
import type { PlayerDeck, GameCard } from "../deck/types";
|
import type { PlayerDeck, GameCard } from "../deck/types";
|
||||||
import type { PlayerState } from "../progress/types";
|
import type { PlayerState } from "../progress/types";
|
||||||
|
|
@ -27,7 +26,7 @@ export type EnemyState = {
|
||||||
maxHp: number;
|
maxHp: number;
|
||||||
buffs: BuffTable;
|
buffs: BuffTable;
|
||||||
currentIntentId: string;
|
currentIntentId: string;
|
||||||
intentData: Record<string, EnemyIntentDesert>;
|
intentData: Record<string, EnemyDesert>;
|
||||||
isAlive: boolean;
|
isAlive: boolean;
|
||||||
hadDefendBroken: boolean;
|
hadDefendBroken: boolean;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { EffectDesert } from './effectDesert.csv';
|
||||||
|
|
||||||
|
type CardDesertTable = readonly {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly desc: string;
|
||||||
|
readonly type: "item" | "status";
|
||||||
|
readonly costType: "energy" | "uses" | "none";
|
||||||
|
readonly costCount: number;
|
||||||
|
readonly targetType: "single" | "none";
|
||||||
|
readonly unplayable: boolean;
|
||||||
|
readonly onPlay: readonly ["self" | "target" | "all" | "random" | "player", EffectDesert, number];
|
||||||
|
readonly onDraw: readonly ["self" | "target" | "all" | "random" | "player", EffectDesert, number];
|
||||||
|
readonly onDiscard: readonly ["self" | "target" | "all" | "random" | "player", EffectDesert, number];
|
||||||
|
}[];
|
||||||
|
|
||||||
|
export type CardDesert = CardDesertTable[number];
|
||||||
|
|
||||||
|
declare function getData(): CardDesertTable;
|
||||||
|
export default getData;
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
type EffectDesertTable = readonly {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly description: string;
|
||||||
|
readonly timing: "instant" | "temporary" | "lingering" | "permanent" | "posture" | "card" | "cardDraw" | "cardHand" | "item" | "itemUntilPlayed";
|
||||||
|
}[];
|
||||||
|
|
||||||
|
export type EffectDesert = EffectDesertTable[number];
|
||||||
|
|
||||||
|
declare function getData(): EffectDesertTable;
|
||||||
|
export default getData;
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
type EncounterDesertTable = readonly {
|
||||||
|
readonly type: "minion" | "elite" | "event" | "shop" | "camp" | "curio";
|
||||||
|
readonly name: string;
|
||||||
|
readonly description: string;
|
||||||
|
readonly enemies: readonly [string, number, number];
|
||||||
|
readonly dialogue: string;
|
||||||
|
}[];
|
||||||
|
|
||||||
|
export type EncounterDesert = EncounterDesertTable[number];
|
||||||
|
|
||||||
|
declare function getData(): EncounterDesertTable;
|
||||||
|
export default getData;
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import type { EffectDesert } from './effectDesert.csv';
|
||||||
|
|
||||||
|
type EnemyDesertTable = readonly {
|
||||||
|
readonly enemy: string;
|
||||||
|
readonly intentId: string;
|
||||||
|
readonly initialIntent: boolean;
|
||||||
|
readonly nextIntents: readonly string[];
|
||||||
|
readonly brokenIntent: readonly string[];
|
||||||
|
readonly initBuffs: readonly [EffectDesert, readonly stacks: number];
|
||||||
|
readonly effects: readonly ["self" | "player" | "team", EffectDesert, number];
|
||||||
|
}[];
|
||||||
|
|
||||||
|
export type EnemyDesert = EnemyDesertTable[number];
|
||||||
|
|
||||||
|
declare function getData(): EnemyDesertTable;
|
||||||
|
export default getData;
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import type { CardDesert } from './cardDesert.csv';
|
||||||
|
|
||||||
|
type HeroItemFighter1Table = readonly {
|
||||||
|
readonly type: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly shape: string;
|
||||||
|
readonly card: CardDesert;
|
||||||
|
readonly price: number;
|
||||||
|
}[];
|
||||||
|
|
||||||
|
export type HeroItemFighter1 = HeroItemFighter1Table[number];
|
||||||
|
|
||||||
|
declare function getData(): HeroItemFighter1Table;
|
||||||
|
export default getData;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Data
|
// Data
|
||||||
export { heroItemFighter1Data, encounterDesertData } from './data';
|
export { heroItemFighter1Data, encounterDesertData, enemyDesertData, effectDesertData, cardDesertData } from './data';
|
||||||
export { default as encounterDesertCsv } from './data/encounterDesert.csv';
|
export { default as encounterDesertCsv } from './data/encounterDesert.csv';
|
||||||
export type { EncounterDesert } from './data/encounterDesert.csv';
|
export type { EncounterDesert, CardDesert } from './data';
|
||||||
|
|
||||||
// Deck
|
// Deck
|
||||||
export type { GameCard, GameCardMeta, PlayerDeck, DeckRegions } from './deck';
|
export type { GameCard, GameCardMeta, PlayerDeck, DeckRegions } from './deck';
|
||||||
|
|
|
||||||
|
|
@ -66,5 +66,5 @@ export default defineConfig({
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
outDir: 'dist/samples',
|
outDir: 'dist/samples',
|
||||||
external: ['@preact/signals-core', 'mutative', 'inline-schema', 'boardgame-core'],
|
external: ['@preact/signals-core', 'mutative', 'inline-schema', 'boardgame-core'],
|
||||||
esbuildPlugins: [csvLoader(), rewriteBoardgameImports(), yarnSpinnerPlugin()],
|
esbuildPlugins: [csvLoader({ writeToDisk: true }), rewriteBoardgameImports(), yarnSpinnerPlugin()],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue