feat: add NpcControlView component for managing NPC policies and priorities
This commit is contained in:
@@ -23,7 +23,9 @@ import {
|
||||
|
||||
import type { WorldStateRow } from '../../context.js';
|
||||
import { authedProcedure, router } from '../../trpc.js';
|
||||
import { MAX_NATION_TURNS, listNationTurns } from '../../turns/reservedTurns.js';
|
||||
import { getMyGeneral } from '../shared/general.js';
|
||||
import { resolveSecretPermission } from '../shared/secretPermission.js';
|
||||
|
||||
type PermissionKind = 'normal' | 'ambassador' | 'auditor';
|
||||
|
||||
@@ -869,6 +871,89 @@ export const nationRouter = router({
|
||||
},
|
||||
};
|
||||
}),
|
||||
getChiefCenter: authedProcedure.query(async ({ ctx }) => {
|
||||
const me = await getMyGeneral(ctx);
|
||||
assertNationAccess(me);
|
||||
|
||||
const [nation, worldState, nationGenerals] = await Promise.all([
|
||||
ctx.db.nation.findUnique({
|
||||
where: { id: me.nationId },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
level: true,
|
||||
meta: true,
|
||||
},
|
||||
}),
|
||||
ctx.db.worldState.findFirst(),
|
||||
ctx.db.general.findMany({
|
||||
where: { nationId: me.nationId, officerLevel: { gte: 5 } },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
officerLevel: true,
|
||||
npcState: true,
|
||||
turnTime: true,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
if (!nation) {
|
||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Nation not found' });
|
||||
}
|
||||
if (!worldState) {
|
||||
throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'World state is not initialized.' });
|
||||
}
|
||||
|
||||
const permissionLevel = resolveSecretPermission(
|
||||
{
|
||||
nationId: me.nationId,
|
||||
officerLevel: me.officerLevel,
|
||||
meta: me.meta,
|
||||
penalty: me.penalty,
|
||||
},
|
||||
nation.meta
|
||||
);
|
||||
if (permissionLevel < 1) {
|
||||
throw new TRPCError({ code: 'FORBIDDEN', message: '권한이 부족합니다.' });
|
||||
}
|
||||
|
||||
const chiefLevels = [12, 10, 8, 6, 11, 9, 7, 5];
|
||||
const generalByLevel = new Map(nationGenerals.map((general) => [general.officerLevel, general]));
|
||||
|
||||
const turnsByLevel = await Promise.all(
|
||||
chiefLevels.map((level) => listNationTurns(ctx.db, nation.id, level))
|
||||
);
|
||||
|
||||
const chiefs = chiefLevels.map((level, idx) => {
|
||||
const entry = generalByLevel.get(level);
|
||||
return {
|
||||
officerLevel: level,
|
||||
name: entry?.name ?? null,
|
||||
npcState: entry?.npcState ?? null,
|
||||
turnTime: entry?.turnTime ? entry.turnTime.toISOString() : null,
|
||||
turns: turnsByLevel[idx],
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
me: {
|
||||
id: me.id,
|
||||
officerLevel: me.officerLevel,
|
||||
nationId: me.nationId,
|
||||
},
|
||||
nation: {
|
||||
id: nation.id,
|
||||
name: nation.name,
|
||||
level: nation.level,
|
||||
},
|
||||
currentYear: worldState.currentYear,
|
||||
currentMonth: worldState.currentMonth,
|
||||
turnTermMinutes: Math.max(1, Math.round(worldState.tickSeconds / 60)),
|
||||
maxTurns: MAX_NATION_TURNS,
|
||||
chiefs,
|
||||
};
|
||||
}),
|
||||
changePermission: authedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
|
||||
Reference in New Issue
Block a user