Merge branch 'main' into ue4

This commit is contained in:
TrèsAbhi committed 2025-06-08 12:19:04 -05:00
commit 53c2f9605f
18 files changed
+93 -91

No files matched your search

@@ -1,5 +0,0 @@
import { MessageFns } from '../protos';
export function encodePBBuffer<Type>(message: MessageFns<Type>, data: Type) {
return Buffer.from(message.encode(data).finish());
}
-1
View File
@@ -1,3 +1,2 @@
export * from './encodePBBuffer';
export * from './fetchPB'; export * from './fetchPB';
export * from './pbMap'; export * from './pbMap';
+1 -1
View File
@@ -3,7 +3,7 @@ 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 { dvp } from '../../../submodules/blitzkit-closed/src/dvp'; import { dvp } from '../../../submodules/blitzkit-closed/src/dava/dvp';
import { readStringDVPL } from '../src/core/blitz/readStringDVPL'; import { readStringDVPL } from '../src/core/blitz/readStringDVPL';
import { DATA } from './buildAssets/constants'; import { DATA } from './buildAssets/constants';
import { readYAMLDVPL } from './core/blitz/readYAMLDVPL'; import { readYAMLDVPL } from './core/blitz/readYAMLDVPL';
+2 -3
View File
@@ -8,7 +8,6 @@ import {
Samples, Samples,
averageDefinitionsAllStatsKeys, averageDefinitionsAllStatsKeys,
emptySamples, emptySamples,
encodePBBuffer,
getAccountInfo, getAccountInfo,
getTankStats, getTankStats,
idToRegion, idToRegion,
@@ -235,11 +234,11 @@ async function postWork() {
commitAssets('averages', [ commitAssets('averages', [
{ {
path: `averages/${latest}.pb`, path: `averages/${latest}.pb`,
content: encodePBBuffer(AverageDefinitions, averageDefinitions), content: AverageDefinitions.encode(averageDefinitions).finish(),
}, },
{ {
path: 'averages/manifest.json', path: 'averages/manifest.json',
content: Buffer.from(JSON.stringify(manifest), 'utf-8'), content: new TextEncoder().encode(JSON.stringify(manifest)),
}, },
]); ]);
} }
@@ -7,7 +7,6 @@ import {
ConsumableTankCategoryFilterCategory, ConsumableTankCategoryFilterCategory,
Crew, Crew,
CrewType, CrewType,
encodePBBuffer,
EquipmentDefinitions, EquipmentDefinitions,
EquipmentSlot, EquipmentSlot,
GameDefinitions, GameDefinitions,
@@ -1772,39 +1771,39 @@ export async function definitions() {
await commitAssets('definitions', [ await commitAssets('definitions', [
{ {
content: encodePBBuffer(GameDefinitions, gameDefinitions), content: GameDefinitions.encode(gameDefinitions).finish(),
path: 'definitions/game.pb', path: 'definitions/game.pb',
}, },
{ {
content: encodePBBuffer(TankDefinitions, tankDefinitions), content: TankDefinitions.encode(tankDefinitions).finish(),
path: 'definitions/tanks.pb', path: 'definitions/tanks.pb',
}, },
{ {
content: encodePBBuffer(ModelDefinitions, modelDefinitions), content: ModelDefinitions.encode(modelDefinitions).finish(),
path: 'definitions/models.pb', path: 'definitions/models.pb',
}, },
{ {
content: encodePBBuffer(EquipmentDefinitions, equipmentDefinitions), content: EquipmentDefinitions.encode(equipmentDefinitions).finish(),
path: 'definitions/equipment.pb', path: 'definitions/equipment.pb',
}, },
{ {
content: encodePBBuffer(ConsumableDefinitions, consumableDefinitions), content: ConsumableDefinitions.encode(consumableDefinitions).finish(),
path: 'definitions/consumables.pb', path: 'definitions/consumables.pb',
}, },
{ {
content: encodePBBuffer(ProvisionDefinitions, provisionDefinitions), content: ProvisionDefinitions.encode(provisionDefinitions).finish(),
path: 'definitions/provisions.pb', path: 'definitions/provisions.pb',
}, },
{ {
content: encodePBBuffer(SkillDefinitions, skillDefinitions), content: SkillDefinitions.encode(skillDefinitions).finish(),
path: 'definitions/skills.pb', path: 'definitions/skills.pb',
}, },
{ {
content: encodePBBuffer(MapDefinitions, mapDefinitions), content: MapDefinitions.encode(mapDefinitions).finish(),
path: 'definitions/maps.pb', path: 'definitions/maps.pb',
}, },
{ {
content: encodePBBuffer(CamouflageDefinitions, camouflageDefinitions), content: CamouflageDefinitions.encode(camouflageDefinitions).finish(),
path: 'definitions/camouflages.pb', path: 'definitions/camouflages.pb',
}, },
]); ]);
+6 -6
View File
@@ -1,4 +1,4 @@
import { Avatar, encodePBBuffer, fetchGlossary, Gallery } from '@blitzkit/core'; import { Avatar, fetchGlossary, Gallery } from '@blitzkit/core';
import locales from '@blitzkit/i18n/locales.json'; import locales from '@blitzkit/i18n/locales.json';
import { extname } from 'path'; import { extname } from 'path';
import ProgressBar from 'progress'; import ProgressBar from 'progress';
@@ -68,13 +68,13 @@ export async function glossary() {
gallery.avatars.push(avatar); gallery.avatars.push(avatar);
const content = await fetch(url).then((response) => const content = await fetch(url)
response.arrayBuffer(), .then((response) => response.arrayBuffer())
); .then((buffer) => new Uint8Array(buffer));
changes.push({ changes.push({
path: `gallery/avatars/${key}${avatar.extension}`, path: `gallery/avatars/${key}${avatar.extension}`,
content: Buffer.from(content), content,
}); });
bar.tick(); bar.tick();
@@ -83,7 +83,7 @@ export async function glossary() {
changes.push({ changes.push({
path: 'definitions/gallery.pb', path: 'definitions/gallery.pb',
content: encodePBBuffer(Gallery, gallery), content: Gallery.encode(gallery).finish(),
}); });
await commitAssets('glossary', changes); await commitAssets('glossary', changes);
@@ -32,7 +32,7 @@ export async function migration() {
await commitAssets('migration', [ await commitAssets('migration', [
{ {
path: 'definitions/migration.json', path: 'definitions/migration.json',
content: Buffer.from(JSON.stringify(map)), content: new TextEncoder().encode(JSON.stringify(map)),
}, },
]); ]);
} }
@@ -1,6 +1,5 @@
import { import {
assertSecret, assertSecret,
encodePBBuffer,
fetchTankDefinitions, fetchTankDefinitions,
PopularTanks, PopularTanks,
} from '@blitzkit/core'; } from '@blitzkit/core';
@@ -70,7 +69,7 @@ export async function popularTanks() {
await commitAssets('popular tanks', [ await commitAssets('popular tanks', [
{ {
path: 'definitions/popular-tanks.pb', path: 'definitions/popular-tanks.pb',
content: encodePBBuffer(PopularTanks, popularTanks), content: PopularTanks.encode(popularTanks).finish(),
}, },
]); ]);
} }
@@ -29,10 +29,11 @@ export async function tankArmors() {
const id = toUniqueId(nation, tank.id); const id = toUniqueId(nation, tank.id);
const model = await extractArmor(DATA, `${nation}-${tankKey}`); const model = await extractArmor(DATA, `${nation}-${tankKey}`);
const content = await nodeIO.writeBinary(model);
changes.push({ changes.push({
path: `3d/tanks/armor/${id}.glb`, path: `3d/tanks/armor/${id}.glb`,
content: Buffer.from(await nodeIO.writeBinary(model)), content,
}); });
}), }),
); );
@@ -1,7 +1,7 @@
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 { readdir, writeFile } from 'fs/promises';
import { extractModel } from '../core/blitz/extractModel'; import { extractModel } from '../core/blitz/extractModel';
import { readXMLDVPL } from '../core/blitz/readXMLDVPL'; import { readXMLDVPL } from '../core/blitz/readXMLDVPL';
import { readYAMLDVPL } from '../core/blitz/readYAMLDVPL'; import { readYAMLDVPL } from '../core/blitz/readYAMLDVPL';
@@ -33,6 +33,8 @@ export async function tankModels() {
const id = toUniqueId(nation, tank.id); const id = toUniqueId(nation, tank.id);
if (id !== 21777) continue;
const parameters = await readYAMLDVPL<TankParameters>( const parameters = await readYAMLDVPL<TankParameters>(
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`, `${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`,
); );
@@ -41,6 +43,8 @@ export async function tankModels() {
parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, ''), parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, ''),
); );
await writeFile('../../temp/model.glb', await nodeIO.writeBinary(model));
changes.push({ changes.push({
path: `3d/tanks/models/${id}.glb`, path: `3d/tanks/models/${id}.glb`,
content: Buffer.from(await nodeIO.writeBinary(model)), content: Buffer.from(await nodeIO.writeBinary(model)),
@@ -164,7 +164,7 @@ const content = RatingLeaderboard.encode({
const changes: FileChange[] = [ const changes: FileChange[] = [
{ {
path: `regions/${normalizedServer}/rating/${info.current_season}.pb`, path: `regions/${normalizedServer}/rating/${info.current_season}.pb`,
content: Buffer.from(content), content,
}, },
]; ];
@@ -1,12 +1,15 @@
import { DdsReadStream, PvrReadStream } from '@blitzkit/core'; import { DdsReadStream, PvrReadStream } from '@blitzkit/core';
import { existsSync } from 'fs'; import { existsSync } from 'fs';
import sharp from 'sharp'; import sharp from 'sharp';
import { DATA_COMPRESSED } from '../../../buildAssets/constants';
import { readDVPLFile } from '../readDVPLFile'; import { readDVPLFile } from '../readDVPLFile';
import { TextureMutation } from './constants'; import { TextureMutation } from './constants';
export async function readTexture(path: string, mutation?: TextureMutation) { export async function readTexture(path: string, mutation?: TextureMutation) {
const ddsTexturePath = path.replace('.tex', '.dx11.dds'); const ddsTexturePath = path.replace('.tex', '.dx11.dds');
const isDds = existsSync(`${ddsTexturePath}.dvpl`); const isDds = existsSync(
`${ddsTexturePath}${DATA_COMPRESSED ? '.dvpl' : ''}`,
);
const resolvedTexturePath = isDds const resolvedTexturePath = isDds
? ddsTexturePath ? ddsTexturePath
: ddsTexturePath.replace('.dds', '.pvr'); : ddsTexturePath.replace('.dds', '.pvr');
@@ -75,5 +78,4 @@ export async function readTexture(path: string, mutation?: TextureMutation) {
default: default:
return await sharp(raw.data, { raw }).jpeg().toBuffer(); return await sharp(raw.data, { raw }).jpeg().toBuffer();
} }
} }
@@ -1,11 +1,18 @@
import { asset } from '@blitzkit/core'; import { asset } from '@blitzkit/core';
import ProgressBar from 'progress'; import ProgressBar from 'progress';
import { compareUint8Arrays } from './compareUint8Arrays';
import { GithubChangeBlob, createBlob } from './createBlob'; import { GithubChangeBlob, createBlob } from './createBlob';
import { octokit } from './octokit'; import { octokit } from './octokit';
export interface FileChange { export interface FileChange {
path: string; path: string;
content: Buffer; content: Uint8Array;
}
enum DiffStatus {
New,
Changed,
Unchanged,
} }
const heuristicFormats = ['glb', 'webp', 'jpg', 'png']; const heuristicFormats = ['glb', 'webp', 'jpg', 'png'];
@@ -20,35 +27,44 @@ export async function commitMultipleFiles(
await Promise.all( await Promise.all(
changesRaw.map(async (change) => { changesRaw.map(async (change) => {
const response = await fetch(asset(change.path)); const response = await fetch(asset(change.path), {
let isNew: boolean; headers: { 'Accept-Encoding': 'identity' },
let isDifferent: boolean; });
let diff: number; let diff: { change: number; status: DiffStatus };
if (response.status === 404) { if (response.status === 404) {
isNew = true; diff = { change: change.content.length, status: DiffStatus.New };
diff = change.content.length;
isDifferent = true;
} else if ( } else if (
response.headers.has('Content-Length') && response.headers.has('Content-Length') &&
parseInt(response.headers.get('Content-Length')!) !== Number(response.headers.get('Content-Length')) !== change.content.length
change.content.length
) { ) {
isNew = false; diff = {
diff = change:
change.content.length - change.content.length -
parseInt(response.headers.get('Content-Length')!); Number(response.headers.get('Content-Length')),
isDifferent = true; status: DiffStatus.Changed,
};
} else if (response.status === 200) { } else if (response.status === 200) {
isNew = false; if (
const buffer = Buffer.from(await response.arrayBuffer()); heuristicFormats.some((format) => change.path.endsWith(`.${format}`))
) {
if (buffer.equals(new Uint8Array(change.content))) { /**
diff = 0; * Heuristic: if it's a large blob like a .glb, a diff = 0 might end
isDifferent = false; * up being a false positive with isDifferent = true. So, it's okay
* to assume it's unchanged.
*/
diff = { change: 0, status: DiffStatus.Unchanged };
} else { } else {
diff = change.content.length - buffer.length; const buffer = new Uint8Array(await response.arrayBuffer());
isDifferent = true;
if (compareUint8Arrays(buffer, change.content)) {
diff = { change: 0, status: DiffStatus.Unchanged };
} else {
diff = {
change: change.content.length - buffer.length,
status: DiffStatus.Changed,
};
}
} }
} else { } else {
throw new Error( throw new Error(
@@ -56,33 +72,15 @@ export async function commitMultipleFiles(
); );
} }
/** if (diff.status === DiffStatus.Unchanged) {
* Heuristic: if it's a large blob like a .glb, a diff = 0 might end up console.log(`🔵 (${diff.change.toLocaleString()}B) ${change.path}`);
* being a false positive with isDifferent = true. So, it's okay to
* assume it's unchanged.
*/
if (
diff === 0 &&
heuristicFormats.some((format) => change.path.endsWith(`.${format}`))
) {
isDifferent = false;
isNew = false;
}
if (isNew) {
console.log(
`🟢 (+${change.content.length.toLocaleString()}B) ${change.path}`,
);
changes.push(change);
} else if (isDifferent) {
console.log(
`🟡 (${diff > 0 ? '+' : ''}${diff.toLocaleString()}B) ${change.path}`,
);
changes.push(change);
} else { } else {
console.log( console.log(
`🔵 (${change.content.length.toLocaleString()}B) ${change.path}`, `${
diff.status === DiffStatus.New ? '🟢' : '🟡'
} (+${diff.change.toLocaleString()}B) ${change.path}`,
); );
changes.push(change);
} }
}), }),
); );
@@ -0,0 +1,9 @@
export function compareUint8Arrays(a: Uint8Array, b: Uint8Array) {
if (a.length !== b.length) return false;
for (let index = 0; index < a.length; index++) {
if (a[index] !== b[index]) return false;
}
return true;
}
@@ -20,7 +20,7 @@ export const createBlob = throttle(
await octokit.git.createBlob({ await octokit.git.createBlob({
owner, owner,
repo, repo,
content: change.content.toString('base64'), content: Buffer.from(change.content).toString('base64'),
encoding: 'base64', encoding: 'base64',
}) })
).data; ).data;
@@ -34,6 +34,7 @@ export const createBlob = throttle(
} catch (error) { } catch (error) {
console.warn( console.warn(
`Failed blob ${change.path}; retrying in ${TIME_PER_BLOB}ms...`, `Failed blob ${change.path}; retrying in ${TIME_PER_BLOB}ms...`,
error,
); );
await new Promise((resolve) => setTimeout(resolve, TIME_PER_BLOB)); await new Promise((resolve) => setTimeout(resolve, TIME_PER_BLOB));
+3 -6
View File
@@ -134,14 +134,12 @@ function post() {
const files = idsChunked.map((chunk, index) => { const files = idsChunked.map((chunk, index) => {
const didsWriteStream = new DidsWriteStream().dids(chunk); const didsWriteStream = new DidsWriteStream().dids(chunk);
const buffer = didsWriteStream.uint8Array; const buffer = didsWriteStream.uint8Array;
const compressed = compress(buffer); const content = compress(buffer);
console.log( console.log(
`Chunk ${index} with ${chunk.length} ids (compressed: ${compressed.length}; uncompressed: ${buffer.length})`, `Chunk ${index} with ${chunk.length} ids (compressed: ${content.length}; uncompressed: ${buffer.length})`,
); );
const content = Buffer.from(compressed);
return { return {
content, content,
path: `ids/${index}.dids.lz4`, path: `ids/${index}.dids.lz4`,
@@ -151,13 +149,12 @@ function post() {
commitAssets('discovered ids', [ commitAssets('discovered ids', [
...files, ...files,
{ {
content: Buffer.from( content: new TextEncoder().encode(
JSON.stringify({ JSON.stringify({
chunks: idsChunked.length, chunks: idsChunked.length,
count: ids.length, count: ids.length,
time: Date.now(), time: Date.now(),
} satisfies DiscoveredIdsDefinitions), } satisfies DiscoveredIdsDefinitions),
'utf-8',
), ),
path: 'ids/manifest.json', path: 'ids/manifest.json',
}, },
+1 -2
View File
@@ -1,6 +1,5 @@
import { import {
asset, asset,
encodePBBuffer,
fetchTankDefinitions, fetchTankDefinitions,
Reviews, Reviews,
Video, Video,
@@ -81,7 +80,7 @@ for (const tank of tanksSanitized) {
} }
await commitAssets('reviews', [ await commitAssets('reviews', [
{ {
content: encodePBBuffer(Reviews, reviews), content: Reviews.encode(reviews).finish(),
path: 'definitions/reviews.pb', path: 'definitions/reviews.pb',
}, },
]); ]);