import type { GeneralTriggerState } from '@sammo-ts/logic/domain/entities.js'; import { compileCrewTypeCatalog } from '@sammo-ts/logic/crewType/catalog.js'; import { createCrewTypeWarTriggerRegistry } from '@sammo-ts/logic/war/crewTypeTriggers.js'; import { createInheritBuffModules } from '@sammo-ts/logic/inheritance/inheritBuff.js'; import { createItemActionModules, createItemModuleRegistry, ITEM_KEYS, loadItemModules, type ItemModule, } from '@sammo-ts/logic/items/index.js'; import type { UnitSetDefinition } from '@sammo-ts/logic/world/types.js'; import type { GeneralActionModule } from './general.js'; import type { WarActionModule } from '@sammo-ts/logic/war/actions.js'; import { createOfficerLevelActionModules } from './officerLevel.js'; import { createTraitCatalog, DOMESTIC_TRAIT_KEYS, EVENT_DOMESTIC_TRAIT_KEYS, loadDomesticTraitModules, loadEventDomesticTraitModules, loadNationTraitModules, loadPersonalityTraitModules, loadWarTraitModules, NATION_TRAIT_KEYS, PERSONALITY_TRAIT_KEYS, TraitGeneralActionRouter, TraitWarActionRouter, WAR_TRAIT_KEYS, } from './traits/index.js'; import type { NationTraitModule } from './traits/nation/index.js'; import { createScenarioEffectActionModules } from './scenarioEffect.js'; import type { ScenarioEffectKey } from '@sammo-ts/logic/scenario/scenarioEffect.js'; export interface ActionModuleBundle { general: RefOrderedActionStack>; war: RefOrderedActionStack>; itemModules: ItemModule[]; nationTraitModules: NationTraitModule[]; } const refActionOrderBrand: unique symbol = Symbol('RefOrderedActionStack'); export type RefOrderedActionStack = ReadonlyArray & { readonly [refActionOrderBrand]: true; }; interface RefActionSlots { nation: Module; officer: Module; domestic: Module; war: Module; personality: Module; crewType: Module | null; inheritance: Module; scenario: Module | null; items: readonly Module[]; } const markRefOrderedActionStack: ( stack: Module[] ) => asserts stack is Module[] & { readonly [refActionOrderBrand]: true } = (stack) => { Object.defineProperty(stack, refActionOrderBrand, { value: true, enumerable: false, writable: false, }); }; // ref General::getActionList()의 소유권 순서를 한 곳에서만 조립합니다. export const createRefOrderedActionStack = (slots: RefActionSlots): RefOrderedActionStack => { const stack = [ slots.nation, slots.officer, slots.domestic, slots.war, slots.personality, ...(slots.crewType ? [slots.crewType] : []), slots.inheritance, ...(slots.scenario ? [slots.scenario] : []), ...slots.items, ]; markRefOrderedActionStack(stack); return stack; }; // General::getActionList와 같은 소유권 순서로 실제 턴과 시뮬레이터의 모듈을 조립한다. export const loadActionModuleBundle = async ( unitSet?: UnitSetDefinition, scenarioEffect?: ScenarioEffectKey | null ): Promise> => { const [domestic, eventDomestic, war, personality, nation, itemModules] = await Promise.all([ loadDomesticTraitModules([...DOMESTIC_TRAIT_KEYS]), loadEventDomesticTraitModules([...EVENT_DOMESTIC_TRAIT_KEYS]), loadWarTraitModules([...WAR_TRAIT_KEYS]), loadPersonalityTraitModules([...PERSONALITY_TRAIT_KEYS]), loadNationTraitModules([...NATION_TRAIT_KEYS]), loadItemModules([...ITEM_KEYS]) as Promise[]>, ]); const traitCatalog = createTraitCatalog({ domestic: [...domestic, ...eventDomestic], war, personality, nation, }); const officer = createOfficerLevelActionModules(); const items = createItemActionModules(createItemModuleRegistry(itemModules)); const inherit = createInheritBuffModules(); const scenario = createScenarioEffectActionModules(scenarioEffect); const crewTypeCatalog = unitSet?.crewTypes?.length ? compileCrewTypeCatalog(unitSet, createCrewTypeWarTriggerRegistry()) : null; return { general: createRefOrderedActionStack>({ nation: new TraitGeneralActionRouter('nation', traitCatalog), officer: officer.general, domestic: new TraitGeneralActionRouter('domestic', traitCatalog), war: new TraitGeneralActionRouter('war', traitCatalog), personality: new TraitGeneralActionRouter('personality', traitCatalog), crewType: crewTypeCatalog ? (crewTypeCatalog.generalActionModule as GeneralActionModule) : null, inheritance: inherit.general as GeneralActionModule, scenario: scenario.general, items: items.general, }), war: createRefOrderedActionStack>({ nation: new TraitWarActionRouter('nation', traitCatalog), officer: officer.war, domestic: new TraitWarActionRouter('domestic', traitCatalog), war: new TraitWarActionRouter('war', traitCatalog), personality: new TraitWarActionRouter('personality', traitCatalog), crewType: crewTypeCatalog ? (crewTypeCatalog.warActionModule as WarActionModule) : null, inheritance: inherit.war as WarActionModule, scenario: scenario.war, items: items.war, }), itemModules, nationTraitModules: nation, }; };