build: 切换包管理器至 pnpm 并新增西安参考底图工具与资源

- 移除 npm 锁文件 package-lock.json 与本地 node_modules 目录
- 配置 pnpm 工作区,允许 esbuild 的安装期构建脚本
- 添加 scripts/fetch-reference-maps.py 用于抓取拼接高德地图瓦片生成参考底图
- 生成两张西安参考底图并保存至 public/assets/maps/ 目录
- 更新 CHANGELOG.md 记录版本变更历史
This commit is contained in:
Stephen committed 2026-10-19 00:19:40 +08:00
1 parent b0467054c8
commit 415103a284
8 files changed
+974 -1248

No files matched your search

+17
View File
@@ -3,6 +3,23 @@
本项目所有显著变更均记录于此。 本项目所有显著变更均记录于此。
版本号:`vYYYY.MM.DD-XX`;类型标签:[Add] / [Change] / [Fix] / [Remove] / [Doc] / [Chore] 版本号:`vYYYY.MM.DD-XX`;类型标签:[Add] / [Change] / [Fix] / [Remove] / [Doc] / [Chore]
## v2026.10.17-03
22:45 · 抓取西安高德瓦片生成两张高清参考底图(仅供绘制参照,不参与游戏运行时加载)。
- [Add] `public/assets/maps/xian-reference-full-z12.png`(1536×1280):全域概览,覆盖游戏 viewBox 对应范围(西至沣河、东至兵马俑/临潼)
- [Add] `public/assets/maps/xian-reference-city-z14.png`(2304×2304):主城区高清图,覆盖城墙 / 回民街 / 大明宫 / 小雁塔 / 陕历博 / 大雁塔 / 曲江
- [Add] `scripts/fetch-reference-maps.py`:高德路网瓦片(webrd01~04)抓取 + PIL 拼接 + 版权署名条;Wikimedia Commons 与 OSM 瓦片服务在当前网络不可达,故改用高德源
- [Doc] 版权说明:参考图基于高德地图数据,已叠署名条,仅限项目内部参照(校准手账 SVG 坐标 / 走势),对外分发前应从 `public/` 移出
## v2026.10.17-02
21:06 · 包管理器由 npm 迁移至 pnpm 11(无依赖版本变化)。
- [Chore] 删除 `node_modules/` 与 `package-lock.json`,改用 `pnpm install` 生成 `pnpm-lock.yaml`(入库)
- [Add] 新增 `pnpm-workspace.yaml`:`allowBuilds: { esbuild: true }` 批准 esbuild 安装期构建脚本(pnpm 11 安全策略默认忽略,未批准会拦截 `pnpm run` 的依赖状态检查)
- [Chore] `.gitignore` 日志段已含 `pnpm-debug.log*`,无额外调整
## v2026.10.17-01 ## v2026.10.17-01
18:27 · 全量代码审查后的缺陷修复与性能优化(不改变玩法与视觉基调)。 18:27 · 全量代码审查后的缺陷修复与性能优化(不改变玩法与视觉基调)。
-1248
View File
File diff suppressed because it is too large. Load diff
+775
View File
@@ -0,0 +1,775 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
phaser:
specifier: ^3.80.0
version: 3.80.0
phaser3-rex-plugins:
specifier: ^1.80.0
version: 1.80.20(graphology-types@0.24.8)
devDependencies:
vite:
specifier: ^5.4.0
version: 5.4.0
packages:
'@babel/runtime@7.29.10':
resolution: {integrity: sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==}
engines: {node: '>=6.9.0'}
'@esbuild/aix-ppc64@0.21.3':
resolution: {integrity: sha512-yTgnwQpFVYfvvo4SvRFB0SwrW8YjOxEoT7wfMT7Ol5v7v5LDNvSGo67aExmxOb87nQNeWPVvaGBNfQ7BXcrZ9w==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.21.3':
resolution: {integrity: sha512-c+ty9necz3zB1Y+d/N+mC6KVVkGUUOcm4ZmT5i/Fk5arOaY3i6CA3P5wo/7+XzV8cb4GrI/Zjp8NuOQ9Lfsosw==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.21.3':
resolution: {integrity: sha512-bviJOLMgurLJtF1/mAoJLxDZDL6oU5/ztMHnJQRejbJrSc9FFu0QoUoFhvi6qSKJEw9y5oGyvr9fuDtzJ30rNQ==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.21.3':
resolution: {integrity: sha512-JReHfYCRK3FVX4Ra+y5EBH1b9e16TV2OxrPAvzMsGeES0X2Ndm9ImQRI4Ket757vhc5XBOuGperw63upesclRw==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.21.3':
resolution: {integrity: sha512-U3fuQ0xNiAkXOmQ6w5dKpEvXQRSpHOnbw7gEfHCRXPeTKW9sBzVck6C5Yneb8LfJm0l6le4NQfkNPnWMSlTFUQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.21.3':
resolution: {integrity: sha512-3m1CEB7F07s19wmaMNI2KANLcnaqryJxO1fXHUV5j1rWn+wMxdUYoPyO2TnAbfRZdi7ADRwJClmOwgT13qlP3Q==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.21.3':
resolution: {integrity: sha512-fsNAAl5pU6wmKHq91cHWQT0Fz0vtyE1JauMzKotrwqIKAswwP5cpHUCxZNSTuA/JlqtScq20/5KZ+TxQdovU/g==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.21.3':
resolution: {integrity: sha512-tci+UJ4zP5EGF4rp8XlZIdq1q1a/1h9XuronfxTMCNBslpCtmk97Q/5qqy1Mu4zIc0yswN/yP/BLX+NTUC1bXA==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.21.3':
resolution: {integrity: sha512-vvG6R5g5ieB4eCJBQevyDMb31LMHthLpXTc2IGkFnPWS/GzIFDnaYFp558O+XybTmYrVjxnryru7QRleJvmZ6Q==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.21.3':
resolution: {integrity: sha512-f6kz2QpSuyHHg01cDawj0vkyMwuIvN62UAguQfnNVzbge2uWLhA7TCXOn83DT0ZvyJmBI943MItgTovUob36SQ==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.21.3':
resolution: {integrity: sha512-HjCWhH7K96Na+66TacDLJmOI9R8iDWDDiqe17C7znGvvE4sW1ECt9ly0AJ3dJH62jHyVqW9xpxZEU1jKdt+29A==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.21.3':
resolution: {integrity: sha512-BGpimEccmHBZRcAhdlRIxMp7x9PyJxUtj7apL2IuoG9VxvU/l/v1z015nFs7Si7tXUwEsvjc1rOJdZCn4QTU+Q==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.21.3':
resolution: {integrity: sha512-5rMOWkp7FQGtAH3QJddP4w3s47iT20hwftqdm7b+loe95o8JU8ro3qZbhgMRy0VuFU0DizymF1pBKkn3YHWtsw==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.21.3':
resolution: {integrity: sha512-h0zj1ldel89V5sjPLo5H1SyMzp4VrgN1tPkN29TmjvO1/r0MuMRwJxL8QY05SmfsZRs6TF0c/IDH3u7XYYmbAg==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.21.3':
resolution: {integrity: sha512-dkAKcTsTJ+CRX6bnO17qDJbLoW37npd5gSNtSzjYQr0svghLJYGYB0NF1SNcU1vDcjXLYS5pO4qOW4YbFama4A==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.21.3':
resolution: {integrity: sha512-vnD1YUkovEdnZWEuMmy2X2JmzsHQqPpZElXx6dxENcIwTu+Cu5ERax6+Ke1QsE814Zf3c6rxCfwQdCTQ7tPuXA==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.21.3':
resolution: {integrity: sha512-IOXOIm9WaK7plL2gMhsWJd+l2bfrhfilv0uPTptoRoSb2p09RghhQQp9YY6ZJhk/kqmeRt6siRdMSLLwzuT0KQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-x64@0.21.3':
resolution: {integrity: sha512-uTgCwsvQ5+vCQnqM//EfDSuomo2LhdWhFPS8VL8xKf+PKTCrcT/2kPPoWMTs22aB63MLdGMJiE3f1PHvCDmUOw==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-x64@0.21.3':
resolution: {integrity: sha512-vNAkR17Ub2MgEud2Wag/OE4HTSI6zlb291UYzHez/psiKarp0J8PKGDnAhMBcHFoOHMXHfExzmjMojJNbAStrQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
'@esbuild/sunos-x64@0.21.3':
resolution: {integrity: sha512-W8H9jlGiSBomkgmouaRoTXo49j4w4Kfbl6I1bIdO/vT0+0u4f20ko3ELzV3hPI6XV6JNBVX+8BC+ajHkvffIJA==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.21.3':
resolution: {integrity: sha512-EjEomwyLSCg8Ag3LDILIqYCZAq/y3diJ04PnqGRgq8/4O3VNlXyMd54j/saShaN4h5o5mivOjAzmU6C3X4v0xw==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.21.3':
resolution: {integrity: sha512-WGiE/GgbsEwR33++5rzjiYsKyHywE8QSZPF7Rfx9EBfK3Qn3xyR6IjyCr5Uk38Kg8fG4/2phN7sXp4NPWd3fcw==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.21.3':
resolution: {integrity: sha512-xRxC0jaJWDLYvcUvjQmHCJSfMrgmUuvsoXgDeU/wTorQ1ngDdUBuFtgY3W1Pc5sprGAvZBtWdJX7RPg/iZZUqA==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==}
engines: {node: ^22.20 || ^24.12 || >=25}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rollup/rollup-android-arm-eabi@4.64.7':
resolution: {integrity: sha512-GFF2tHk0NqYVObrK0+/ps/LEXsV/v2q6Lyiy7mZr+Ej24fpQScvqK2ziz9NHeEQYnKWKym38Ml7dZbPtC9tuAw==}
cpu: [arm]
os: [android]
'@rollup/rollup-android-arm64@4.64.7':
resolution: {integrity: sha512-BOymcXJFYYXqluDidj6sLelNjXruC3u1BqVxLn2OPCXH9xaPSOTH+MS4uychsGI1NU7tJoiv9KvqijDHFe+hhQ==}
cpu: [arm64]
os: [android]
'@rollup/rollup-darwin-arm64@4.64.7':
resolution: {integrity: sha512-jgVpGweIbls2H5jfBB70tnX52abMd5pJr3xmtoDILx6JdmGl+Un+tMb9R+MbHPVB46tTBpY8emtn7M71SnQhEQ==}
cpu: [arm64]
os: [darwin]
'@rollup/rollup-darwin-x64@4.64.7':
resolution: {integrity: sha512-AVMpt94mrXH7WjyWKmd9nT4RC5yM0AN3Lt6A89xVIsuLDi3dDX6dxMytLbW36FlppY9JsoqUoS3LUUpUrYxiMQ==}
cpu: [x64]
os: [darwin]
'@rollup/rollup-freebsd-arm64@4.64.7':
resolution: {integrity: sha512-Nje29c/MyajxRNFGU05oyeTDS6SWdMg/wWMSlZSBTBju5BKz2NVc0kFiFSQGzRELNiB+CBk/ZvAVsWsENgjGag==}
cpu: [arm64]
os: [freebsd]
'@rollup/rollup-freebsd-x64@4.64.7':
resolution: {integrity: sha512-xxgN5/kMzCNz/NYJ4t49B0/WS6InNlWv6xvgwUQqNnWM9WJMMwMUGWrAxdNEgYWdHL0sMnuh8I87StGrIMTA+w==}
cpu: [x64]
os: [freebsd]
'@rollup/rollup-linux-arm-gnueabihf@4.64.7':
resolution: {integrity: sha512-5U/9gVn/X657I8+NHoHO9Wnfyd0lEXwqbslobRoB9TC8SwYzOitcIr6TLE7531Q/NWs3L4mb+YOGzlf3vHIeYw==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.64.7':
resolution: {integrity: sha512-hcDS0a/Y8ggM3dcOfzH7UpSaogCViWTtNDSl0EXpWIj8g8/r86ITqptjil2hayTXS0Umzb+Yt3mjgpQVFVf2+A==}
cpu: [arm]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.64.7':
resolution: {integrity: sha512-awbAr4N7Qd/yjZAQBEEPzgcPveYG2Gi5L6gq1/Bp+3SMRjn5F68Wv1zKsntzvvoioBR6yKvhLtWqu11am1TsxA==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.64.7':
resolution: {integrity: sha512-Ut7xQJfeLhzu2yN3rHzVvL9ccyPJvN4aCdP1V7hJ5lGxX/eCzgB9SiMk/Md3J+rWWZgvoYsDW4BUFggJr32pBA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-loong64-gnu@4.64.7':
resolution: {integrity: sha512-trqoni/vHkuM5oo5iQhoKPh6fjjD7E80pMgCXWgGxU8vSRPUlwvG8GeYvEEcB6eJAxNa99WH9iVHPHelgtKiHA==}
cpu: [loong64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-loong64-musl@4.64.7':
resolution: {integrity: sha512-gvlUy0XFIwtUWiQmhc+4GT2Knm3KosinpUVhr7CtTFA78gFDnE5NWwMPzHrJsYpKkh2LlY7yvBIboN1FAV6Xeg==}
cpu: [loong64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-ppc64-gnu@4.64.7':
resolution: {integrity: sha512-8yS/kSXTJ/47Z62JW+C2AJ3vd/8zZw016vFjtNpZwmZlwJumLua4s1i78dkYuSSqQ+0aIMxJcBp/4uIwp2ehjA==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-ppc64-musl@4.64.7':
resolution: {integrity: sha512-mxVSKvvty0hOP1AFo/l4Kpv3i3HK0zx4rYUrirZDToYlWhS3xzmIkq3vUJ7rtrM2cPyXveDyDT6M1FfXZ9hTRA==}
cpu: [ppc64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-riscv64-gnu@4.64.7':
resolution: {integrity: sha512-lEse1zra1CagM+uHH2bl28GInDsZZ45NJzHei2OMaXQFzZWKBO1hFo07rS0xB6ayV4WU360UrSmPDSyCMpYsUQ==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-riscv64-musl@4.64.7':
resolution: {integrity: sha512-d/cqCoiG9WMZ5VuJZ5Qdlv9g97QyoGwnmvHccvGhKSacTy7xFrAS+jMcJSBdMNOw1oacSkl6p7K6O/DRYTKL3g==}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-s390x-gnu@4.64.7':
resolution: {integrity: sha512-kVEA//CeDOZZP1XCH2JBgqXb9+ALlwuA/4civaazMVdgzaSQC9WM38w65zG/LLk0lA7F9Od19CSBZW7J9mCbNg==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.64.7':
resolution: {integrity: sha512-14oLfDsOSr0TSntT/34jRg/V8B2XW/Jomh9zX9CjIM9gwwNlI1OCymS/GVn0DV32h67eRf7U0GGem0rvfXgNwQ==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.64.7':
resolution: {integrity: sha512-dFVtPfjZqAnUPpPY4Bfg+87yo1IBW9HiY8iCFtg49Pn46MfZTebSHZh8PL6SOsgyt9LQP8Nj/sE6jm3aWpySmQ==}
cpu: [x64]
os: [linux]
libc: [musl]
'@rollup/rollup-openbsd-x64@4.64.7':
resolution: {integrity: sha512-Dm9CZ2SM3u2NgvBj4awW/gGqkOwzH8f6MSYIJE6+bKcKLI+T0+LhpD6vtetTfrIIx+rLXDf5RJqBP6v7V5O+wg==}
cpu: [x64]
os: [openbsd]
'@rollup/rollup-openharmony-arm64@4.64.7':
resolution: {integrity: sha512-oaxsvS2mL6+78741CT2HCORBvy1USg3Wqpt5qvZwy3aMXRMl4zxyDo8maeFRWJkF3dp0Wbi71fKH5Gr9YI3vYA==}
cpu: [arm64]
os: [openharmony]
'@rollup/rollup-win32-arm64-msvc@4.64.7':
resolution: {integrity: sha512-UKZz1Y4mxUqkWh60uH7B1aZn6UcAimPk4ipRktpb3wfZq7JrzZYyAXTwiafkb3T+kd5P3Sf+vzcRdsDks4WtjQ==}
cpu: [arm64]
os: [win32]
'@rollup/rollup-win32-ia32-msvc@4.64.7':
resolution: {integrity: sha512-WWkSuC1J+mZJnsDh0mRaCAFSWfQdl6y3fDjZeWElI6zHo8CcOSG5lY3yurKJjEq+FrX0WD60sFrVVpbHqzMmrw==}
cpu: [ia32]
os: [win32]
'@rollup/rollup-win32-x64-gnu@4.64.7':
resolution: {integrity: sha512-u9bp2yXCI3/BUjUxY6uWknAY32pfvvDCPysyUTySotx0dj3ydlFHrRQYfn/b/kZgnfjyEwySMtI7Ga054uiysQ==}
cpu: [x64]
os: [win32]
'@rollup/rollup-win32-x64-msvc@4.64.7':
resolution: {integrity: sha512-EhX6N3XPMEnVU5cRfNgzPOKcSucsbu3nNNWuoAaEuKIqmddBKHN5b9d4rPe65T1I+FaOT176JKiZNsUBp3rqbA==}
cpu: [x64]
os: [win32]
'@types/estree@1.0.9':
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
cross-fetch@4.0.0:
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
dagre@0.8.5:
resolution: {integrity: sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==}
esbuild@0.21.3:
resolution: {integrity: sha512-Kgq0/ZsAPzKrbOjCQcjoSmPoWhlcVnGAUo7jvaLHoxW1Drto0KGkR1xBNg2Cp43b9ImvxmPEJZ9xkfcnqPsfBw==}
engines: {node: '>=12'}
hasBin: true
eventemitter3@3.1.2:
resolution: {integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==}
eventemitter3@5.0.4:
resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}
events@3.3.0:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
graphlib@2.1.8:
resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==}
graphology-types@0.24.8:
resolution: {integrity: sha512-hDRKYXa8TsoZHjgEaysSRyPdT6uB78Ci8WnjgbStlQysz7xR52PInxNsmnB7IBOM1BhikxkNyCVEFgmPKnpx3Q==}
graphology@0.25.4:
resolution: {integrity: sha512-33g0Ol9nkWdD6ulw687viS8YJQBxqG5LWII6FI6nul0pq6iM2t5EKquOTFDbyTblRB3O9I+7KX4xI8u5ffekAQ==}
peerDependencies:
graphology-types: '>=0.24.0'
i18next-http-backend@2.5.2:
resolution: {integrity: sha512-+K8HbDfrvc1/2X8jpb7RLhI9ZxBDpx3xogYkQwGKlWAUXLSEGXzgdt3EcUjLlBCdMwdQY+K+EUF6oh8oB6rwHw==}
i18next@22.5.1:
resolution: {integrity: sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==}
js-yaml@4.3.2:
resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==}
hasBin: true
lodash@4.18.1:
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
mustache@4.2.0:
resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
hasBin: true
nanoid@3.3.20:
resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
node-fetch@2.7.0:
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
engines: {node: 4.x || >=6.0.0}
peerDependencies:
encoding: ^0.1.0
peerDependenciesMeta:
encoding:
optional: true
obliterator@2.0.5:
resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==}
papaparse@5.7.0:
resolution: {integrity: sha512-qBGxg/7Q3Kl9Wfhrz2Z74UnvnHTXLNG6jmKJFeBvP2+y4lV7So+7SR62+Zd47JvdrCkX+nDcnr0ObPzek/+6RA==}
phaser3-rex-plugins@1.80.20:
resolution: {integrity: sha512-XZLUy74r1jUaRWpGplRhhA+wEeOvnNb0qlhlyMtwdwZwIlCA7C7WtgvynOB/PyVrzS09cUBwEFyG+A3P5fL+Uw==}
phaser@3.80.0:
resolution: {integrity: sha512-LUEPFzQKXSlPxrDjFUaeq6t47j1Y58F67OsCKflvDH1DUSwVxAD1/vDUPQJj+dWniKBxAlL1BoCXQnjmtcJxUQ==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
postcss@8.5.30:
resolution: {integrity: sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==}
engines: {node: ^10 || ^12 || >=14}
rollup@4.64.7:
resolution: {integrity: sha512-aCiJONoZp0lNGJ6sYqspLkh6UXaWEey/7Ko2TZyXQ4kgzAhDUxAgbt/oulXKmD+zFHXw1k+RF6ZZWOrjp7DZnQ==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
source-map-js@1.2.2:
resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==}
engines: {node: '>=0.10.0'}
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
vite@5.4.0:
resolution: {integrity: sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
'@types/node': ^18.0.0 || >=20.0.0
less: '*'
lightningcss: ^1.21.0
sass: '*'
sass-embedded: '*'
stylus: '*'
sugarss: '*'
terser: ^5.4.0
peerDependenciesMeta:
'@types/node':
optional: true
less:
optional: true
lightningcss:
optional: true
sass:
optional: true
sass-embedded:
optional: true
stylus:
optional: true
sugarss:
optional: true
terser:
optional: true
webfontloader@1.6.28:
resolution: {integrity: sha512-Egb0oFEga6f+nSgasH3E0M405Pzn6y3/9tOVanv/DLfa1YBIgcv90L18YyWnvXkRbIM17v5Kv6IT2N6g1x5tvQ==}
webidl-conversions@3.0.0:
resolution: {integrity: sha512-GOK494qXZl0XBbr/YPRW2BL6oLfe+d0KDSWndKH7NdxJwJ0fCdhQG46Q2D7BmIS6cN/FJgtju8srRt/jlG9abA==}
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
snapshots:
'@babel/runtime@7.29.10': {}
'@esbuild/aix-ppc64@0.21.3':
optional: true
'@esbuild/android-arm64@0.21.3':
optional: true
'@esbuild/android-arm@0.21.3':
optional: true
'@esbuild/android-x64@0.21.3':
optional: true
'@esbuild/darwin-arm64@0.21.3':
optional: true
'@esbuild/darwin-x64@0.21.3':
optional: true
'@esbuild/freebsd-arm64@0.21.3':
optional: true
'@esbuild/freebsd-x64@0.21.3':
optional: true
'@esbuild/linux-arm64@0.21.3':
optional: true
'@esbuild/linux-arm@0.21.3':
optional: true
'@esbuild/linux-ia32@0.21.3':
optional: true
'@esbuild/linux-loong64@0.21.3':
optional: true
'@esbuild/linux-mips64el@0.21.3':
optional: true
'@esbuild/linux-ppc64@0.21.3':
optional: true
'@esbuild/linux-riscv64@0.21.3':
optional: true
'@esbuild/linux-s390x@0.21.3':
optional: true
'@esbuild/linux-x64@0.21.3':
optional: true
'@esbuild/netbsd-x64@0.21.3':
optional: true
'@esbuild/openbsd-x64@0.21.3':
optional: true
'@esbuild/sunos-x64@0.21.3':
optional: true
'@esbuild/win32-arm64@0.21.3':
optional: true
'@esbuild/win32-ia32@0.21.3':
optional: true
'@esbuild/win32-x64@0.21.3':
optional: true
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
optional: true
'@rollup/rollup-android-arm-eabi@4.64.7':
optional: true
'@rollup/rollup-android-arm64@4.64.7':
optional: true
'@rollup/rollup-darwin-arm64@4.64.7':
optional: true
'@rollup/rollup-darwin-x64@4.64.7':
optional: true
'@rollup/rollup-freebsd-arm64@4.64.7':
optional: true
'@rollup/rollup-freebsd-x64@4.64.7':
optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.64.7':
optional: true
'@rollup/rollup-linux-arm-musleabihf@4.64.7':
optional: true
'@rollup/rollup-linux-arm64-gnu@4.64.7':
optional: true
'@rollup/rollup-linux-arm64-musl@4.64.7':
optional: true
'@rollup/rollup-linux-loong64-gnu@4.64.7':
optional: true
'@rollup/rollup-linux-loong64-musl@4.64.7':
optional: true
'@rollup/rollup-linux-ppc64-gnu@4.64.7':
optional: true
'@rollup/rollup-linux-ppc64-musl@4.64.7':
optional: true
'@rollup/rollup-linux-riscv64-gnu@4.64.7':
optional: true
'@rollup/rollup-linux-riscv64-musl@4.64.7':
optional: true
'@rollup/rollup-linux-s390x-gnu@4.64.7':
optional: true
'@rollup/rollup-linux-x64-gnu@4.64.7':
optional: true
'@rollup/rollup-linux-x64-musl@4.64.7':
optional: true
'@rollup/rollup-openbsd-x64@4.64.7':
optional: true
'@rollup/rollup-openharmony-arm64@4.64.7':
optional: true
'@rollup/rollup-win32-arm64-msvc@4.64.7':
optional: true
'@rollup/rollup-win32-ia32-msvc@4.64.7':
optional: true
'@rollup/rollup-win32-x64-gnu@4.64.7':
optional: true
'@rollup/rollup-win32-x64-msvc@4.64.7':
optional: true
'@types/estree@1.0.9': {}
argparse@2.0.1: {}
cross-fetch@4.0.0:
dependencies:
node-fetch: 2.7.0
transitivePeerDependencies:
- encoding
dagre@0.8.5:
dependencies:
graphlib: 2.1.8
lodash: 4.18.1
esbuild@0.21.3:
optionalDependencies:
'@esbuild/aix-ppc64': 0.21.3
'@esbuild/android-arm': 0.21.3
'@esbuild/android-arm64': 0.21.3
'@esbuild/android-x64': 0.21.3
'@esbuild/darwin-arm64': 0.21.3
'@esbuild/darwin-x64': 0.21.3
'@esbuild/freebsd-arm64': 0.21.3
'@esbuild/freebsd-x64': 0.21.3
'@esbuild/linux-arm': 0.21.3
'@esbuild/linux-arm64': 0.21.3
'@esbuild/linux-ia32': 0.21.3
'@esbuild/linux-loong64': 0.21.3
'@esbuild/linux-mips64el': 0.21.3
'@esbuild/linux-ppc64': 0.21.3
'@esbuild/linux-riscv64': 0.21.3
'@esbuild/linux-s390x': 0.21.3
'@esbuild/linux-x64': 0.21.3
'@esbuild/netbsd-x64': 0.21.3
'@esbuild/openbsd-x64': 0.21.3
'@esbuild/sunos-x64': 0.21.3
'@esbuild/win32-arm64': 0.21.3
'@esbuild/win32-ia32': 0.21.3
'@esbuild/win32-x64': 0.21.3
eventemitter3@3.1.2: {}
eventemitter3@5.0.4: {}
events@3.3.0: {}
fsevents@2.3.3:
optional: true
graphlib@2.1.8:
dependencies:
lodash: 4.18.1
graphology-types@0.24.8: {}
graphology@0.25.4(graphology-types@0.24.8):
dependencies:
events: 3.3.0
graphology-types: 0.24.8
obliterator: 2.0.5
i18next-http-backend@2.5.2:
dependencies:
cross-fetch: 4.0.0
transitivePeerDependencies:
- encoding
i18next@22.5.1:
dependencies:
'@babel/runtime': 7.29.10
js-yaml@4.3.2:
dependencies:
argparse: 2.0.1
lodash@4.18.1: {}
mustache@4.2.0: {}
nanoid@3.3.20: {}
node-fetch@2.7.0:
dependencies:
whatwg-url: 5.0.0
obliterator@2.0.5: {}
papaparse@5.7.0: {}
phaser3-rex-plugins@1.80.20(graphology-types@0.24.8):
dependencies:
dagre: 0.8.5
eventemitter3: 3.1.2
graphology: 0.25.4(graphology-types@0.24.8)
i18next: 22.5.1
i18next-http-backend: 2.5.2
js-yaml: 4.3.2
mustache: 4.2.0
papaparse: 5.7.0
webfontloader: 1.6.28
transitivePeerDependencies:
- encoding
- graphology-types
phaser@3.80.0:
dependencies:
eventemitter3: 5.0.4
picocolors@1.1.1: {}
postcss@8.5.30:
dependencies:
nanoid: 3.3.20
picocolors: 1.1.1
source-map-js: 1.2.2
rollup@4.64.7:
dependencies:
'@types/estree': 1.0.9
optionalDependencies:
'@napi-rs/lzma-linux-x64-gnu': 1.5.1
'@rollup/rollup-android-arm-eabi': 4.64.7
'@rollup/rollup-android-arm64': 4.64.7
'@rollup/rollup-darwin-arm64': 4.64.7
'@rollup/rollup-darwin-x64': 4.64.7
'@rollup/rollup-freebsd-arm64': 4.64.7
'@rollup/rollup-freebsd-x64': 4.64.7
'@rollup/rollup-linux-arm-gnueabihf': 4.64.7
'@rollup/rollup-linux-arm-musleabihf': 4.64.7
'@rollup/rollup-linux-arm64-gnu': 4.64.7
'@rollup/rollup-linux-arm64-musl': 4.64.7
'@rollup/rollup-linux-loong64-gnu': 4.64.7
'@rollup/rollup-linux-loong64-musl': 4.64.7
'@rollup/rollup-linux-ppc64-gnu': 4.64.7
'@rollup/rollup-linux-ppc64-musl': 4.64.7
'@rollup/rollup-linux-riscv64-gnu': 4.64.7
'@rollup/rollup-linux-riscv64-musl': 4.64.7
'@rollup/rollup-linux-s390x-gnu': 4.64.7
'@rollup/rollup-linux-x64-gnu': 4.64.7
'@rollup/rollup-linux-x64-musl': 4.64.7
'@rollup/rollup-openbsd-x64': 4.64.7
'@rollup/rollup-openharmony-arm64': 4.64.7
'@rollup/rollup-win32-arm64-msvc': 4.64.7
'@rollup/rollup-win32-ia32-msvc': 4.64.7
'@rollup/rollup-win32-x64-gnu': 4.64.7
'@rollup/rollup-win32-x64-msvc': 4.64.7
fsevents: 2.3.3
source-map-js@1.2.2: {}
tr46@0.0.3: {}
vite@5.4.0:
dependencies:
esbuild: 0.21.3
postcss: 8.5.30
rollup: 4.64.7
optionalDependencies:
fsevents: 2.3.3
webfontloader@1.6.28: {}
webidl-conversions@3.0.0: {}
whatwg-url@5.0.0:
dependencies:
tr46: 0.0.3
webidl-conversions: 3.0.0
+7
View File
@@ -0,0 +1,7 @@
# pnpm 设置(pnpm 11 起配置从 package.json 的 pnpm 字段迁移至此)
# https://pnpm.io/settings
#
# 允许运行安装期构建脚本的依赖白名单:
# esbuild 需 postinstall 安装平台二进制,否则 vite dev/build 失败。
allowBuilds:
esbuild: true
Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 KiB

+175
View File
@@ -0,0 +1,175 @@
#!/usr/bin/env python3
"""
抓取高德地图瓦片并拼接为西安参考底图。
文件用途:
- 生成两张高清参考地图(仅作绘制参照与人工核对,不参与游戏运行时加载):
1) 西安全域概览(z12,覆盖游戏 viewBox 对应的真实地理范围);
2) 主城区高清图(z14,覆盖城墙 / 大雁塔 / 曲江 / 大明宫一带)。
核心职责:
1. 由经纬度 bbox 计算指定 zoom 下的瓦片行列范围(Web 墨卡托);
2. 下载高德矢量路网瓦片(style=8,中文标注),失败重试并以灰块占位;
3. 用 PIL 拼接瓦片并在底部加版权署名条("底图数据 © 高德地图")。
主要流程:
python3 scripts/fetch-reference-maps.py
→ 依次抓取两组配置 → 拼接 → 输出到 public/assets/maps/
"""
import io
import math
import time
import urllib.request
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
# 项目根目录(脚本位于 scripts/ 下)。
PROJECT_ROOT = Path(__file__).resolve().parent.parent
# 瓦片输出目录。
OUT_DIR = PROJECT_ROOT / "public" / "assets" / "maps"
# 高德瓦片服务(style=8 标准矢量路网图,中文标注)。
TILE_URL = (
"https://webrd0{sub}.is.autonavi.com/appmaptile"
"?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"
)
# 请求 UA(遵守瓦片服务礼仪)。
UA = "XianTravelGame/0.1 (local reference fetching; contact: dev)"
# 瓦片尺寸(像素)。
TILE_SIZE = 256
# 单瓦片下载失败重试次数。
MAX_RETRY = 3
def deg2tile(lon: float, lat: float, zoom: int) -> tuple[int, int]:
"""经纬度转 Web 墨卡托瓦片坐标。
Args:
lon: 经度(度)。
lat: 纬度(度)。
zoom: 缩放级别。
Returns:
(x, y) 瓦片行列号(左上角所属瓦片)。
"""
n = 2 ** zoom
x = int((lon + 180.0) / 360.0 * n)
lat_rad = math.radians(lat)
y = int((1.0 - math.asinh(math.tan(lat_rad)) / math.pi) / 2.0 * n)
return x, y
def fetch_tile(zoom: int, x: int, y: int) -> Image.Image | None:
"""下载单张瓦片(子域名轮转与重试)。
高德路网瓦片子域名为 webrd01~webrd04;重试时轮换子域名以规避单点故障。
Args:
zoom: 缩放级别。
x: 瓦片列号。
y: 瓦片行号。
Returns:
成功返回 PIL 图像,最终失败返回 None。
"""
for attempt in range(MAX_RETRY):
sub = (x + y + attempt) % 4 + 1 # 轮转 1-4 子域名,重试时换域。
url = TILE_URL.format(sub=sub, x=x, y=y, z=zoom)
try:
req = urllib.request.Request(url, headers={"User-Agent": UA})
with urllib.request.urlopen(req, timeout=10) as resp:
data = resp.read()
return Image.open(io.BytesIO(data)).convert("RGB")
except Exception:
time.sleep(0.5)
return None
def stitch(bbox: dict, zoom: int, out_name: str) -> Path:
"""按 bbox 抓取并拼接整图。
Args:
bbox: {"west": float, "east": float, "south": float, "north": float}。
zoom: 缩放级别。
out_name: 输出文件名。
Returns:
输出文件路径。
"""
x0, y0 = deg2tile(bbox["west"], bbox["north"], zoom)
x1, y1 = deg2tile(bbox["east"], bbox["south"], zoom)
cols, rows = x1 - x0 + 1, y1 - y0 + 1
total = cols * rows
print(f"[{out_name}] z{zoom} 瓦片 {cols}×{rows}({total} 张),范围 x{x0}-{x1} y{y0}-{y1}")
canvas = Image.new("RGB", (cols * TILE_SIZE, rows * TILE_SIZE), "#e8e0d0")
failed = 0
for row in range(rows):
for col in range(cols):
img = fetch_tile(zoom, x0 + col, y0 + row)
if img is None:
failed += 1
draw = ImageDraw.Draw(canvas)
left = col * TILE_SIZE
top = row * TILE_SIZE
draw.rectangle(
[left, top, left + TILE_SIZE - 1, top + TILE_SIZE - 1],
fill="#d0d0d0",
)
else:
canvas.paste(img, (col * TILE_SIZE, row * TILE_SIZE))
time.sleep(0.08) # 温和限速。
if failed:
print(f"[{out_name}] 警告:{failed}/{total} 张瓦片下载失败(已用灰块占位)")
add_attribution(canvas)
out_path = OUT_DIR / out_name
canvas.save(out_path, optimize=True)
print(f"[{out_name}] 已保存 {canvas.width}×{canvas.height} → {out_path}")
return out_path
def add_attribution(canvas: Image.Image) -> None:
"""在拼接图底部叠加版权署名条。
Args:
canvas: 待标注的拼接图。
"""
bar_h = 34
draw = ImageDraw.Draw(canvas)
draw.rectangle([0, canvas.height - bar_h, canvas.width, canvas.height], fill=(255, 253, 247))
text = "底图数据 © 高德地图 | 仅作项目内部绘制参考,禁止商用分发"
font = None
for candidate in ("PingFang.ttc", "Hiragino Sans GB.ttc", "Arial Unicode.ttf"):
try:
font = ImageFont.truetype(candidate, 16)
break
except OSError:
continue
if font is None:
font = ImageFont.load_default()
draw.text((12, canvas.height - bar_h + 8), text, fill=(107, 78, 46), font=font)
def main() -> None:
"""入口:依次生成全域概览与主城区高清图。"""
OUT_DIR.mkdir(parents=True, exist_ok=True)
# 全域概览(z12):对应游戏 viewBox 的真实地理范围(西至沣河,东至兵马俑)。
stitch(
bbox={"west": 108.82, "east": 109.31, "south": 34.14, "north": 34.42},
zoom=12,
out_name="xian-reference-full-z12.png",
)
# 主城区高清(z14):城墙 / 回民街 / 大明宫 / 小雁塔 / 陕历博 / 大雁塔 / 曲江。
stitch(
bbox={"west": 108.87, "east": 109.04, "south": 34.19, "north": 34.33},
zoom=14,
out_name="xian-reference-city-z14.png",
)
if __name__ == "__main__":
main()