feat: Implement general and nation turn commands with command specifications

- Added command specifications for various general turn commands including talent scouting, appointments, and military actions.
- Introduced command specifications for nation turn commands such as assignments and declarations of war.
- Created a command environment interface to encapsulate command-related parameters.
- Developed a command profile loader to manage default and custom command profiles.
- Established a reserved turn action context to facilitate command execution with necessary context data.
- Updated the default command profile JSON to include new commands and their configurations.
This commit is contained in:
2026-01-01 15:17:30 +00:00
parent 49942cea5e
commit bfbcb4472e
36 changed files with 1089 additions and 750 deletions
+2
View File
@@ -1,5 +1,7 @@
export * from './definition.js';
export * from './engine.js';
export * from './turn/commandEnv.js';
export * from './turn/commandProfile.js';
export * from './turn/general/index.js';
export * from './turn/nation/index.js';
export * from './instant/general/index.js';
@@ -0,0 +1,24 @@
export interface TurnCommandEnv {
develCost: number;
trainDelta: number;
atmosDelta: number;
maxTrainByCommand: number;
maxAtmosByCommand: number;
sabotageDefaultProb: number;
sabotageProbCoefByStat: number;
sabotageDefenceCoefByGeneralCount: number;
sabotageDamageMin: number;
sabotageDamageMax: number;
openingPartYear: number;
maxGeneral: number;
defaultNpcGold: number;
defaultNpcRice: number;
defaultCrewTypeId: number;
defaultSpecialDomestic: string | null;
defaultSpecialWar: string | null;
initialNationGenLimit: number;
maxTechLevel: number;
baseGold: number;
baseRice: number;
maxResourceActionAmount: number;
}
@@ -0,0 +1,78 @@
import {
GENERAL_TURN_COMMAND_KEYS,
isGeneralTurnCommandKey,
type GeneralTurnCommandKey,
} from './general/index.js';
import {
NATION_TURN_COMMAND_KEYS,
isNationTurnCommandKey,
type NationTurnCommandKey,
} from './nation/index.js';
export interface TurnCommandProfile {
general: GeneralTurnCommandKey[];
nation: NationTurnCommandKey[];
}
const isRecord = (value: unknown): value is Record<string, unknown> =>
value !== null && typeof value === 'object' && !Array.isArray(value);
const asStringArray = (value: unknown): string[] | null => {
if (!Array.isArray(value)) {
return null;
}
const list = value.filter((entry): entry is string => typeof entry === 'string');
return list.length > 0 ? list : null;
};
const parseKeyList = <
T extends string
>(options: {
raw: unknown;
defaults: T[];
isKey: (value: string) => value is T;
label: string;
}): T[] => {
const rawList = asStringArray(options.raw);
if (!rawList) {
return options.defaults;
}
const parsed: T[] = [];
for (const value of rawList) {
if (!options.isKey(value)) {
throw new Error(
`Unknown ${options.label} command key: ${value}`
);
}
parsed.push(value);
}
return parsed;
};
export const DEFAULT_TURN_COMMAND_PROFILE: TurnCommandProfile = {
general: [...GENERAL_TURN_COMMAND_KEYS],
nation: [...NATION_TURN_COMMAND_KEYS],
};
export const parseTurnCommandProfile = (
raw: unknown,
fallback: TurnCommandProfile = DEFAULT_TURN_COMMAND_PROFILE
): TurnCommandProfile => {
if (!isRecord(raw)) {
return fallback;
}
return {
general: parseKeyList({
raw: raw.general,
defaults: fallback.general,
isKey: isGeneralTurnCommandKey,
label: 'general',
}),
nation: parseKeyList({
raw: raw.nation,
defaults: fallback.nation,
isKey: isNationTurnCommandKey,
label: 'nation',
}),
};
};
@@ -8,6 +8,8 @@ import type {
} from '../../engine.js';
import { createGeneralPatchEffect, createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface UprisingArgs {}
@@ -53,3 +55,11 @@ export class ActionDefinition<
};
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_거병',
category: '전략',
reqArg: false,
args: {},
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition(),
};
@@ -8,6 +8,8 @@ import type {
} from '../../engine.js';
import { createGeneralPatchEffect, createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface FoundingArgs {}
@@ -53,3 +55,11 @@ export class ActionDefinition<
};
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_건국',
category: '전략',
reqArg: false,
args: {},
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition(),
};
@@ -26,6 +26,8 @@ import {
createNationPatchEffect,
} from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface TechResearchArgs {}
@@ -127,3 +129,15 @@ export class ActionDefinition<
};
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_기술연구',
category: '내정',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition({
costGold: env.develCost,
maxTechLevel: env.maxTechLevel,
}),
};
@@ -1,5 +1,7 @@
import type { GeneralTriggerState } from '../../../domain/entities.js';
import { CityDevelopmentActionDefinition } from './cityDevelopment.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export class ActionDefinition<
TriggerState extends GeneralTriggerState = GeneralTriggerState
@@ -18,3 +20,12 @@ export class ActionDefinition<
);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_농지개간',
category: '내정',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition({ develCost: env.develCost }),
};
@@ -15,6 +15,8 @@ import type {
} from '../../engine.js';
import { createGeneralPatchEffect, createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface BoostMoraleArgs {}
@@ -89,3 +91,15 @@ export class ActionDefinition<
};
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_사기진작',
category: '군사',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition({
atmosDelta: env.atmosDelta,
maxAtmosByCommand: env.maxAtmosByCommand,
}),
};
@@ -37,6 +37,8 @@ import {
createGeneralPatchEffect,
createLogEffect,
} from '../../engine.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export type DomesticCriticalPick = 'fail' | 'normal' | 'success';
@@ -437,3 +439,11 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_상업투자',
category: '내정',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) => new ActionDefinition([], env),
};
@@ -1,5 +1,7 @@
import type { GeneralTriggerState } from '../../../domain/entities.js';
import { CityDevelopmentActionDefinition } from './cityDevelopment.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export class ActionDefinition<
TriggerState extends GeneralTriggerState = GeneralTriggerState
@@ -18,3 +20,12 @@ export class ActionDefinition<
);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_성벽보수',
category: '내정',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition({ develCost: env.develCost }),
};
@@ -1,5 +1,7 @@
import type { GeneralTriggerState } from '../../../domain/entities.js';
import { CityDevelopmentActionDefinition } from './cityDevelopment.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export class ActionDefinition<
TriggerState extends GeneralTriggerState = GeneralTriggerState
@@ -18,3 +20,12 @@ export class ActionDefinition<
);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_수비강화',
category: '내정',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition({ develCost: env.develCost }),
};
@@ -15,6 +15,8 @@ import type {
} from '../../engine.js';
import { createGeneralPatchEffect, createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface RecoveryArgs {}
@@ -77,3 +79,11 @@ export class ActionDefinition<
};
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_요양',
category: '개인',
reqArg: false,
args: {},
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition(),
};
@@ -34,6 +34,8 @@ import {
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import { buildRecruitmentGeneral } from './recruitment.js';
import { JosaUtil } from '@sammo-ts/common';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface VolunteerRecruitArgs {}
@@ -431,3 +433,11 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_의병모집',
category: '전략',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) => new ActionDefinition([], env),
};
@@ -32,6 +32,8 @@ import {
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import { buildRecruitmentGeneral } from './recruitment.js';
import { JosaUtil } from '@sammo-ts/common';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface TalentScoutArgs {}
@@ -468,3 +470,11 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_인재탐색',
category: '인사',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) => new ActionDefinition([], env),
};
@@ -11,6 +11,8 @@ import type {
} from '../../engine.js';
import { createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface AppointmentArgs {
destNationId: number;
@@ -63,3 +65,11 @@ export class ActionDefinition<
};
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_임관',
category: '전략',
reqArg: true,
args: { destNationId: 0 },
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition(),
};
@@ -1,5 +1,7 @@
import type { GeneralTriggerState } from '../../../domain/entities.js';
import { CityDevelopmentActionDefinition } from './cityDevelopment.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export class ActionDefinition<
TriggerState extends GeneralTriggerState = GeneralTriggerState
@@ -18,3 +20,12 @@ export class ActionDefinition<
);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_주민선정',
category: '내정',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition({ develCost: env.develCost }),
};
@@ -36,6 +36,8 @@ import {
createLogEffect,
} from '../../engine.js';
import type { MapDefinition, UnitSetDefinition } from '../../../world/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
import {
type CrewTypeAvailabilityContext,
findCrewTypeById,
@@ -600,3 +602,11 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_징병',
category: '내정',
reqArg: true,
args: {},
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition([], {}),
};
@@ -14,6 +14,8 @@ import type {
} from '../../engine.js';
import { createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface DispatchArgs {
destCityId: number;
@@ -69,3 +71,11 @@ export class ActionDefinition<
};
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_출병',
category: '군사',
reqArg: true,
args: { destCityId: 0 },
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition(),
};
@@ -1,5 +1,7 @@
import type { GeneralTriggerState } from '../../../domain/entities.js';
import { CityDevelopmentActionDefinition } from './cityDevelopment.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export class ActionDefinition<
TriggerState extends GeneralTriggerState = GeneralTriggerState
@@ -18,3 +20,12 @@ export class ActionDefinition<
);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_치안강화',
category: '내정',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition({ develCost: env.develCost }),
};
@@ -36,6 +36,8 @@ import {
createLogEffect,
} from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface FireAttackArgs {
destCityId: number;
@@ -503,3 +505,11 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_화계',
category: '계략',
reqArg: true,
args: { destCityId: 0 },
createDefinition: (env: TurnCommandEnv) => new ActionDefinition([], env),
};
@@ -15,6 +15,8 @@ import type {
} from '../../engine.js';
import { createGeneralPatchEffect, createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface TrainingArgs {}
@@ -89,3 +91,15 @@ export class ActionDefinition<
};
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: 'che_훈련',
category: '군사',
reqArg: false,
args: {},
createDefinition: (env: TurnCommandEnv) =>
new ActionDefinition({
trainDelta: env.trainDelta,
maxTrainByCommand: env.maxTrainByCommand,
}),
};
@@ -1,3 +1,25 @@
import type { GeneralActionDefinition } from '../../definition.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type * as UprisingModule from './che_거병.js';
import type * as AppointmentModule from './che_임관.js';
import type * as FoundingModule from './che_건국.js';
import type * as TrainingModule from './che_훈련.js';
import type * as BoostMoraleModule from './che_사기진작.js';
import type * as RecoveryModule from './che_요양.js';
import type * as DispatchModule from './che_출병.js';
import type * as ResidentsSelectionModule from './che_주민선정.js';
import type * as FarmingModule from './che_농지개간.js';
import type * as CommerceInvestmentModule from './che_상업투자.js';
import type * as TechResearchModule from './che_기술연구.js';
import type * as SecurityUpgradeModule from './che_치안강화.js';
import type * as DefenceUpgradeModule from './che_수비강화.js';
import type * as WallRepairModule from './che_성벽보수.js';
import type * as FireAttackModule from './che_화계.js';
import type * as TalentScoutModule from './che_인재탐색.js';
import type * as VolunteerRecruitModule from './che_의병모집.js';
import type * as RecruitModule from './che_징병.js';
import type * as RestModule from './휴식.js';
export type GeneralTurnCommandKey =
| 'che_거병'
| 'che_임관'
@@ -19,25 +41,40 @@ export type GeneralTurnCommandKey =
| 'che_징병'
| '휴식';
import type * as UprisingModule from './che_거병.js';
import type * as AppointmentModule from './che_임관.js';
import type * as FoundingModule from './che_건국.js';
import type * as TrainingModule from './che_훈련.js';
import type * as BoostMoraleModule from './che_사기진작.js';
import type * as RecoveryModule from './che_요양.js';
import type * as DispatchModule from './che_출병.js';
import type * as ResidentsSelectionModule from './che_주민선정.js';
import type * as FarmingModule from './che_농지개간.js';
import type * as CommerceInvestmentModule from './che_상업투자.js';
import type * as TechResearchModule from './che_기술연구.js';
import type * as SecurityUpgradeModule from './che_치안강화.js';
import type * as DefenceUpgradeModule from './che_수비강화.js';
import type * as WallRepairModule from './che_성벽보수.js';
import type * as FireAttackModule from './che_화계.js';
import type * as TalentScoutModule from './che_인재탐색.js';
import type * as VolunteerRecruitModule from './che_의병모집.js';
import type * as RecruitModule from './che_징병.js';
import type * as RestModule from './휴식.js';
export const GENERAL_TURN_COMMAND_KEYS: GeneralTurnCommandKey[] = [
'che_거병',
'che_임관',
'che_건국',
'che_훈련',
'che_사기진작',
'che_요양',
'che_출병',
'che_주민선정',
'che_농지개간',
'che_상업투자',
'che_기술연구',
'che_치안강화',
'che_수비강화',
'che_성벽보수',
'che_화계',
'che_인재탐색',
'che_의병모집',
'che_징병',
'휴식',
];
export const isGeneralTurnCommandKey = (
value: string
): value is GeneralTurnCommandKey =>
(GENERAL_TURN_COMMAND_KEYS as string[]).includes(value);
export interface GeneralTurnCommandSpec {
key: GeneralTurnCommandKey;
category: string;
reqArg: boolean;
args: Record<string, unknown>;
createDefinition(env: TurnCommandEnv): GeneralActionDefinition;
}
export type GeneralTurnCommandModule =
| typeof UprisingModule
@@ -106,6 +143,26 @@ export class GeneralTurnCommandLoader {
}
}
export const loadGeneralTurnCommandSpecs = async (
keys: GeneralTurnCommandKey[],
loader: GeneralTurnCommandLoader = new GeneralTurnCommandLoader()
): Promise<GeneralTurnCommandSpec[]> => {
const specs: GeneralTurnCommandSpec[] = [];
const seen = new Set<string>();
for (const key of keys) {
if (seen.has(key)) {
continue;
}
seen.add(key);
const module = await loader.load(key);
if (!('commandSpec' in module)) {
throw new Error(`Missing commandSpec for general command: ${key}`);
}
specs.push(module.commandSpec);
}
return specs;
};
export {
ActionDefinition as UprisingActionDefinition,
} from './che_거병.js';
@@ -12,6 +12,8 @@ import type {
} from '../../engine.js';
import { createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { GeneralTurnCommandSpec } from './index.js';
export interface RestArgs {}
@@ -66,3 +68,11 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: GeneralTurnCommandSpec = {
key: '휴식',
category: '개인',
reqArg: false,
args: {},
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition(),
};
@@ -28,6 +28,8 @@ import type {
import { createGeneralPatchEffect, createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import { JosaUtil } from '@sammo-ts/common';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { NationTurnCommandSpec } from './index.js';
export interface AssignmentArgs {
destGeneralId: number;
@@ -206,3 +208,11 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: NationTurnCommandSpec = {
key: 'che_발령',
category: '인사',
reqArg: true,
args: { destGeneralId: 0, destCityId: 0 },
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition({}),
};
@@ -14,6 +14,8 @@ import type {
} from '../../engine.js';
import { createLogEffect } from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { NationTurnCommandSpec } from './index.js';
export interface DeclareWarArgs {
destNationId: number;
@@ -72,3 +74,11 @@ export class ActionDefinition<
};
}
}
export const commandSpec: NationTurnCommandSpec = {
key: 'che_선전포고',
category: '외교',
reqArg: true,
args: { destNationId: 0 },
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition(),
};
@@ -32,6 +32,8 @@ import {
createNationPatchEffect,
} from '../../engine.js';
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { NationTurnCommandSpec } from './index.js';
import { JosaUtil } from '@sammo-ts/common';
export interface AwardArgs {
@@ -266,3 +268,21 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: NationTurnCommandSpec = {
key: 'che_포상',
category: '인사',
reqArg: true,
args: { isGold: true, amount: 1, destGeneralId: 0 },
createDefinition: (env: TurnCommandEnv) => {
const maxAmount =
env.maxResourceActionAmount > 0
? env.maxResourceActionAmount
: Math.max(env.baseGold, env.baseRice, 1000);
return new ActionDefinition({
baseGold: env.baseGold,
baseRice: env.baseRice,
maxAmount,
});
},
};
@@ -1,13 +1,35 @@
import type { GeneralActionDefinition } from '../../definition.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type * as NationRestModule from './휴식.js';
import type * as AwardModule from './che_포상.js';
import type * as AssignmentModule from './che_발령.js';
import type * as DeclarationModule from './che_선전포고.js';
export type NationTurnCommandKey =
| '휴식'
| 'che_포상'
| 'che_발령'
| 'che_선전포고';
import type * as NationRestModule from './휴식.js';
import type * as AwardModule from './che_포상.js';
import type * as AssignmentModule from './che_발령.js';
import type * as DeclarationModule from './che_선전포고.js';
export const NATION_TURN_COMMAND_KEYS: NationTurnCommandKey[] = [
'휴식',
'che_포상',
'che_발령',
'che_선전포고',
];
export const isNationTurnCommandKey = (
value: string
): value is NationTurnCommandKey =>
(NATION_TURN_COMMAND_KEYS as string[]).includes(value);
export interface NationTurnCommandSpec {
key: NationTurnCommandKey;
category: string;
reqArg: boolean;
args: Record<string, unknown>;
createDefinition(env: TurnCommandEnv): GeneralActionDefinition;
}
export type NationTurnCommandModule =
| typeof NationRestModule
@@ -46,6 +68,26 @@ export class NationTurnCommandLoader {
}
}
export const loadNationTurnCommandSpecs = async (
keys: NationTurnCommandKey[],
loader: NationTurnCommandLoader = new NationTurnCommandLoader()
): Promise<NationTurnCommandSpec[]> => {
const specs: NationTurnCommandSpec[] = [];
const seen = new Set<string>();
for (const key of keys) {
if (seen.has(key)) {
continue;
}
seen.add(key);
const module = await loader.load(key);
if (!('commandSpec' in module)) {
throw new Error(`Missing commandSpec for nation command: ${key}`);
}
specs.push(module.commandSpec);
}
return specs;
};
export {
ActionDefinition as NationRestActionDefinition,
ActionResolver as NationRestActionResolver,
@@ -10,6 +10,8 @@ import type {
GeneralActionOutcome,
GeneralActionResolveContext,
} from '../../engine.js';
import type { TurnCommandEnv } from '../commandEnv.js';
import type { NationTurnCommandSpec } from './index.js';
export interface NationRestArgs {}
@@ -56,3 +58,11 @@ export class ActionDefinition<
return this.resolver.resolve(context, args);
}
}
export const commandSpec: NationTurnCommandSpec = {
key: '휴식',
category: '휴식',
reqArg: false,
args: {},
createDefinition: (_env: TurnCommandEnv) => new ActionDefinition(),
};