Merge remote-tracking branch 'origin/master' into codex/tiaoyitiao
# Conflicts: # server-rs/crates/api-server/src/jump_hop.rs # server-rs/crates/api-server/src/modules/jump_hop.rs
This commit is contained in:
@@ -11,6 +11,10 @@ import type {
|
||||
CreatePuzzleAgentSessionRequest,
|
||||
PuzzleAgentSessionSnapshot,
|
||||
} from '../../packages/shared/src/contracts/puzzleAgentSession';
|
||||
import type {
|
||||
PuzzleClearSessionSnapshotResponse,
|
||||
PuzzleClearWorkspaceCreateRequest,
|
||||
} from '../../packages/shared/src/contracts/puzzleClear';
|
||||
import type {
|
||||
CustomWorldGenerationProgress,
|
||||
CustomWorldGenerationStep,
|
||||
@@ -33,6 +37,7 @@ export type MiniGameDraftGenerationKind =
|
||||
| 'match3d'
|
||||
| 'baby-object-match'
|
||||
| 'jump-hop'
|
||||
| 'puzzle-clear'
|
||||
| 'wooden-fish';
|
||||
|
||||
export type MiniGameDraftGenerationPhase =
|
||||
@@ -66,6 +71,11 @@ export type MiniGameDraftGenerationPhase =
|
||||
| 'jump-hop-tile-atlas'
|
||||
| 'jump-hop-slice-tiles'
|
||||
| 'jump-hop-write-draft'
|
||||
| 'puzzle-clear-draft'
|
||||
| 'puzzle-clear-background'
|
||||
| 'puzzle-clear-atlas'
|
||||
| 'puzzle-clear-slices'
|
||||
| 'puzzle-clear-write-draft'
|
||||
| 'wooden-fish-draft'
|
||||
| 'wooden-fish-hit-object'
|
||||
| 'wooden-fish-background'
|
||||
@@ -418,6 +428,41 @@ const JUMP_HOP_STEPS = [
|
||||
|
||||
const JUMP_HOP_ESTIMATED_WAIT_MS = 5 * 60_000;
|
||||
|
||||
const PUZZLE_CLEAR_STEPS = [
|
||||
{
|
||||
id: 'puzzle-clear-draft',
|
||||
label: '整理玩法草稿',
|
||||
detail: '保存作品信息、主题词与底图策略。',
|
||||
weight: 8,
|
||||
},
|
||||
{
|
||||
id: 'puzzle-clear-background',
|
||||
label: '准备场地底图',
|
||||
detail: '处理上传底图或生成中央场地底图。',
|
||||
weight: 22,
|
||||
},
|
||||
{
|
||||
id: 'puzzle-clear-atlas',
|
||||
label: '生成复合图集',
|
||||
detail: '生成 135 组复合图案 atlas。',
|
||||
weight: 42,
|
||||
},
|
||||
{
|
||||
id: 'puzzle-clear-slices',
|
||||
label: '切分卡牌碎片',
|
||||
detail: '按预排坐标切成 1x1 卡牌碎片并校验。',
|
||||
weight: 20,
|
||||
},
|
||||
{
|
||||
id: 'puzzle-clear-write-draft',
|
||||
label: '写入正式草稿',
|
||||
detail: '保存底图、图集、碎片和作品摘要。',
|
||||
weight: 8,
|
||||
},
|
||||
] as const satisfies ReadonlyArray<MiniGameStepDefinition>;
|
||||
|
||||
const PUZZLE_CLEAR_ESTIMATED_WAIT_MS = 620_000;
|
||||
|
||||
const WOODEN_FISH_STEPS = [
|
||||
{
|
||||
id: 'wooden-fish-draft',
|
||||
@@ -497,6 +542,9 @@ function getStepDefinitions(kind: MiniGameDraftGenerationKind) {
|
||||
if (kind === 'jump-hop') {
|
||||
return JUMP_HOP_STEPS;
|
||||
}
|
||||
if (kind === 'puzzle-clear') {
|
||||
return PUZZLE_CLEAR_STEPS;
|
||||
}
|
||||
if (kind === 'wooden-fish') {
|
||||
return WOODEN_FISH_STEPS;
|
||||
}
|
||||
@@ -571,9 +619,11 @@ export function createMiniGameDraftGenerationState(
|
||||
? 'baby-object-draft'
|
||||
: kind === 'jump-hop'
|
||||
? 'jump-hop-draft'
|
||||
: kind === 'wooden-fish'
|
||||
? 'wooden-fish-draft'
|
||||
: 'compile',
|
||||
: kind === 'puzzle-clear'
|
||||
? 'puzzle-clear-draft'
|
||||
: kind === 'wooden-fish'
|
||||
? 'wooden-fish-draft'
|
||||
: 'compile',
|
||||
startedAtMs,
|
||||
completedAssetCount: 0,
|
||||
totalAssetCount: 0,
|
||||
@@ -657,6 +707,24 @@ function resolveJumpHopPhaseByElapsedMs(
|
||||
return 'jump-hop-draft';
|
||||
}
|
||||
|
||||
function resolvePuzzleClearPhaseByElapsedMs(
|
||||
elapsedMs: number,
|
||||
): MiniGameDraftGenerationPhase {
|
||||
if (elapsedMs >= 590_000) {
|
||||
return 'puzzle-clear-write-draft';
|
||||
}
|
||||
if (elapsedMs >= 470_000) {
|
||||
return 'puzzle-clear-slices';
|
||||
}
|
||||
if (elapsedMs >= 120_000) {
|
||||
return 'puzzle-clear-atlas';
|
||||
}
|
||||
if (elapsedMs >= 8_000) {
|
||||
return 'puzzle-clear-background';
|
||||
}
|
||||
return 'puzzle-clear-draft';
|
||||
}
|
||||
|
||||
function buildWoodenFishPhaseTimeline(): Array<{
|
||||
phase: Extract<
|
||||
MiniGameDraftGenerationPhase,
|
||||
@@ -798,6 +866,8 @@ function resolveElapsedActiveStepProgressRatio(
|
||||
? BABY_OBJECT_MATCH_ESTIMATED_WAIT_MS
|
||||
: kind === 'jump-hop'
|
||||
? JUMP_HOP_ESTIMATED_WAIT_MS
|
||||
: kind === 'puzzle-clear'
|
||||
? PUZZLE_CLEAR_ESTIMATED_WAIT_MS
|
||||
: kind === 'wooden-fish'
|
||||
? WOODEN_FISH_ESTIMATED_WAIT_MS
|
||||
: 1;
|
||||
@@ -924,7 +994,14 @@ export function buildMiniGameDraftGenerationProgress(
|
||||
...state,
|
||||
phase: resolveJumpHopPhaseByElapsedMs(elapsedMs),
|
||||
}
|
||||
: state;
|
||||
: state.kind === 'puzzle-clear' &&
|
||||
state.phase !== 'failed' &&
|
||||
state.phase !== 'ready'
|
||||
? {
|
||||
...state,
|
||||
phase: resolvePuzzleClearPhaseByElapsedMs(elapsedMs),
|
||||
}
|
||||
: state;
|
||||
|
||||
const puzzleTimedSteps =
|
||||
normalizedState.kind === 'puzzle'
|
||||
@@ -984,6 +1061,11 @@ export function buildMiniGameDraftGenerationProgress(
|
||||
normalizedState.kind,
|
||||
elapsedMs,
|
||||
)
|
||||
: normalizedState.kind === 'puzzle-clear'
|
||||
? resolveElapsedActiveStepProgressRatio(
|
||||
normalizedState.kind,
|
||||
elapsedMs,
|
||||
)
|
||||
: normalizedState.kind === 'wooden-fish'
|
||||
? (woodenFishTimeline?.activeStepProgressRatio ?? 0)
|
||||
: 0;
|
||||
@@ -1023,6 +1105,8 @@ export function buildMiniGameDraftGenerationProgress(
|
||||
? '宝贝识物草稿已准备完成,可进入结果页继续发布。'
|
||||
: normalizedState.kind === 'jump-hop'
|
||||
? '跳一跳草稿已准备完成,可进入结果页试玩或发布。'
|
||||
: normalizedState.kind === 'puzzle-clear'
|
||||
? '拼消消草稿已准备完成,可进入结果页试玩或发布。'
|
||||
: normalizedState.kind === 'wooden-fish'
|
||||
? '敲木鱼草稿已准备完成,可进入结果页试玩或发布。'
|
||||
: '首关草稿与正式图已准备完成,可进入结果页补作品信息。'
|
||||
@@ -1050,6 +1134,11 @@ export function buildMiniGameDraftGenerationProgress(
|
||||
? Math.max(0, BABY_OBJECT_MATCH_ESTIMATED_WAIT_MS - elapsedMs)
|
||||
: normalizedState.kind === 'jump-hop'
|
||||
? Math.max(0, JUMP_HOP_ESTIMATED_WAIT_MS - elapsedMs)
|
||||
: normalizedState.kind === 'puzzle-clear'
|
||||
? Math.max(
|
||||
0,
|
||||
PUZZLE_CLEAR_ESTIMATED_WAIT_MS - elapsedMs,
|
||||
)
|
||||
: normalizedState.kind === 'wooden-fish'
|
||||
? Math.max(0, WOODEN_FISH_ESTIMATED_WAIT_MS - elapsedMs)
|
||||
: null,
|
||||
@@ -1163,6 +1252,49 @@ export function buildWoodenFishGenerationAnchorEntries(
|
||||
.filter((entry) => entry.value.trim());
|
||||
}
|
||||
|
||||
export function buildPuzzleClearGenerationAnchorEntries(
|
||||
session: PuzzleClearSessionSnapshotResponse | null | undefined,
|
||||
formPayload: PuzzleClearWorkspaceCreateRequest | null | undefined = null,
|
||||
): CustomWorldStructuredAnchorEntry[] {
|
||||
const draft = session?.draft;
|
||||
const entries: Array<MiniGameAnchorSource | null> = [
|
||||
{
|
||||
key: 'puzzle-clear-title',
|
||||
label: '作品',
|
||||
value:
|
||||
formPayload?.workTitle?.trim() || draft?.workTitle?.trim() || '拼消消',
|
||||
},
|
||||
{
|
||||
key: 'puzzle-clear-theme',
|
||||
label: '主题',
|
||||
value:
|
||||
formPayload?.themePrompt?.trim() || draft?.themePrompt?.trim() || '',
|
||||
},
|
||||
{
|
||||
key: 'puzzle-clear-background',
|
||||
label: '底图',
|
||||
value:
|
||||
formPayload?.boardBackgroundPrompt?.trim() ||
|
||||
draft?.boardBackgroundPrompt?.trim() ||
|
||||
(formPayload?.boardBackgroundAsset ?? draft?.boardBackgroundAsset)
|
||||
?.prompt?.trim() ||
|
||||
(formPayload?.generateBoardBackground ??
|
||||
draft?.generateBoardBackground
|
||||
? 'AI生成'
|
||||
: '上传底图'),
|
||||
},
|
||||
];
|
||||
|
||||
return entries
|
||||
.filter((entry): entry is MiniGameAnchorSource => Boolean(entry))
|
||||
.map((entry) => ({
|
||||
id: entry.key,
|
||||
label: entry.label,
|
||||
value: entry.value,
|
||||
}))
|
||||
.filter((entry) => entry.value.trim());
|
||||
}
|
||||
|
||||
export function buildPuzzleGenerationAnchorEntries(
|
||||
session: PuzzleAgentSessionSnapshot | null | undefined,
|
||||
formPayload: CreatePuzzleAgentSessionRequest | null | undefined = null,
|
||||
|
||||
Reference in New Issue
Block a user