feat(game): 添加奖池功能支持
- 在国际化文件中添加奖池相关的翻译配置 - 定义 JackpotPoolState 和 GameJackpotPoolDto 类型接口 - 在 DashboardState 中添加 jackpotPool 字段 - 实现 normalizeJackpotPoolState 函数处理奖池数据转换 - 更新游戏 API 中的初始化和数据归一化逻辑 - 添加 Oxanium 字体依赖并配置奖池金额字体样式 - 实现 JackpotPoolTicker 组件显示动态增长的奖池金额 - 在消息广播组件中集成奖池显示功能 - 更新实时同步钩子中的奖池数据处理逻辑
This commit is contained in:
12
.cloudbase-sites/preview.json
Normal file
12
.cloudbase-sites/preview.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"pid": 98343,
|
||||
"port": 17174,
|
||||
"host": "0.0.0.0",
|
||||
"base": "/",
|
||||
"framework": "vite-react",
|
||||
"command": "/Users/jiaunun/.nvm/versions/node/v24.15.0/bin/node /Users/jiaunun/Desktop/36-character-flower/node_modules/vite/bin/vite.js --host 0.0.0.0 --port 17174 --strictPort --base /",
|
||||
"internalUrl": "http://127.0.0.1:17174/",
|
||||
"logPath": "/Users/jiaunun/Desktop/36-character-flower/.cloudbase-sites/logs/preview-1784093877629.log",
|
||||
"cwd": "/Users/jiaunun/Desktop/36-character-flower",
|
||||
"startedAt": "2026-07-15T05:37:58.655Z"
|
||||
}
|
||||
@@ -29,6 +29,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource-variable/geist": "^5.2.8",
|
||||
"@fontsource-variable/oxanium": "^5.2.8",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@tanstack/react-query": "^5.99.0",
|
||||
"@tanstack/react-query-devtools": "^5.99.0",
|
||||
|
||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
||||
'@fontsource-variable/geist':
|
||||
specifier: ^5.2.8
|
||||
version: 5.2.9
|
||||
'@fontsource-variable/oxanium':
|
||||
specifier: ^5.2.8
|
||||
version: 5.2.8
|
||||
'@hookform/resolvers':
|
||||
specifier: ^5.2.2
|
||||
version: 5.4.0(react-hook-form@7.75.0(react@19.2.5))
|
||||
@@ -635,6 +638,9 @@ packages:
|
||||
'@fontsource-variable/geist@5.2.9':
|
||||
resolution: {integrity: sha512-TP+QSBG3wxKGPE33CbMy/L0Nu3qvJ6Fy81Yc4LnQ95xH+i+cfEp8fyU8/kfV14YwszxIFPhnoMTbjL71waVpyQ==}
|
||||
|
||||
'@fontsource-variable/oxanium@5.2.8':
|
||||
resolution: {integrity: sha512-W3HWxRLXVB6yox3dgm1DIGOp98pz8KglwiM6/2BsMopvZrg98mXI9citFWz2pUX0FOOLwf8fmHxX+KrIn+6BoA==}
|
||||
|
||||
'@hono/node-server@1.19.14':
|
||||
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==}
|
||||
engines: {node: '>=18.14.1'}
|
||||
@@ -4785,6 +4791,8 @@ snapshots:
|
||||
|
||||
'@fontsource-variable/geist@5.2.9': {}
|
||||
|
||||
'@fontsource-variable/oxanium@5.2.8': {}
|
||||
|
||||
'@hono/node-server@1.19.14(hono@4.12.18)':
|
||||
dependencies:
|
||||
hono: 4.12.18
|
||||
|
||||
@@ -30,6 +30,7 @@ import type {
|
||||
GameBootstrapSnapshot,
|
||||
GameCell,
|
||||
GameCellDto,
|
||||
GameJackpotPoolDto,
|
||||
GameLobbyInitDto,
|
||||
GameLobbyInitResult,
|
||||
GameLobbyPeriodDto,
|
||||
@@ -40,6 +41,7 @@ import type {
|
||||
GameRoundFeedDto,
|
||||
HistoryEntry,
|
||||
HistoryEntryDto,
|
||||
JackpotPoolState,
|
||||
NoticeConfirmDto,
|
||||
NoticeDetailDto,
|
||||
NoticeListDto,
|
||||
@@ -164,10 +166,33 @@ function normalizeAnnouncementState(dto: AnnouncementStateDto) {
|
||||
} satisfies AnnouncementState
|
||||
}
|
||||
|
||||
function normalizeJackpotPoolState(
|
||||
dto: GameJackpotPoolDto | null | undefined,
|
||||
updatedAt: string | null,
|
||||
) {
|
||||
if (!dto) {
|
||||
return null
|
||||
}
|
||||
|
||||
const current = Number(dto.current)
|
||||
const speed = Number(dto.speed)
|
||||
|
||||
if (!Number.isFinite(current) || !Number.isFinite(speed)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
current,
|
||||
speedPerSecond: Math.max(0, speed),
|
||||
updatedAt,
|
||||
} satisfies JackpotPoolState
|
||||
}
|
||||
|
||||
function normalizeDashboardState(dto: DashboardStateDto) {
|
||||
return {
|
||||
countdownMs: dto.countdown_ms,
|
||||
featuredCellId: dto.featured_cell_id,
|
||||
jackpotPool: normalizeJackpotPoolState(dto.jackpot_pool, dto.updated_at),
|
||||
onlinePlayers: dto.online_players,
|
||||
tableLimitMax: dto.table_limit_max,
|
||||
tableLimitMin: dto.table_limit_min,
|
||||
@@ -334,6 +359,7 @@ export function normalizeGameLobbyInit(dto: GameLobbyInitDto) {
|
||||
dashboard: {
|
||||
countdownMs: 0,
|
||||
featuredCellId: null,
|
||||
jackpotPool: normalizeJackpotPoolState(dto.jackpot_pool, baseIso),
|
||||
onlinePlayers: 0,
|
||||
tableLimitMax: Number(dto.bet_config.max_bet_per_number) || 0,
|
||||
tableLimitMin: Number(dto.bet_config.min_bet_per_number) || 0,
|
||||
|
||||
138
src/components/jackpot-pool-ticker.tsx
Normal file
138
src/components/jackpot-pool-ticker.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import diamond from '@/assets/system/diamond.webp'
|
||||
import { SmartImage } from '@/components/smart-image.tsx'
|
||||
import { cn } from '@/lib/utils.ts'
|
||||
import { useGameSessionStore } from '@/store/game'
|
||||
|
||||
const JACKPOT_POOL_TICK_MS = 1000
|
||||
const jackpotPoolFormatter = new Intl.NumberFormat('en-US', {
|
||||
maximumFractionDigits: 2,
|
||||
minimumFractionDigits: 2,
|
||||
})
|
||||
|
||||
type JackpotPoolTickerProps = {
|
||||
className?: string
|
||||
variant?: 'inline' | 'standalone'
|
||||
}
|
||||
|
||||
export function JackpotPoolTicker({
|
||||
className,
|
||||
variant = 'standalone',
|
||||
}: JackpotPoolTickerProps) {
|
||||
const { t } = useTranslation()
|
||||
const jackpotPool = useGameSessionStore(
|
||||
(state) => state.dashboard.jackpotPool,
|
||||
)
|
||||
const poolCurrent = jackpotPool?.current ?? null
|
||||
const poolSpeedPerSecond = jackpotPool?.speedPerSecond ?? 0
|
||||
const poolUpdatedAt = jackpotPool?.updatedAt ?? null
|
||||
const [nowMs, setNowMs] = useState(() => Date.now())
|
||||
|
||||
useEffect(() => {
|
||||
setNowMs(Date.now())
|
||||
|
||||
if (poolCurrent === null || poolSpeedPerSecond <= 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const timerId = window.setInterval(() => {
|
||||
setNowMs(Date.now())
|
||||
}, JACKPOT_POOL_TICK_MS)
|
||||
|
||||
return () => {
|
||||
window.clearInterval(timerId)
|
||||
}
|
||||
}, [poolCurrent, poolSpeedPerSecond])
|
||||
|
||||
const displayAmount = useMemo(() => {
|
||||
if (poolCurrent === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
const updatedAtMs = poolUpdatedAt ? Date.parse(poolUpdatedAt) : Number.NaN
|
||||
const baseTimeMs = Number.isFinite(updatedAtMs) ? updatedAtMs : nowMs
|
||||
const elapsedSeconds = Math.max(0, (nowMs - baseTimeMs) / 1000)
|
||||
|
||||
return poolCurrent + elapsedSeconds * poolSpeedPerSecond
|
||||
}, [nowMs, poolCurrent, poolSpeedPerSecond, poolUpdatedAt])
|
||||
|
||||
if (displayAmount === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
const amountLabel = jackpotPoolFormatter.format(displayAmount)
|
||||
const isInline = variant === 'inline'
|
||||
const amountCharacterCounts = new Map<string, number>()
|
||||
const amountCharacterItems = Array.from(amountLabel).map((character) => {
|
||||
const nextCount = (amountCharacterCounts.get(character) ?? 0) + 1
|
||||
|
||||
amountCharacterCounts.set(character, nextCount)
|
||||
|
||||
return {
|
||||
character,
|
||||
key: `${character}-${nextCount}`,
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<section
|
||||
aria-label={t('game.jackpotPool.ariaLabel', { amount: amountLabel })}
|
||||
className={cn(
|
||||
'relative flex w-full min-w-0 items-center overflow-hidden whitespace-nowrap',
|
||||
isInline
|
||||
? 'h-design-20 rounded-[3px] border border-[#B86A13]/55 bg-[rgba(32,18,3,0.72)] px-design-4 md:h-design-52 md:rounded-[4px] md:px-design-10'
|
||||
: 'h-design-34 !rounded-[4px] border border-[#B86A13]/70 bg-[rgba(32,18,3,0.82)] !px-design-10 !py-0 md:h-design-48 md:!rounded-[5px] md:!px-design-16',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<SmartImage
|
||||
alt={t('game.jackpotPool.iconAlt')}
|
||||
className={cn(
|
||||
'shrink-0',
|
||||
isInline
|
||||
? 'mr-design-3 h-design-10 w-design-10 md:mr-design-8 md:h-design-24 md:w-design-24'
|
||||
: 'mr-design-5 h-design-14 w-design-14 md:mr-design-10 md:h-design-26 md:w-design-26',
|
||||
)}
|
||||
src={diamond}
|
||||
/>
|
||||
<span
|
||||
className={cn(
|
||||
'shrink-0 font-bold tracking-[0.08em] text-[#D8AA49]',
|
||||
isInline
|
||||
? 'mr-[20px] text-design-6 md:text-design-12'
|
||||
: 'mr-[20px] text-design-8 md:text-design-14',
|
||||
)}
|
||||
>
|
||||
{t('game.jackpotPool.label')}
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
'min-w-0 shrink truncate font-jackpot-amount font-extrabold leading-none tabular-nums [font-variation-settings:"wght"_760]',
|
||||
isInline
|
||||
? 'text-design-10 md:text-design-27'
|
||||
: 'text-design-16 md:text-design-30',
|
||||
)}
|
||||
>
|
||||
{amountCharacterItems.map(({ character, key }) => {
|
||||
const isNumber = /\d/.test(character)
|
||||
|
||||
return (
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className={cn(
|
||||
'inline-block text-[#FFD15A]',
|
||||
isNumber
|
||||
? '[text-shadow:0_0_calc(var(--design-unit)*3)_rgba(255,240,166,0.88),0_0_calc(var(--design-unit)*7)_rgba(255,209,90,0.64),0_calc(var(--design-unit)*1)_0_rgba(92,43,2,0.92)]'
|
||||
: 'mx-[0.03em] text-[#D49322]',
|
||||
)}
|
||||
key={key}
|
||||
>
|
||||
{character}
|
||||
</span>
|
||||
)
|
||||
})}
|
||||
</span>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { AnimatePresence, motion, useReducedMotion } from 'motion/react'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import broadcast from '@/assets/system/broadcast.webp'
|
||||
import { JackpotPoolTicker } from '@/components/jackpot-pool-ticker.tsx'
|
||||
import { SmartImage } from '@/components/smart-image.tsx'
|
||||
import { cn } from '@/lib/utils.ts'
|
||||
import { useGameSessionStore } from '@/store/game'
|
||||
@@ -103,65 +104,71 @@ export function MessageBroadcast({ className }: MessageBroadcastProps) {
|
||||
aria-label={t('game.jackpotBroadcast.ariaLabel')}
|
||||
className={cn(
|
||||
'common-neon-inset flex w-full min-w-0 items-center overflow-hidden',
|
||||
'h-design-24 gap-design-5 !rounded-[3px] !px-design-7 !py-0 text-design-8',
|
||||
'md:h-design-65 md:gap-design-10 md:!rounded-[5px] md:!px-design-20 md:text-design-16',
|
||||
'h-design-24 gap-design-4 !rounded-[3px] !px-design-5 !py-0 text-design-8',
|
||||
'md:h-design-65 md:gap-design-12 md:!rounded-[5px] md:!px-design-20 md:text-design-16',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<SmartImage
|
||||
className="h-design-12 w-design-12 shrink-0 md:h-design-24 md:w-design-24"
|
||||
alt={t('game.jackpotBroadcast.iconAlt')}
|
||||
src={broadcast}
|
||||
/>
|
||||
<div className="relative h-design-16 min-w-0 flex-1 overflow-hidden md:h-design-28">
|
||||
<AnimatePresence>
|
||||
{activeBroadcast ? (
|
||||
<motion.div
|
||||
aria-label={activeBroadcastLabel}
|
||||
className="absolute inset-0 flex min-w-max items-center whitespace-nowrap font-semibold"
|
||||
key={activeBroadcast.id}
|
||||
initial={
|
||||
prefersReducedMotion
|
||||
? { opacity: 0 }
|
||||
: { opacity: 1, x: '108%' }
|
||||
}
|
||||
animate={
|
||||
prefersReducedMotion
|
||||
? { opacity: 1 }
|
||||
: { opacity: 1, x: '-108%' }
|
||||
}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{
|
||||
duration: prefersReducedMotion
|
||||
? 0.18
|
||||
: MESSAGE_BROADCAST_ANIMATION_MS / 1000,
|
||||
ease: prefersReducedMotion ? [0.16, 1, 0.3, 1] : 'linear',
|
||||
}}
|
||||
>
|
||||
<span className="text-[#D5F7FF]">
|
||||
{t('game.jackpotBroadcast.prefix')}
|
||||
</span>
|
||||
<span className="ml-design-4 text-[#4BFFFE] md:ml-design-8">
|
||||
{activeBroadcast.nickname}
|
||||
</span>
|
||||
<span className="mx-design-4 text-[#D5F7FF] md:mx-design-8">
|
||||
{t('game.jackpotBroadcast.separator')}
|
||||
</span>
|
||||
<span className="text-[#78FF7F]">
|
||||
{t('game.jackpotBroadcast.streak', {
|
||||
count: activeBroadcast.currentStreak,
|
||||
})}
|
||||
</span>
|
||||
<span className="mx-design-4 text-[#D5F7FF] md:mx-design-8">
|
||||
{t('game.jackpotBroadcast.winAction')}
|
||||
</span>
|
||||
<span className="text-[#FFB72B]">
|
||||
{formatWinAmount(activeBroadcast.totalWin)}
|
||||
</span>
|
||||
</motion.div>
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
<div className="flex min-w-0 flex-1 items-center gap-design-4 md:gap-design-10">
|
||||
<SmartImage
|
||||
className="h-design-12 w-design-12 shrink-0 md:h-design-24 md:w-design-24"
|
||||
alt={t('game.jackpotBroadcast.iconAlt')}
|
||||
src={broadcast}
|
||||
/>
|
||||
<div className="relative h-design-16 min-w-0 flex-1 overflow-hidden md:h-design-28">
|
||||
<AnimatePresence>
|
||||
{activeBroadcast ? (
|
||||
<motion.div
|
||||
aria-label={activeBroadcastLabel}
|
||||
className="absolute inset-0 flex min-w-max items-center whitespace-nowrap font-semibold"
|
||||
key={activeBroadcast.id}
|
||||
initial={
|
||||
prefersReducedMotion
|
||||
? { opacity: 0 }
|
||||
: { opacity: 1, x: '108%' }
|
||||
}
|
||||
animate={
|
||||
prefersReducedMotion
|
||||
? { opacity: 1 }
|
||||
: { opacity: 1, x: '-108%' }
|
||||
}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{
|
||||
duration: prefersReducedMotion
|
||||
? 0.18
|
||||
: MESSAGE_BROADCAST_ANIMATION_MS / 1000,
|
||||
ease: prefersReducedMotion ? [0.16, 1, 0.3, 1] : 'linear',
|
||||
}}
|
||||
>
|
||||
<span className="text-[#D5F7FF]">
|
||||
{t('game.jackpotBroadcast.prefix')}
|
||||
</span>
|
||||
<span className="ml-design-4 text-[#4BFFFE] md:ml-design-8">
|
||||
{activeBroadcast.nickname}
|
||||
</span>
|
||||
<span className="mx-design-4 text-[#D5F7FF] md:mx-design-8">
|
||||
{t('game.jackpotBroadcast.separator')}
|
||||
</span>
|
||||
<span className="text-[#78FF7F]">
|
||||
{t('game.jackpotBroadcast.streak', {
|
||||
count: activeBroadcast.currentStreak,
|
||||
})}
|
||||
</span>
|
||||
<span className="mx-design-4 text-[#D5F7FF] md:mx-design-8">
|
||||
{t('game.jackpotBroadcast.winAction')}
|
||||
</span>
|
||||
<span className="text-[#FFB72B]">
|
||||
{formatWinAmount(activeBroadcast.totalWin)}
|
||||
</span>
|
||||
</motion.div>
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
<JackpotPoolTicker
|
||||
variant="inline"
|
||||
className="!w-fit max-w-[54%] shrink-0 md:max-w-[calc(var(--design-unit)*320)]"
|
||||
/>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ function createEmptyDashboardState(nowIso: string): DashboardState {
|
||||
return {
|
||||
countdownMs: 0,
|
||||
featuredCellId: null,
|
||||
jackpotPool: null,
|
||||
onlinePlayers: 0,
|
||||
tableLimitMax: 0,
|
||||
tableLimitMin: 0,
|
||||
|
||||
@@ -63,6 +63,7 @@ function applyLobbySync(result: Awaited<ReturnType<typeof getGameLobbyInit>>) {
|
||||
},
|
||||
dashboard: {
|
||||
...currentSessionState.dashboard,
|
||||
jackpotPool: result.snapshot.dashboard.jackpotPool,
|
||||
tableLimitMax: result.snapshot.dashboard.tableLimitMax,
|
||||
tableLimitMin: result.snapshot.dashboard.tableLimitMin,
|
||||
},
|
||||
|
||||
@@ -178,6 +178,11 @@ export default {
|
||||
streak: '{{count}}-win streak',
|
||||
winAction: 'won',
|
||||
},
|
||||
jackpotPool: {
|
||||
ariaLabel: 'Current jackpot pool {{amount}}',
|
||||
iconAlt: 'Jackpot pool',
|
||||
label: 'Jackpot',
|
||||
},
|
||||
actions: {
|
||||
unifiedBetHint: 'Unified bet',
|
||||
totalBet: 'Total bet',
|
||||
|
||||
@@ -177,6 +177,11 @@ export default {
|
||||
streak: 'streak {{count}} menang',
|
||||
winAction: 'memenangkan',
|
||||
},
|
||||
jackpotPool: {
|
||||
ariaLabel: 'Pool jackpot saat ini {{amount}}',
|
||||
iconAlt: 'Pool jackpot',
|
||||
label: 'Jackpot',
|
||||
},
|
||||
actions: {
|
||||
unifiedBetHint: 'Bet seragam',
|
||||
totalBet: 'Total bet',
|
||||
|
||||
@@ -180,6 +180,11 @@ export default {
|
||||
streak: 'streak {{count}} menang',
|
||||
winAction: 'memenangi',
|
||||
},
|
||||
jackpotPool: {
|
||||
ariaLabel: 'Dana jackpot semasa {{amount}}',
|
||||
iconAlt: 'Dana jackpot',
|
||||
label: 'Jackpot',
|
||||
},
|
||||
actions: {
|
||||
unifiedBetHint: 'Taruhan seragam',
|
||||
totalBet: 'Jumlah taruhan',
|
||||
|
||||
@@ -175,6 +175,11 @@ export default {
|
||||
streak: '{{count}} 连胜',
|
||||
winAction: '赢得',
|
||||
},
|
||||
jackpotPool: {
|
||||
ariaLabel: '彩金池当前金额 {{amount}}',
|
||||
iconAlt: '彩金池',
|
||||
label: '彩金池',
|
||||
},
|
||||
actions: {
|
||||
unifiedBetHint: '统一下注额',
|
||||
totalBet: '总下注',
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
@import "tw-animate-css";
|
||||
@import "shadcn/tailwind.css";
|
||||
@import "@fontsource-variable/geist";
|
||||
@import "@fontsource-variable/oxanium";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@@ -12,6 +13,8 @@
|
||||
--font-mono:
|
||||
"JetBrains Mono", "SFMono-Regular", "SF Mono", Consolas, monospace;
|
||||
--font-countdown: "Countdown", "Inter", "SF Pro Display", sans-serif;
|
||||
--font-jackpot-amount:
|
||||
"Oxanium Variable", "Countdown", "SF Pro Display", sans-serif;
|
||||
--color-game-bg: #07111f;
|
||||
--color-game-surface: #0d1b2d;
|
||||
--color-game-surface-strong: #12253d;
|
||||
|
||||
@@ -109,9 +109,16 @@ export interface AnnouncementState {
|
||||
lastUpdatedAt: string | null
|
||||
}
|
||||
|
||||
export interface JackpotPoolState {
|
||||
current: number
|
||||
speedPerSecond: number
|
||||
updatedAt: string | null
|
||||
}
|
||||
|
||||
export interface DashboardState {
|
||||
countdownMs: number
|
||||
featuredCellId: number | null
|
||||
jackpotPool: JackpotPoolState | null
|
||||
onlinePlayers: number
|
||||
tableLimitMax: number
|
||||
tableLimitMin: number
|
||||
@@ -332,6 +339,7 @@ export interface AnnouncementStateDto {
|
||||
export interface DashboardStateDto {
|
||||
countdown_ms: number
|
||||
featured_cell_id: number | null
|
||||
jackpot_pool?: GameJackpotPoolDto | null
|
||||
online_players: number
|
||||
table_limit_max: number
|
||||
table_limit_min: number
|
||||
@@ -339,6 +347,11 @@ export interface DashboardStateDto {
|
||||
updated_at: string | null
|
||||
}
|
||||
|
||||
export interface GameJackpotPoolDto {
|
||||
current: string
|
||||
speed: string
|
||||
}
|
||||
|
||||
export interface ConnectionStateDto {
|
||||
connected_at: string | null
|
||||
last_error: string | null
|
||||
@@ -451,6 +464,7 @@ export interface GameLobbyStreakWinRewardDto {
|
||||
export interface GameLobbyInitDto {
|
||||
bet_config: GameLobbyBetConfigDto
|
||||
dictionary: GameLobbyDictionaryItemDto[]
|
||||
jackpot_pool?: GameJackpotPoolDto | null
|
||||
period?: GameLobbyPeriodDto | null
|
||||
runtime_enabled: boolean
|
||||
server_time: number
|
||||
|
||||
Reference in New Issue
Block a user