fix: guard incomplete general lifespans
This commit is contained in:
@@ -1159,22 +1159,32 @@ export const createReservedTurnHandler = async (options: {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
currentCity = currentCity ? { ...currentCity, meta: { ...currentCity.meta } } : currentCity;
|
currentCity = currentCity ? { ...currentCity, meta: { ...currentCity.meta } } : currentCity;
|
||||||
const cityGeneralCopies = new Map<number, TurnGeneral>();
|
let cityGeneralCopies: Map<number, TurnGeneral> | undefined;
|
||||||
for (const general of worldView?.listGenerals() ?? []) {
|
const getCityGeneralCopies = (): Map<number, TurnGeneral> => {
|
||||||
cityGeneralCopies.set(
|
if (cityGeneralCopies) {
|
||||||
general.id,
|
return cityGeneralCopies;
|
||||||
general.id === currentGeneral.id ? currentGeneral : cloneTurnGeneral(general)
|
}
|
||||||
);
|
cityGeneralCopies = new Map<number, TurnGeneral>();
|
||||||
}
|
for (const general of worldView?.listGenerals() ?? []) {
|
||||||
cityGeneralCopies.set(currentGeneral.id, currentGeneral);
|
if (general.cityId !== currentGeneral.cityId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cityGeneralCopies.set(
|
||||||
|
general.id,
|
||||||
|
general.id === currentGeneral.id ? currentGeneral : cloneTurnGeneral(general)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cityGeneralCopies.set(currentGeneral.id, currentGeneral);
|
||||||
|
return cityGeneralCopies;
|
||||||
|
};
|
||||||
const preTurnPipeline = new GeneralActionPipeline(env.generalActionModules ?? []);
|
const preTurnPipeline = new GeneralActionPipeline(env.generalActionModules ?? []);
|
||||||
const preTurnContext = createGeneralTriggerContext({
|
const preTurnContext = createGeneralTriggerContext({
|
||||||
general: currentGeneral,
|
general: currentGeneral,
|
||||||
nation: currentNation,
|
nation: currentNation,
|
||||||
worldView: {
|
worldView: {
|
||||||
listGenerals: () => Array.from(cityGeneralCopies.values()),
|
listGenerals: () => Array.from(getCityGeneralCopies().values()),
|
||||||
listGeneralsByCity: (cityId) =>
|
listGeneralsByCity: (cityId) =>
|
||||||
Array.from(cityGeneralCopies.values()).filter((general) => general.cityId === cityId),
|
Array.from(getCityGeneralCopies().values()).filter((general) => general.cityId === cityId),
|
||||||
},
|
},
|
||||||
rng: preprocessRng,
|
rng: preprocessRng,
|
||||||
log: {
|
log: {
|
||||||
@@ -1209,7 +1219,7 @@ export const createReservedTurnHandler = async (options: {
|
|||||||
}
|
}
|
||||||
preTurnContext.skill.activate('pre.병력군량소모');
|
preTurnContext.skill.activate('pre.병력군량소모');
|
||||||
}
|
}
|
||||||
for (const [generalId, next] of cityGeneralCopies) {
|
for (const [generalId, next] of cityGeneralCopies ?? []) {
|
||||||
if (generalId === currentGeneral.id) {
|
if (generalId === currentGeneral.id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1399,7 +1409,7 @@ export const createReservedTurnHandler = async (options: {
|
|||||||
let deleteGeneral = false;
|
let deleteGeneral = false;
|
||||||
const deletedTroopIds: number[] = [];
|
const deletedTroopIds: number[] = [];
|
||||||
const lifecycleSnapshot = cloneTurnGeneral(currentGeneral);
|
const lifecycleSnapshot = cloneTurnGeneral(currentGeneral);
|
||||||
if (currentGeneral.meta.killturn <= 0) {
|
if (currentGeneral.meta.killturn <= 0 && typeof currentGeneral.deadYear === 'number') {
|
||||||
if (
|
if (
|
||||||
currentGeneral.npcState === 1 &&
|
currentGeneral.npcState === 1 &&
|
||||||
typeof currentGeneral.deadYear === 'number' &&
|
typeof currentGeneral.deadYear === 'number' &&
|
||||||
|
|||||||
@@ -272,6 +272,27 @@ describe('legacy general turn lifecycle', () => {
|
|||||||
expect(harness.world.peekDirtyState().deletedGenerals).toContain(1);
|
expect(harness.world.peekDirtyState().deletedGenerals).toContain(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps compatibility fixtures without legacy lifespan metadata alive', async () => {
|
||||||
|
const harness = await createTurnTestHarness({
|
||||||
|
snapshot: makeSnapshot([
|
||||||
|
makeGeneral({
|
||||||
|
deadYear: undefined,
|
||||||
|
npcState: 2,
|
||||||
|
meta: { killturn: 1 },
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
state: makeState(),
|
||||||
|
schedule,
|
||||||
|
map,
|
||||||
|
});
|
||||||
|
|
||||||
|
await harness.runOneTick();
|
||||||
|
|
||||||
|
expect(harness.world.getGeneralById(1)).not.toBeNull();
|
||||||
|
expect(harness.world.getGeneralById(1)!.meta.killturn).toBe(0);
|
||||||
|
expect(harness.world.peekDirtyState().lifecycleEvents[0]?.outcome).toBe('active');
|
||||||
|
});
|
||||||
|
|
||||||
it('retires a player general and resets inherited stats and rank state', async () => {
|
it('retires a player general and resets inherited stats and rank state', async () => {
|
||||||
const harness = await createTurnTestHarness({
|
const harness = await createTurnTestHarness({
|
||||||
snapshot: makeSnapshot([
|
snapshot: makeSnapshot([
|
||||||
|
|||||||
Reference in New Issue
Block a user