feat: add wooden fish play template
This commit is contained in:
@@ -16,6 +16,10 @@ import type {
|
||||
CustomWorldGenerationStep,
|
||||
} from '../../packages/shared/src/contracts/runtime';
|
||||
import type { SquareHoleSessionSnapshot } from '../../packages/shared/src/contracts/squareHoleAgent';
|
||||
import type {
|
||||
WoodenFishSessionSnapshotResponse,
|
||||
WoodenFishWorkspaceCreateRequest,
|
||||
} from '../../packages/shared/src/contracts/woodenFish';
|
||||
import type { CustomWorldStructuredAnchorEntry } from './customWorldAgentGenerationProgress';
|
||||
import type {
|
||||
CreateJumpHopSessionRequest,
|
||||
@@ -28,7 +32,8 @@ export type MiniGameDraftGenerationKind =
|
||||
| 'square-hole'
|
||||
| 'match3d'
|
||||
| 'baby-object-match'
|
||||
| 'jump-hop';
|
||||
| 'jump-hop'
|
||||
| 'wooden-fish';
|
||||
|
||||
export type MiniGameDraftGenerationPhase =
|
||||
| 'idle'
|
||||
@@ -59,6 +64,10 @@ export type MiniGameDraftGenerationPhase =
|
||||
| 'jump-hop-tile-atlas'
|
||||
| 'jump-hop-slice-tiles'
|
||||
| 'jump-hop-write-draft'
|
||||
| 'wooden-fish-draft'
|
||||
| 'wooden-fish-hit-object'
|
||||
| 'wooden-fish-hit-sound'
|
||||
| 'wooden-fish-write-draft'
|
||||
| 'puzzle-images'
|
||||
| 'puzzle-ui-background'
|
||||
| 'puzzle-select-image'
|
||||
@@ -313,6 +322,35 @@ const JUMP_HOP_STEPS = [
|
||||
|
||||
const JUMP_HOP_ESTIMATED_WAIT_MS = 5 * 60_000;
|
||||
|
||||
const WOODEN_FISH_STEPS = [
|
||||
{
|
||||
id: 'wooden-fish-draft',
|
||||
label: '整理玩法草稿',
|
||||
detail: '保存作品信息、敲击物、音效和飘字配置。',
|
||||
weight: 10,
|
||||
},
|
||||
{
|
||||
id: 'wooden-fish-hit-object',
|
||||
label: '生成敲击物图案',
|
||||
detail: '使用 image2 生成最终运行态敲击物图案。',
|
||||
weight: 48,
|
||||
},
|
||||
{
|
||||
id: 'wooden-fish-hit-sound',
|
||||
label: '准备敲击音效',
|
||||
detail: '生成或写回短促敲击音效资产。',
|
||||
weight: 30,
|
||||
},
|
||||
{
|
||||
id: 'wooden-fish-write-draft',
|
||||
label: '写入正式草稿',
|
||||
detail: '保存图案、音效、飘字和封面摘要。',
|
||||
weight: 12,
|
||||
},
|
||||
] as const satisfies ReadonlyArray<MiniGameStepDefinition>;
|
||||
|
||||
const WOODEN_FISH_ESTIMATED_WAIT_MS = 5 * 60_000;
|
||||
|
||||
function clampProgress(value: number) {
|
||||
return Math.max(0, Math.min(100, Math.round(value)));
|
||||
}
|
||||
@@ -333,6 +371,9 @@ function getStepDefinitions(kind: MiniGameDraftGenerationKind) {
|
||||
if (kind === 'jump-hop') {
|
||||
return JUMP_HOP_STEPS;
|
||||
}
|
||||
if (kind === 'wooden-fish') {
|
||||
return WOODEN_FISH_STEPS;
|
||||
}
|
||||
return BIG_FISH_STEPS;
|
||||
}
|
||||
|
||||
@@ -390,8 +431,10 @@ export function createMiniGameDraftGenerationState(
|
||||
? 'match3d-work-title'
|
||||
: kind === 'baby-object-match'
|
||||
? 'baby-object-draft'
|
||||
: kind === 'jump-hop'
|
||||
? 'jump-hop-draft'
|
||||
: kind === 'jump-hop'
|
||||
? 'jump-hop-draft'
|
||||
: kind === 'wooden-fish'
|
||||
? 'wooden-fish-draft'
|
||||
: 'compile',
|
||||
startedAtMs: Date.now(),
|
||||
completedAssetCount: 0,
|
||||
@@ -481,6 +524,21 @@ function resolveJumpHopPhaseByElapsedMs(
|
||||
return 'jump-hop-draft';
|
||||
}
|
||||
|
||||
function resolveWoodenFishPhaseByElapsedMs(
|
||||
elapsedMs: number,
|
||||
): MiniGameDraftGenerationPhase {
|
||||
if (elapsedMs >= 270_000) {
|
||||
return 'wooden-fish-write-draft';
|
||||
}
|
||||
if (elapsedMs >= 185_000) {
|
||||
return 'wooden-fish-hit-sound';
|
||||
}
|
||||
if (elapsedMs >= 12_000) {
|
||||
return 'wooden-fish-hit-object';
|
||||
}
|
||||
return 'wooden-fish-draft';
|
||||
}
|
||||
|
||||
function resolvePuzzleTimelineByElapsedMs(elapsedMs: number) {
|
||||
let elapsedBeforePhase = 0;
|
||||
|
||||
@@ -566,6 +624,13 @@ export function buildMiniGameDraftGenerationProgress(
|
||||
...state,
|
||||
phase: resolveJumpHopPhaseByElapsedMs(elapsedMs),
|
||||
}
|
||||
: state.kind === 'wooden-fish' &&
|
||||
state.phase !== 'failed' &&
|
||||
state.phase !== 'ready'
|
||||
? {
|
||||
...state,
|
||||
phase: resolveWoodenFishPhaseByElapsedMs(elapsedMs),
|
||||
}
|
||||
: state;
|
||||
|
||||
const steps = getStepDefinitions(normalizedState.kind);
|
||||
@@ -597,6 +662,8 @@ export function buildMiniGameDraftGenerationProgress(
|
||||
? 0.52
|
||||
: normalizedState.kind === 'jump-hop'
|
||||
? 0.5
|
||||
: normalizedState.kind === 'wooden-fish'
|
||||
? 0.5
|
||||
: 0;
|
||||
const overallProgress =
|
||||
normalizedState.phase === 'failed'
|
||||
@@ -630,6 +697,8 @@ export function buildMiniGameDraftGenerationProgress(
|
||||
? '宝贝识物草稿已准备完成,可进入结果页继续发布。'
|
||||
: normalizedState.kind === 'jump-hop'
|
||||
? '跳一跳草稿已准备完成,可进入结果页试玩或发布。'
|
||||
: normalizedState.kind === 'wooden-fish'
|
||||
? '敲木鱼草稿已准备完成,可进入结果页试玩或发布。'
|
||||
: '首关草稿与正式图已准备完成,可进入结果页补作品信息。'
|
||||
: activeStep.detail),
|
||||
batchLabel: activeStep.label,
|
||||
@@ -655,6 +724,8 @@ export function buildMiniGameDraftGenerationProgress(
|
||||
)
|
||||
: normalizedState.kind === 'jump-hop'
|
||||
? Math.max(0, JUMP_HOP_ESTIMATED_WAIT_MS - elapsedMs)
|
||||
: normalizedState.kind === 'wooden-fish'
|
||||
? Math.max(0, WOODEN_FISH_ESTIMATED_WAIT_MS - elapsedMs)
|
||||
: null,
|
||||
activeStepIndex,
|
||||
steps: buildMiniGameProgressSteps(
|
||||
@@ -725,6 +796,57 @@ export function buildJumpHopGenerationAnchorEntries(
|
||||
.filter((entry) => entry.value.trim());
|
||||
}
|
||||
|
||||
export function buildWoodenFishGenerationAnchorEntries(
|
||||
session: WoodenFishSessionSnapshotResponse | null | undefined,
|
||||
formPayload: WoodenFishWorkspaceCreateRequest | null | undefined = null,
|
||||
): CustomWorldStructuredAnchorEntry[] {
|
||||
const draft = session?.draft;
|
||||
const entries: Array<MiniGameAnchorSource | null> = [
|
||||
{
|
||||
key: 'wooden-fish-hit-object',
|
||||
label: '敲击物',
|
||||
value:
|
||||
formPayload?.hitObjectPrompt?.trim() ||
|
||||
draft?.hitObjectPrompt?.trim() ||
|
||||
'',
|
||||
},
|
||||
{
|
||||
key: 'wooden-fish-hit-sound',
|
||||
label: '音效',
|
||||
value:
|
||||
formPayload?.hitSoundPrompt?.trim() ||
|
||||
draft?.hitSoundPrompt?.trim() ||
|
||||
draft?.hitSoundAsset?.prompt?.trim() ||
|
||||
'',
|
||||
},
|
||||
{
|
||||
key: 'wooden-fish-words',
|
||||
label: '飘字',
|
||||
value:
|
||||
formPayload?.floatingWords
|
||||
?.map((word) => word.trim())
|
||||
.filter(Boolean)
|
||||
.slice(0, 8)
|
||||
.join('、') ||
|
||||
draft?.floatingWords
|
||||
?.map((word) => word.trim())
|
||||
.filter(Boolean)
|
||||
.slice(0, 8)
|
||||
.join('、') ||
|
||||
'',
|
||||
},
|
||||
];
|
||||
|
||||
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