239 lines
6.2 KiB
TypeScript
239 lines
6.2 KiB
TypeScript
import type {
|
|
DragPuzzlePieceRequest,
|
|
AdvancePuzzleNextLevelRequest,
|
|
PuzzleRunResponse,
|
|
StartPuzzleRunRequest,
|
|
SubmitPuzzleLeaderboardRequest,
|
|
SwapPuzzlePiecesRequest,
|
|
UpdatePuzzleRuntimePauseRequest,
|
|
UsePuzzleRuntimePropRequest,
|
|
} from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
|
|
import {
|
|
type ApiRequestOptions,
|
|
type ApiRetryOptions,
|
|
requestJson,
|
|
} from '../apiClient';
|
|
|
|
const PUZZLE_RUNTIME_API_BASE = '/api/runtime/puzzle/runs';
|
|
const PUZZLE_RUNTIME_READ_RETRY: ApiRetryOptions = {
|
|
maxRetries: 1,
|
|
baseDelayMs: 120,
|
|
maxDelayMs: 360,
|
|
};
|
|
const PUZZLE_RUNTIME_WRITE_RETRY: ApiRetryOptions = {
|
|
maxRetries: 1,
|
|
baseDelayMs: 120,
|
|
maxDelayMs: 360,
|
|
retryUnsafeMethods: true,
|
|
};
|
|
type PuzzleRuntimeRequestOptions = Pick<
|
|
ApiRequestOptions,
|
|
| 'authImpact'
|
|
| 'skipRefresh'
|
|
| 'notifyAuthStateChange'
|
|
| 'clearAuthOnUnauthorized'
|
|
>;
|
|
|
|
/**
|
|
* 从某个已发布拼图作品开始一次 run。
|
|
*/
|
|
export async function startPuzzleRun(
|
|
payload: StartPuzzleRunRequest,
|
|
options: PuzzleRuntimeRequestOptions = {},
|
|
) {
|
|
return requestJson<PuzzleRunResponse>(
|
|
PUZZLE_RUNTIME_API_BASE,
|
|
{
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
},
|
|
'启动拼图玩法失败',
|
|
{
|
|
retry: PUZZLE_RUNTIME_WRITE_RETRY,
|
|
authImpact: options.authImpact,
|
|
skipRefresh: options.skipRefresh,
|
|
notifyAuthStateChange: options.notifyAuthStateChange,
|
|
clearAuthOnUnauthorized: options.clearAuthOnUnauthorized,
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 读取拼图运行态快照。
|
|
*/
|
|
export async function getPuzzleRun(runId: string) {
|
|
return requestJson<PuzzleRunResponse>(
|
|
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}`,
|
|
{
|
|
method: 'GET',
|
|
},
|
|
'读取拼图运行快照失败',
|
|
{
|
|
retry: PUZZLE_RUNTIME_READ_RETRY,
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 提交两块交换请求。
|
|
*/
|
|
export async function swapPuzzlePieces(
|
|
runId: string,
|
|
payload: SwapPuzzlePiecesRequest,
|
|
) {
|
|
return requestJson<PuzzleRunResponse>(
|
|
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/swap`,
|
|
{
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
},
|
|
'交换拼图块失败',
|
|
{
|
|
retry: PUZZLE_RUNTIME_WRITE_RETRY,
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 提交拖拽拼图块或已合并拼图组后的目标格。
|
|
*/
|
|
export async function dragPuzzlePieceOrGroup(
|
|
runId: string,
|
|
payload: DragPuzzlePieceRequest,
|
|
) {
|
|
return requestJson<PuzzleRunResponse>(
|
|
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/drag`,
|
|
{
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
},
|
|
'拖动拼图块失败',
|
|
{
|
|
retry: PUZZLE_RUNTIME_WRITE_RETRY,
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 进入推荐出的下一关。
|
|
*/
|
|
export async function advancePuzzleNextLevel(
|
|
runId: string,
|
|
payload: AdvancePuzzleNextLevelRequest = {},
|
|
options: PuzzleRuntimeRequestOptions = {},
|
|
) {
|
|
const targetProfileId = payload.targetProfileId?.trim() ?? '';
|
|
return requestJson<PuzzleRunResponse>(
|
|
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/next-level`,
|
|
{
|
|
method: 'POST',
|
|
...(targetProfileId
|
|
? {
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ targetProfileId }),
|
|
}
|
|
: {}),
|
|
},
|
|
'进入下一关失败',
|
|
{
|
|
retry: PUZZLE_RUNTIME_WRITE_RETRY,
|
|
authImpact: options.authImpact,
|
|
skipRefresh: options.skipRefresh,
|
|
notifyAuthStateChange: options.notifyAuthStateChange,
|
|
clearAuthOnUnauthorized: options.clearAuthOnUnauthorized,
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 提交通关成绩并读取真实排行榜。
|
|
*/
|
|
export async function submitPuzzleLeaderboard(
|
|
runId: string,
|
|
payload: SubmitPuzzleLeaderboardRequest,
|
|
options: PuzzleRuntimeRequestOptions = {},
|
|
) {
|
|
return requestJson<PuzzleRunResponse>(
|
|
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/leaderboard`,
|
|
{
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
},
|
|
'提交拼图排行榜失败',
|
|
{
|
|
retry: PUZZLE_RUNTIME_WRITE_RETRY,
|
|
authImpact: options.authImpact,
|
|
skipRefresh: options.skipRefresh,
|
|
notifyAuthStateChange: options.notifyAuthStateChange,
|
|
clearAuthOnUnauthorized: options.clearAuthOnUnauthorized,
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 暂停或恢复正式拼图运行态计时。
|
|
*/
|
|
export async function updatePuzzleRunPause(
|
|
runId: string,
|
|
payload: UpdatePuzzleRuntimePauseRequest,
|
|
options: PuzzleRuntimeRequestOptions = {},
|
|
) {
|
|
return requestJson<PuzzleRunResponse>(
|
|
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/pause`,
|
|
{
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
},
|
|
'更新拼图计时状态失败',
|
|
{
|
|
retry: PUZZLE_RUNTIME_WRITE_RETRY,
|
|
authImpact: options.authImpact,
|
|
skipRefresh: options.skipRefresh,
|
|
notifyAuthStateChange: options.notifyAuthStateChange,
|
|
clearAuthOnUnauthorized: options.clearAuthOnUnauthorized,
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 使用正式拼图道具,服务端负责扣除泥点并更新运行态。
|
|
*/
|
|
export async function usePuzzleRuntimeProp(
|
|
runId: string,
|
|
payload: UsePuzzleRuntimePropRequest,
|
|
options: PuzzleRuntimeRequestOptions = {},
|
|
) {
|
|
return requestJson<PuzzleRunResponse>(
|
|
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/props`,
|
|
{
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
},
|
|
'使用拼图道具失败',
|
|
{
|
|
retry: PUZZLE_RUNTIME_WRITE_RETRY,
|
|
authImpact: options.authImpact,
|
|
skipRefresh: options.skipRefresh,
|
|
notifyAuthStateChange: options.notifyAuthStateChange,
|
|
clearAuthOnUnauthorized: options.clearAuthOnUnauthorized,
|
|
},
|
|
);
|
|
}
|
|
|
|
export const puzzleRuntimeClient = {
|
|
advanceNextLevel: advancePuzzleNextLevel,
|
|
drag: dragPuzzlePieceOrGroup,
|
|
getRun: getPuzzleRun,
|
|
submitLeaderboard: submitPuzzleLeaderboard,
|
|
startRun: startPuzzleRun,
|
|
swap: swapPuzzlePieces,
|
|
updatePause: updatePuzzleRunPause,
|
|
useProp: usePuzzleRuntimeProp,
|
|
};
|