From 896fbbb49bc31814178db14581edd56155018521 Mon Sep 17 00:00:00 2001 From: lonelywolf <13281126@qq.com> Date: Wed, 28 Oct 2026 09:27:11 +0000 Subject: [PATCH] S14V1.70 --- build/build.bat | 122 +++++++ build/build.ps1 | 873 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 995 insertions(+) create mode 100644 build/build.bat create mode 100644 build/build.ps1 diff --git a/build/build.bat b/build/build.bat new file mode 100644 index 0000000..e6d817d --- /dev/null +++ b/build/build.bat @@ -0,0 +1,122 @@ +@echo off +setlocal EnableExtensions +title BadWolf ¹ýÂËÆ÷¹¹½¨¹¤¾ß + +rem ============================================================ +rem BadWolf ¹ýÂËÆ÷¹¹½¨Èë¿Ú build.bat v1.2 +rem ±¾ÎļþΪ GBK(cp936) + CRLF ±àÂ룻¸ÄÎݸÇ뱣³ָñàÂ룬·ñÔòÖÐÎÄÂÒÂ롣 +rem ============================================================ + +rem ---- ¼Ç¼ԭ´úÂëҳ£¬Í˳öǰ»¹ԭ¡£±¾ÎļþÊÇ GBK£¬¿ØÖÆ̨·Ç 936 ÏÈÇйýȥ¡£ +rem chcp ^nul 2>nul + +set "RC=0" +set "HERE=%~dp0" +set "PS1=%HERE%build.ps1" +set "MENU=" +if "%~1"=="" set "MENU=1" + +if not exist "%PS1%" goto nops1 +if /i "%~1"=="help" goto help +if "%~1"=="/?" goto help +if "%~1"=="?" goto help + +if defined MENU goto menu +goto run + +rem ---------------------------------------------------------------- ²˵¥ +:menu +cls +echo ============================================================ +echo BadWolf ¹ýÂËÆ÷¹¹½¨¹¤¾ß +echo ============================================================ +echo. +echo 1. УÑé ֻ¶Á¼ì²飬²»дÈκÎÎļþ +echo 2. ¹¹½¨ °´ģ¿éÖؽ¨ºϲ¢°棬×Զ¯±¸·ݣ¬ֻÁô×î½ü 2 ·Ý +echo 3. ÐкŻ»Ëã ºϲ¢°æÐкÅ Óë ģ¿éÐкÅ »¥Ï໻Ëã +echo 4. µ¼³ö Éú³ÉÐкÅӳÉä±í +echo 0. Í˳ö +echo. +set "SEL=" +set /p "SEL=ÇëÊäÈëÐòºźó»سµ£¬ֱ½ӻسµ = УÑ飺" +if "%SEL%"=="0" goto done +if "%SEL%"=="2" goto mBld +if "%SEL%"=="3" goto mMap +if "%SEL%"=="4" goto mExp +goto mChk + +:mChk +set "ARGS=check" +goto run2 + +:mBld +set "ARGS=build" +goto run2 + +:mMap +echo. +set "Q=" +set /p "Q=ÇëÊäÈëÐкţ¬ÀýÈç 1939 »ò 16:139£¬ֱ½ӻسµ·µ»ز˵¥£º" +if "%Q%"=="" goto menu +set "ARGS=map %Q%" +goto run2 + +:mExp +set "ARGS=export" +goto run2 + +rem ---------------------------------------------------------------- ִÐÐ +:run +set "ARGS=%*" + +:run2 +echo. +powershell -NoProfile -ExecutionPolicy Bypass -File "%PS1%" %ARGS% +set "RC=%ERRORLEVEL%" +echo. +if "%RC%"=="0" echo [Íê³É] Í˳öÂë 0£ºУÑéͨ¹ý +if "%RC%"=="1" echo [עÒâ] Í˳öÂë 1£º·¢ÏÖÎÊÌ⣬¼ûÉÏÃæµÄ x Ïî»ò²îÒì¿é +if "%RC%"=="2" echo [ʧ°Ü] Í˳öÂë 2£º»·¾³ÎÊÌ⣬ȱÎļþ»òģ¿é±àºÅÖظ´ +if not defined MENU goto done +echo. +pause +goto menu + +rem ---------------------------------------------------------------- °ïÖú +:help +echo. +echo BadWolf ¹ýÂËÆ÷¹¹½¨½ű¾ ÃüÁîÐÐÓ÷¨ +echo. +echo build.bat ´򿪲˵¥ +echo build.bat check УÑ飬²»дÎļþ +echo build.bat build Öؽ¨ºϲ¢°棬×Զ¯±¸·Ý +echo build.bat map 1939 ºϲ¢°æÐкÅ ת ģ¿éÐкÅ +echo build.bat map 16:139 ģ¿éÐкÅ ת ºϲ¢°æÐкÅ +echo build.bat export µ¼³öÐкÅӳÉä±í +echo. +echo ¸½¼ӲÎÊý +echo -NoBackup build ʱ²»±¸·ÝԭÎļþ +echo -KeepBackups 3 ±¸·ݱ£Áô·ÝÊý£¬ĬÈÏ 2 +echo -Strict ÓÐÌáʾÏîҲË㲻ͨ¹ý +echo. +echo Í˳öÂë 0 ͨ¹ý 1 ÓÐÎÊÌâ 2 »·¾³ÎÊÌâ +echo. +goto done + +rem ---------------------------------------------------------------- ȱÎļþ +:nops1 +echo. +echo [´íÎó] ͬĿ¼ÏÂÕҲ»µ½ build.ps1 +echo ÇëȷÈÏ build.bat Óë build.ps1 ·ÅÔÚͬһ¸öÎļþ¼ÐÀ +echo. +pause +set "RC=2" +goto done + +:done +if defined OLDCP chcp %OLDCP% nul 2>nul +exit /b %RC% diff --git a/build/build.ps1 b/build/build.ps1 new file mode 100644 index 0000000..ca2c848 --- /dev/null +++ b/build/build.ps1 @@ -0,0 +1,873 @@ +#requires -Version 5.1 +<# + BadWolf 过滤器构建脚本 build.ps1 v1.2 + ------------------------------------------------------------------ + 用途:把模块目录下的 txt 按文件名排序拼接成 BadWolf-LootFilter.txt, + 并完成一致性校验与行号换算。纯 PowerShell,无需安装任何软件。 + + v1.2 相对 v1.1 的变化 + ------------------------------------------------------------------ + · 自检新增:孤立 % / 未闭合 % 扫描(半截百分号会吞颜色或漏出明文) + 判定:先整体屏蔽合法占位符 %NAME%,剩下的 % 只放行四种写字面百分号的情形 + (数值后 40%ED / 右括号后 [4-6]%物理减伤 / 夹在两个占位符之间 / + 「物理减伤%」「魔法减伤%」后的百分比示意符) + + v1.1 相对 v1.0 的变化 + ------------------------------------------------------------------ + · 模块白名单:只拼 NN-*.txt,其它 txt 一律跳过并黄字警告(不再静默混入) + · 备份轮转:build 只保留最近 2 份 .bak,可用 -KeepBackups N 调整 + · 临时文件:写盘失败也会清理 .tmp + · 自检新增:物品代码白名单(item_codes.txt)/ 死规则 / Formula 引用完整性 + · 版本行联动:版本行日期落后于最晚模块改动时间时提示 + + 用法(二选一) + ------------------------------------------------------------------ + A. 双击 build.bat → 直接校验(窗口不关) + B. 命令行: + powershell -NoProfile -ExecutionPolicy Bypass -File build.ps1 + powershell -NoProfile -ExecutionPolicy Bypass -File build.ps1 build + powershell -NoProfile -ExecutionPolicy Bypass -File build.ps1 map 1939 + powershell -NoProfile -ExecutionPolicy Bypass -File build.ps1 map 16:139 + powershell -NoProfile -ExecutionPolicy Bypass -File build.ps1 export + + 命令 + ------------------------------------------------------------------ + check 校验(默认,不写任何文件) + build 重建合并版(自动备份 .bak,只保留最近 2 份;-NoBackup 关闭备份) + map 行号换算: 1939(合并→模块) 或 16:139(模块→合并) + export 导出行号映射表 + + 参数 + ------------------------------------------------------------------ + -NoBackup build 时不备份原文件 + -KeepBackups N 备份保留份数,默认 2 + -Strict 有提示项也算不通过(退出码 1) + + 退出码:0 一致 / 1 有问题 / 2 环境问题 +#> +param( + [Parameter(Position = 0)][string]$Command = 'check', + [Parameter(Position = 1)][string]$Arg = '', + [switch]$NoBackup, + [switch]$Strict, + [int]$KeepBackups = 2 +) + +$ErrorActionPreference = 'Stop' + +# ---------------------------------------------------------------- 基础路径 +$Root = $PSScriptRoot +$MergedName = 'BadWolf-LootFilter.txt' +$MergedPath = Join-Path $Root $MergedName +$MapName = [char]0x884C + [char]0x53F7 + [char]0x6620 + [char]0x5C04 + [char]0x8868 + '.md' + +function Write-Line([string]$s) { Write-Host $s } +function Format-N([long]$n) { return $n.ToString('N0', [System.Globalization.CultureInfo]::InvariantCulture) } +function Get-Bar { return ('=' * 74) } +function Write-Head([string]$t) { Write-Host ""; Write-Host "[$t]"; Write-Host ('-' * 74) } + +function Get-Md5Hex([byte[]]$Bytes) { + $md5 = [System.Security.Cryptography.MD5]::Create() + try { $h = $md5.ComputeHash($Bytes) } finally { $md5.Dispose() } + return (-join ($h | ForEach-Object { $_.ToString('x2') })) +} + +# ---------------------------------------------------------------- 模块目录 +# 只认「≥10 个 数字-xxx.txt」的目录;多个候选直接报错,绝不猜 +function Get-ModuleDir { + $cands = @() + foreach ($d in @(Get-ChildItem -LiteralPath $Root -Directory -ErrorAction SilentlyContinue)) { + $n = @(Get-ChildItem -LiteralPath $d.FullName -Filter '*.txt' -File -ErrorAction SilentlyContinue | + Where-Object { $_.Name -match '^\d{2}-' }).Count + if ($n -gt 0) { $cands += [pscustomobject]@{ Path = $d.FullName; Count = $n } } + } + $good = @($cands | Where-Object { $_.Count -ge 10 } | Sort-Object -Descending Count) + + if ($good.Count -eq 0) { + $tip = '' + if ($cands.Count -gt 0) { + $tip = ';候选目录(文件数不足):' + (($cands | ForEach-Object { "$($_.Path)($($_.Count)个)" }) -join ',') + } + throw "找不到模块目录:$Root 下没有包含 ≥10 个 `00-xxx.txt` 形式文件的文件夹$tip" + } + if ($good.Count -gt 1) { + $list = ($good | ForEach-Object { "$($_.Path)($($_.Count) 个)" }) -join ';' + throw "检测到多个可能的模块目录,为避免用错目录构建,已停止:$list。请把多余的移走或改名。" + } + return $good[0].Path +} + +# ---------------------------------------------------------------- 载入模块 +# 白名单:只认「NN-名称.txt」;名字里带 副本/备份/copy/bak/(1) 的视为复制品,同样跳过 +$script:SkippedModules = @() +$CopyNameRe = '副本|备份|复制|copy|bak|backup|\(\d+\)' + +function Get-Modules([string]$Dir) { + $allTxt = @(Get-ChildItem -LiteralPath $Dir -Filter '*.txt' -File) + $files = @($allTxt | Where-Object { + $_.Name -match '^\d{2}-.*\.txt$' -and $_.Name -notmatch $CopyNameRe + } | Sort-Object Name) + $script:SkippedModules = @($allTxt | Where-Object { + -not ($_.Name -match '^\d{2}-.*\.txt$') -or ($_.Name -match $CopyNameRe) + } | Sort-Object Name | ForEach-Object { $_.Name }) + $list = New-Object System.Collections.ArrayList + $cursor = 1 + $strict = [System.Text.UTF8Encoding]::new($false, $true) + + foreach ($f in $files) { + $bytes = [System.IO.File]::ReadAllBytes($f.FullName) + $text = [System.Text.Encoding]::UTF8.GetString($bytes) + $errors = New-Object System.Collections.ArrayList + + try { [void]$strict.GetString($bytes) } + catch { [void]$errors.Add('不是合法的 UTF-8 编码') } + + if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { + [void]$errors.Add('含 UTF-8 BOM') + } + $lfOnly = ([regex]::Matches($text, "(?.bak(文件名时间戳可直接按名倒序) +function Remove-OldBackup([int]$Keep) { + $dir = Split-Path -Parent $MergedPath + $pat = (Split-Path -Leaf $MergedPath) + '.*.bak' + $all = @(Get-ChildItem -LiteralPath $dir -Filter $pat -File -ErrorAction SilentlyContinue | + Sort-Object Name -Descending) + if ($all.Count -le $Keep) { return @() } + $gone = @($all | Select-Object -Skip $Keep) + foreach ($g in $gone) { Remove-Item -LiteralPath $g.FullName -Force -ErrorAction SilentlyContinue } + return $gone +} + +# ---------------------------------------------------------------- build +function Invoke-Build($Mods) { + Write-Line (Get-Bar) + Write-Line " BadWolf 过滤器 构建" + Write-Line (Get-Bar) + + $bad = @($Mods | Where-Object { $_.Errors.Count -gt 0 }) + if ($bad.Count -gt 0) { + Write-Line " [中止] 以下模块存在编码/换行问题:" + foreach ($m in $bad) { + Write-Line " $($m.Name)" + foreach ($e in $m.Errors) { Write-Line " ! $e" } + } + return 1 + } + + $cat = Join-Bytes $Mods + $old = @() + if (Test-Path -LiteralPath $MergedPath) { $old = [System.IO.File]::ReadAllBytes($MergedPath) } + + $same = $false + if ($old.Length -eq $cat.Length) { + $same = $true + for ($i = 0; $i -lt $cat.Length; $i++) { if ($cat[$i] -ne $old[$i]) { $same = $false; break } } + } + if ($same) { + Write-Line " 合并版已是最新,无需重建。" + Write-Line "" + return Invoke-Check $Mods + } + + if (-not $NoBackup -and (Test-Path -LiteralPath $MergedPath)) { + $stamp = Get-Date -Format 'yyyyMMdd-HHmmss' + $bak = "$MergedPath.$stamp.bak" + Copy-Item -LiteralPath $MergedPath -Destination $bak -Force + Write-Line " 已备份 → $(Split-Path -Leaf $bak)" + if ($KeepBackups -gt 0) { + $gone = @(Remove-OldBackup $KeepBackups) + if ($gone.Count -gt 0) { + Write-Line " 轮转 删除旧备份 $($gone.Count) 份(保留最近 $KeepBackups 份):$(($gone | ForEach-Object { $_.Name }) -join ', ')" + } else { + Write-Line " 轮转 现有备份未超过 $KeepBackups 份,无需删除" + } + } + } + + $tmp = "$MergedPath.tmp" + try { + [System.IO.File]::WriteAllBytes($tmp, $cat) + Move-Item -LiteralPath $tmp -Destination $MergedPath -Force + } finally { + if (Test-Path -LiteralPath $tmp) { Remove-Item -LiteralPath $tmp -Force -ErrorAction SilentlyContinue } + } + + $new = [System.IO.File]::ReadAllBytes($MergedPath) + $lineN = ([regex]::Matches([System.Text.Encoding]::UTF8.GetString($new), "\n")).Count + Write-Line " 已写入 $(Format-N $new.Length) B / $(Format-N $lineN) 行 MD5 $(Get-Md5Hex $new)" + + $okWrite = $false + if ($new.Length -eq $cat.Length) { + $okWrite = $true + for ($i = 0; $i -lt $cat.Length; $i++) { if ($new[$i] -ne $cat[$i]) { $okWrite = $false; break } } + } + if ($okWrite) { Write-Line " 写入校验通过(逐字节一致)" } else { Write-Line " [错误] 写入校验失败"; return 1 } + + Write-Line "" + return Invoke-Check $Mods +} + +# ---------------------------------------------------------------- map +function Invoke-Map($Mods, [string]$Q) { + if ($Q -match ':') { + $parts = $Q.Split(':') + $code = $parts[0]; $ln = 0 + if (-not [int]::TryParse($parts[1], [ref]$ln)) { Write-Line "无法解析行号:$Q"; return 1 } + $m = $Mods | Where-Object { $_.Code -eq $code -or $_.Name.StartsWith($code) } | Select-Object -First 1 + if ($null -eq $m) { Write-Line "找不到模块:$code"; return 1 } + if ($ln -lt 1 -or $ln -gt $m.LineCount) { Write-Line "$($m.Name) 只有 $($m.LineCount) 行"; return 1 } + $merged = $m.Start + $ln - 1 + Write-Line "$($m.Name) 第 $ln 行 → 合并版 L$merged" + $lines = Get-Lines $m.Text + if ($ln -le $lines.Count) { Write-Line " $($lines[$ln - 1])" } + return 0 + } + + $ln = 0 + if (-not [int]::TryParse($Q, [ref]$ln)) { Write-Line "无法解析行号:$Q"; return 1 } + $m = Find-ModuleOfLine $Mods $ln + if ($null -eq $m) { Write-Line "L$ln 超出范围(1-$($Mods[$Mods.Count-1].End))"; return 1 } + Write-Line "合并版 L$ln → $($m.Name) 第 $($ln - $m.Start + 1) 行" + return 0 +} + +# ---------------------------------------------------------------- export +function Invoke-Export($Mods) { + $cat = Join-Bytes $Mods + $end = $Mods[$Mods.Count - 1].End + $sb = New-Object System.Text.StringBuilder + [void]$sb.AppendLine('# BadWolf 过滤器行号映射表') + [void]$sb.AppendLine('') + [void]$sb.AppendLine("- 生成时间:$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')") + [void]$sb.AppendLine("- 模块数:$($Mods.Count)") + [void]$sb.AppendLine("- 模块拼接:$(Format-N $cat.Length) 字节 / $(Format-N $end) 行 / MD5 ``$(Get-Md5Hex $cat)``") + [void]$sb.AppendLine('- 换算:`合并行 = 模块起始行 + 模块行 - 1`') + [void]$sb.AppendLine('') + [void]$sb.AppendLine('| 模块 | 合并版起 | 合并版止 | 行数 | 字节 |') + [void]$sb.AppendLine('|---|---:|---:|---:|---:|') + foreach ($m in $Mods) { + [void]$sb.AppendLine("| $($m.Name) | $($m.Start) | $($m.End) | $($m.LineCount) | $(Format-N $m.ByteLen) |") + } + [void]$sb.AppendLine("| **合计** | 1 | $end | $end | $(Format-N $cat.Length) |") + [void]$sb.AppendLine('') + [void]$sb.AppendLine('## 常用锚点') + [void]$sb.AppendLine('') + foreach ($m in $Mods) { + if (@('00','09','16','22','28','37','39') -contains $m.Code) { + [void]$sb.AppendLine("- ``$($m.Code)`` $($m.Name) → L$($m.Start)–L$($m.End)") + } + } + $path = Join-Path $Root $MapName + [System.IO.File]::WriteAllText($path, $sb.ToString(), (New-Object System.Text.UTF8Encoding($false))) + Write-Line "已导出 $path" + return 0 +} + +# ---------------------------------------------------------------- 主流程 +try { + $moduleDir = Get-ModuleDir +} catch { + Write-Line "[错误] $($_.Exception.Message)" + exit 2 +} + +Write-Line (Get-Bar) +Write-Line " BadWolf 过滤器构建工具(PowerShell 版)" +Write-Line (Get-Bar) +Write-Line " 脚本位置 $PSCommandPath" +Write-Line " 模块目录 $moduleDir" +Write-Line " 合并版 $MergedPath" + +$mods = Get-Modules $moduleDir +if ($mods.Count -eq 0) { Write-Line "[错误] 模块目录里没有 NN-*.txt 模块文件"; exit 2 } + +if ($script:SkippedModules.Count -gt 0) { + Write-Host "" + Write-Host " [警告] 以下 txt 不符合「NN-名称.txt」,已跳过(不会进入合并版):" -ForegroundColor Yellow + foreach ($n in $script:SkippedModules) { Write-Host " - $n" -ForegroundColor Yellow } + Write-Host " 若是正式模块,请改名成 40-xxx.txt 这种形式。" -ForegroundColor Yellow +} + +# 编号必须唯一:两个 16-xxx.txt 会让合并版多出一整段,且顺序取决于文件名,必须人工处理 +$dupCodes = @($mods | Group-Object Code | Where-Object { $_.Count -gt 1 }) +if ($dupCodes.Count -gt 0) { + Write-Line "" + Write-Line "[错误] 模块编号重复,已停止(避免把两份内容都拼进合并版):" + foreach ($g in $dupCodes) { + $names = ($g.Group | ForEach-Object { $_.Name }) -join ' / ' + Write-Line (" [$($g.Name)] $names") + } + Write-Line " 处理办法:把多余的那份移出模块目录,或改成未占用的编号。" + exit 2 +} + +switch ($Command.ToLowerInvariant()) { + 'build' { exit (Invoke-Build $mods) } + 'map' { if ([string]::IsNullOrWhiteSpace($Arg)) { Write-Line "用法:build.bat map 1939 或 build.bat map 16:139"; exit 2 }; exit (Invoke-Map $mods $Arg) } + 'export' { exit (Invoke-Export $mods) } + 'check' { exit (Invoke-Check $mods) } + default { Write-Line "[错误] 未知命令:$Command(可用 check / build / map / export)"; exit 2 } +}