{"_id":"@agentduel/replay-player","_rev":"5-8d306908000d415d152634fc19e1996d","name":"@agentduel/replay-player","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.0":{"name":"@agentduel/replay-player","version":"0.1.0","license":"Apache-2.0","_id":"@agentduel/replay-player@0.1.0","maintainers":[{"name":"furlxy","email":"furlxy@gmail.com"}],"dist":{"shasum":"27f49106fa52367e3a7af1ae1d8fa3bab7c79776","tarball":"https://registry.npmjs.org/@agentduel/replay-player/-/replay-player-0.1.0.tgz","fileCount":100,"integrity":"sha512-kompstPUfBcRR7O01lUp86oLAe0ORWnIo4Bn7udi1iV7IBzcTQXIJlSMkl1YK0xdAKBhOIpoSFwlarDNPVRd6A==","signatures":[{"sig":"MEQCIB82q/ntoEYsDgjoBktbZS83swCO7mP3MIu+8nhU3LpfAiBJa3e5j54BWpXebVBuogIOkKQq+9DKH99MhTfIBwkhuQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1013731},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/assets/agentduel-replay-player.css"},"gitHead":"da8a5eb15b256bfea823dbedffef577e0e3c2f0c","scripts":{"dev":"vite --config vite.demo.config.ts","test":"vitest run","build":"npm run clean && tsc -p tsconfig.build.json && vite build","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","typecheck":"tsc --noEmit -p tsconfig.json","pack:check":"npm pack --dry-run"},"_npmUser":{"name":"furlxy","email":"furlxy@gmail.com"},"_npmVersion":"11.6.0","description":"AgentDuel battle replay player for React applications","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"24.9.0","dependencies":{"i18next":"^25.3.2","pixi.js":"^8.8.1","react-i18next":"^15.6.1","canvas-confetti":"^1.9.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.3.5","react":"^19.1.0","vitest":"^3.2.4","react-dom":"^19.1.0","typescript":"^5.8.3","@types/node":"^22.15.32","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.6.0","@types/canvas-confetti":"^1.9.0","postcss-prefix-selector":"^2.1.1"},"peerDependencies":{"react":">=18.2.0","react-dom":">=18.2.0"},"_npmOperationalInternal":{"tmp":"tmp/replay-player_0.1.0_1787047053130_0.6737198451427229","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@agentduel/replay-player","version":"0.1.1","license":"Apache-2.0","_id":"@agentduel/replay-player@0.1.1","maintainers":[{"name":"furlxy","email":"furlxy@gmail.com"}],"dist":{"shasum":"e89b69573cc7961d5a7a8b238f458efb279d88ee","tarball":"https://registry.npmjs.org/@agentduel/replay-player/-/replay-player-0.1.1.tgz","fileCount":96,"integrity":"sha512-UvUiyJVX5bagjTG/PlkvS5vPfl2f+rrxgERolDSAEP0vrKIdVWXZaXfey5Mta4lQeSbTUTPGDpO1Q1kTOvAoLw==","signatures":[{"sig":"MEMCIAF+0+b1vHJr5WHH3knTKlN4TDIA43tfr5iLty6i2k8oAh80LKMJQZuf2L9EEMwvEIy+EMTIUYul8tV/IBvTqevT","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1016900},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/assets/index.css"},"gitHead":"da8a5eb15b256bfea823dbedffef577e0e3c2f0c","scripts":{"dev":"vite --config vite.demo.config.ts","test":"vitest run","build":"npm run clean && tsc -p tsconfig.build.json && vite build","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","typecheck":"tsc --noEmit -p tsconfig.json","pack:check":"npm pack --dry-run"},"_npmUser":{"name":"furlxy","email":"furlxy@gmail.com"},"_npmVersion":"11.6.0","description":"AgentDuel battle replay player for React applications","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"24.9.0","dependencies":{"i18next":"^25.3.2","pixi.js":"^8.8.1","react-i18next":"^15.6.1","canvas-confetti":"^1.9.3","@agentduel/component":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.3.5","react":"^19.1.0","vitest":"^3.2.4","react-dom":"^19.1.0","typescript":"^5.8.3","@types/node":"^22.15.32","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.6.0","@types/canvas-confetti":"^1.9.0","postcss-prefix-selector":"^2.1.1","vite-plugin-lib-inject-css":"^2.2.2"},"peerDependencies":{"react":">=18.2.0","react-dom":">=18.2.0"},"_npmOperationalInternal":{"tmp":"tmp/replay-player_0.1.1_1787136114218_0.13093556187983046","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@agentduel/replay-player","version":"0.1.2","license":"Apache-2.0","_id":"@agentduel/replay-player@0.1.2","maintainers":[{"name":"furlxy","email":"furlxy@gmail.com"}],"dist":{"shasum":"9d236c7f6c9be6c828ec2e5fa8cb60996eb98474","tarball":"https://registry.npmjs.org/@agentduel/replay-player/-/replay-player-0.1.2.tgz","fileCount":96,"integrity":"sha512-8qv/BxZrGE/UXM8713YqaS1ktf6c2B0QIAA0ZsGKa/+eQcAGUwOveBm6wN+2cUDFoCj9TB2tUDHWiq+9ka6hRQ==","signatures":[{"sig":"MEUCIQDlt4Upwu2ryhH6OS5NuzB1CBu271IDwg1sFtbqMHFgjAIgX+iqRdknqCiVYNaQFoldeT9czKOU6mRI4fZlfCzEPG0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1024698},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/assets/index.css"},"gitHead":"09a3ec65185b2917831d4f0f71cbc381b6a10547","scripts":{"dev":"vite --config vite.demo.config.ts","test":"vitest run","build":"npm run clean && tsc -p tsconfig.build.json && vite build","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","typecheck":"tsc --noEmit -p tsconfig.json","pack:check":"npm pack --dry-run"},"_npmUser":{"name":"furlxy","email":"furlxy@gmail.com"},"_npmVersion":"11.6.0","description":"AgentDuel battle replay player for React applications","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"24.9.0","dependencies":{"i18next":"^25.3.2","pixi.js":"^8.8.1","react-i18next":"^15.6.1","canvas-confetti":"^1.9.3","@agentduel/component":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.3.5","react":"^19.1.0","vitest":"^3.2.4","react-dom":"^19.1.0","typescript":"^5.8.3","@types/node":"^22.15.32","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.6.0","@types/canvas-confetti":"^1.9.0","postcss-prefix-selector":"^2.1.1","vite-plugin-lib-inject-css":"^2.2.2"},"peerDependencies":{"react":">=18.2.0","react-dom":">=18.2.0"},"_npmOperationalInternal":{"tmp":"tmp/replay-player_0.1.2_1787221104537_0.6066917484941177","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@agentduel/replay-player","version":"0.1.4","license":"Apache-2.0","_id":"@agentduel/replay-player@0.1.4","maintainers":[{"name":"furlxy","email":"furlxy@gmail.com"}],"dist":{"shasum":"944377eae5853cdc71629f43a12d66311bf85e17","tarball":"https://registry.npmjs.org/@agentduel/replay-player/-/replay-player-0.1.4.tgz","fileCount":92,"integrity":"sha512-4cHmtu/B0VrI1hicm22fwdukgNNeBfqrVK2g1aPWRY4cmV/fNqT62WtcDErMbBsYuu/9ONCGtaLPhvkUd+kM1w==","signatures":[{"sig":"MEYCIQDkMx5k1qnpC79AMIyIL4y3CeY3tDXEmY/9p9vPENsyZgIhAIlL/EhSBiCpC6s9/5nleg3KMrwmNO5QizSgzgkvK6Dg","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1000141},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/assets/index.css"},"gitHead":"72cd9fe799a0ceaa43741c73bfcae952ed763591","scripts":{"dev":"vite --config vite.demo.config.ts","test":"vitest run","build":"npm run clean && tsc -p tsconfig.build.json && vite build","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","typecheck":"tsc --noEmit -p tsconfig.json","pack:check":"npm pack --dry-run"},"_npmUser":{"name":"furlxy","email":"furlxy@gmail.com"},"_npmVersion":"11.6.0","description":"AgentDuel battle replay player for React applications","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"24.9.0","dependencies":{"i18next":"^25.3.2","pixi.js":"^8.8.1","react-i18next":"^15.6.1","canvas-confetti":"^1.9.3","@agentduel/component":"^0.1.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.3.5","react":"^19.1.0","vitest":"^3.2.4","react-dom":"^19.1.0","typescript":"^5.8.3","@types/node":"^22.15.32","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.6.0","@types/canvas-confetti":"^1.9.0","postcss-prefix-selector":"^2.1.1","vite-plugin-lib-inject-css":"^2.2.2"},"peerDependencies":{"react":">=18.2.0","react-dom":">=18.2.0"},"_npmOperationalInternal":{"tmp":"tmp/replay-player_0.1.4_1787224205918_0.8659867166678641","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@agentduel/replay-player","version":"0.1.5","description":"AgentDuel battle replay player for React applications","license":"Apache-2.0","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./styles.css":"./dist/assets/index.css"},"sideEffects":["**/*.css"],"publishConfig":{"access":"public"},"scripts":{"dev":"vite --config vite.demo.config.ts","test":"vitest run","typecheck":"tsc --noEmit -p tsconfig.json","build":"npm run clean && tsc -p tsconfig.build.json && vite build","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","pack:check":"npm pack --dry-run"},"peerDependencies":{"react":">=18.2.0","react-dom":">=18.2.0"},"dependencies":{"@agentduel/component":"^0.1.6","canvas-confetti":"^1.9.3","i18next":"^25.3.2","pixi.js":"^8.8.1","react-i18next":"^15.6.1"},"devDependencies":{"@types/canvas-confetti":"^1.9.0","@types/node":"^22.15.32","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.6.0","postcss-prefix-selector":"^2.1.1","react":"^19.1.0","react-dom":"^19.1.0","typescript":"^5.8.3","vite":"^6.3.5","vite-plugin-lib-inject-css":"^2.2.2","vitest":"^3.2.4"},"engines":{"node":">=20.19.0"},"_id":"@agentduel/replay-player@0.1.5","gitHead":"671b98b50184c4baf74f3d0be482d8aee8e8b06c","_nodeVersion":"22.19.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-cQdwv8MkkE2xzSCQjnDtMv7KiBaqnR1dt7VoSBKIt7F/jLS5v1NNSHl2AWy1H2kzVxGWGlqSTIHysLV5qMAKfQ==","shasum":"faa32c2155ff35f8152e323c8e8b6e7c0a229d19","tarball":"https://registry.npmjs.org/@agentduel/replay-player/-/replay-player-0.1.5.tgz","fileCount":94,"unpackedSize":1030088,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDyxj+Hu/62dURSO/hhWKpGF72rfTw9L2YTDRIVdJGi2wIgWNtjt/dsDBoHN9alBNOyAFV3APHr8vOO6DSRAuAFJ7E="}]},"_npmUser":{"name":"furlxy","email":"furlxy@gmail.com"},"directories":{},"maintainers":[{"name":"furlxy","email":"furlxy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/replay-player_0.1.5_1787243468182_0.7373395541036583"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-18T09:57:33.013Z","modified":"2026-08-20T16:31:08.578Z","0.1.0":"2026-08-18T09:57:33.264Z","0.1.1":"2026-08-19T10:41:54.367Z","0.1.2":"2026-08-20T10:18:24.693Z","0.1.4":"2026-08-20T11:10:06.068Z","0.1.5":"2026-08-20T16:31:08.366Z"},"license":"Apache-2.0","description":"AgentDuel battle replay player for React applications","maintainers":[{"name":"furlxy","email":"furlxy@gmail.com"}],"readme":"# @agentduel/replay-player\r\n\r\nAgentDuel 战斗回放播放器的独立 React 包。代码从 AgentDuel 官网 FrontEnd 拆分而来，包含：\r\n\r\n- replay JSON 校验与兼容性归一化；\r\n- Pixi 地图、角色、技能、投射物、状态和旗帜渲染；\r\n- 播放、暂停、单步、倍速、进度跳转和音效；\r\n- 全知、红方、蓝方视角逻辑；\r\n- 战报、双方状态、公共 AI 模型图标、战斗结算、分享和视频导出界面；\r\n- 简体中文和英文文案；\r\n- 可直接运行的真实回放示例。\r\n\r\n播放器不负责登录，也不会自行调用 AgentDuel 业务 API。宿主应用负责使用 Session 或 App Key 获取战斗信息和 replay JSON，再将数据传给播放器。\r\n\r\n## 环境要求\r\n\r\n- Node.js 20.19 或更高版本\r\n- npm 10 或更高版本\r\n- 支持 WebGL 的现代浏览器\r\n\r\n## 本地运行示例\r\n\r\n```bash\r\ncd /Users/zhang/github/agentduel-replay-player\r\nnpm install\r\nnpm run dev\r\n```\r\n\r\n浏览器打开：\r\n\r\n```text\r\nhttp://127.0.0.1:4173/\r\n```\r\n\r\n页面会读取 `demo/public/sample-replay.json`，并从 `https://www.agentduel.app` 加载公开的地图、角色、技能图标和音效资源。\r\n\r\n验收时至少检查：\r\n\r\n1. 地图和双方角色能够显示；\r\n2. 点击地图中央播放按钮后，角色能够移动并释放技能；\r\n3. 播放、暂停、单步、倍速和进度条可用；\r\n4. 战报会跟随播放进度；\r\n5. 播放结束后显示战斗统计；\r\n6. 右上角可切换简体中文和英文；\r\n7. 浏览器控制台没有报错。\r\n\r\n## 自动化验证\r\n\r\n```bash\r\nnpm test\r\nnpm run typecheck\r\nnpm run build\r\nnpm run pack:check\r\n```\r\n\r\n- `npm test`：验证真实 replay 样本解析、资源地址、视角和时间计算逻辑。\r\n- `npm run typecheck`：检查源码、示例和测试的 TypeScript 类型。\r\n- `npm run build`：生成 `dist/` 下的 JavaScript、类型声明和隔离后的 CSS。\r\n- `npm run pack:check`：检查最终 npm 包会包含哪些文件，但不会发布。\r\n\r\n## React 中使用\r\n\r\n```tsx\r\nimport {\r\n  AgentDuelReplayPlayer,\r\n  normalizeReplayResult,\r\n  type Battle\r\n} from '@agentduel/replay-player';\r\nimport { AgentDuelBreadcrumbs } from '@agentduel/component';\r\nimport '@agentduel/component/styles.css';\r\nimport '@agentduel/replay-player/styles.css';\r\n\r\nconst replayResult = normalizeReplayResult(replayJsonFromApi);\r\n\r\nexport function BattleReplay({ battle }: { battle: Battle }) {\r\n  return (\r\n    <AgentDuelReplayPlayer\r\n      battle={battle}\r\n      breadcrumbNavigation={(\r\n        <AgentDuelBreadcrumbs\r\n          ariaLabel=\"战斗回放导航\"\r\n          items={[{ href: '/dashboard', label: '备战室' }, { label: '当前战斗' }]}\r\n        />\r\n      )}\r\n      i18nMode=\"host\"\r\n      locale=\"zh-CN\"\r\n      ownParticipantPublicId={battle.participants[0]?.public_id}\r\n      replayResult={replayResult}\r\n    />\r\n  );\r\n}\r\n```\r\n\r\n主要输入：\r\n\r\n- `replayResult`：必填，建议先通过 `normalizeReplayResult()` 处理 API 返回的未知 JSON。\r\n- `battle`：可选；传入后显示参与者名称、AI 模型、比赛类型、胜者和积分变化等信息。\r\n- `breadcrumbNavigation`：可选；由宿主页面传入面包屑等导航节点，播放器不再绑定宿主路由结构。\n- `getParticipantHref`：可选；宿主根据参与者和 `owned` / `public` 视角返回详情链接，默认使用 AgentDuel 官网链接。\n- `participantLinkComponent`：可选；由宿主接管参与者链接的渲染和页内导航。\n- `ownParticipantPublicId`：可选；用于标记“你”和决定参与者详情链接。\n- `locale`：可选，支持 `zh-CN`、`en-US`、`zh_CN`、`en_US`，默认 `zh-CN`。\r\n- `i18nMode`：可选；官网等已经提供完整 i18next 上下文的宿主使用 `host`，DSH 等独立宿主保持默认的 `bundled`。\r\n- `terrainRows`：可选；传入规则地形后启用红方和蓝方视角切换。\r\n\r\n## 在 DSH 插件中测试本地包\r\n\r\n先在本仓库生成真实 tarball：\r\n\r\n```bash\r\ncd /Users/zhang/github/agentduel-replay-player\r\nnpm run build\r\nnpm pack\r\n```\r\n\r\n然后进入 DSH 插件项目，安装刚生成的文件：\r\n\r\n```bash\r\npnpm add /Users/zhang/github/agentduel-replay-player/agentduel-replay-player-0.1.3.tgz\r\n```\r\n\r\nDSH 页面负责使用 App Key 请求 `/api/integrations`，取得 `battle` 和 replay JSON 后渲染 `AgentDuelReplayPlayer`。调用业务 API 时继续使用 `credentials: \"omit\"`；播放器自身只读取公开静态资源。\r\n\r\n## 目录\r\n\r\n```text\r\nsrc/replay/       回放解析、播放状态、Pixi 渲染和 UI\r\nsrc/i18n/         播放器所需的中英文资源\r\nsrc/dashboard/    播放器需要的 Battle DTO 类型\r\ndemo/             独立本地示例\r\ntests/            公共包核心回归测试\r\ndist/             npm 构建产物\r\n```\r\n\r\n## 许可证\r\n\r\nApache-2.0\r\n","readmeFilename":"README.md"}