설문 확인 cursor와 메인 실시간 탭 범위를 reset 고유 serverId로 구분한다. 설문 생성의 daemon 비의존 outbox 경로와 이전 시즌 cursor 회귀를 테스트한다.
88 lines
3.7 KiB
TypeScript
88 lines
3.7 KiB
TypeScript
import { TRPCError } from '@trpc/server';
|
|
|
|
import { asNumber, asRecord } from '@sammo-ts/common';
|
|
|
|
import { zWorldStateConfig, zWorldStateMeta } from '../../context.js';
|
|
import { isSelectionPoolWorld, resolveSelectionMaxGeneral } from '@sammo-ts/game-engine/turn/selectPoolService.js';
|
|
import { loadCurrentGameTime } from '../../services/gameClock.js';
|
|
import { procedure, router } from '../../trpc.js';
|
|
|
|
export const lobbyRouter = router({
|
|
info: procedure.query(async ({ ctx }) => {
|
|
const rawWorldState = await ctx.db.worldState.findFirst();
|
|
if (!rawWorldState) {
|
|
throw new TRPCError({
|
|
code: 'NOT_FOUND',
|
|
message: 'World state not found',
|
|
});
|
|
}
|
|
|
|
const worldState = {
|
|
...rawWorldState,
|
|
config: zWorldStateConfig.parse(rawWorldState.config),
|
|
meta: zWorldStateMeta.parse(rawWorldState.meta),
|
|
};
|
|
|
|
const userCnt = await ctx.db.general.count({ where: { npcState: { lt: 2 } } });
|
|
const npcCnt = await ctx.db.general.count({ where: { npcState: { gte: 2 } } });
|
|
const nationCnt = await ctx.db.nation.count({ where: { level: { gt: 0 } } });
|
|
const rawConfig = asRecord(rawWorldState.config);
|
|
const scenarioTitle = asRecord(asRecord(rawWorldState.meta).scenarioMeta).title;
|
|
const autorunUser = worldState.meta.autorun_user;
|
|
const autorunOptions = autorunUser?.options
|
|
? Object.entries(autorunUser.options)
|
|
.filter(([, enabled]) => enabled)
|
|
.map(([option]) => option)
|
|
: [];
|
|
const gameTime = await loadCurrentGameTime(ctx.db);
|
|
|
|
let myGeneral = null;
|
|
if (ctx.auth?.user.id) {
|
|
const general = await ctx.db.general.findFirst({
|
|
where: { userId: ctx.auth.user.id },
|
|
select: { name: true, picture: true, imageServer: true },
|
|
});
|
|
if (general) {
|
|
myGeneral = {
|
|
name: general.name,
|
|
picture: general.picture,
|
|
imageServer: general.imageServer,
|
|
};
|
|
}
|
|
}
|
|
|
|
return {
|
|
serverId: worldState.meta.serverId?.trim() || ctx.profile?.name || 'game',
|
|
year: worldState.currentYear,
|
|
month: worldState.currentMonth,
|
|
userCnt,
|
|
maxUserCnt: resolveSelectionMaxGeneral(rawWorldState),
|
|
npcCnt,
|
|
nationCnt,
|
|
turnTerm: worldState.tickSeconds / 60,
|
|
fictionMode: worldState.config.fictionMode ?? '사실',
|
|
starttime: worldState.meta.starttime ?? '',
|
|
opentime: worldState.meta.opentime ?? '',
|
|
preopenAt: worldState.meta.preopenAt ?? '',
|
|
turntime: worldState.meta.turntime ?? '',
|
|
serverTime: gameTime.now.toISOString(),
|
|
clockMode: gameTime.mode ?? 'realtime',
|
|
otherTextInfo: worldState.meta.otherTextInfo ?? '',
|
|
npcMode: worldState.config.npcMode ?? 0,
|
|
defaultStatTotal: asNumber(asRecord(rawConfig.stat).total, 165),
|
|
autorunUser:
|
|
autorunUser?.limit_minutes && autorunUser.limit_minutes > 0 && autorunOptions.length > 0
|
|
? {
|
|
limitMinutes: autorunUser.limit_minutes,
|
|
options: autorunOptions,
|
|
}
|
|
: null,
|
|
isUnited: worldState.meta.isunited ?? worldState.meta.isUnited ?? 0,
|
|
selectionPoolEnabled: isSelectionPoolWorld(rawWorldState),
|
|
npcPossessionEnabled: worldState.config.npcMode === 1,
|
|
scenarioTitle: typeof scenarioTitle === 'string' ? scenarioTitle : '',
|
|
myGeneral,
|
|
};
|
|
}),
|
|
});
|