fix: 가오픈 빙의 후보 시간을 논리 시계에 맞춤

This commit is contained in:
2026-09-23 04:15:20 +00:00
parent b2b6723c4d
commit dee72bdf7b
2 changed files with 26 additions and 7 deletions
@@ -18,6 +18,7 @@ const mode = computed({
},
});
const sample = shallowRef<ReturnType<typeof sampleServerClock>>(null);
const preopenLogicalSample = shallowRef<ReturnType<typeof sampleServerClock>>(null);
const now = ref(Date.now());
const engineRunning = ref<boolean | null>(null);
const haltedAt = ref<number | null>(null);
@@ -32,6 +33,9 @@ export const receiveClockSample = (
): void => {
if (!input.serverTime) return;
const wallTime = input.serverWallTime ? new Date(input.serverWallTime).getTime() : undefined;
const startsAt = input.clockStartsAt ? new Date(input.clockStartsAt).getTime() : NaN;
const isPreopenSample =
input.clockMode === 'realtime' && wallTime !== undefined && Number.isFinite(startsAt) && wallTime < startsAt;
// 메인 화면의 이전 표본을 heartbeat가 재전달해도 더 최신 lobby 표본을 되감지 않는다.
if (
wallTime !== undefined &&
@@ -44,14 +48,20 @@ export const receiveClockSample = (
wallTime !== undefined &&
wallTime === sample.value.serverWallTimeMs &&
new Date(input.serverTime).getTime() === sample.value.serverTimeMs &&
input.turnEngineRunning === engineRunning.value
input.turnEngineRunning === engineRunning.value &&
isPreopenSample === (preopenLogicalSample.value !== null)
)
return;
const sampledAt = Date.now();
// PREOPEN's displayed clock is intentionally frozen. Its negative logical tick
// still advances, so candidate deadlines need the unpaused server sample.
preopenLogicalSample.value = isPreopenSample ? sampleServerClock(input, sampledAt) : null;
receiveClockEngineState(input.turnEngineRunning ?? null);
sample.value = sampleServerClock(
input.turnEngineRunning === false ? { ...input, clockRunning: false, clockStartsAt: null } : input
input.turnEngineRunning === false ? { ...input, clockRunning: false, clockStartsAt: null } : input,
sampledAt
);
now.value = Date.now();
now.value = sampledAt;
};
export const advanceClockDisplay = (): void => {
@@ -64,7 +74,13 @@ const projection = computed(() =>
sample.value ? projectServerClock(sample.value, haltedAt.value ?? now.value) : null
);
// 마감 판정은 표시 모드와 무관하게 서버가 투영한 GAME 시각을 사용한다.
const gameTime = computed(() => projection.value?.time ?? null);
const gameTime = computed(() => {
const preopen = preopenLogicalSample.value;
if (preopen) {
return new Date(preopen.serverTimeMs + Math.max(0, now.value - preopen.sampledClientTimeMs));
}
return projection.value?.time ?? null;
});
const accelerated = computed(() => projection.value?.rate === 2 && engineRunning.value !== false);
const label = computed(() => (mode.value === 'real' ? '실제 시간 기준' : '게임 시간 기준'));
const time = computed(() => {