Merge branch 'main' into dev

This commit is contained in:
TrèsAbhi committed 2025-11-26 13:58:44 -06:00
commit a692d1ee0b
43 files changed
+577 -604

No files matched your search

+2 -112
View File
@@ -55,117 +55,13 @@ env:
PUBLIC_ASSET_FAST_REPO: assets PUBLIC_ASSET_FAST_REPO: assets
PUBLIC_ASSET_BASE: ${{ secrets.PUBLIC_ASSET_BASE }} PUBLIC_ASSET_BASE: ${{ secrets.PUBLIC_ASSET_BASE }}
GH_TOKEN: ${{ secrets.GH_TOKEN }} GH_TOKEN: ${{ secrets.GH_TOKEN }}
STEAM_USERNAME: ${{ secrets.STEAM_USERNAME }}
STEAM_PASSWORD: ${{ secrets.STEAM_PASSWORD }}
jobs: jobs:
download_client:
name: Download client
runs-on: ubuntu-latest
steps:
- if: github.event.inputs.archive_url != ''
uses: easimon/maximize-build-space@master
with:
root-reserve-mb: 512
swap-size-mb: 1024
remove-dotnet: "true"
remove-haskell: "true"
remove-android: "true"
remove-codeql: "true"
remove-docker-images: "true"
- if: github.event.inputs.archive_url != '' && endsWith(github.event.inputs.archive_url, '.wgpkg')
run: |
sudo apt update
sudo apt install -y p7zip-full
- uses: actions/checkout@v4
if: github.event.inputs.archive_url == ''
with:
submodules: recursive
token: ${{ secrets.GH_TOKEN }}
- uses: arduino/setup-protoc@v3
if: github.event.inputs.archive_url == ''
with:
repo-token: ${{ secrets.GH_TOKEN }}
- uses: oven-sh/setup-bun@v1
if: github.event.inputs.archive_url == ''
- run: bun run setup
if: github.event.inputs.archive_url == ''
- name: (Steam) Setup DepotDownloader
if: github.event.inputs.archive_url == ''
run: bun run setup:depotdownloader
- name: (Steam) Download client
if: github.event.inputs.archive_url == ''
run: |
chmod +x ./temp/depotDownloader/DepotDownloader
./temp/depotDownloader/DepotDownloader -q -os windows -app 444200 -username ${{ secrets.DEPOT_DOWNLOADER_USERNAME }} -password "${{ secrets.DEPOT_DOWNLOADER_PASSWORD }}"
mkdir -p temp/game
mv depots/444202/*/* temp/game
rm -rf depots
- name: (Steam) Apply patches
if: github.event.inputs.archive_url == ''
run: bun setup:patches --manual
- name: (ZIP) Download client
if: github.event.inputs.archive_url != '' && endsWith(github.event.inputs.archive_url, '.zip')
env:
ARCHIVE_URL: ${{ github.event.inputs.archive_url }}
run: |
mkdir -p temp/game
wget -q -O temp/archive.zip $ARCHIVE_URL
unzip -q temp/archive.zip -d temp/archive
rm temp/archive.zip
mv temp/archive/app/* temp/game
- name: (WGPKG) Download client
if: github.event.inputs.archive_url != '' && endsWith(github.event.inputs.archive_url, '.wgpkg')
env:
ARCHIVE_URL: ${{ github.event.inputs.archive_url }}
run: |
mkdir -p temp/archives
mkdir -p temp/game
i=1
urls=()
while :; do
part=$(printf "%03d" $i)
url="${ARCHIVE_URL}.${part}"
if wget --spider -q "$url"; then
urls+=("$url")
((i++))
else
break
fi
done
for url in "${urls[@]}"; do
dest="temp/archives/$(basename "$url")"
wget -q -O "$dest" "$url" &
done
wait
first=$(ls temp/archives/*.001 | head -n 1)
7z x "$first" -otemp/game
rm -rf temp/archives
- name: Archive game
uses: actions/upload-artifact@v4
with:
name: game
path: temp/game
build_assets: build_assets:
name: Build assets name: Build assets
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: download_client
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -178,12 +74,6 @@ jobs:
- uses: oven-sh/setup-bun@v1 - uses: oven-sh/setup-bun@v1
- run: bun run setup - run: bun run setup
- name: Download game
uses: actions/download-artifact@v4
with:
name: game
path: temp/game
- name: AppArmor hack - name: AppArmor hack
run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
+3
View File
@@ -11,6 +11,7 @@
"analyticsreporting", "analyticsreporting",
"APAC", "APAC",
"apcr", "apcr",
"appinfo",
"applypatches", "applypatches",
"artefacts", "artefacts",
"astrojs", "astrojs",
@@ -111,6 +112,7 @@
"leaderboards", "leaderboards",
"lerp", "lerp",
"LINEARSIZE", "LINEARSIZE",
"linktarget",
"lmao", "lmao",
"loadouts", "loadouts",
"loddist", "loddist",
@@ -171,6 +173,7 @@
"ratingleaderboard", "ratingleaderboard",
"raycaster", "raycaster",
"Redirector", "Redirector",
"Relogin",
"researchable", "researchable",
"Resvg", "Resvg",
"rizz", "rizz",
+92 -3
View File
@@ -69,14 +69,17 @@
"@types/bun": "^1.3.1", "@types/bun": "^1.3.1",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/lz4js": "^0.2.1", "@types/lz4js": "^0.2.1",
"@types/steam-user": "^5.1.0",
"@types/three": "^0.180.0", "@types/three": "^0.180.0",
"adm-zip": "^0.5.16", "adm-zip": "^0.5.16",
"crc": "^4.3.2", "crc": "^4.3.2",
"dotenv": "^17.2.2", "dotenv": "^17.2.2",
"fast-xml-parser": "^5.3.2",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lz4js": "^0.2.0", "lz4js": "^0.2.0",
"pickleparser": "^0.2.1", "pickleparser": "^0.2.1",
"protobufjs": "^7.5.4", "protobufjs": "^7.5.4",
"steam-user": "^5.2.3",
"three": "^0.180.0", "three": "^0.180.0",
"ts-proto": "^2.7.7", "ts-proto": "^2.7.7",
"yaml": "^2.8.1", "yaml": "^2.8.1",
@@ -382,6 +385,10 @@
"@babel/types": ["@babel/[email protected]", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q=="], "@babel/types": ["@babel/[email protected]", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q=="],
"@bbob/parser": ["@bbob/[email protected]", "", { "dependencies": { "@bbob/plugin-helper": "^2.9.0" } }, "sha512-tldSYsMoEclke/B1nqL7+HbYMWZHTKvpbEHRSHuY+sZvS1o7Jpdfjb+KPpwP9wLI3p3r7GPv69/wGy+Xibs9yA=="],
"@bbob/plugin-helper": ["@bbob/[email protected]", "", {}, "sha512-idpUcNQ2co6T1oU/7/DG/ZRfipSSkTn9Ozw9f5vaXH7nzV3qhqZnhFVlHTzGGnRlzKlBwWOBzOdWi4Zeqg1c5A=="],
"@blitzkit/app": ["@blitzkit/app@workspace:packages/app"], "@blitzkit/app": ["@blitzkit/app@workspace:packages/app"],
"@blitzkit/bot": ["@blitzkit/bot@workspace:packages/bot"], "@blitzkit/bot": ["@blitzkit/bot@workspace:packages/bot"],
@@ -414,6 +421,12 @@
"@discordjs/ws": ["@discordjs/[email protected]", "", { "dependencies": { "@discordjs/collection": "^2.1.0", "@discordjs/rest": "^2.5.1", "@discordjs/util": "^1.1.0", "@sapphire/async-queue": "^1.5.2", "@types/ws": "^8.5.10", "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "^0.38.1", "tslib": "^2.6.2", "ws": "^8.17.0" } }, "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw=="], "@discordjs/ws": ["@discordjs/[email protected]", "", { "dependencies": { "@discordjs/collection": "^2.1.0", "@discordjs/rest": "^2.5.1", "@discordjs/util": "^1.1.0", "@sapphire/async-queue": "^1.5.2", "@types/ws": "^8.5.10", "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "^0.38.1", "tslib": "^2.6.2", "ws": "^8.17.0" } }, "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw=="],
"@doctormckay/stdlib": ["@doctormckay/[email protected]", "", { "dependencies": { "psl": "^1.9.0" } }, "sha512-bwy+gPn6oa2KTpfxJKX3leZoV/wHDVtO0/gq3usPvqPswG//dcf3jVB8LcbRRsKO3BXCt5DqctOQ+Xb07ivxnw=="],
"@doctormckay/steam-crypto": ["@doctormckay/[email protected]", "", {}, "sha512-lsxgLw640gEdZBOXpVIcYWcYD+V+QbtEsMPzRvjmjz2XXKc7QeEMyHL07yOFRmay+cUwO4ObKTJO0dSInEuq5g=="],
"@doctormckay/user-agents": ["@doctormckay/[email protected]", "", {}, "sha512-F+sL1YmebZTY2CnjoR9BXFEULpq7y8dxyLx48LZVa0BSDseXdLG/DtPISfM1iNv1XKCeiBzVNfAT/MOQ69v1Zw=="],
"@emmetio/abbreviation": ["@emmetio/[email protected]", "", { "dependencies": { "@emmetio/scanner": "^1.0.4" } }, "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA=="], "@emmetio/abbreviation": ["@emmetio/[email protected]", "", { "dependencies": { "@emmetio/scanner": "^1.0.4" } }, "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA=="],
"@emmetio/css-abbreviation": ["@emmetio/[email protected]", "", { "dependencies": { "@emmetio/scanner": "^1.0.4" } }, "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw=="], "@emmetio/css-abbreviation": ["@emmetio/[email protected]", "", { "dependencies": { "@emmetio/scanner": "^1.0.4" } }, "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw=="],
@@ -914,6 +927,8 @@
"@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="], "@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="],
"@types/bytebuffer": ["@types/[email protected]", "", { "dependencies": { "@types/long": "^3.0.0", "@types/node": "*" } }, "sha512-lV4YLiolMdD4upDmr4vnfiwV/FN9Jg33eNTSFMkHqyMKqTIAn5TmFTYsARwXwUXeFU7yzRpECmWV1SOhIvdkRQ=="],
"@types/debug": ["@types/[email protected]", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], "@types/debug": ["@types/[email protected]", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
"@types/decompress": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-9z+8yjKr5Wn73Pt17/ldnmQToaFHZxK0N1GHysuk/JIPT8RIdQeoInM01wWPgypRcvb6VH1drjuFpQ4zmY437g=="], "@types/decompress": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-9z+8yjKr5Wn73Pt17/ldnmQToaFHZxK0N1GHysuk/JIPT8RIdQeoInM01wWPgypRcvb6VH1drjuFpQ4zmY437g=="],
@@ -922,6 +937,8 @@
"@types/estree": ["@types/[email protected]", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/estree": ["@types/[email protected]", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"@types/file-manager": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-gEq6de+iMbjmkL3Wj183JQ651h9b331wQ3svXp2K6RkgBg+TtiyIZTMols/a3UtXllVV9kSelz/N3Rgh0n6S4g=="],
"@types/fontkit": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew=="], "@types/fontkit": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew=="],
"@types/hast": ["@types/[email protected]", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], "@types/hast": ["@types/[email protected]", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
@@ -930,6 +947,8 @@
"@types/lodash-es": ["@types/[email protected]", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="], "@types/lodash-es": ["@types/[email protected]", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ=="],
"@types/long": ["@types/[email protected]", "", {}, "sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA=="],
"@types/lz4js": ["@types/[email protected]", "", {}, "sha512-aAnbA4uKPNqZqu0XK1QAwKP0Wskb4Oa7ZFqxW5CMIyGgqYQKFgBxTfK3m3KODXoOLv5t14VregzgrEak13uGQA=="], "@types/lz4js": ["@types/[email protected]", "", {}, "sha512-aAnbA4uKPNqZqu0XK1QAwKP0Wskb4Oa7ZFqxW5CMIyGgqYQKFgBxTfK3m3KODXoOLv5t14VregzgrEak13uGQA=="],
"@types/markdown-escape": ["@types/[email protected]", "", {}, "sha512-JIc1+s3y5ujKnt/+N+wq6s/QdL2qZ11fP79MijrVXsAAnzSxCbT2j/3prHRouJdZ2yFLN3vkP0HytfnoCczjOw=="], "@types/markdown-escape": ["@types/[email protected]", "", {}, "sha512-JIc1+s3y5ujKnt/+N+wq6s/QdL2qZ11fP79MijrVXsAAnzSxCbT2j/3prHRouJdZ2yFLN3vkP0HytfnoCczjOw=="],
@@ -960,6 +979,10 @@
"@types/stats.js": ["@types/[email protected]", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="], "@types/stats.js": ["@types/[email protected]", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="],
"@types/steam-user": ["@types/[email protected]", "", { "dependencies": { "@types/bytebuffer": "*", "@types/file-manager": "*", "@types/node": "*", "@types/steamid": "*" } }, "sha512-jMCzwmvBA1DaqLTD9h23LzVmzyHy53cdzpJjBSYDI6qT/1LqEUM9xRt4Vb0Y9kOIr+BZckCewDw8Bk6n8e3BTA=="],
"@types/steamid": ["@types/[email protected]", "", {}, "sha512-LC0oaiNq3gqMI18MV935CnlyHmDooKRszK56jHv0+b7EbJwf5k++YsD52zWeJUD8nuYqP9LpIgpXGiYBOxpcYQ=="],
"@types/three": ["@types/[email protected]", "", { "dependencies": { "@dimforge/rapier3d-compat": "~0.12.0", "@tweenjs/tween.js": "~23.1.3", "@types/stats.js": "*", "@types/webxr": "*", "@webgpu/types": "*", "fflate": "~0.8.2", "meshoptimizer": "~0.22.0" } }, "sha512-ykFtgCqNnY0IPvDro7h+9ZeLY+qjgUWv+qEvUt84grhenO60Hqd4hScHE7VTB9nOQ/3QM8lkbNE+4vKjEpUxKg=="], "@types/three": ["@types/[email protected]", "", { "dependencies": { "@dimforge/rapier3d-compat": "~0.12.0", "@tweenjs/tween.js": "~23.1.3", "@types/stats.js": "*", "@types/webxr": "*", "@webgpu/types": "*", "fflate": "~0.8.2", "meshoptimizer": "~0.22.0" } }, "sha512-ykFtgCqNnY0IPvDro7h+9ZeLY+qjgUWv+qEvUt84grhenO60Hqd4hScHE7VTB9nOQ/3QM8lkbNE+4vKjEpUxKg=="],
"@types/trusted-types": ["@types/[email protected]", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], "@types/trusted-types": ["@types/[email protected]", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
@@ -1006,7 +1029,7 @@
"adm-zip": ["[email protected]", "", {}, "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ=="], "adm-zip": ["[email protected]", "", {}, "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ=="],
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], "agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
"ajv": ["[email protected]", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], "ajv": ["[email protected]", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
@@ -1086,6 +1109,8 @@
"bignumber.js": ["[email protected]", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], "bignumber.js": ["[email protected]", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
"binarykvparser": ["[email protected]", "", { "dependencies": { "long": "^3.2.0" } }, "sha512-B1N5ZxC8I9oSLis7Rg36DxsZJoIikUGU2XwpI0FKFCaPIJIEYi0B9UeIk3QU006axzq0TI9KC3iXelfGGgnWew=="],
"bl": ["[email protected]", "", { "dependencies": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" } }, "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww=="], "bl": ["[email protected]", "", { "dependencies": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" } }, "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww=="],
"boolbase": ["[email protected]", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], "boolbase": ["[email protected]", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
@@ -1118,6 +1143,8 @@
"bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="], "bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
"bytebuffer": ["[email protected]", "", { "dependencies": { "long": "~3" } }, "sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ=="],
"c12": ["[email protected]", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^16.6.1", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.4.2", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw=="], "c12": ["[email protected]", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^16.6.1", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.4.2", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw=="],
"call-bind": ["[email protected]", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], "call-bind": ["[email protected]", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
@@ -1238,6 +1265,8 @@
"csv-parse": ["[email protected]", "", {}, "sha512-CEE+jwpgLn+MmtCpVcPtiCZpVtB6Z2OKPTr34pycYYoL7sxdOkXDdQ4lRiw6ioC0q6BLqhc6cKweCVvral8yhw=="], "csv-parse": ["[email protected]", "", {}, "sha512-CEE+jwpgLn+MmtCpVcPtiCZpVtB6Z2OKPTr34pycYYoL7sxdOkXDdQ4lRiw6ioC0q6BLqhc6cKweCVvral8yhw=="],
"cuint": ["[email protected]", "", {}, "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw=="],
"cwise-compiler": ["[email protected]", "", { "dependencies": { "uniq": "^1.0.0" } }, "sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ=="], "cwise-compiler": ["[email protected]", "", { "dependencies": { "uniq": "^1.0.0" } }, "sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ=="],
"data-uri-to-buffer": ["[email protected]", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], "data-uri-to-buffer": ["[email protected]", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],
@@ -1410,7 +1439,7 @@
"fast-uri": ["[email protected]", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], "fast-uri": ["[email protected]", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
"fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], "fast-xml-parser": ["fast-xml-parser@5.3.2", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-n8v8b6p4Z1sMgqRmqLJm3awW4NX7NkaKPfb3uJIBTSH7Pdvufi3PQ3/lJLQrvxcMYl7JI2jnDO90siPEpD8JBA=="],
"fastq": ["[email protected]", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], "fastq": ["[email protected]", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
@@ -1424,6 +1453,8 @@
"fflate": ["[email protected]", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], "fflate": ["[email protected]", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
"file-manager": ["[email protected]", "", { "dependencies": { "@doctormckay/stdlib": "^1.14.1" } }, "sha512-y/K/1OCha04OXOxzo3cXJYtIzEk/CUMBb7Okipxueu0u+xCiuoocbwPyh1smUBasOobo4GAYmjgjD9Vh5zI51w=="],
"file-type": ["[email protected]", "", {}, "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ=="], "file-type": ["[email protected]", "", {}, "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ=="],
"filelist": ["[email protected]", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="], "filelist": ["[email protected]", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="],
@@ -1702,6 +1733,8 @@
"ktx-parse": ["[email protected]", "", {}, "sha512-mKp3y+FaYgR7mXWAbyyzpa/r1zDWeaunH+INJO4fou3hb45XuNSwar+7llrRyvpMWafxSIi99RNFJ05MHedaJQ=="], "ktx-parse": ["[email protected]", "", {}, "sha512-mKp3y+FaYgR7mXWAbyyzpa/r1zDWeaunH+INJO4fou3hb45XuNSwar+7llrRyvpMWafxSIi99RNFJ05MHedaJQ=="],
"kvparser": ["[email protected]", "", {}, "sha512-5P/5qpTAHjVYWqcI55B3yQwSY2FUrYYrJj5i65V1Wmg7/4W4OnBcaodaEvLyVuugeOnS+BAaKm9LbPazGJcRyA=="],
"leven": ["[email protected]", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], "leven": ["[email protected]", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
"lie": ["[email protected]", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="], "lie": ["[email protected]", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="],
@@ -1728,6 +1761,8 @@
"lz4js": ["[email protected]", "", {}, "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg=="], "lz4js": ["[email protected]", "", {}, "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg=="],
"lzma": ["[email protected]", "", { "bin": { "lzma.js": "bin/lzma.js" } }, "sha512-DcfiawQ1avYbW+hsILhF38IKAlnguc/fjHrychs9hdxe4qLykvhT5VTGNs5YRWgaNePh7NTxGD4uv4gKsRomCQ=="],
"maath": ["[email protected]", "", { "peerDependencies": { "@types/three": ">=0.134.0", "three": ">=0.134.0" } }, "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g=="], "maath": ["[email protected]", "", { "peerDependencies": { "@types/three": ">=0.134.0", "three": ">=0.134.0" } }, "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g=="],
"magic-bytes.js": ["[email protected]", "", {}, "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA=="], "magic-bytes.js": ["[email protected]", "", {}, "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA=="],
@@ -1868,6 +1903,8 @@
"nlcst-to-string": ["[email protected]", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="], "nlcst-to-string": ["[email protected]", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="],
"node-bignumber": ["[email protected]", "", {}, "sha512-VoTZHmdFQpZH1+q1dz2qcHNCwTWsJg2T3PYwlAyDNFOfVhSYUKQBLFcCpCud+wJBGgCttGavZILaIggDIKqEQQ=="],
"node-domexception": ["[email protected]", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], "node-domexception": ["[email protected]", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
"node-fetch": ["[email protected]", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], "node-fetch": ["[email protected]", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
@@ -1948,6 +1985,8 @@
"perfect-debounce": ["[email protected]", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], "perfect-debounce": ["[email protected]", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
"permessage-deflate": ["[email protected]", "", { "dependencies": { "safe-buffer": "*" } }, "sha512-EUNi/RIsyJ1P1u9QHFwMOUWMYetqlE22ZgGbad7YP856WF4BFF0B7DuNy6vEGsgNNud6c/SkdWzkne71hH8MjA=="],
"pickleparser": ["[email protected]", "", { "bin": { "pickletojson": "bin/pickletojson.js", "pickleparser": "bin/pickletojson.js" } }, "sha512-kMzY3uFYcR6OjOqr7nV2nkaXaBsUEOafu3zgPxeD6s/2ueMfVQH8lrymcDWBPGx0OkVxGMikxQit6jgByXjwBg=="], "pickleparser": ["[email protected]", "", { "bin": { "pickletojson": "bin/pickletojson.js", "pickleparser": "bin/pickletojson.js" } }, "sha512-kMzY3uFYcR6OjOqr7nV2nkaXaBsUEOafu3zgPxeD6s/2ueMfVQH8lrymcDWBPGx0OkVxGMikxQit6jgByXjwBg=="],
"picocolors": ["[email protected]", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picocolors": ["[email protected]", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
@@ -1996,6 +2035,8 @@
"proxy-from-env": ["[email protected]", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], "proxy-from-env": ["[email protected]", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
"psl": ["[email protected]", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="],
"pump": ["[email protected]", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], "pump": ["[email protected]", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
"punycode": ["[email protected]", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "punycode": ["[email protected]", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
@@ -2172,7 +2213,7 @@
"socks": ["[email protected]", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="], "socks": ["[email protected]", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
"socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="], "socks-proxy-agent": ["socks-proxy-agent@7.0.0", "", { "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww=="],
"source-map": ["[email protected]", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "source-map": ["[email protected]", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
@@ -2190,6 +2231,16 @@
"statuses": ["[email protected]", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "statuses": ["[email protected]", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
"steam-appticket": ["[email protected]", "", { "dependencies": { "@doctormckay/stdlib": "^1.6.0", "@doctormckay/steam-crypto": "^1.2.0", "bytebuffer": "^5.0.1", "protobufjs": "^6.8.8", "steamid": "^1.1.0" } }, "sha512-zwDwZALGv3RanE8RHNYcQU3u4Ez23EzMuQ4Lh15uIHddpDh6TI6uFGbC0HNyt6y+UJYSILe77A33VhFZKQiaqQ=="],
"steam-session": ["[email protected]", "", { "dependencies": { "@doctormckay/stdlib": "^2.9.0", "@doctormckay/user-agents": "^1.0.0", "debug": "^4.3.4", "kvparser": "^1.0.1", "node-bignumber": "^1.2.2", "protobufjs": "^7.1.0", "socks-proxy-agent": "^7.0.0", "steamid": "^2.0.0", "tiny-typed-emitter": "^2.1.0", "websocket13": "^4.0.0" } }, "sha512-MLvg1uMLEOIRHZS5LKruy1w5OqHb8EL7TeMxIY2a4mUcaVOgszz060+jo4c7s3gFeedyuoqGcfwJrR0pLKYzLw=="],
"steam-totp": ["[email protected]", "", {}, "sha512-bTKlc/NoIUQId+my+O556s55DDsNNXfVIPWFDNVu68beql7AJhV0c+GTjFxfwCDYfdc4NkAme+0WrDdnY2D2VA=="],
"steam-user": ["[email protected]", "", { "dependencies": { "@bbob/parser": "^2.2.0", "@doctormckay/stdlib": "^2.9.1", "@doctormckay/steam-crypto": "^1.2.0", "adm-zip": "^0.5.10", "binarykvparser": "^2.2.0", "bytebuffer": "^5.0.0", "file-manager": "^2.0.0", "kvparser": "^1.0.1", "lzma": "^2.3.2", "protobufjs": "^7.2.4", "socks-proxy-agent": "^7.0.0", "steam-appticket": "^1.0.1", "steam-session": "^1.8.0", "steam-totp": "^2.0.1", "steamid": "^2.0.0", "websocket13": "^4.0.0", "zstddec": "^0.1.0" } }, "sha512-6Yzaa0l7fcSRaaJzHjfuqettYqAsrW3+1AEu/cj4M/lgRYXa0DfOAjuWj0/wesfkogwuXNE4N/ZMZvNir8TVtw=="],
"steamid": ["[email protected]", "", {}, "sha512-ndt1cvuuSC+i8fcxVsmeyRlgGsR1QsoAuIXz+eabj8/Y4GIWE2+mgHA7Hys61JDHOxttfWtXHtN2m5TNYTlORg=="],
"stop-iteration-iterator": ["[email protected]", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], "stop-iteration-iterator": ["[email protected]", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
"streamx": ["[email protected]", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg=="], "streamx": ["[email protected]", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg=="],
@@ -2246,6 +2297,8 @@
"tiny-inflate": ["[email protected]", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], "tiny-inflate": ["[email protected]", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="],
"tiny-typed-emitter": ["[email protected]", "", {}, "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA=="],
"tinyexec": ["[email protected]", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], "tinyexec": ["[email protected]", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="],
"tinyglobby": ["[email protected]", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "tinyglobby": ["[email protected]", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
@@ -2438,6 +2491,10 @@
"webidl-conversions": ["[email protected]", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], "webidl-conversions": ["[email protected]", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="],
"websocket-extensions": ["[email protected]", "", {}, "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="],
"websocket13": ["[email protected]", "", { "dependencies": { "@doctormckay/stdlib": "^2.7.1", "bytebuffer": "^5.0.1", "permessage-deflate": "^0.1.7", "tiny-typed-emitter": "^2.1.0", "websocket-extensions": "^0.1.4" } }, "sha512-7+hxkUVTKQlUDTzN2rJI7fJRBXCT6dvRXr1aZflxUZlpNJutHBkKiEIbZOCGs0A1s7vxAmcAXngsNUQMSUTiVQ=="],
"whatwg-encoding": ["[email protected]", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="], "whatwg-encoding": ["[email protected]", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="],
"whatwg-mimetype": ["[email protected]", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="], "whatwg-mimetype": ["[email protected]", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
@@ -2532,6 +2589,8 @@
"zod-to-ts": ["[email protected]", "", { "peerDependencies": { "typescript": "^4.9.4 || ^5.0.2", "zod": "^3" } }, "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA=="], "zod-to-ts": ["[email protected]", "", { "peerDependencies": { "typescript": "^4.9.4 || ^5.0.2", "zod": "^3" } }, "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA=="],
"zstddec": ["[email protected]", "", {}, "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg=="],
"zustand": ["[email protected]", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw=="], "zustand": ["[email protected]", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw=="],
"zwitch": ["[email protected]", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], "zwitch": ["[email protected]", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
@@ -2556,6 +2615,8 @@
"@blitzkit/scripts/@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="], "@blitzkit/scripts/@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="],
"@blitzkit/scripts/fast-xml-parser": ["[email protected]", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="],
"@blitzkit/website/vite": ["[email protected]", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg=="], "@blitzkit/website/vite": ["[email protected]", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg=="],
"@discordjs/rest/@discordjs/collection": ["@discordjs/[email protected]", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], "@discordjs/rest/@discordjs/collection": ["@discordjs/[email protected]", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
@@ -2594,8 +2655,12 @@
"babel-plugin-polyfill-corejs2/semver": ["[email protected]", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "babel-plugin-polyfill-corejs2/semver": ["[email protected]", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"binarykvparser/long": ["[email protected]", "", { "bundled": true }, "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg=="],
"boxen/string-width": ["[email protected]", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], "boxen/string-width": ["[email protected]", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
"bytebuffer/long": ["[email protected]", "", {}, "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg=="],
"c12/dotenv": ["[email protected]", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], "c12/dotenv": ["[email protected]", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
"cheerio/undici": ["[email protected]", "", {}, "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g=="], "cheerio/undici": ["[email protected]", "", {}, "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g=="],
@@ -2612,6 +2677,8 @@
"favilib/sharp": ["[email protected]", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], "favilib/sharp": ["[email protected]", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
"file-manager/@doctormckay/stdlib": ["@doctormckay/[email protected]", "", {}, "sha512-XhuUOzElz6fnNdt70IYNKqhPAEpGaL4JHOhAvklRh0hAhVPW+/wLxaWT3DWUbaG5Dta5YvIp7+cZK3GhIpAuug=="],
"filelist/minimatch": ["[email protected]", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], "filelist/minimatch": ["[email protected]", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
"get-uri/data-uri-to-buffer": ["[email protected]", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="], "get-uri/data-uri-to-buffer": ["[email protected]", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="],
@@ -2622,6 +2689,10 @@
"http-errors/statuses": ["[email protected]", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], "http-errors/statuses": ["[email protected]", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],
"http-proxy-agent/agent-base": ["[email protected]", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
"https-proxy-agent/agent-base": ["[email protected]", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
"its-fine/@types/react-reconciler": ["@types/[email protected]", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="], "its-fine/@types/react-reconciler": ["@types/[email protected]", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="],
"linebreak/base64-js": ["[email protected]", "", {}, "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="], "linebreak/base64-js": ["[email protected]", "", {}, "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw=="],
@@ -2630,12 +2701,20 @@
"micromatch/picomatch": ["[email protected]", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "micromatch/picomatch": ["[email protected]", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"pac-proxy-agent/agent-base": ["[email protected]", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
"pac-proxy-agent/socks-proxy-agent": ["[email protected]", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
"parse5/entities": ["[email protected]", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "parse5/entities": ["[email protected]", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
"prompts/kleur": ["[email protected]", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], "prompts/kleur": ["[email protected]", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
"proxy-agent/agent-base": ["[email protected]", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
"proxy-agent/lru-cache": ["[email protected]", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], "proxy-agent/lru-cache": ["[email protected]", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
"proxy-agent/socks-proxy-agent": ["[email protected]", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
"react-dom/scheduler": ["[email protected]", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], "react-dom/scheduler": ["[email protected]", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
"react-promise-suspense/fast-deep-equal": ["[email protected]", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="], "react-promise-suspense/fast-deep-equal": ["[email protected]", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="],
@@ -2650,6 +2729,12 @@
"stats-gl/three": ["[email protected]", "", {}, "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="], "stats-gl/three": ["[email protected]", "", {}, "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="],
"steam-appticket/@doctormckay/stdlib": ["@doctormckay/[email protected]", "", {}, "sha512-XhuUOzElz6fnNdt70IYNKqhPAEpGaL4JHOhAvklRh0hAhVPW+/wLxaWT3DWUbaG5Dta5YvIp7+cZK3GhIpAuug=="],
"steam-appticket/protobufjs": ["[email protected]", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/long": "^4.0.1", "@types/node": ">=13.7.0", "long": "^4.0.0" }, "bin": { "pbjs": "bin/pbjs", "pbts": "bin/pbts" } }, "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw=="],
"steam-appticket/steamid": ["[email protected]", "", { "dependencies": { "cuint": "^0.2.1" } }, "sha512-t86YjtP1LtPt8D+TaIARm6PtC9tBnF1FhxQeLFs6ohG7vDUfQuy/M8II14rx1TTUkVuYoWHP/7DlvTtoCGULcw=="],
"string_decoder/safe-buffer": ["[email protected]", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], "string_decoder/safe-buffer": ["[email protected]", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
"tar-fs/tar-stream": ["[email protected]", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="], "tar-fs/tar-stream": ["[email protected]", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="],
@@ -2770,6 +2855,10 @@
"filelist/minimatch/brace-expansion": ["[email protected]", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "filelist/minimatch/brace-expansion": ["[email protected]", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
"steam-appticket/protobufjs/@types/long": ["@types/[email protected]", "", {}, "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA=="],
"steam-appticket/protobufjs/long": ["[email protected]", "", {}, "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="],
"widest-line/string-width/emoji-regex": ["[email protected]", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="], "widest-line/string-width/emoji-regex": ["[email protected]", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="],
"widest-line/string-width/strip-ansi": ["[email protected]", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], "widest-line/string-width/strip-ansi": ["[email protected]", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
+5
View File
@@ -0,0 +1,5 @@
# BlitzKit 1.29.4
## Technical Changes
- BlitzKit now partially downloads game files instead of the entire game, allowing for faster updates
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "blitzkit", "name": "blitzkit",
"version": "1.29.3", "version": "1.29.4",
"license": "BlitzKit License", "license": "BlitzKit License",
"private": true, "private": true,
"scripts": { "scripts": {
+3
View File
@@ -13,14 +13,17 @@
"@types/bun": "^1.3.1", "@types/bun": "^1.3.1",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/lz4js": "^0.2.1", "@types/lz4js": "^0.2.1",
"@types/steam-user": "^5.1.0",
"@types/three": "^0.180.0", "@types/three": "^0.180.0",
"adm-zip": "^0.5.16", "adm-zip": "^0.5.16",
"crc": "^4.3.2", "crc": "^4.3.2",
"dotenv": "^17.2.2", "dotenv": "^17.2.2",
"fast-xml-parser": "^5.3.2",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lz4js": "^0.2.0", "lz4js": "^0.2.0",
"pickleparser": "^0.2.1", "pickleparser": "^0.2.1",
"protobufjs": "^7.5.4", "protobufjs": "^7.5.4",
"steam-user": "^5.2.3",
"three": "^0.180.0", "three": "^0.180.0",
"ts-proto": "^2.7.7", "ts-proto": "^2.7.7",
"yaml": "^2.8.1" "yaml": "^2.8.1"
+25
View File
@@ -0,0 +1,25 @@
export enum BlitzVFSSourceType {
Steam,
}
type BlitzVFSSource = {
type: BlitzVFSSourceType;
username: string;
password: string;
app: number;
os: "windows";
};
export class BlitzVFS {
constructor(private source: BlitzVFSSource) {}
async init() {
return this;
}
async file(path: string) {
return new Uint8Array();
}
}
+33 -32
View File
@@ -1,32 +1,33 @@
export * from './canSplash'; export * from "./canSplash";
export * from './clans'; export * from "./clans";
export * from './classes'; export * from "./classes";
export * from './constants'; export * from "./constants";
export * from './equipmentPrice'; export * from "./equipmentPrice";
export * from './fetchBlitz'; export * from "./fetchBlitz";
export * from './fetchGlossary'; export * from "./fetchGlossary";
export * from './generateStats'; export * from "./generateStats";
export * from './getAccountAchievements'; export * from "./getAccountAchievements";
export * from './getAccountInfo'; export * from "./getAccountInfo";
export * from './getClanAccountInfo'; export * from "./getClanAccountInfo";
export * from './getClanInfo'; export * from "./getClanInfo";
export * from './getLeagueFromScore'; export * from "./getLeagueFromScore";
export * from './getRatingInfo'; export * from "./getRatingInfo";
export * from './getRatingLeague'; export * from "./getRatingLeague";
export * from './getRatingNeighbors'; export * from "./getRatingNeighbors";
export * from './getTankStats'; export * from "./getTankStats";
export * from './idToRegion'; export * from "./idToRegion";
export * from './isOnGoingRatingSeason'; export * from "./isOnGoingRatingSeason";
export * from './isValidBlitzId'; export * from "./isValidBlitzId";
export * from './nations'; export * from "./nations";
export * from './normalizeExtra'; export * from "./normalizeExtra";
export * from './normalizeIds'; export * from "./normalizeIds";
export * from './permanentSkills'; export * from "./permanentSkills";
export * from './rating'; export * from "./rating";
export * from './regions'; export * from "./readDVPL";
export * from './regionSubdomainToRegion'; export * from "./regions";
export * from './regionToRegionSubdomain'; export * from "./regionSubdomainToRegion";
export * from './searchClansAcrossRegions'; export * from "./regionToRegionSubdomain";
export * from './searchCurrentRatingPlayers'; export * from "./searchClansAcrossRegions";
export * from './searchPlayersAcrossRegions'; export * from "./searchCurrentRatingPlayers";
export * from './toUniqueId'; export * from "./searchPlayersAcrossRegions";
export * from "./toUniqueId";
@@ -1,5 +1,5 @@
import { crc32 } from 'crc'; import { crc32 } from "crc";
import { decompressBlock } from 'lz4js'; import { decompressBlock } from "lz4js";
/** /**
* Thanks Maddoxkkm! Modified heavily to be modern. * Thanks Maddoxkkm! Modified heavily to be modern.
@@ -9,10 +9,10 @@ export function readDVPL(buffer: Buffer) {
const footerBuffer = buffer.subarray(buffer.length - 20, buffer.length); const footerBuffer = buffer.subarray(buffer.length - 20, buffer.length);
if ( if (
footerBuffer.toString('utf8', 16, 20) !== 'DVPL' || footerBuffer.toString("utf8", 16, 20) !== "DVPL" ||
footerBuffer.length !== 20 footerBuffer.length !== 20
) { ) {
throw new SyntaxError('Invalid DVPL footer'); throw new SyntaxError("Invalid DVPL footer");
} }
const footerData = { const footerData = {
@@ -24,15 +24,15 @@ export function readDVPL(buffer: Buffer) {
const targetBlock = buffer.subarray(0, buffer.length - 20); const targetBlock = buffer.subarray(0, buffer.length - 20);
if (targetBlock.length !== footerData.cSize) { if (targetBlock.length !== footerData.cSize) {
throw new RangeError('DVPL size mismatch'); throw new RangeError("DVPL size mismatch");
} }
if (crc32(targetBlock) !== footerData.crc32) { if (crc32(targetBlock) !== footerData.crc32) {
throw new TypeError('DVPL CRC32 mismatch'); throw new TypeError("DVPL CRC32 mismatch");
} }
if (footerData.type === 0) { if (footerData.type === 0) {
if (!(footerData.oSize === footerData.cSize && footerData.type === 0)) { if (!(footerData.oSize === footerData.cSize && footerData.type === 0)) {
throw new RangeError('DVPL type and size mismatch'); throw new RangeError("DVPL type and size mismatch");
} }
return targetBlock; return targetBlock;
@@ -44,17 +44,17 @@ export function readDVPL(buffer: Buffer) {
destination, destination,
0, 0,
source.length, source.length,
0, 0
); );
if (decompressedSize !== footerData.oSize) { if (decompressedSize !== footerData.oSize) {
throw new RangeError( throw new RangeError(
`Decompressed DVPL size mismatch (${decompressedSize} vs ${footerData.oSize})`, `Decompressed DVPL size mismatch (${decompressedSize} vs ${footerData.oSize})`
); );
} }
return Buffer.from(destination); return Buffer.from(destination);
} else { } else {
throw new SyntaxError('Unknown DVPL format'); throw new SyntaxError("Unknown DVPL format");
} }
} }
+11 -10
View File
@@ -1,10 +1,11 @@
export * from './blitz'; export * from "./blitz";
export * from './blitzkit'; export * from "./blitzkit";
export * from './imgur'; export * from "./imgur";
export * from './math'; export * from "./math";
export * from './patreon'; export * from "./patreon";
export * from './protobuf'; export * from "./protobuf";
export * from './protos'; export * from "./protos";
export * from './statistics'; export * from "./statistics";
export * from './streams'; export * from "./steam";
export * from './types'; export * from "./streams";
export * from "./types";
+1
View File
@@ -0,0 +1 @@
export * from "./vfs";
+155
View File
@@ -0,0 +1,155 @@
import { XMLParser } from "fast-xml-parser";
import { normalize } from "path/posix";
import SteamUser, { EConnectionProtocol } from "steam-user";
import { parse } from "yaml";
import { readDVPL } from "../blitz";
interface SteamManifestFile {
chunks: {
sha: string;
crc: number;
offset: string;
cb_original: number;
cb_compressed: number;
}[];
filename: string;
size: string;
flags: number;
sha_filename: string;
sha_content: string;
linktarget: unknown;
}
interface SteamManifest {
files: SteamManifestFile[];
depot_id: number;
gid_manifest: string;
creation_time: number;
filenames_encrypted: boolean;
cb_disk_original: string;
cb_disk_compressed: string;
unique_chunks: number;
crc_encrypted: number;
crc_clear: number;
}
export class SteamVFS {
private steam = new SteamUser({ protocol: EConnectionProtocol.TCP });
private textDecoder = new TextDecoder();
private xmlParser = new XMLParser();
private manifest: Map<string, SteamManifestFile> = new Map();
constructor(
private username: string,
private password: string,
private app: number,
private depot: number
) {}
async init() {
this.steam.logOn({
accountName: this.username,
password: this.password,
});
await new Promise((resolve) => this.steam.once("loggedOn", resolve));
const productInfo = await this.steam.getProductInfo([this.app], []);
const manifest: SteamManifest = await new Promise((resolve) => {
// @ts-expect-error
this.steam.getManifest(
this.app,
this.depot,
productInfo.apps[this.app].appinfo.depots[this.depot].manifests.public
.gid,
"public",
// @ts-expect-error
(_, response) => {
resolve(response);
}
);
});
const paths: string[] = [];
for (const file of manifest.files) {
const path = file.filename.replaceAll("\\", "/");
paths.push(path);
this.manifest.set(path, file);
}
return this;
}
has(path: string) {
const normalized = normalize(path);
const dvplPath = `${normalized}.dvpl`;
return (
(this.manifest.has(dvplPath) && dvplPath) ||
(this.manifest.has(normalized) && normalized)
);
}
assert(requested: string) {
const path = this.has(requested);
if (!path) throw new Error(`File not found: ${requested}`);
return path;
}
dir(path: string) {
const parentSegments = path.split("/").length;
const children: string[] = [];
for (const child of this.manifest.keys()) {
const childSegments = child.split("/");
if (
child.startsWith(path) &&
parentSegments + 1 === childSegments.length
) {
children.push(childSegments.at(-1)!);
}
}
return children;
}
async file(requested: string) {
const path = this.assert(requested);
const fileManifest = this.manifest.get(path)!;
const downloaded: { type: "complete"; file: Buffer } =
// @ts-expect-error
await this.steam.downloadFile(this.app, this.depot, fileManifest);
let buffer = downloaded.file;
if (path.endsWith(".dvpl")) buffer = readDVPL(downloaded.file);
return new Uint8Array(buffer);
}
async text(path: string) {
const file = await this.file(path);
return this.textDecoder.decode(file);
}
async yaml<Type>(path: string) {
const file = await this.text(path);
return parse(file) as Type;
}
async xml<Type>(path: string) {
const file = await this.text(path);
return this.xmlParser.parse(file) as Type;
}
dispose() {
this.steam.logOff();
}
[Symbol.dispose]() {
this.dispose();
}
}
+7 -9
View File
@@ -4,12 +4,10 @@ import { mkdir, writeFile } from "fs/promises";
import { parse as parsePath } from "path"; import { parse as parsePath } from "path";
import ProgressBar from "progress"; import ProgressBar from "progress";
import { parse as parseYaml, stringify as stringifyYaml } from "yaml"; import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
import { readStringDVPL } from "../src/core/blitz/readStringDVPL"; import { vfs } from "./buildAssets/constants";
import { DATA } from "./buildAssets/constants";
import { readYAMLDVPL } from "./core/blitz/readYAMLDVPL";
import { writeDVPL } from "./core/blitz/writeDVPL"; import { writeDVPL } from "./core/blitz/writeDVPL";
const versionTextFile = await readStringDVPL(`${DATA}/version.txt`); const versionTextFile = await vfs.text(`Data/version.txt`);
const currentVersion = versionTextFile const currentVersion = versionTextFile
.split(" ")[0] .split(" ")[0]
.split(".") .split(".")
@@ -51,7 +49,7 @@ while (true) {
const { dir } = parsePath(path); const { dir } = parsePath(path);
try { try {
await mkdir(`${DATA}/${dir}`, { recursive: true }); await mkdir(`Data/${dir}`, { recursive: true });
} catch (error) { } catch (error) {
console.warn(`Failed to make directory "${dir}"`); console.warn(`Failed to make directory "${dir}"`);
} }
@@ -60,7 +58,7 @@ while (true) {
const buffer = Buffer.from(data); const buffer = Buffer.from(data);
await writeFile( await writeFile(
`${DATA}/${path}${isDvpl ? "" : ".dvpl"}`, `Data/${path}${isDvpl ? "" : ".dvpl"}`,
new Uint8Array(isDvpl ? buffer : writeDVPL(buffer)) new Uint8Array(isDvpl ? buffer : writeDVPL(buffer))
); );
@@ -76,14 +74,14 @@ while (true) {
}/en.yaml` }/en.yaml`
); );
const newStrings = parseYaml(await localizationsResponse.text()); const newStrings = parseYaml(await localizationsResponse.text());
const oldStrings = await readYAMLDVPL<Record<string, string>>( const oldStrings = await vfs.yaml<Record<string, string>>(
`${DATA}/Strings/en.yaml` `Data/Strings/en.yaml`
); );
const patchedStrings = { ...oldStrings, ...newStrings }; const patchedStrings = { ...oldStrings, ...newStrings };
const patchedContent = stringifyYaml(patchedStrings); const patchedContent = stringifyYaml(patchedStrings);
await writeFile( await writeFile(
`${DATA}/Strings/en.yaml`, `Data/Strings/en.yaml`,
new Uint8Array(writeDVPL(Buffer.from(patchedContent))) new Uint8Array(writeDVPL(Buffer.from(patchedContent)))
); );
} }
@@ -1,19 +1,16 @@
import { readdir } from "fs/promises";
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { readStringDVPL } from "../../src/core/blitz/readStringDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
export async function boosterIcons() { export async function boosterIcons() {
console.log("Building booster icons..."); console.log("Building booster icons...");
using uploader = new AssetUploader("booster icons"); using uploader = new AssetUploader("booster icons");
const boosterFiles = (await readdir(`${DATA}/Gfx/Shared/boosters`)).filter( const boosterFiles = (vfs.dir(`Data/Gfx/Shared/boosters`)).filter(
(file) => !file.includes("@2x.txt") && !file.startsWith("texture0") (file) => !file.includes("@2x.txt") && !file.startsWith("texture0")
); );
const image = sharp( const image = sharp(
await readDVPLFile(`${DATA}/Gfx/Shared/boosters/texture0.packed.webp`) await vfs.file(`Data/Gfx/Shared/boosters/texture0.packed.webp`)
); );
for (const file of boosterFiles) { for (const file of boosterFiles) {
@@ -21,7 +18,7 @@ export async function boosterIcons() {
if (name === undefined) continue; if (name === undefined) continue;
const sizes = (await readStringDVPL(`${DATA}/Gfx/Shared/boosters/${file}`)) const sizes = (await vfs.text(`Data/Gfx/Shared/boosters/${file}`))
.split("\n")[4] .split("\n")[4]
.split(" ") .split(" ")
.map(Number); .map(Number);
@@ -1,13 +1,12 @@
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
export async function camouflageIcons() { export async function camouflageIcons() {
console.log("Building camouflage icons..."); console.log("Building camouflage icons...");
using uploader = new AssetUploader("camo icons"); using uploader = new AssetUploader("camo icons");
const content = await readDVPLFile( const content = await vfs.file(
`${DATA}/Gfx/UI/Hangar/IconCamouflage.packed.webp` `Data/Gfx/UI/Hangar/IconCamouflage.packed.webp`
); );
await uploader.add({ content, path: "icons/camo.webp" }); await uploader.add({ content, path: "icons/camo.webp" });
+9 -30
View File
@@ -1,32 +1,11 @@
import { readdir } from "fs/promises"; import { assertSecret, SteamVFS } from "@blitzkit/core";
import { argv } from "process";
const WINDOWS_APPS = "C:/Program Files/WindowsApps"; const APP = 444200;
const wotbPackageRegex = /7458BE2C\..+_\d+(\.\d+)+_x64__.+/; const DEPOT = 444202;
const isManual = argv.includes("--manual"); export const vfs = await new SteamVFS(
assertSecret(import.meta.env.STEAM_USERNAME),
let data: string; assertSecret(import.meta.env.STEAM_PASSWORD),
let compressed: boolean; APP,
DEPOT
if (isManual) { ).init();
data = "../../temp/game/Data";
compressed = true;
} else {
const directories = await readdir(WINDOWS_APPS).then((files) =>
files.filter((file) => wotbPackageRegex.test(file))
);
if (directories.length !== 1) {
throw new Error(
`Expected 1 directory for WoTB Windows App, got ${directories.length}.`
);
}
const [windowsApp] = directories;
data = `${WINDOWS_APPS}/${windowsApp}/Data`;
compressed = false;
}
export const DATA = data;
export const DATA_COMPRESSED = compressed;
@@ -1,11 +1,6 @@
import { existsSync } from "fs";
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { readStringDVPL } from "../../src/core/blitz/readStringDVPL";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
import { ConsumablesCommon, ProvisionsCommon } from "./definitions"; import { ConsumablesCommon, ProvisionsCommon } from "./definitions";
interface Mappings { interface Mappings {
@@ -33,20 +28,20 @@ export async function consumableProvisionIcons() {
styles.map(async (path) => styles.map(async (path) =>
Object.values( Object.values(
( (
await readYAMLDVPL<Mappings>(`${DATA}/${path}`) await vfs.yaml<Mappings>(`Data/${path}`)
).StyleSheets ).StyleSheets
) )
) )
).then((array) => array.flat()); ).then((array) => array.flat());
for (const match of ( for (const match of (
await readStringDVPL( await vfs.text(
`${DATA}/XML/item_defs/vehicles/common/consumables/list.xml` `Data/XML/item_defs/vehicles/common/consumables/list.xml`
) )
).matchAll(listItemsPattern)) { ).matchAll(listItemsPattern)) {
const consumablesCommon = await readXMLDVPL<{ const consumablesCommon = await vfs.xml<{
root: ConsumablesCommon; root: ConsumablesCommon;
}>(`${DATA}/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`); }>(`Data/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`);
for (const consumable of Object.values(consumablesCommon.root)) { for (const consumable of Object.values(consumablesCommon.root)) {
const styleSheet = styleSheets.find((styleSheet) => const styleSheet = styleSheets.find((styleSheet) =>
@@ -67,9 +62,9 @@ export async function consumableProvisionIcons() {
.replace(".psd", "") .replace(".psd", "")
.replace(".txt", ""); .replace(".txt", "");
if (existsSync(`${DATA}/${configPath}.packed.webp`)) { if (vfs.has(`Data/${configPath}.packed.webp`)) {
const image = sharp( const image = sharp(
await readDVPLFile(`${DATA}/${configPath}.packed.webp`) await vfs.file(`Data/${configPath}.packed.webp`)
); );
const content = await image.trim({ threshold: 100 }).toBuffer(); const content = await image.trim({ threshold: 100 }).toBuffer();
@@ -79,14 +74,14 @@ export async function consumableProvisionIcons() {
}); });
} else { } else {
const consumablesTexture = sharp( const consumablesTexture = sharp(
await readDVPLFile( await vfs.file(
`${`${DATA}/${configPath}` `${`Data/${configPath}`
.split("/") .split("/")
.slice(0, -1) .slice(0, -1)
.join("/")}/texture0.packed.webp` .join("/")}/texture0.packed.webp`
) )
); );
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt`)) const sizes = (await vfs.text(`Data/${configPath}.txt`))
.split("\n")[4] .split("\n")[4]
.split(" ") .split(" ")
.map(Number); .map(Number);
@@ -109,13 +104,13 @@ export async function consumableProvisionIcons() {
} }
for (const match of ( for (const match of (
await readStringDVPL( await vfs.text(
`${DATA}/XML/item_defs/vehicles/common/provisions/list.xml` `Data/XML/item_defs/vehicles/common/provisions/list.xml`
) )
).matchAll(listItemsPattern)) { ).matchAll(listItemsPattern)) {
const provisionsCommon = await readXMLDVPL<{ const provisionsCommon = await vfs.xml<{
root: ProvisionsCommon; root: ProvisionsCommon;
}>(`${DATA}/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`); }>(`Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`);
for (const provision of Object.values(provisionsCommon.root)) { for (const provision of Object.values(provisionsCommon.root)) {
const styleSheet = styleSheets.find((styleSheet) => const styleSheet = styleSheets.find((styleSheet) =>
@@ -136,9 +131,9 @@ export async function consumableProvisionIcons() {
.replace(".psd", "") .replace(".psd", "")
.replace(".txt", ""); .replace(".txt", "");
if (existsSync(`${DATA}/${configPath}.packed.webp`)) { if (vfs.has(`Data/${configPath}.packed.webp`)) {
const image = sharp( const image = sharp(
await readDVPLFile(`${DATA}/${configPath}.packed.webp`) await vfs.file(`Data/${configPath}.packed.webp`)
); );
const content = await image.trim({ threshold: 100 }).toBuffer(); const content = await image.trim({ threshold: 100 }).toBuffer();
@@ -148,14 +143,14 @@ export async function consumableProvisionIcons() {
}); });
} else { } else {
const provisionsTexture = sharp( const provisionsTexture = sharp(
await readDVPLFile( await vfs.file(
`${`${DATA}/${configPath}` `${`Data/${configPath}`
.split("/") .split("/")
.slice(0, -1) .slice(0, -1)
.join("/")}/texture0.packed.webp` .join("/")}/texture0.packed.webp`
) )
); );
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt`)) const sizes = (await vfs.text(`Data/${configPath}.txt`))
.split("\n")[4] .split("\n")[4]
.split(" ") .split(" ")
.map(Number); .map(Number);
@@ -1,8 +1,7 @@
import { assertSecret, BlitzGlossary } from "@blitzkit/core"; import { assertSecret, BlitzGlossary } from "@blitzkit/core";
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
const ICONS = [ const ICONS = [
["currency_silver_m.packed.webp", "silver"], ["currency_silver_m.packed.webp", "silver"],
@@ -21,7 +20,7 @@ export async function currencies() {
for (const [file, name] of ICONS) { for (const [file, name] of ICONS) {
const content = await sharp( const content = await sharp(
await readDVPLFile(`${DATA}/Gfx/Lobby/currency/${file}`) await vfs.file(`Data/Gfx/Lobby/currency/${file}`)
) )
.trim() .trim()
.toBuffer(); .toBuffer();
+49 -55
View File
@@ -32,16 +32,12 @@ import {
} from "@blitzkit/core"; } from "@blitzkit/core";
import { SUPPORTED_LOCALE_BLITZ_MAP } from "@blitzkit/i18n"; import { SUPPORTED_LOCALE_BLITZ_MAP } from "@blitzkit/i18n";
import locales from "@blitzkit/i18n/locales.json"; import locales from "@blitzkit/i18n/locales.json";
import { readdir } from "fs/promises";
import { deburr } from "lodash-es"; import { deburr } from "lodash-es";
import { parse as parsePath } from "path"; import { parse as parsePath } from "path";
import type { Vector3Tuple } from "three"; import type { Vector3Tuple } from "three";
import { parse as parseYaml } from "yaml"; import { parse as parseYaml } from "yaml";
import { readStringDVPL } from "../core/blitz/readStringDVPL";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
import type { Avatar } from "./skillIcons"; import type { Avatar } from "./skillIcons";
import type { TankParameters } from "./tankIcons"; import type { TankParameters } from "./tankIcons";
@@ -540,9 +536,9 @@ export async function definitions() {
using uploader = new AssetUploader("definitions"); using uploader = new AssetUploader("definitions");
const gameDefinitions: GameDefinitions = { const gameDefinitions: GameDefinitions = {
version: (await readStringDVPL(`${DATA}/version.txt`)).split(" ")[0], version: (await vfs.text('Data/version.txt')).split(" ")[0],
nations: ( nations: (
await readYAMLDVPL<AvailableNationsYaml>(`${DATA}/available_nations.yaml`) await vfs.yaml<AvailableNationsYaml>('Data/available_nations.yaml')
).available_nations, ).available_nations,
gameModes: {}, gameModes: {},
roles: {}, roles: {},
@@ -565,12 +561,10 @@ export async function definitions() {
[TankClass.TANK_DESTROYER]: { skills: [] }, [TankClass.TANK_DESTROYER]: { skills: [] },
}, },
}; };
const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( const nations = vfs.dir('Data/XML/item_defs/vehicles').filter((nation) => nation !== "common")
(nations) => nations.filter((nation) => nation !== "common")
);
const tankStringIdMap: Record<string, number> = {}; const tankStringIdMap: Record<string, number> = {};
const optionalDevices = await readXMLDVPL<{ root: OptionalDevices }>( const optionalDevices = await vfs.xml<{ root: OptionalDevices }>(
`${DATA}/XML/item_defs/vehicles/common/optional_devices.xml` 'Data/XML/item_defs/vehicles/common/optional_devices.xml'
); );
const stringsI18n: Record<string, Record<string, string>> = {}; const stringsI18n: Record<string, Record<string, string>> = {};
@@ -582,8 +576,8 @@ export async function definitions() {
) )
.then((response) => response.text()) .then((response) => response.text())
.then((string) => parseYaml(string) as BlitzStrings); .then((string) => parseYaml(string) as BlitzStrings);
const preInstalled = await readYAMLDVPL<BlitzStrings>( const preInstalled = await vfs.yaml<BlitzStrings>(
`${DATA}/Strings/${blitzLocale}.yaml` `Data/Strings/${blitzLocale}.yaml`
); );
stringsI18n[locale] = { stringsI18n[locale] = {
@@ -616,15 +610,15 @@ export async function definitions() {
return { locales: collection } satisfies I18nString; return { locales: collection } satisfies I18nString;
} }
const optionalDeviceSlots = await readXMLDVPL<{ const optionalDeviceSlots = await vfs.xml<{
root: OptionalDeviceSlots; root: OptionalDeviceSlots;
}>(`${DATA}/XML/item_defs/vehicles/common/optional_device_slots.xml`); }>(`Data/XML/item_defs/vehicles/common/optional_device_slots.xml`);
const consumables: ConsumablesCommon = {}; const consumables: ConsumablesCommon = {};
const provisions: ProvisionsCommon = {}; const provisions: ProvisionsCommon = {};
for (const match of ( for (const match of (
await readStringDVPL( await vfs.text(
`${DATA}/XML/item_defs/vehicles/common/consumables/list.xml` `Data/XML/item_defs/vehicles/common/consumables/list.xml`
) )
).matchAll(/<items path="(.+)\.xml"\/>/g)) { ).matchAll(/<items path="(.+)\.xml"\/>/g)) {
if (match[1] === "prototypes") continue; if (match[1] === "prototypes") continue;
@@ -632,16 +626,16 @@ export async function definitions() {
Object.assign( Object.assign(
consumables, consumables,
( (
await readXMLDVPL<{ root: ConsumablesCommon }>( await vfs.xml<{ root: ConsumablesCommon }>(
`${DATA}/XML/item_defs/vehicles/common/consumables/${match[1]}.xml` `Data/XML/item_defs/vehicles/common/consumables/${match[1]}.xml`
) )
).root ).root
); );
} }
for (const match of ( for (const match of (
await readStringDVPL( await vfs.text(
`${DATA}/XML/item_defs/vehicles/common/provisions/list.xml` `Data/XML/item_defs/vehicles/common/provisions/list.xml`
) )
).matchAll(/<items path="(.+)\.xml"\/>/g)) { ).matchAll(/<items path="(.+)\.xml"\/>/g)) {
if (match[1] === "prototypes") continue; if (match[1] === "prototypes") continue;
@@ -649,34 +643,34 @@ export async function definitions() {
Object.assign( Object.assign(
provisions, provisions,
( (
await readXMLDVPL<{ root: ConsumablesCommon }>( await vfs.xml<{ root: ConsumablesCommon }>(
`${DATA}/XML/item_defs/vehicles/common/provisions/${match[1]}.xml` `Data/XML/item_defs/vehicles/common/provisions/${match[1]}.xml`
) )
).root ).root
); );
} }
const avatar = await readXMLDVPL<{ root: Avatar }>( const avatar = await vfs.xml<{ root: Avatar }>(
`${DATA}/XML/item_defs/tankmen/avatar.xml` `Data/XML/item_defs/tankmen/avatar.xml`
); );
const maps = await readYAMLDVPL<Maps>(`${DATA}/maps.yaml`); const maps = await vfs.yaml<Maps>(`Data/maps.yaml`);
const tankXps = new Map<number, ResearchCost>(); const tankXps = new Map<number, ResearchCost>();
const camouflagesXml = await readXMLDVPL<{ root: CamouflagesXML }>( const camouflagesXml = await vfs.xml<{ root: CamouflagesXML }>(
`${DATA}/XML/item_defs/vehicles/common/camouflages.xml` `Data/XML/item_defs/vehicles/common/camouflages.xml`
); );
const camouflagesYaml = await readYAMLDVPL<CamouflagesYaml>( const camouflagesYaml = await vfs.yaml<CamouflagesYaml>(
`${DATA}/camouflages.yaml` `Data/camouflages.yaml`
); );
const camouflagesXmlEntries = Object.entries(camouflagesXml.root.camouflages); const camouflagesXmlEntries = Object.entries(camouflagesXml.root.camouflages);
const squadBattleTypeStyles = await readYAMLDVPL<SquadBattleTypeStyles>( const squadBattleTypeStyles = await vfs.yaml<SquadBattleTypeStyles>(
`${DATA}/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml` `Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`
); );
const gameTypeSelectorStyles = await readYAMLDVPL<SquadBattleTypeStyles>( const gameTypeSelectorStyles = await vfs.yaml<SquadBattleTypeStyles>(
`${DATA}/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml` `Data/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml`
); );
const gameModeNativeNames: Record<string, number> = {}; const gameModeNativeNames: Record<string, number> = {};
const combatRoles = await readYAMLDVPL<CombatRolesYaml>( const combatRoles = await vfs.yaml<CombatRolesYaml>(
`${DATA}/XML/item_defs/vehicles/common/combat_roles.yaml` `Data/XML/item_defs/vehicles/common/combat_roles.yaml`
); );
const consumableNativeNames: Record<string, number> = {}; const consumableNativeNames: Record<string, number> = {};
const provisionNativeNames: Record<string, number> = {}; const provisionNativeNames: Record<string, number> = {};
@@ -727,8 +721,8 @@ export async function definitions() {
const idToNation: Record<number, string> = {}; const idToNation: Record<number, string> = {};
for (const nation of nations) { for (const nation of nations) {
const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>( const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml` `Data/XML/item_defs/vehicles/${nation}/list.xml`
); );
for (const tankKey in tankList.root) { for (const tankKey in tankList.root) {
@@ -811,24 +805,24 @@ export async function definitions() {
}); });
for (const nation of nations) { for (const nation of nations) {
const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>( const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml` `Data/XML/item_defs/vehicles/${nation}/list.xml`
); );
const turretList = await readXMLDVPL<{ const turretList = await vfs.xml<{
root: TurretDefinitionsList; root: TurretDefinitionsList;
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/turrets.xml`); }>(`Data/XML/item_defs/vehicles/${nation}/components/turrets.xml`);
const gunList = await readXMLDVPL<{ const gunList = await vfs.xml<{
root: GunDefinitionsList; root: GunDefinitionsList;
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/guns.xml`); }>(`Data/XML/item_defs/vehicles/${nation}/components/guns.xml`);
const shellList = await readXMLDVPL<{ const shellList = await vfs.xml<{
root: ShellDefinitionsList; root: ShellDefinitionsList;
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/shells.xml`); }>(`Data/XML/item_defs/vehicles/${nation}/components/shells.xml`);
const enginesList = await readXMLDVPL<{ const enginesList = await vfs.xml<{
root: EngineDefinitionsList; root: EngineDefinitionsList;
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/engines.xml`); }>(`Data/XML/item_defs/vehicles/${nation}/components/engines.xml`);
const chassisList = await readXMLDVPL<{ const chassisList = await vfs.xml<{
root: ChassisDefinitionsList; root: ChassisDefinitionsList;
}>(`${DATA}/XML/item_defs/vehicles/${nation}/components/chassis.xml`); }>(`Data/XML/item_defs/vehicles/${nation}/components/chassis.xml`);
function resolveUnlocks(unlocks?: BlitzModuleType) { function resolveUnlocks(unlocks?: BlitzModuleType) {
if (!unlocks) return []; if (!unlocks) return [];
@@ -879,11 +873,11 @@ export async function definitions() {
const trackXps = new Map<number, ResearchCost>(); const trackXps = new Map<number, ResearchCost>();
const tank = tankList.root[tankKey]; const tank = tankList.root[tankKey];
let tankPrice: TankPrice; let tankPrice: TankPrice;
const tankDefinition = await readXMLDVPL<{ root: VehicleDefinitions }>( const tankDefinition = await vfs.xml<{ root: VehicleDefinitions }>(
`${DATA}/XML/item_defs/vehicles/${nation}/${tankKey}.xml` `Data/XML/item_defs/vehicles/${nation}/${tankKey}.xml`
); );
const tankParameters = await readYAMLDVPL<TankParameters>( const tankParameters = await vfs.yaml<TankParameters>(
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` `Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`
); );
const turretOrigin = tankDefinition.root.hull.turretPositions.turret const turretOrigin = tankDefinition.root.hull.turretPositions.turret
.split(" ") .split(" ")
@@ -1,10 +1,6 @@
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { readStringDVPL } from "../../src/core/blitz/readStringDVPL";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
import { OptionalDevices } from "./definitions"; import { OptionalDevices } from "./definitions";
interface Mappings { interface Mappings {
@@ -20,15 +16,15 @@ export async function equipmentIcons() {
console.log("Building equipment icons..."); console.log("Building equipment icons...");
using uploader = new AssetUploader("equipment icons"); using uploader = new AssetUploader("equipment icons");
const optionalDevices = await readXMLDVPL<{ root: OptionalDevices }>( const optionalDevices = await vfs.xml<{ root: OptionalDevices }>(
`${DATA}/XML/item_defs/vehicles/common/optional_devices.xml` `Data/XML/item_defs/vehicles/common/optional_devices.xml`
); );
const mappings = await readYAMLDVPL<Mappings>( const mappings = await vfs.yaml<Mappings>(
`${DATA}/UI/Screens3/Lobby/Inventory/OptionalDevices/OptionalDevicesItemImage.style.yaml` `Data/UI/Screens3/Lobby/Inventory/OptionalDevices/OptionalDevicesItemImage.style.yaml`
); );
const image = sharp( const image = sharp(
await readDVPLFile( await vfs.file(
`${DATA}/Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp` `Data/Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp`
) )
); );
@@ -54,7 +50,7 @@ export async function equipmentIcons() {
if (configPath.startsWith("Gfx/Lobby")) { if (configPath.startsWith("Gfx/Lobby")) {
const configPathWebp = configPath.replace(".txt", ""); const configPathWebp = configPath.replace(".txt", "");
const image = sharp( const image = sharp(
await readDVPLFile(`${DATA}/${configPathWebp}.packed.webp`) await vfs.file(`Data/${configPathWebp}.packed.webp`)
); );
const content = await image.trim().toBuffer(); const content = await image.trim().toBuffer();
@@ -63,7 +59,7 @@ export async function equipmentIcons() {
content, content,
}); });
} else { } else {
const config = await readStringDVPL(`${DATA}/${configPath}`); const config = await vfs.text(`Data/${configPath}`);
const sizes = config.split("\n")[4].split(" ").map(Number); const sizes = config.split("\n")[4].split(" ").map(Number);
const content = await image const content = await image
.clone() .clone()
+8 -17
View File
@@ -1,37 +1,28 @@
import { readdir } from "fs/promises";
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../core/blitz/readDVPLFile";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
export async function flags() { export async function flags() {
console.log("Building flags..."); console.log("Building flags...");
using uploader = new AssetUploader("flags"); using uploader = new AssetUploader("flags");
const circleFiles = await readdir(`${DATA}/Gfx/Lobby/flags`).then((files) => const circleFiles = vfs.dir(`Data/Gfx/Lobby/flags`).filter(
files.filter(
(flag) => (flag) =>
flag.startsWith("flag_profile-stat_") && flag.startsWith("flag_profile-stat_") &&
!flag.endsWith("@2x.packed.webp") !flag.endsWith("@2x.packed.webp")
) );
); const scratchedFiles = vfs.dir(`Data/Gfx/Lobby/flags`).filter(
const scratchedFiles = await readdir(`${DATA}/Gfx/Lobby/flags`).then(
(files) =>
files.filter(
(flag) => (flag) =>
flag.startsWith("flag_tutor-tank_") && flag.startsWith("flag_tutor-tank_") &&
!flag.endsWith("@2x.packed.webp") !flag.endsWith("@2x.packed.webp")
) )
); const fadedFiles = vfs.dir(`Data/Gfx/Lobby/flags`).filter(
const fadedFiles = await readdir(`${DATA}/Gfx/Lobby/flags`).then((files) =>
files.filter(
(flag) => (flag) =>
flag.startsWith("flag_filter_") && flag.endsWith("@2x.packed.webp") flag.startsWith("flag_filter_") && flag.endsWith("@2x.packed.webp")
) )
);
for (const flag of circleFiles) { for (const flag of circleFiles) {
const image = sharp(await readDVPLFile(`${DATA}/Gfx/Lobby/flags/${flag}`)); const image = sharp(await vfs.file(`Data/Gfx/Lobby/flags/${flag}`));
const content = await image.trim({ threshold: 100 }).toBuffer(); const content = await image.trim({ threshold: 100 }).toBuffer();
const name = flag.match(/flag_profile-stat_(.+)\.packed\.webp/)![1]; const name = flag.match(/flag_profile-stat_(.+)\.packed\.webp/)![1];
@@ -42,7 +33,7 @@ export async function flags() {
} }
for (const flag of scratchedFiles) { for (const flag of scratchedFiles) {
const content = await readDVPLFile(`${DATA}/Gfx/Lobby/flags/${flag}`); const content = await vfs.file(`Data/Gfx/Lobby/flags/${flag}`);
const name = flag.match(/flag_tutor-tank_(.+)\.packed\.webp/)![1]; const name = flag.match(/flag_tutor-tank_(.+)\.packed\.webp/)![1];
uploader.add({ uploader.add({
@@ -53,7 +44,7 @@ export async function flags() {
for (const flag of fadedFiles) { for (const flag of fadedFiles) {
const content = await sharp( const content = await sharp(
await readDVPLFile(`${DATA}/Gfx/Lobby/flags/${flag}`) await vfs.file(`Data/Gfx/Lobby/flags/${flag}`)
) )
.trim({ .trim({
threshold: 100, threshold: 100,
@@ -1,19 +1,17 @@
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
import { SquadBattleTypeStyles } from "./definitions"; import { SquadBattleTypeStyles } from "./definitions";
export async function gameModeBanners() { export async function gameModeBanners() {
console.log("Building game mode banners..."); console.log("Building game mode banners...");
using uploader = new AssetUploader("game mode banners"); using uploader = new AssetUploader("game mode banners");
const gameTypeSelectorStyles = await readYAMLDVPL<SquadBattleTypeStyles>( const gameTypeSelectorStyles = await vfs.yaml<SquadBattleTypeStyles>(
`${DATA}/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml` `Data/UI/Screens/Lobby/Hangar/GameTypeSelector.yaml`
); );
const squadBattleTypeStyles = await readYAMLDVPL<SquadBattleTypeStyles>( const squadBattleTypeStyles = await vfs.yaml<SquadBattleTypeStyles>(
`${DATA}/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml` `Data/UI/Screens3/Lobby/Hangar/Squad/SquadBattleType.yaml`
); );
const bannerMatches: { name: string; path: string }[] = []; const bannerMatches: { name: string; path: string }[] = [];
@@ -37,7 +35,7 @@ export async function gameModeBanners() {
} }
const content = await sharp( const content = await sharp(
await readDVPLFile(`${DATA}${path}.packed.webp`) await vfs.file(`Data${path}.packed.webp`)
) )
.trim({ background: { r: 0, g: 0, b: 0, alpha: 0 } }) .trim({ background: { r: 0, g: 0, b: 0, alpha: 0 } })
.toBuffer(); .toBuffer();
+12 -9
View File
@@ -1,16 +1,8 @@
import { config } from "dotenv"; import { config } from "dotenv";
import { argv } from "process"; import { argv } from "process";
config();
const allTargets = argv.includes("--all-targets");
const targets = argv
.find((argument) => argument.startsWith("--target"))
?.split("=")[1]
.split(",");
import { boosterIcons } from "./boosterIcons"; import { boosterIcons } from "./boosterIcons";
import { camouflageIcons } from "./camouflageIcons"; import { camouflageIcons } from "./camouflageIcons";
import { vfs } from "./constants";
import { consumableProvisionIcons } from "./consumableProvisionIcons"; import { consumableProvisionIcons } from "./consumableProvisionIcons";
import { currencies } from "./currencies"; import { currencies } from "./currencies";
import { definitions } from "./definitions"; import { definitions } from "./definitions";
@@ -27,6 +19,14 @@ import { tankArmors } from "./tankArmors";
import { tankIcons } from "./tankIcons"; import { tankIcons } from "./tankIcons";
import { tankModels } from "./tankModels"; import { tankModels } from "./tankModels";
config();
const allTargets = argv.includes("--all-targets");
const targets = argv
.find((argument) => argument.startsWith("--target"))
?.split("=")[1]
.split(",");
if (!targets && !allTargets) throw new Error("No target(s) specified"); if (!targets && !allTargets) throw new Error("No target(s) specified");
const methods = [ const methods = [
@@ -59,3 +59,6 @@ for (const method of methods) {
} }
} }
} }
vfs.dispose();
process.exit(0);
@@ -1,8 +1,6 @@
import { toUniqueId } from "@blitzkit/core"; import { toUniqueId } from "@blitzkit/core";
import { readdir } from "fs/promises";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
import { VehicleDefinitionList } from "./definitions"; import { VehicleDefinitionList } from "./definitions";
export async function migration() { export async function migration() {
@@ -10,13 +8,11 @@ export async function migration() {
using uploader = new AssetUploader("migration map"); using uploader = new AssetUploader("migration map");
const map: Record<string, number> = {}; const map: Record<string, number> = {};
const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common");
(nations) => nations.filter((nation) => nation !== "common")
);
for (const nation of nations) { for (const nation of nations) {
const tankList = await readXMLDVPL<{ root: VehicleDefinitionList }>( const tankList = await vfs.xml<{ root: VehicleDefinitionList }>(
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml` `Data/XML/item_defs/vehicles/${nation}/list.xml`
); );
for (const tankKey in tankList.root) { for (const tankKey in tankList.root) {
@@ -1,24 +1,20 @@
import { readdir } from "fs/promises";
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
export async function moduleIcons() { export async function moduleIcons() {
console.log("Building module icons..."); console.log("Building module icons...");
using uploader = new AssetUploader("module icons"); using uploader = new AssetUploader("module icons");
const files = await readdir(`${DATA}/Gfx/UI/ModulesTechTree`).then((dir) => const files = vfs.dir(`Data/Gfx/UI/ModulesTechTree`).filter(
dir.filter(
(file) => !file.endsWith("@2x.packed.webp") && file.startsWith("vehicle") (file) => !file.endsWith("@2x.packed.webp") && file.startsWith("vehicle")
) )
);
for (const file of files) { for (const file of files) {
const nameRaw = file.match(/vehicle(.+)\.packed\.webp/)![1]; const nameRaw = file.match(/vehicle(.+)\.packed\.webp/)![1];
const name = nameRaw[0].toLowerCase() + nameRaw.slice(1); const name = nameRaw[0].toLowerCase() + nameRaw.slice(1);
const content = await sharp( const content = await sharp(
await readDVPLFile(`${DATA}/Gfx/UI/ModulesTechTree/${file}`) await vfs.file(`Data/Gfx/UI/ModulesTechTree/${file}`)
) )
.trim() .trim()
.toBuffer(); .toBuffer();
+8 -11
View File
@@ -1,28 +1,25 @@
import { readdir } from "fs/promises";
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../../src/core/blitz/readDVPLFile";
import { readStringDVPL } from "../../src/core/blitz/readStringDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
export async function shellIcons() { export async function shellIcons() {
console.log("Building shell icons..."); console.log("Building shell icons...");
using uploader = new AssetUploader("shell icons"); using uploader = new AssetUploader("shell icons");
const image = sharp( const image = sharp(
await readDVPLFile( await vfs.file(
`${DATA}/Gfx/Shared/tank-supply/ammunition/big/texture0.packed.webp` `Data/Gfx/Shared/tank-supply/ammunition/big/texture0.packed.webp`
) )
); );
const files = await readdir( const files = vfs.dir(
`${DATA}/Gfx/Shared/tank-supply/ammunition/big` `Data/Gfx/Shared/tank-supply/ammunition/big`
).then((files) => files.filter((file) => file.endsWith("_l.txt"))); ).filter((file) => file.endsWith("_l.txt"))
for (const file of files) { for (const file of files) {
const name = file.match(/(.+)_l\.txt/)![1]; const name = file.match(/(.+)_l\.txt/)![1];
const sizes = ( const sizes = (
await readStringDVPL( await vfs.text(
`${DATA}/Gfx/Shared/tank-supply/ammunition/big/${file}` `Data/Gfx/Shared/tank-supply/ammunition/big/${file}`
) )
) )
.split("\n")[4] .split("\n")[4]
@@ -1,9 +1,7 @@
import { TankClass } from "@blitzkit/core"; import { TankClass } from "@blitzkit/core";
import sharp from "sharp"; import sharp from "sharp";
import { readDVPLFile } from "../core/blitz/readDVPLFile";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
interface SkillIcon { interface SkillIcon {
name: string; name: string;
@@ -27,8 +25,8 @@ export interface Avatar {
export async function skillIcons() { export async function skillIcons() {
console.log("Building skill icons..."); console.log("Building skill icons...");
const avatar = await readXMLDVPL<{ root: Avatar }>( const avatar = await vfs.xml<{ root: Avatar }>(
`${DATA}/XML/item_defs/tankmen/avatar.xml` `Data/XML/item_defs/tankmen/avatar.xml`
); );
using uploader = new AssetUploader("skill icons"); using uploader = new AssetUploader("skill icons");
@@ -36,8 +34,8 @@ export async function skillIcons() {
const skill = avatar.root.skills[key]; const skill = avatar.root.skills[key];
const icon = Array.isArray(skill.icon) ? skill.icon[0] : skill.icon; const icon = Array.isArray(skill.icon) ? skill.icon[0] : skill.icon;
const name = icon.name.split("/").at(-1)!.replace(/_\d$/, ""); const name = icon.name.split("/").at(-1)!.replace(/_\d$/, "");
const path = `${DATA}${icon.name.replace("~res:", "")}.packed.webp`; const path = `Data${icon.name.replace("~res:", "")}.packed.webp`;
const image = sharp(await readDVPLFile(path)).trim(); const image = sharp(await vfs.file(path)).trim();
const content = await image.toBuffer(); const content = await image.toBuffer();
await uploader.add({ content, path: `icons/skills/${name}.webp` }); await uploader.add({ content, path: `icons/skills/${name}.webp` });
@@ -1,10 +1,8 @@
import { toUniqueId } from "@blitzkit/core"; import { toUniqueId } from "@blitzkit/core";
import { NodeIO } from "@gltf-transform/core"; import { NodeIO } from "@gltf-transform/core";
import { readdir } from "fs/promises";
import { extractArmor } from "../core/blitz/extractArmor"; import { extractArmor } from "../core/blitz/extractArmor";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
import { VehicleDefinitionList } from "./definitions"; import { VehicleDefinitionList } from "./definitions";
export async function tankArmors() { export async function tankArmors() {
@@ -12,13 +10,11 @@ export async function tankArmors() {
using uploader = new AssetUploader("tank armors"); using uploader = new AssetUploader("tank armors");
const nodeIO = new NodeIO(); const nodeIO = new NodeIO();
const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common");
(nations) => nations.filter((nation) => nation !== "common")
);
for (const nation of nations) { for (const nation of nations) {
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>( const tanks = await vfs.xml<{ root: VehicleDefinitionList }>(
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml` `Data/XML/item_defs/vehicles/${nation}/list.xml`
); );
for (const tankKey in tanks.root) { for (const tankKey in tanks.root) {
@@ -27,7 +23,7 @@ export async function tankArmors() {
if (tankKey.includes("tutorial_bot")) continue; if (tankKey.includes("tutorial_bot")) continue;
const id = toUniqueId(nation, tank.id); const id = toUniqueId(nation, tank.id);
const model = await extractArmor(DATA, `${nation}-${tankKey}`); const model = await extractArmor(vfs, `${nation}-${tankKey}`);
const content = await nodeIO.writeBinary(model); const content = await nodeIO.writeBinary(model);
await uploader.add({ path: `3d/tanks/armor/${id}.glb`, content }); await uploader.add({ path: `3d/tanks/armor/${id}.glb`, content });
+10 -16
View File
@@ -1,12 +1,8 @@
import { NATION_IDS } from "@blitzkit/core"; import { NATION_IDS } from "@blitzkit/core";
import { readdir } from "fs/promises";
import sharp from "sharp"; import sharp from "sharp";
import type { Vector3Tuple } from "three"; import type { Vector3Tuple } from "three";
import { readDVPLFile } from "../core/blitz/readDVPLFile";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
import type { VehicleDefinitionList } from "./definitions"; import type { VehicleDefinitionList } from "./definitions";
export interface TankParameters { export interface TankParameters {
@@ -45,13 +41,11 @@ export async function tankIcons() {
console.log("Building tank icons..."); console.log("Building tank icons...");
using uploader = new AssetUploader("tank icons"); using uploader = new AssetUploader("tank icons");
const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common")
(nations) => nations.filter((nation) => nation !== "common")
);
for (const nation of nations) { for (const nation of nations) {
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>( const tanks = await vfs.xml<{ root: VehicleDefinitionList }>(
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml` `Data/XML/item_defs/vehicles/${nation}/list.xml`
); );
for (const tankKey in tanks.root) { for (const tankKey in tanks.root) {
@@ -62,19 +56,19 @@ export async function tankIcons() {
const nationVehicleId = tank.id; const nationVehicleId = tank.id;
const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1; const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1;
const parameters = await readYAMLDVPL<TankParameters>( const parameters = await vfs.yaml<TankParameters>(
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` `Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`
); );
const smallPath = `${DATA}/${parameters.resourcesPath.smallIconPath const smallPath = `Data/${parameters.resourcesPath.smallIconPath
.replace(/~res:\//, "") .replace(/~res:\//, "")
.replace(/\..+/, "")}.packed.webp`; .replace(/\..+/, "")}.packed.webp`;
const bigPath = `${DATA}/${parameters.resourcesPath.bigIconPath const bigPath = `Data/${parameters.resourcesPath.bigIconPath
.replace(/~res:\//, "") .replace(/~res:\//, "")
.replace(/\..+/, "")}.packed.webp`; .replace(/\..+/, "")}.packed.webp`;
const big = await sharp(await readDVPLFile(bigPath)) const big = await sharp(await vfs.file(bigPath))
.trim() .trim()
.toBuffer(); .toBuffer();
const small = await sharp(await readDVPLFile(smallPath)) const small = await sharp(await vfs.file(smallPath))
.trim() .trim()
.toBuffer(); .toBuffer();
+7 -12
View File
@@ -1,12 +1,9 @@
import { toUniqueId } from "@blitzkit/core"; import { toUniqueId } from "@blitzkit/core";
import { NodeIO } from "@gltf-transform/core"; import { NodeIO } from "@gltf-transform/core";
import { ALL_EXTENSIONS } from "@gltf-transform/extensions"; import { ALL_EXTENSIONS } from "@gltf-transform/extensions";
import { readdir } from "fs/promises";
import { extractModel } from "../core/blitz/extractModel"; import { extractModel } from "../core/blitz/extractModel";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { AssetUploader } from "../core/github/assetUploader"; import { AssetUploader } from "../core/github/assetUploader";
import { DATA } from "./constants"; import { vfs } from "./constants";
import { VehicleDefinitionList } from "./definitions"; import { VehicleDefinitionList } from "./definitions";
import { TankParameters } from "./tankIcons"; import { TankParameters } from "./tankIcons";
@@ -15,14 +12,12 @@ export async function tankModels() {
using uploader = new AssetUploader("tank models"); using uploader = new AssetUploader("tank models");
const nodeIO = new NodeIO().registerExtensions(ALL_EXTENSIONS); const nodeIO = new NodeIO().registerExtensions(ALL_EXTENSIONS);
const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common")
(nations) => nations.filter((nation) => nation !== "common")
);
for (const nationIndex in nations) { for (const nationIndex in nations) {
const nation = nations[nationIndex]; const nation = nations[nationIndex];
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>( const tanks = await vfs.xml<{ root: VehicleDefinitionList }>(
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml` `Data/XML/item_defs/vehicles/${nation}/list.xml`
); );
const entries = Object.entries(tanks.root); const entries = Object.entries(tanks.root);
@@ -30,11 +25,11 @@ export async function tankModels() {
if (tankKey.includes("tutorial_bot")) continue; if (tankKey.includes("tutorial_bot")) continue;
const id = toUniqueId(nation, tank.id); const id = toUniqueId(nation, tank.id);
const parameters = await readYAMLDVPL<TankParameters>( const parameters = await vfs.yaml<TankParameters>(
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` `Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`
); );
const model = await extractModel( const model = await extractModel(
DATA, vfs,
parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, "") parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, "")
); );
const content = Buffer.from(await nodeIO.writeBinary(model)); const content = Buffer.from(await nodeIO.writeBinary(model));
+29 -29
View File
@@ -2,24 +2,24 @@ import {
Hierarchy, Hierarchy,
Sc2ReadStream, Sc2ReadStream,
ScgReadStream, ScgReadStream,
SteamVFS,
VertexAttribute, VertexAttribute,
} from '@blitzkit/core'; } from "@blitzkit/core";
import { Accessor, Document, Node, Scene } from '@gltf-transform/core'; import { Accessor, Document, Node, Scene } from "@gltf-transform/core";
import { times } from 'lodash-es'; import { times } from "lodash-es";
import { import {
vertexAttributeGLTFName, vertexAttributeGLTFName,
vertexAttributeGltfVectorSizes, vertexAttributeGltfVectorSizes,
} from './extractModel/constants'; } from "./extractModel/constants";
import { readDVPLFile } from './readDVPLFile';
export async function extractArmor(data: string, fileName: string) { export async function extractArmor(vfs: SteamVFS, fileName: string) {
const sc2Path = `${data}/3d/Tanks/CollisionMeshes/${fileName}.sc2`; const sc2Path = `Data/3d/Tanks/CollisionMeshes/${fileName}.sc2`;
const scgPath = `${data}/3d/Tanks/CollisionMeshes/${fileName}.scg`; const scgPath = `Data/3d/Tanks/CollisionMeshes/${fileName}.scg`;
const sc2 = new Sc2ReadStream( const sc2 = new Sc2ReadStream(
(await readDVPLFile(sc2Path)).buffer as ArrayBuffer, (await vfs.file(sc2Path)).buffer as ArrayBuffer
).sc2(); ).sc2();
const scg = new ScgReadStream( const scg = new ScgReadStream(
(await readDVPLFile(scgPath)).buffer as ArrayBuffer, (await vfs.file(scgPath)).buffer as ArrayBuffer
).scg(); ).scg();
const document = new Document(); const document = new Document();
const scene = document.createScene(); const scene = document.createScene();
@@ -29,21 +29,21 @@ export async function extractArmor(data: string, fileName: string) {
hierarchies.forEach((hierarchy) => { hierarchies.forEach((hierarchy) => {
const components = times( const components = times(
hierarchy.components.count, hierarchy.components.count,
(index) => hierarchy.components[index.toString().padStart(4, '0')], (index) => hierarchy.components[index.toString().padStart(4, "0")]
); );
components.forEach((component) => { components.forEach((component) => {
switch (component['comp.typename']) { switch (component["comp.typename"]) {
case 'TransformComponent': case "TransformComponent":
break; break;
case 'RenderComponent': { case "RenderComponent": {
const batch = component['rc.renderObj']['ro.batches']['0000']; const batch = component["rc.renderObj"]["ro.batches"]["0000"];
const polygonGroup = scg.get(batch['rb.datasource']); const polygonGroup = scg.get(batch["rb.datasource"]);
if (!polygonGroup) { if (!polygonGroup) {
console.warn( console.warn(
`Missing polygon group ${batch['rb.datasource']} (${hierarchy.name}); skipping...`, `Missing polygon group ${batch["rb.datasource"]} (${hierarchy.name}); skipping...`
); );
break; break;
@@ -73,7 +73,7 @@ export async function extractArmor(data: string, fileName: string) {
VertexAttribute.TANGENT, VertexAttribute.TANGENT,
attributes attributes
.get(VertexAttribute.TANGENT)! .get(VertexAttribute.TANGENT)!
.map((tangent) => [...tangent, 1]), .map((tangent) => [...tangent, 1])
); );
} }
@@ -85,7 +85,7 @@ export async function extractArmor(data: string, fileName: string) {
const vertexSize = vertexAttributeGltfVectorSizes[attribute]; const vertexSize = vertexAttributeGltfVectorSizes[attribute];
const accessor = document const accessor = document
.createAccessor(name) .createAccessor(name)
.setType(vertexSize === 1 ? 'SCALAR' : `VEC${vertexSize}`) .setType(vertexSize === 1 ? "SCALAR" : `VEC${vertexSize}`)
.setArray(new Float32Array(value.flat())) .setArray(new Float32Array(value.flat()))
.setBuffer(buffer); .setBuffer(buffer);
@@ -94,19 +94,19 @@ export async function extractArmor(data: string, fileName: string) {
hardJointIndices.forEach((hardJointIndex) => { hardJointIndices.forEach((hardJointIndex) => {
const node = document.createNode( const node = document.createNode(
`${hierarchy.name}_armor_${hardJointIndex}`, `${hierarchy.name}_armor_${hardJointIndex}`
); );
const mesh = document.createMesh(batch['##name']); const mesh = document.createMesh(batch["##name"]);
const indicesAccessor = document const indicesAccessor = document
.createAccessor() .createAccessor()
.setType('SCALAR') .setType("SCALAR")
.setArray( .setArray(
new Uint16Array( new Uint16Array(
polygonGroup.indices.filter( polygonGroup.indices.filter(
(index) => (index) =>
vertexHardJointIndices.get(index) === hardJointIndex, vertexHardJointIndices.get(index) === hardJointIndex
), )
), )
) )
.setBuffer(buffer); .setBuffer(buffer);
const primitive = document const primitive = document
@@ -127,18 +127,18 @@ export async function extractArmor(data: string, fileName: string) {
default: default:
throw new TypeError( throw new TypeError(
`Unhandled component type: ${component['comp.typename']}`, `Unhandled component type: ${component["comp.typename"]}`
); );
} }
}); });
if (hierarchy['#hierarchy']) { if (hierarchy["#hierarchy"]) {
parseHierarchies(hierarchy['#hierarchy'], parent); parseHierarchies(hierarchy["#hierarchy"], parent);
} }
}); });
} }
parseHierarchies(sc2['#hierarchy'], scene); parseHierarchies(sc2["#hierarchy"], scene);
return document; return document;
} }
@@ -2,6 +2,7 @@ import {
Hierarchy, Hierarchy,
Sc2ReadStream, Sc2ReadStream,
ScgReadStream, ScgReadStream,
SteamVFS,
Textures, Textures,
VertexAttribute, VertexAttribute,
} from "@blitzkit/core"; } from "@blitzkit/core";
@@ -10,7 +11,6 @@ import { dedup, prune } from "@gltf-transform/functions";
import { times } from "lodash-es"; import { times } from "lodash-es";
import { dirname } from "path"; import { dirname } from "path";
import { readBaseColor } from "../readBaseColor"; import { readBaseColor } from "../readBaseColor";
import { readDVPLFile } from "../readDVPLFile";
import { readNormal } from "../readNormal"; import { readNormal } from "../readNormal";
import { readRoughnessMetallic } from "../readRoughnessMetallic"; import { readRoughnessMetallic } from "../readRoughnessMetallic";
import { import {
@@ -25,14 +25,14 @@ const omitMeshNames = {
end: ["_POINT"], end: ["_POINT"],
}; };
export async function extractModel(data: string, path: string) { export async function extractModel(vfs: SteamVFS, path: string) {
const sc2Path = `${data}/3d/${path}.sc2`; const sc2Path = `Data/3d/${path}.sc2`;
const scgPath = `${data}/3d/${path}.scg`; const scgPath = `Data/3d/${path}.scg`;
const sc2 = new Sc2ReadStream( const sc2 = new Sc2ReadStream(
(await readDVPLFile(sc2Path)).buffer as ArrayBuffer (await vfs.file(sc2Path)).buffer as ArrayBuffer
).sc2(); ).sc2();
const scg = new ScgReadStream( const scg = new ScgReadStream(
(await readDVPLFile(scgPath)).buffer as ArrayBuffer (await vfs.file(scgPath)).buffer as ArrayBuffer
).scg(); ).scg();
const document = new Document(); const document = new Document();
const scene = document.createScene(); const scene = document.createScene();
@@ -67,11 +67,11 @@ export async function extractModel(data: string, path: string) {
.setMimeType("image/webp") .setMimeType("image/webp")
.setImage( .setImage(
await readBaseColor( await readBaseColor(
`${data}/3d/${dirname(path)}/${ `Data/3d/${dirname(path)}/${
textures.baseColorMap ?? textures.albedo textures.baseColorMap ?? textures.albedo
}`, }`,
textures.miscMap textures.miscMap
? `${data}/3d/${dirname(path)}/${textures.miscMap}` ? `Data/3d/${dirname(path)}/${textures.miscMap}`
: undefined : undefined
) )
) )
@@ -103,7 +103,7 @@ export async function extractModel(data: string, path: string) {
.setMimeType("image/webp") .setMimeType("image/webp")
.setImage( .setImage(
await readRoughnessMetallic( await readRoughnessMetallic(
`${data}/3d/${dirname(path)}/${textures.baseRMMap}` `Data/3d/${dirname(path)}/${textures.baseRMMap}`
) )
) )
); );
@@ -118,7 +118,7 @@ export async function extractModel(data: string, path: string) {
.setMimeType("image/webp") .setMimeType("image/webp")
.setImage( .setImage(
await readNormal( await readNormal(
`${data}/3d/${dirname(path)}/${ `Data/3d/${dirname(path)}/${
textures.baseNormalMap ?? textures.normalmap textures.baseNormalMap ?? textures.normalmap
}`, }`,
isBase isBase
@@ -1,6 +0,0 @@
import { readDVPLFile } from './readDVPLFile';
export async function readBase64DVPL(file: string) {
const buffer = await readDVPLFile(file);
return buffer.toString('base64');
}
@@ -1,21 +0,0 @@
import { readFile } from 'fs/promises';
import { DATA_COMPRESSED } from '../../buildAssets/constants';
import { readDVPL } from './readDVPL';
export async function readDVPLFile(file: string) {
let path: string;
if (DATA_COMPRESSED) {
path = file.endsWith('.dvpl') ? file : `${file}.dvpl`;
} else {
path = file.replace('.dvpl', '');
}
const content = await readFile(path);
if (!DATA_COMPRESSED) return content;
const dvpl = readDVPL(content);
return dvpl;
}
@@ -1,6 +0,0 @@
import { readDVPLFile } from './readDVPLFile';
export async function readStringDVPL(file: string) {
const buffer = await readDVPLFile(file);
return buffer.toString();
}
@@ -1,81 +1,17 @@
import { DdsReadStream, PvrReadStream } from "@blitzkit/core"; import { DdsReadStream, PvrReadStream } from "@blitzkit/core";
import { existsSync } from "fs"; import { vfs } from "../../../buildAssets/constants";
import { DATA_COMPRESSED } from "../../../buildAssets/constants";
import { readDVPLFile } from "../readDVPLFile";
export async function readTexture(path: string) { export async function readTexture(path: string) {
const ddsTexturePath = path.replace(".tex", ".dx11.dds"); const ddsTexturePath = path.replace(".tex", ".dx11.dds");
const isDds = existsSync( const isDds = vfs.has(ddsTexturePath);
`${ddsTexturePath}${DATA_COMPRESSED ? ".dvpl" : ""}`
);
const resolvedTexturePath = isDds const resolvedTexturePath = isDds
? ddsTexturePath ? ddsTexturePath
: ddsTexturePath.replace(".dds", ".pvr"); : ddsTexturePath.replace(".dds", ".pvr");
const decompressedDvpl = await readDVPLFile(`${resolvedTexturePath}.dvpl`); const file = await vfs.file(resolvedTexturePath);
const raw = isDds const raw = isDds
? await new DdsReadStream(decompressedDvpl.buffer as ArrayBuffer).dds() ? await new DdsReadStream(file.buffer as ArrayBuffer).dds()
: new PvrReadStream(decompressedDvpl.buffer as ArrayBuffer).pvr(); : new PvrReadStream(file.buffer as ArrayBuffer).pvr();
return raw; return raw;
// switch (mutation) {
// case TextureMutation.Normal: {
// const bytes = 4 * raw.width * raw.height;
// for (let index = 0; index < bytes; index += 4) {
// /**
// * Red is always 255 and blue is always 0. Only alpha and green contain any
// * sort of information.
// */
// let x = raw.data[index + 3] * (2 / 255) - 1;
// let y = raw.data[index + 1] * (2 / 255) - 1;
// const underSqrt = 1 - x ** 2 - y ** 2;
// let z = underSqrt > 0 ? Math.sqrt(underSqrt) : -Math.sqrt(-underSqrt);
// raw.data[index] = Math.round((x + 1) * (255 / 2));
// raw.data[index + 1] = Math.round((y + 1) * (255 / 2));
// raw.data[index + 2] = Math.round((z + 1) * (255 / 2));
// raw.data[index + 3] = 255;
// }
// return await sharp(raw.data, { raw }).jpeg().toBuffer();
// }
// case TextureMutation.RoughnessMetallicness: {
// const newImage = sharp(Buffer.alloc(raw.width * raw.height), {
// raw: { ...raw, channels: 1 },
// });
// const metallicness = sharp(raw.data, { raw })
// .extractChannel("green")
// .jpeg()
// .toBuffer();
// const roughness = sharp(raw.data, { raw })
// .extractChannel("alpha")
// .jpeg()
// .toBuffer();
// return await newImage
// .joinChannel(await Promise.all([roughness, metallicness]))
// .jpeg()
// .toBuffer();
// }
// case TextureMutation.Miscellaneous: {
// /**
// * Alpha is ambient occlusion and green is emissive. But very few tanks
// * use emissive so I am ignoring it for now.
// */
// return await sharp(raw.data, { raw })
// .extractChannel("alpha")
// .jpeg()
// .toBuffer();
// }
// case TextureMutation.Albedo: {
// return await sharp(raw.data, { raw }).removeAlpha().jpeg().toBuffer();
// }
// default:
// return await sharp(raw.data, { raw }).jpeg().toBuffer();
// }
} }
@@ -1,9 +0,0 @@
import { XMLParser } from 'fast-xml-parser';
import { readStringDVPL } from './readStringDVPL';
export async function readXMLDVPL<Type>(file: string) {
const parser = new XMLParser();
const xml = await readStringDVPL(file);
return parser.parse(xml) as Type;
}
@@ -1,7 +0,0 @@
import { readFile } from 'fs/promises';
import { parse } from 'yaml';
export async function readYAML<Type>(file: string) {
const yaml = (await readFile(file)).toString();
return parse(yaml) as Type;
}
@@ -1,8 +0,0 @@
import { parse } from 'yaml';
import { readStringDVPL } from './readStringDVPL';
export async function readYAMLDVPL<Type>(file: string) {
const yaml = await readStringDVPL(file);
return parse(yaml) as Type;
}
@@ -99,7 +99,7 @@ export class AssetUploader {
} }
if (diff.status === DiffStatus.Unchanged) { if (diff.status === DiffStatus.Unchanged) {
// console.log(`🔵 ${change.path}`); console.log(`🔵 ${change.path}`);
} else { } else {
console.log( console.log(
`${diff.status === DiffStatus.New ? "🟢" : "🟡"} (${ `${diff.status === DiffStatus.New ? "🟢" : "🟡"} (${
+17 -17
View File
@@ -1,39 +1,39 @@
import decompress from 'decompress'; import decompress from "decompress";
import { existsSync } from 'fs'; import { existsSync } from "fs";
import { mkdir, readdir, writeFile } from 'fs/promises'; import { mkdir, readdir, writeFile } from "fs/promises";
if (!existsSync('../../temp')) { if (!existsSync("../../temp")) {
console.log('Creating temp directory...'); console.log("Creating temp directory...");
await mkdir('../../temp'); await mkdir("../../temp");
} }
console.log('Downloading depot downloader...'); console.log("Downloading depot downloader...");
await fetch( await fetch(
'https://api.github.com/repos/SteamRE/DepotDownloader/releases/latest', "https://api.github.com/repos/SteamRE/DepotDownloader/releases/latest"
) )
.then( .then(
(response) => (response) =>
response.json() as Promise<{ response.json() as Promise<{
assets: { browser_download_url: string; name: string }[]; assets: { browser_download_url: string; name: string }[];
}>, }>
) )
.then(({ assets }) => { .then(({ assets }) => {
const asset = assets.find(({ name }) => name.includes('linux-x64')); const asset = assets.find(({ name }) => name.includes("linux-x64"));
if (!asset) throw new Error('No asset found'); if (!asset) throw new Error("No asset found");
return fetch(asset.browser_download_url); return fetch(asset.browser_download_url);
}) })
.then((response) => response.arrayBuffer()) .then((response) => response.arrayBuffer())
.then((arrayBuffer) => .then((arrayBuffer) =>
writeFile('../../temp/depotDownloader.zip', new Uint8Array(arrayBuffer)), writeFile("../../temp/depotDownloader.zip", new Uint8Array(arrayBuffer))
); );
console.log('Unzipping...'); console.log("Unzipping...");
await decompress( await decompress(
'../../temp/depotDownloader.zip', "../../temp/depotDownloader.zip",
'../../temp/depotDownloader', "../../temp/depotDownloader"
); );
console.log( console.log(
'Download complete; files:', "Download complete; files:",
await readdir('../../temp/depotDownloader'), await readdir("../../temp/depotDownloader")
); );
+1 -1
View File
@@ -1,4 +1,4 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"include": ["src/**/*"] "include": ["src/**/*", "../core/src/blitz/readDVPL.ts"]
} }
Binary file not shown.