feat: 응답 가능한 서신과 턴 시간 호환 이관

등용장과 이민족 선택 응답을 turn daemon transaction으로 연결하고 Ref의 통일 이후 상태 전이와 수신자별 메시지 저장 규칙을 보존한다.\n\n유산 턴 시간 변경을 nextTurnTimeBase 기반 결정적 계산으로 바로잡고 API, 엔진, Chromium 회귀를 추가한다.
This commit is contained in:
2026-08-19 18:03:56 +00:00
parent 9390195d5f
commit 81279e76b5
26 changed files with 1405 additions and 224 deletions
@@ -0,0 +1,74 @@
import { describe, expect, it } from 'vitest';
import { ActionResolver } from '../../../src/actions/turn/general/che_등용.js';
describe('che_등용 recruitment message', () => {
it('queues the Ref scout prompt with sender and receiver snapshots', () => {
const logs: unknown[] = [];
const general = {
id: 1,
name: '등용자',
nationId: 1,
cityId: 1,
troopId: 0,
gold: 5_000,
experience: 100,
dedication: 100,
stats: { leadership: 70, strength: 60, intelligence: 50 },
role: { items: {} },
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
meta: {},
};
const destination = {
...general,
id: 2,
name: '수신자',
nationId: 2,
experience: 300,
dedication: 200,
};
const sourceNation = { id: 1, name: '위', color: '#ffffff' };
const destinationNation = { id: 2, name: '촉', color: '#000000' };
const messageTime = new Date('0200-01-01T00:10:00.000Z');
const result = new ActionResolver().resolve(
{
general,
nation: sourceNation,
destGeneral: destination,
messageTime,
env: { develCost: 100 },
worldView: { listNations: () => [sourceNation, destinationNation] },
addLog: (text: string, options: unknown) => logs.push({ text, options }),
} as never,
{ destGeneralId: destination.id }
);
expect(result.effects).toContainEqual({
type: 'message:add',
draft: {
msgType: 'private',
src: {
generalId: general.id,
generalName: general.name,
nationId: sourceNation.id,
nationName: sourceNation.name,
color: sourceNation.color,
icon: '',
},
dest: {
generalId: destination.id,
generalName: destination.name,
nationId: destinationNation.id,
nationName: destinationNation.name,
color: destinationNation.color,
icon: '',
},
text: '위로 망명 권유 서신',
time: messageTime,
validUntil: new Date('9999-12-31T12:59:59.000Z'),
option: { action: 'scout' },
},
});
});
});