건국 커맨드 구현 및 테스트 추가
This commit is contained in:
@@ -244,6 +244,7 @@ export const createDatabaseTurnHooks = async (
|
||||
diplomacy,
|
||||
logs,
|
||||
createdGenerals,
|
||||
createdNations,
|
||||
createdTroops,
|
||||
createdDiplomacy,
|
||||
} = world.consumeDirtyState();
|
||||
@@ -260,6 +261,7 @@ export const createDatabaseTurnHooks = async (
|
||||
});
|
||||
|
||||
const createdIds = new Set(createdGenerals.map((general) => general.id));
|
||||
const createdNationIds = new Set(createdNations.map((nation) => nation.id));
|
||||
const createdTroopIds = new Set(createdTroops.map((troop) => troop.id));
|
||||
const createdDiplomacyKeys = new Set(
|
||||
createdDiplomacy.map((entry) => `${entry.fromNationId}:${entry.toNationId}`)
|
||||
@@ -270,6 +272,21 @@ export const createDatabaseTurnHooks = async (
|
||||
data: createdGenerals.map(buildGeneralCreate),
|
||||
});
|
||||
}
|
||||
if (createdNations.length > 0) {
|
||||
await prisma.nation.createMany({
|
||||
data: createdNations.map((nation) => ({
|
||||
id: nation.id,
|
||||
name: nation.name,
|
||||
color: nation.color,
|
||||
capitalCityId: nation.capitalCityId,
|
||||
gold: nation.gold,
|
||||
rice: nation.rice,
|
||||
level: nation.level,
|
||||
typeCode: nation.typeCode,
|
||||
meta: asJson(nation.meta),
|
||||
})),
|
||||
});
|
||||
}
|
||||
if (createdTroops.length > 0) {
|
||||
await prisma.troop.createMany({
|
||||
data: createdTroops.map(buildTroopCreate),
|
||||
@@ -307,12 +324,14 @@ export const createDatabaseTurnHooks = async (
|
||||
data: buildCityUpdate(city),
|
||||
})
|
||||
),
|
||||
...nations.map((nation) =>
|
||||
prisma.nation.update({
|
||||
where: { id: nation.id },
|
||||
data: buildNationUpdate(nation),
|
||||
})
|
||||
),
|
||||
...nations
|
||||
.filter((nation) => !createdNationIds.has(nation.id))
|
||||
.map((nation) =>
|
||||
prisma.nation.update({
|
||||
where: { id: nation.id },
|
||||
data: buildNationUpdate(nation),
|
||||
})
|
||||
),
|
||||
...troops
|
||||
.filter((troop) => !createdTroopIds.has(troop.id))
|
||||
.map((troop) =>
|
||||
|
||||
@@ -38,6 +38,7 @@ export interface GeneralTurnResult {
|
||||
}>;
|
||||
created?: {
|
||||
generals: TurnGeneral[];
|
||||
nations?: Nation[];
|
||||
troops?: Troop[];
|
||||
};
|
||||
}
|
||||
@@ -162,6 +163,7 @@ export class InMemoryTurnWorld {
|
||||
private readonly dirtyTroopIds = new Set<number>();
|
||||
private readonly dirtyDiplomacyKeys = new Set<string>();
|
||||
private readonly createdGeneralIds = new Set<number>();
|
||||
private readonly createdNationIds = new Set<number>();
|
||||
private readonly createdTroopIds = new Set<number>();
|
||||
private readonly createdDiplomacyKeys = new Set<string>();
|
||||
private readonly deletedTroopIds = new Set<number>();
|
||||
@@ -358,6 +360,44 @@ export class InMemoryTurnWorld {
|
||||
};
|
||||
}
|
||||
|
||||
getNextNationId(): number {
|
||||
const meta = this.state.meta as Record<string, unknown>;
|
||||
let lastId = (meta.lastNationId as number | undefined) ?? 0;
|
||||
if (lastId === 0) {
|
||||
const currentIds = Array.from(this.nations.keys());
|
||||
lastId = currentIds.length > 0 ? Math.max(...currentIds) : 0;
|
||||
}
|
||||
|
||||
const nextId = lastId + 1;
|
||||
this.state = {
|
||||
...this.state,
|
||||
meta: {
|
||||
...this.state.meta,
|
||||
lastNationId: nextId,
|
||||
},
|
||||
};
|
||||
return nextId;
|
||||
}
|
||||
|
||||
getNextGeneralId(): number {
|
||||
const meta = this.state.meta as Record<string, unknown>;
|
||||
let lastId = (meta.lastGeneralId as number | undefined) ?? 0;
|
||||
if (lastId === 0) {
|
||||
const currentIds = Array.from(this.generals.keys());
|
||||
lastId = currentIds.length > 0 ? Math.max(...currentIds) : 0;
|
||||
}
|
||||
|
||||
const nextId = lastId + 1;
|
||||
this.state = {
|
||||
...this.state,
|
||||
meta: {
|
||||
...this.state.meta,
|
||||
lastGeneralId: nextId,
|
||||
},
|
||||
};
|
||||
return nextId;
|
||||
}
|
||||
|
||||
setCheckpoint(checkpoint?: TurnCheckpoint): void {
|
||||
this.checkpoint = checkpoint;
|
||||
}
|
||||
@@ -474,6 +514,16 @@ export class InMemoryTurnWorld {
|
||||
this.dirtyGeneralIds.add(createdGeneral.id);
|
||||
this.createdGeneralIds.add(createdGeneral.id);
|
||||
}
|
||||
if (result.created.nations) {
|
||||
for (const createdNation of result.created.nations) {
|
||||
if (this.nations.has(createdNation.id)) {
|
||||
continue;
|
||||
}
|
||||
this.nations.set(createdNation.id, { ...createdNation });
|
||||
this.dirtyNationIds.add(createdNation.id);
|
||||
this.createdNationIds.add(createdNation.id);
|
||||
}
|
||||
}
|
||||
if (result.created.troops) {
|
||||
for (const createdTroop of result.created.troops) {
|
||||
if (this.troops.has(createdTroop.id)) {
|
||||
@@ -535,6 +585,7 @@ export class InMemoryTurnWorld {
|
||||
diplomacy: TurnDiplomacy[];
|
||||
logs: LogEntryDraft[];
|
||||
createdGenerals: TurnGeneral[];
|
||||
createdNations: Nation[];
|
||||
createdTroops: Troop[];
|
||||
createdDiplomacy: TurnDiplomacy[];
|
||||
} {
|
||||
@@ -544,6 +595,9 @@ export class InMemoryTurnWorld {
|
||||
const createdGenerals = Array.from(this.createdGeneralIds)
|
||||
.map((id) => this.generals.get(id))
|
||||
.filter((general): general is TurnGeneral => Boolean(general));
|
||||
const createdNations = Array.from(this.createdNationIds)
|
||||
.map((id) => this.nations.get(id))
|
||||
.filter((nation): nation is Nation => Boolean(nation));
|
||||
const cities = Array.from(this.dirtyCityIds)
|
||||
.map((id) => this.cities.get(id))
|
||||
.filter((city): city is City => Boolean(city));
|
||||
@@ -572,6 +626,7 @@ export class InMemoryTurnWorld {
|
||||
this.dirtyTroopIds.clear();
|
||||
this.dirtyDiplomacyKeys.clear();
|
||||
this.createdGeneralIds.clear();
|
||||
this.createdNationIds.clear();
|
||||
this.createdTroopIds.clear();
|
||||
this.createdDiplomacyKeys.clear();
|
||||
this.deletedTroopIds.clear();
|
||||
@@ -587,6 +642,7 @@ export class InMemoryTurnWorld {
|
||||
diplomacy,
|
||||
logs,
|
||||
createdGenerals,
|
||||
createdNations,
|
||||
createdTroops,
|
||||
createdDiplomacy,
|
||||
};
|
||||
|
||||
@@ -305,6 +305,8 @@ class WorldStateView implements StateView {
|
||||
return this.overrides.nation;
|
||||
}
|
||||
return this.world.getNationById(req.id);
|
||||
case 'nationList':
|
||||
return this.world.listNations();
|
||||
case 'destNation':
|
||||
return this.world.getNationById(req.id);
|
||||
case 'diplomacy':
|
||||
@@ -402,16 +404,34 @@ export const createReservedTurnHandler = async (options: {
|
||||
|
||||
let nextGeneralId: number | null = null;
|
||||
const createGeneralId = (): number => {
|
||||
const world = options.getWorld();
|
||||
if (world) {
|
||||
return world.getNextGeneralId();
|
||||
}
|
||||
|
||||
if (nextGeneralId === null) {
|
||||
const world = options.getWorld();
|
||||
const ids = world ? world.listGenerals().map((general) => general.id) : [];
|
||||
nextGeneralId = ids.length > 0 ? Math.max(...ids) + 1 : 1;
|
||||
nextGeneralId = 1;
|
||||
}
|
||||
const result = nextGeneralId;
|
||||
nextGeneralId += 1;
|
||||
return result;
|
||||
};
|
||||
|
||||
let nextNationId: number | null = null;
|
||||
const createNationId = (): number => {
|
||||
const world = options.getWorld();
|
||||
if (world) {
|
||||
return world.getNextNationId();
|
||||
}
|
||||
|
||||
if (nextNationId === null) {
|
||||
nextNationId = 1;
|
||||
}
|
||||
const result = nextNationId;
|
||||
nextNationId += 1;
|
||||
return result;
|
||||
};
|
||||
|
||||
return {
|
||||
execute(context): GeneralTurnResult {
|
||||
const worldRef = options.getWorld();
|
||||
@@ -434,7 +454,8 @@ export const createReservedTurnHandler = async (options: {
|
||||
destNationId: number;
|
||||
patch: DiplomacyPatch;
|
||||
}> = [];
|
||||
const created: TurnGeneral[] = [];
|
||||
const createdGenerals: TurnGeneral[] = [];
|
||||
const createdNations: Nation[] = [];
|
||||
|
||||
let currentGeneral = context.general;
|
||||
let currentCity = context.city;
|
||||
@@ -518,6 +539,7 @@ export const createReservedTurnHandler = async (options: {
|
||||
worldRef: worldView,
|
||||
actionArgs: actionArgsRecord,
|
||||
createGeneralId,
|
||||
createNationId,
|
||||
seedBase,
|
||||
},
|
||||
actionContextBuilders
|
||||
@@ -550,6 +572,13 @@ export const createReservedTurnHandler = async (options: {
|
||||
currentGeneral = resolution.general as TurnGeneral;
|
||||
currentCity = resolution.city ?? currentCity;
|
||||
currentNation = resolution.nation ?? currentNation;
|
||||
|
||||
if (!currentNation && resolution.created?.nations) {
|
||||
currentNation =
|
||||
(resolution.created.nations as Nation[]).find((n) => n.id === currentGeneral.nationId) ??
|
||||
currentNation;
|
||||
}
|
||||
|
||||
logs.push(...resolution.logs);
|
||||
if (worldOverlay) {
|
||||
worldOverlay.syncGeneral(currentGeneral);
|
||||
@@ -608,14 +637,23 @@ export const createReservedTurnHandler = async (options: {
|
||||
}
|
||||
|
||||
if (resolution.created?.generals) {
|
||||
const createdGenerals = resolution.created.generals as TurnGeneral[];
|
||||
created.push(...createdGenerals);
|
||||
const newGenerals = resolution.created.generals as TurnGeneral[];
|
||||
createdGenerals.push(...newGenerals);
|
||||
if (worldOverlay) {
|
||||
for (const general of createdGenerals) {
|
||||
for (const general of newGenerals) {
|
||||
worldOverlay.syncGeneral(general);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (resolution.created?.nations) {
|
||||
const newNations = resolution.created.nations as Nation[];
|
||||
createdNations.push(...newNations);
|
||||
if (worldOverlay) {
|
||||
for (const nation of newNations) {
|
||||
worldOverlay.syncNation(nation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return applyNextTurnAt ? resolution.nextTurnAt : undefined;
|
||||
};
|
||||
@@ -642,7 +680,13 @@ export const createReservedTurnHandler = async (options: {
|
||||
logs,
|
||||
patches,
|
||||
...(diplomacyPatches.length > 0 ? { diplomacyPatches } : undefined),
|
||||
created: created.length > 0 ? { generals: created } : undefined,
|
||||
created:
|
||||
createdGenerals.length > 0 || createdNations.length > 0
|
||||
? {
|
||||
generals: createdGenerals,
|
||||
...(createdNations.length > 0 ? { nations: createdNations } : {}),
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user