feat(local): 运行链路默认切到 3DTank/src,启动时按需打单包
serve.js 新增 --src:unpacked/module_*.js、resources.json、index.json 与 unpacked.pack.json 路由到源码目录(加载器与 hornet_bundle 仍走镜像);修复 403 白名单未包含 src 目录。Start-LocalAndRelay 默认跑 src,源码更新或单包缺失时自动打包,-Build 强制重打,-Split 回退切割产物;恢复 ps1 的 UTF-8 BOM 以免 Windows PowerShell 误读中文。
This commit is contained in:
1 parent
fd952e814c
commit
a487c28dc1
3 files changed
+92
-11
No files matched your search
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
.SYNOPSIS
|
||||
一键启动 3DTank 本地镜像(serve.js)+ 中继(wss_server.js relay 模式)
|
||||
|
||||
@@ -30,6 +30,14 @@
|
||||
.EXAMPLE
|
||||
// 强制走 c2(官方默认主服)
|
||||
.\Start-LocalAndRelay.ps1 -SRV 2 -OpenBrowser
|
||||
|
||||
.EXAMPLE
|
||||
// 默认直接跑 3DTank/src 源码;改了 src 之后强制重打单包再起
|
||||
.\Start-LocalAndRelay.ps1 -Build -OpenBrowser
|
||||
|
||||
.EXAMPLE
|
||||
// 回到切割产物(3dtank.com/play/static/js/unpacked)
|
||||
.\Start-LocalAndRelay.ps1 -Split -OpenBrowser
|
||||
#>
|
||||
# 注意:这里刻意不用 [CmdletBinding()]。
|
||||
# PowerShell 原生不支持 -SRV=1 这种等号写法(会报 "parameter cannot be found"),
|
||||
@@ -50,7 +58,9 @@ param(
|
||||
[switch]$NoLog, # 中继:不写 log.txt(默认写)
|
||||
[switch]$NoHex, # 中继:log.txt 不写十六进制(日志体积大幅减小)
|
||||
[switch]$Quiet, # 中继:只写 log.txt,不刷控制台
|
||||
[switch]$NoTunnel # 中继:关闭 _reconnectFast 隧道接管(默认开启:战场连接也走中继)
|
||||
[switch]$NoTunnel, # 中继:关闭 _reconnectFast 隧道接管(默认开启:战场连接也走中继)
|
||||
[switch]$Build, # 强制重打单包(src 模式默认只在缺失/源码更新时打包)
|
||||
[switch]$Split # 改回用切割产物 unpacked,而不是 3DTank/src 源码
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
@@ -158,13 +168,43 @@ if ($FetchAssets) {
|
||||
try { & $NodeExe fetch_assets.js --concurrency 10 | Out-Host } finally { Pop-Location }
|
||||
}
|
||||
|
||||
# ---------- 3.5) 生成单包(unpacked.pack.json):126 个小文件 → 1 个包 ----------
|
||||
$PackScript = Join-Path (Split-Path -Parent $Project) 'tools\pack_unpacked.js'
|
||||
if (Test-Path $PackScript) {
|
||||
Write-Host '[打包] pack_unpacked.js 生成单包(unpacked.pack.json)...' -ForegroundColor Cyan
|
||||
try { & $NodeExe $PackScript | Out-Host } catch { Write-Warning ('打包失败: ' + $_.Exception.Message) }
|
||||
# ---------- 3.5) 模块来源与单包 ----------
|
||||
# 默认:直接跑反编译源码 3DTank/src(改完代码刷新即生效),启动时按需打单包保证加载速度
|
||||
# -Build:强制重打单包
|
||||
# -Split:改回切割产物 3dtank.com/play/static/js/unpacked
|
||||
$UseSrc = -not $Split
|
||||
$SrcDir = Join-Path $Project 'src'
|
||||
$RootDir = Split-Path -Parent $Project
|
||||
$PackScript = Join-Path $RootDir 'tools\pack_unpacked.js'
|
||||
if (-not (Test-Path $PackScript)) { throw ('找不到打包脚本: ' + $PackScript) }
|
||||
|
||||
if ($UseSrc) {
|
||||
if (-not (Test-Path $SrcDir)) {
|
||||
throw ('找不到源码目录 ' + $SrcDir + ',请先运行 3DTank/tools/extract.js 生成,或加 -Split 用切割产物')
|
||||
}
|
||||
$PackDir = $SrcDir
|
||||
$PackFile = Join-Path $SrcDir 'unpacked.pack.json'
|
||||
} else {
|
||||
Write-Warning ('未找到 ' + $PackScript + ',跳过单包(将逐文件加载)')
|
||||
$PackDir = Join-Path $RootDir '3dtank.com\play\static\js\unpacked'
|
||||
$PackFile = Join-Path $RootDir '3dtank.com\play\static\js\unpacked.pack.json'
|
||||
}
|
||||
|
||||
$NeedPack = $Build -or (-not (Test-Path $PackFile))
|
||||
if (-not $NeedPack) {
|
||||
$PackTime = (Get-Item $PackFile).LastWriteTimeUtc
|
||||
$Newest = Get-ChildItem $PackDir -Filter 'module_*.js' -ErrorAction SilentlyContinue |
|
||||
Sort-Object LastWriteTimeUtc -Descending | Select-Object -First 1
|
||||
if ($Newest -and $Newest.LastWriteTimeUtc -gt $PackTime) {
|
||||
$NeedPack = $true
|
||||
Write-Host ('[打包] 检测到源码有更新(' + $Newest.Name + '),重新打包') -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
if ($NeedPack) {
|
||||
Write-Host ('[打包] ' + $PackDir + ' → ' + $PackFile) -ForegroundColor Cyan
|
||||
& $NodeExe $PackScript $PackDir $PackFile | Out-Host
|
||||
if ($LASTEXITCODE -ne 0) { throw '单包打包失败' }
|
||||
} else {
|
||||
Write-Host '[打包] 单包已是最新,跳过(要强制重打请加 -Build)' -ForegroundColor DarkGray
|
||||
}
|
||||
|
||||
# ---------- 4) 中继(可选;默认不启动 —— 页面直连真实服务器) ----------
|
||||
@@ -187,6 +227,7 @@ if ($WithRelay) {
|
||||
# 默认加 --real-config:/config.xml 取真实站点(--config-upstream 决定 c1 / c2),游戏据此直连对应服务器
|
||||
# 走中继(-WithRelay)时改用 --relay-port:serve.js 动态把 config 改写为 ws://localhost:<RelayPort>/(不落盘)
|
||||
$MirrorArgs = @('serve.js', '--port', "$MirrorPort", '--config-upstream', $ConfigUpstream)
|
||||
if ($UseSrc) { $MirrorArgs += @('--src', $SrcDir) }
|
||||
if ($WithRelay) { $MirrorArgs += @('--relay-port', "$RelayPort") } else { $MirrorArgs += '--real-config' }
|
||||
if ($Hook) { $MirrorArgs += '--ws-hook' }
|
||||
Write-Host ("[镜像] serve.js http://localhost:{0}/ {1}{2}" -f $MirrorPort, ($(if ($WithRelay) {'(config → 本地中继)'} else {'(config → 真实服务器,直连)'})), ($(if ($Hook) {' + ws 抓包'} else {''}))) -ForegroundColor Green
|
||||
@@ -201,7 +242,8 @@ $MirrorOk = Test-TcpOpen '127.0.0.1' $MirrorPort
|
||||
|
||||
Write-Host ''
|
||||
Write-Host '================= 已启动 =================' -ForegroundColor Yellow
|
||||
Write-Host ("浏览器打开 : http://localhost:{0}/" -f $MirrorPort) -ForegroundColor White
|
||||
Write-Host ("浏览器打开 : http://localhost:{0}/" -f $MirrorPort) -ForegroundColor White
|
||||
Write-Host ("模块来源 : {0}" -f ($(if ($UseSrc) {'3DTank/src(反编译源码,改完刷新即生效)'} else {'unpacked(切割产物)'}))) -ForegroundColor White
|
||||
Write-Host ("工具链 : 默认已注入(纯净页 http://localhost:{0}/#nohornet);切勿加查询参数 ?xxx —— 会被游戏当成 config 参数,导致握手失败 1005" -f $MirrorPort) -ForegroundColor White
|
||||
if ($WithRelay) {
|
||||
Write-Host ("连接路径 : 页面 → ws://localhost:{0}/ (中继)→ {1}" -f $RelayPort, $Upstream) -ForegroundColor White
|
||||
|
||||
@@ -216,6 +216,26 @@ KT/
|
||||
|
||||
## 8. 产出"可启动 JS"的端到端流程
|
||||
|
||||
### 8.1 运行时模块来源(src 模式,默认)
|
||||
|
||||
`Start-LocalAndRelay.ps1` 默认直接加载 **`3DTank/src`**(反编译源码),改完代码刷新即生效:
|
||||
|
||||
| 行为 | 说明 |
|
||||
|---|---|
|
||||
| 启动时打包 | 单包缺失、或 `src/module_*.js` 比单包新 → 自动跑 `pack_unpacked.js` |
|
||||
| `-Build` | 强制重打单包 |
|
||||
| `-Split` | 回到切割产物 `3dtank.com/play/static/js/unpacked` |
|
||||
| 路由 | `serve.js --src <目录>`:`unpacked/module_*.js`、`unpacked/resources.json`、`unpacked/index.json`、`unpacked.pack.json` → src 目录 |
|
||||
| 仍取镜像 | 加载器 `main.<hash>.js`、`unpacked/hornet_bundle.js`(HORNET 工具链) |
|
||||
|
||||
打包命令:
|
||||
|
||||
```bash
|
||||
node tools/pack_unpacked.js 3DTank/src 3DTank/src/unpacked.pack.json
|
||||
```
|
||||
|
||||
### 8.2 完整流程
|
||||
|
||||
```bash
|
||||
# 1) 基线
|
||||
node tools/split.js --clean
|
||||
|
||||
+21
-2
@@ -23,6 +23,11 @@ const Arg = (Name, Def) => {
|
||||
const PORT = Number(Arg('port', '8080'));
|
||||
const WEB_DIR = path.resolve(Arg('web', path.join(PROJECT, 'web')));
|
||||
const JS_DIR = path.join(ROOT, '3dtank.com', 'play', 'static', 'js');
|
||||
// --src <目录>:模块源码改从「反编译源码目录」(如 3DTank/src)加载
|
||||
// · /play/static/js/unpacked/module_*.js、resources.json、index.json → src 目录
|
||||
// · /play/static/js/unpacked.pack.json → src 目录里的单包
|
||||
// · 其它(main.<hash>.js 加载器、unpacked/hornet_bundle.js 工具链)仍走 JS_DIR
|
||||
const SRC_DIR = Arg('src', '') ? path.resolve(Arg('src', '')) : '';
|
||||
const MISSING_LOG = path.join(PROJECT, 'names', 'missing.txt');
|
||||
// 页面内探针的网络转储落盘位置:POST /__probe__?f=<name> 追加写对应文件(不传 f 默认 railgun)
|
||||
const PROBE_LOGS = {
|
||||
@@ -94,7 +99,18 @@ function Resolve(UrlPath) {
|
||||
const Clean = decodeURIComponent(UrlPath.split('?')[0]);
|
||||
// 切割版 JS 走 TankIC 目录
|
||||
if (Clean.startsWith('/play/static/js/')) {
|
||||
const P = path.join(JS_DIR, Clean.slice('/play/static/js/'.length));
|
||||
const Rest = Clean.slice('/play/static/js/'.length);
|
||||
// --src:模块与单包改从反编译源码目录取(加载器与 hornet 工具链仍用 JS_DIR)
|
||||
if (SRC_DIR) {
|
||||
if (Rest === 'unpacked.pack.json') return path.join(SRC_DIR, 'unpacked.pack.json');
|
||||
if (Rest.startsWith('unpacked/')) {
|
||||
const Name = Rest.slice('unpacked/'.length);
|
||||
if (/^module_\d+\.js$/.test(Name) || Name === 'resources.json' || Name === 'index.json') {
|
||||
return path.join(SRC_DIR, Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
const P = path.join(JS_DIR, Rest);
|
||||
// 主文件名的 hash 随 bundle 版本变化,而 index.html 里写的是固定名(重新拆分后会失配 → 404)。
|
||||
// 这里兜底:请求 main.<hash>.js 但该文件不存在时,回退到 JS 目录里最新的 main.<hash>.js。
|
||||
if (/[/\\]main\.[0-9a-f]{8}\.js$/.test(P) && !fs.existsSync(P)) {
|
||||
@@ -418,7 +434,9 @@ const Server = http.createServer((Req, Res) => {
|
||||
return;
|
||||
}
|
||||
const File = Resolve(UrlPath);
|
||||
if (!File.startsWith(WEB_DIR) && !File.startsWith(JS_DIR)) {
|
||||
// 允许的根:站点根、切割版 JS、以及 --src 指定的反编译源码目录
|
||||
const Allowed = File.startsWith(WEB_DIR) || File.startsWith(JS_DIR) || (SRC_DIR && File.startsWith(SRC_DIR));
|
||||
if (!Allowed) {
|
||||
Res.writeHead(403).end('Forbidden');
|
||||
return;
|
||||
}
|
||||
@@ -471,6 +489,7 @@ Server.listen(PORT, () => {
|
||||
console.log('本地客户端: http://localhost:' + PORT + '/');
|
||||
console.log(' 站点根 : ' + WEB_DIR);
|
||||
console.log(' 切割版 JS : ' + JS_DIR);
|
||||
console.log(' 模块来源 : ' + (SRC_DIR ? ('src = ' + SRC_DIR + '(单包/模块/资源)') : 'unpacked(切割产物)'));
|
||||
console.log(' 404 记录 : ' + MISSING_LOG);
|
||||
console.log(' config.xml: ' + (RELAY_PORT > 0
|
||||
? ('中继改写 → ws://localhost:' + RELAY_PORT + '/(动态生成,不落盘)')
|
||||
|
||||
Reference in new issue
Block a user