From 808775217239a29e0b892fb65ea30b237b1e231f Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Tue, 1 Apr 2025 15:32:37 -0500 Subject: [PATCH] feat: mirros --- .vscode/tasks.json | 41 +++++ package.json | 5 +- .../website/src/core/blitzkit/blobMirror.ts | 17 +++ .../website/src/pages/api/tanks/full.json.ts | 11 +- .../website/src/pages/api/tanks/full.pb.ts | 8 + .../website/src/pages/api/tanks/list.json.ts | 11 +- .../website/src/pages/api/tanks/list.pb.ts | 8 + src/BlitzKit.CLI/BlitzKit.CLI.csproj | 1 + src/BlitzKit.CLI/Functions/Api.cs | 37 +++++ src/BlitzKit.CLI/Functions/Mangler.cs | 141 +++++++++--------- src/BlitzKit.CLI/Program.cs | 6 +- 11 files changed, 193 insertions(+), 93 deletions(-) create mode 100644 .vscode/tasks.json create mode 100644 packages/website/src/pages/api/tanks/full.pb.ts create mode 100644 packages/website/src/pages/api/tanks/list.pb.ts create mode 100644 src/BlitzKit.CLI/Functions/Api.cs diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..e48eedcdb --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/blitzkit.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/blitzkit.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/blitzkit.sln" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index d6857fb25..2eb36069c 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "start:bot": "bun dist/bot/main.js", "dev:docs": "vitepress dev docs", "dev:website": "cd packages/website && bun run dev", - "dev:api": "bun --filter=@blitzkit/api run dev", "setup:depotdownloader": "bun --filter=@blitzkit/scripts run setup:depotdownloader", "setup:patches": "bun --filter=@blitzkit/scripts run setup:patches", "start:website": "bun --filter=@blitzkit/website run start", @@ -39,7 +38,9 @@ "build:ids": "cd packages/scripts && bun build:ids", "prunestrings": "cd packages/scripts && bun prunestrings", "dev:cli:unpack": "cd src/BlitzKit.CLI && dotnet run unpack \"C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz Playtest\" --no-overwrite", - "mangle": "cd src/BlitzKit.CLI && dotnet run mangle" + "mangle": "cd src/BlitzKit.CLI && dotnet run mangle", + "api": "cd src/BlitzKit.CLI && dotnet run api", + "dev:api": "cd src/BlitzKit.CLI && dotnet watch run api" }, "license": "MIT", "dependencies": { diff --git a/packages/website/src/core/blitzkit/blobMirror.ts b/packages/website/src/core/blitzkit/blobMirror.ts index b3d259de9..31b9cfe8f 100644 --- a/packages/website/src/core/blitzkit/blobMirror.ts +++ b/packages/website/src/core/blitzkit/blobMirror.ts @@ -1,3 +1,6 @@ +import { fetchPB, type MessageFns } from '@blitzkit/core'; +import type { APIRoute } from 'astro'; + export async function blobMirror(url: string) { if (import.meta.env.MODE === 'development') { return Response.redirect(url); @@ -7,3 +10,17 @@ export async function blobMirror(url: string) { return new Response(blob, { headers: response.headers }); } } + +export function apiMirror(path: string) { + const get: APIRoute = () => blobMirror(`http://localhost:5000${path}`); + return get; +} + +export function jsonMirror(path: string, message: MessageFns) { + const get: APIRoute = async () => { + return new Response( + JSON.stringify(await fetchPB(`http://localhost:5000${path}`, message)), + ); + }; + return get; +} diff --git a/packages/website/src/pages/api/tanks/full.json.ts b/packages/website/src/pages/api/tanks/full.json.ts index 9d3552e2d..c4a06fd8c 100644 --- a/packages/website/src/pages/api/tanks/full.json.ts +++ b/packages/website/src/pages/api/tanks/full.json.ts @@ -1,13 +1,10 @@ -import { fetchTanksFull } from '@blitzkit/core'; -import type { APIRoute } from 'astro'; +import { TanksFull } from '@blitzkit/core'; +import { jsonMirror } from '../../../core/blitzkit/blobMirror'; /** - * Returns meta data similar to tanks/[id].json but for all tanks as an array. There is no guarantee of order. + * Identical to tanks/full.pb but in JSON. * * @warning This is a large response. Consider using tanks/[id]/meta.json for individual tanks. * @returns JSON. */ -export const GET: APIRoute = async () => { - const tanksFull = await fetchTanksFull(); - return Response.json(tanksFull.tanks); -}; +export const GET = jsonMirror('/tanks/full.pb', TanksFull); diff --git a/packages/website/src/pages/api/tanks/full.pb.ts b/packages/website/src/pages/api/tanks/full.pb.ts new file mode 100644 index 000000000..392220bc2 --- /dev/null +++ b/packages/website/src/pages/api/tanks/full.pb.ts @@ -0,0 +1,8 @@ +import { apiMirror } from '../../../core/blitzkit/blobMirror'; + +/** + * Returns meta data similar to tanks/[id].json but for all tanks as an array. There is no guarantee of order. + * + * @proto TanksFull + */ +export const GET = apiMirror('/tanks/full.pb'); diff --git a/packages/website/src/pages/api/tanks/list.json.ts b/packages/website/src/pages/api/tanks/list.json.ts index 129d5700e..4b1dc8577 100644 --- a/packages/website/src/pages/api/tanks/list.json.ts +++ b/packages/website/src/pages/api/tanks/list.json.ts @@ -1,12 +1,9 @@ -import { fetchTanks } from '@blitzkit/core'; -import type { APIRoute } from 'astro'; +import { Tanks } from '@blitzkit/core'; +import { jsonMirror } from '../../../core/blitzkit/blobMirror'; /** - * Returns a list of all tank ids. There is no guarantee of order. + * Identical to tanks/list.pb but in JSON. * * @returns JSON. */ -export const GET: APIRoute = async () => { - const tanks = await fetchTanks(); - return Response.json(tanks.tanks); -}; +export const GET = jsonMirror('/tanks/list.pb', Tanks); diff --git a/packages/website/src/pages/api/tanks/list.pb.ts b/packages/website/src/pages/api/tanks/list.pb.ts new file mode 100644 index 000000000..4d3d8c8d4 --- /dev/null +++ b/packages/website/src/pages/api/tanks/list.pb.ts @@ -0,0 +1,8 @@ +import { apiMirror } from '../../../core/blitzkit/blobMirror'; + +/** + * Returns a list of all tank ids. There is no guarantee of order. + * + * @returns JSON. + */ +export const GET = apiMirror('/tanks/list.pb'); diff --git a/src/BlitzKit.CLI/BlitzKit.CLI.csproj b/src/BlitzKit.CLI/BlitzKit.CLI.csproj index decec886e..6ed9c6fa1 100644 --- a/src/BlitzKit.CLI/BlitzKit.CLI.csproj +++ b/src/BlitzKit.CLI/BlitzKit.CLI.csproj @@ -15,6 +15,7 @@ + diff --git a/src/BlitzKit.CLI/Functions/Api.cs b/src/BlitzKit.CLI/Functions/Api.cs new file mode 100644 index 000000000..ababef3a6 --- /dev/null +++ b/src/BlitzKit.CLI/Functions/Api.cs @@ -0,0 +1,37 @@ +using Google.Protobuf; +using Microsoft.AspNetCore.Builder; + +namespace BlitzKit.CLI.Functions +{ + public class Api(string[] args) + { + readonly WebApplication app = WebApplication.Create(); + readonly Mangler mangler = new(args); + + void Map(string path, Func> func) + where T : IMessage + { + app.MapGet( + path, + async (context) => + { + var message = await func(); + var bytes = message.ToByteArray(); + + context.Response.ContentType = "application/octet-stream"; + await context.Response.Body.WriteAsync(bytes); + } + ); + } + + public async Task Run() + { + await mangler.Initialize(); + + Map("/tanks/full.pb", mangler.TanksFull); + Map("/tanks/list.pb", mangler.Tanks); + + app.Run(); + } + } +} diff --git a/src/BlitzKit.CLI/Functions/Mangler.cs b/src/BlitzKit.CLI/Functions/Mangler.cs index de8c583e7..07e94de1a 100644 --- a/src/BlitzKit.CLI/Functions/Mangler.cs +++ b/src/BlitzKit.CLI/Functions/Mangler.cs @@ -49,15 +49,71 @@ namespace BlitzKit.CLI.Functions readonly BlitzProvider provider = new(args.Contains("--depot")); Locales? locales; readonly Dictionary> strings = []; - readonly AssetUploader assetUploader = new("mangled ue assets") { enabled = true }; - public async Task Mangle() + public async Task TanksFull() + { + var dirs = provider.RootDirectory.GetDirectory("Blitz/Content/Tanks").Directories; + TanksFull tanksFull = new(); + + foreach (var dir in dirs) + { + if (dir.Key == "TankStub") + continue; + + foreach (var tankDir in dir.Value.Directories) + { + var tank = MangleTank(tankDir.Value); + tanksFull.Tanks.Add(tank); + } + } + + DeduplicateSlugs(tanksFull); + + return tanksFull; + } + + Tank MangleTank(VFS tankDir) + { + var pdaName = $"PDA_{tankDir.Name}"; + var pda = provider.LoadObject($"{tankDir.Path}/{pdaName}.{pdaName}"); + + var id = pda.Get("TankId").Text; + var name = GetString($"TankEntity__{id.ToLowerInvariant()}__Short_Name"); + var slug = Diacritics.Remove(name.Locales["en"]).ToLower(); + slug = NonAlphanumericRegex().Replace(slug, "-"); + slug = MultipleDashesRegex().Replace(slug, "-"); + slug = TrailingDashRegex().Replace(slug, ""); + + Tank tank = new() + { + Id = id, + Name = name, + Slug = slug, + }; + + return tank; + } + + public async Task Tanks() + { + var tanksFull = await TanksFull(); + Tanks tanks = new(); + + foreach (var tank in tanksFull.Tanks) + { + tanks.Tanks_.Add(tank.Id); + } + + return tanks; + } + + public async Task Initialize() { await FetchStrings(); - await MangleNations(); - await assetUploader.Flush(); } + /////////////////////////////////////////////////////////////////////////// + I18n GetString(string name) { I18n i18n = new(); @@ -109,42 +165,6 @@ namespace BlitzKit.CLI.Functions } } - async Task MangleNations() - { - var dirs = provider.RootDirectory.GetDirectory("Blitz/Content/Tanks").Directories; - TanksFull tanksFull = new(); - - foreach (var dir in dirs) - { - if (dir.Key == "TankStub") - continue; - - foreach (var tankDir in dir.Value.Directories) - { - // if (tankDir.Value.Name != "R90_IS_4") - // continue; - - // if (tankDir.Value.Name != "R81_IS_8") - // continue; - - var tank = await MangleTank(tankDir.Value); - tanksFull.Tanks.Add(tank); - } - } - - DeduplicateSlugs(tanksFull); - Tanks tanks = new(); - - foreach (var tank in tanksFull.Tanks) - { - tanks.Tanks_.Add(tank.Id); - await assetUploader.Add($"tanks/{tank.Id}/meta.pb", tank.ToByteArray()); - } - - await assetUploader.Add("definitions/tanks.pb", tanks.ToByteArray()); - await assetUploader.Add("definitions/tanks-full.pb", tanksFull.ToByteArray()); - } - void DeduplicateSlugs(TanksFull tanksFull) { List checkedSlugs = []; @@ -215,33 +235,6 @@ namespace BlitzKit.CLI.Functions } } - async Task MangleTank(VFS tankDir) - { - var pdaName = $"PDA_{tankDir.Name}"; - var pda = provider.LoadObject($"{tankDir.Path}/{pdaName}.{pdaName}"); - - var id = pda.Get("TankId").Text; - var name = GetString($"TankEntity__{id.ToLowerInvariant()}__Short_Name"); - var slug = Diacritics.Remove(name.Locales["en"]).ToLower(); - slug = NonAlphanumericRegex().Replace(slug, "-"); - slug = MultipleDashesRegex().Replace(slug, "-"); - slug = TrailingDashRegex().Replace(slug, ""); - - await MangleIcon(pda); - await MangleArmor(pda); - - Tank tank = new() - { - Id = id, - Name = name, - Slug = slug, - }; - - await MangleModules(tank, pda); - - return tank; - } - async Task MangleArmor(UObject pda) { var id = pda.Get("TankId").Text; @@ -282,7 +275,7 @@ namespace BlitzKit.CLI.Functions PrettyLog.Warn($"Penetration groups missing for {id}; creating empty list"); } - await assetUploader.Add($"tanks/{id}/armor.pb", tankArmor.ToByteArray()); + // await assetUploader.Add($"tanks/{id}/armor.pb", tankArmor.ToByteArray()); } async Task MangleIcon(UObject pda) @@ -292,7 +285,7 @@ namespace BlitzKit.CLI.Functions if (pda.TryGet("SmallIcon", out var smallIconTexture)) { var smallIcon = BlitzKitExporter.Texture2D(smallIconTexture); - await assetUploader.Add($"tanks/{id}/icons/small.png", smallIcon); + // await assetUploader.Add($"tanks/{id}/icons/small.png", smallIcon); } else { @@ -302,7 +295,7 @@ namespace BlitzKit.CLI.Functions if (pda.TryGet("BigIcon", out var bigIconTexture)) { var bigIcon = BlitzKitExporter.Texture2D(bigIconTexture); - await assetUploader.Add($"tanks/{id}/icons/big.png", bigIcon); + // await assetUploader.Add($"tanks/{id}/icons/big.png", bigIcon); } else { @@ -354,9 +347,9 @@ namespace BlitzKit.CLI.Functions { MonoGltf gltf = new(collision); - await assetUploader.Add( - new($"tanks/{tank.Id}/collision/{moduleName}.glb", gltf.Write()) - ); + // await assetUploader.Add( + // new($"tanks/{tank.Id}/collision/{moduleName}.glb", gltf.Write()) + // ); } else { @@ -365,7 +358,7 @@ namespace BlitzKit.CLI.Functions } } - await assetUploader.Add($"tanks/{tank.Id}/model.pb", tankModel.ToByteArray()); + // await assetUploader.Add($"tanks/{tank.Id}/model.pb", tankModel.ToByteArray()); } } } diff --git a/src/BlitzKit.CLI/Program.cs b/src/BlitzKit.CLI/Program.cs index 41af977f4..84ca6f0fd 100644 --- a/src/BlitzKit.CLI/Program.cs +++ b/src/BlitzKit.CLI/Program.cs @@ -22,10 +22,10 @@ namespace BlitzKit.CLI break; } - case "mangle": + case "api": { - Mangler mangler = new(args); - await mangler.Mangle(); + Api api = new(args); + await api.Run(); break; }