Merge branch 'main' into dev

This commit is contained in:
TrèsAbhi committed 2024-06-26 13:18:47 -05:00
commit 2928db2727
75 files changed
+1732 -7937

No files matched your search

+6 -2
View File
@@ -12,8 +12,12 @@ import { readDVPLFile } from './readDVPLFile';
export async function extractArmor(data: string, fileName: string) {
const sc2Path = `${data}/3d/Tanks/CollisionMeshes/${fileName}.sc2.dvpl`;
const scgPath = `${data}/3d/Tanks/CollisionMeshes/${fileName}.scg.dvpl`;
const sc2 = new Sc2ReadStream((await readDVPLFile(sc2Path)).buffer).sc2();
const scg = new ScgReadStream((await readDVPLFile(scgPath)).buffer).scg();
const sc2 = new Sc2ReadStream(
(await readDVPLFile(sc2Path)).buffer as ArrayBuffer,
).sc2();
const scg = new ScgReadStream(
(await readDVPLFile(scgPath)).buffer as ArrayBuffer,
).scg();
const document = new Document();
const scene = document.createScene();
const buffer = document.createBuffer();
+6 -2
View File
@@ -23,8 +23,12 @@ const omitMeshNames = {
export async function extractModel(data: string, path: string) {
const sc2Path = `${data}/3d/${path}.sc2.dvpl`;
const scgPath = `${data}/3d/${path}.scg.dvpl`;
const sc2 = new Sc2ReadStream((await readDVPLFile(sc2Path)).buffer).sc2();
const scg = new ScgReadStream((await readDVPLFile(scgPath)).buffer).scg();
const sc2 = new Sc2ReadStream(
(await readDVPLFile(sc2Path)).buffer as ArrayBuffer,
).sc2();
const scg = new ScgReadStream(
(await readDVPLFile(scgPath)).buffer as ArrayBuffer,
).scg();
const document = new Document();
const scene = document.createScene();
const buffer = document.createBuffer();
+17 -8
View File
@@ -1,9 +1,8 @@
import { crc32 } from 'crc';
import { decodeBlock } from 'lz4';
import { decompressBlock } from 'lz4js';
/**
* Thanks Maddoxkkm! Modernized heavily.
*
* Thanks Maddoxkkm! Modified heavily to be modern.
* https://github.com/Maddoxkkm/dvpl_converter/
*/
export function readDVPL(buffer: Buffer) {
@@ -30,6 +29,7 @@ export function readDVPL(buffer: Buffer) {
if (crc32(targetBlock) !== footerData.crc32) {
throw new TypeError('DVPL CRC32 mismatch');
}
if (footerData.type === 0) {
if (!(footerData.oSize === footerData.cSize && footerData.type === 0)) {
throw new RangeError('DVPL type and size mismatch');
@@ -37,14 +37,23 @@ export function readDVPL(buffer: Buffer) {
return targetBlock;
} else if (footerData.type === 1 || footerData.type === 2) {
const deDVPLBlock = Buffer.alloc(footerData.oSize);
const DecompressedBlockSize = decodeBlock(targetBlock, deDVPLBlock);
const source = new Uint8Array(targetBlock);
const destination = new Uint8Array(footerData.oSize);
const decompressedSize = decompressBlock(
source,
destination,
0,
source.length,
0,
);
if (DecompressedBlockSize !== footerData.oSize) {
throw new RangeError('Decompressed DVPL size mismatch');
if (decompressedSize !== footerData.oSize) {
throw new RangeError(
`Decompressed DVPL size mismatch (${decompressedSize} vs ${footerData.oSize})`,
);
}
return deDVPLBlock;
return Buffer.from(destination);
} else {
throw new SyntaxError('Unknown DVPL format');
}
+11 -3
View File
@@ -1,5 +1,5 @@
import { crc32 } from 'crc';
import { encodeBlockHC } from 'lz4';
import { compressBlock } from 'lz4js';
/**
* Thanks Maddoxkkm! Modernized heavily.
@@ -7,8 +7,16 @@ import { encodeBlockHC } from 'lz4';
* https://github.com/Maddoxkkm/dvpl_converter/
*/
export function writeDVPL(buffer: Buffer) {
let output = Buffer.alloc(buffer.length);
const compressedBlockSize = encodeBlockHC(buffer, output);
const source = new Uint8Array(buffer);
const destination = new Uint8Array(buffer.length);
const compressedBlockSize = compressBlock(
source,
destination,
0,
source.length,
0,
);
let output = Buffer.from(destination);
if (compressedBlockSize === 0 || compressedBlockSize >= buffer.length) {
const footerBuffer = toDVPLFooter(
+3 -9
View File
@@ -1,3 +1,4 @@
import ProgressBar from 'progress';
import { GithubChangeBlob, createBlob } from './createBlob';
import { octokit } from './octokit';
@@ -30,21 +31,14 @@ export default async function commitMultipleFiles(
})
).data.tree.sha;
const blobs: GithubChangeBlob[] = [];
const bar = new ProgressBar('Blobs :bar', changes.length);
for (const changeIndexString in changes) {
const changeIndex = parseInt(changeIndexString);
const change = changes[changeIndex];
const createdBlob = await createBlob(owner, repo, change);
blobs.push(createdBlob!);
if (verbose) {
console.log(
`Created blob ${changeIndex + 1} / ${changes.length} (${(
(100 * (changeIndex + 1)) /
changes.length
).toFixed(2)}%)`,
);
}
bar.tick();
}
const { data: treeData } = await octokit.git.createTree({
+1 -1
View File
@@ -3,5 +3,5 @@ import { superDecompress } from './superDecompress';
export async function fetchCdonLz4<Type>(url: string) {
return await fetch(url, { cache: 'no-store' })
.then((response) => response.arrayBuffer())
.then((buffer) => superDecompress<Type>(new Uint8Array(buffer)));
.then((buffer) => superDecompress<Type>(buffer));
}
+1
View File
@@ -3,6 +3,7 @@ import { fetchCdonLz4 } from './fetchCdonLz4';
export interface GameDefinitions {
version: string;
nations: string[];
}
export const gameDefinitions = fetchCdonLz4<GameDefinitions>(
+1 -3
View File
@@ -27,9 +27,7 @@ export default async function getArchivedRatingInfo(
)
.then((response) => response.arrayBuffer())
.then((buffer) =>
superDecompress<RatingInfo & { detail: undefined }>(
new Uint8Array(buffer),
),
superDecompress<RatingInfo & { detail: undefined }>(buffer),
);
cache[region][season] = info;
}
+23
View File
@@ -0,0 +1,23 @@
export async function patientFetchJSON<Type extends object>(
url: string,
timeout = 1000,
options?: Partial<{ cache: 'no-store' }>,
) {
let patientJSON: Type;
while (patientJSON! === undefined) {
try {
patientJSON = (await fetch(url, options).then((response) =>
response.json(),
)) as Type;
} catch (error) {
console.warn(
`Failed to fetch ${url} as JSON; retrying in ${timeout}ms...`,
error,
);
await new Promise((resolve) => setTimeout(resolve, timeout));
}
}
return patientJSON;
}
+2 -2
View File
@@ -14,8 +14,8 @@ export async function readTexture(path: string, mutation?: TextureMutation) {
const decompressedDvpl = await readDVPLFile(resolvedTexturePath);
const raw = isDds
? await new DdsReadStream(decompressedDvpl.buffer).dds()
: new PvrReadStream(decompressedDvpl.buffer).pvr();
? await new DdsReadStream(decompressedDvpl.buffer as ArrayBuffer).dds()
: new PvrReadStream(decompressedDvpl.buffer as ArrayBuffer).pvr();
switch (mutation) {
case TextureMutation.Normal: {
+1 -1
View File
@@ -2,7 +2,7 @@ import { decompress } from 'lz4js';
import { CdonReadStream } from '../streams/cdon';
export function superDecompress<Type>(buffer: ArrayBuffer) {
const decompressed = decompress(new Uint8Array(buffer)).buffer;
const decompressed = decompress(new Uint8Array(buffer)).buffer as ArrayBuffer;
const read = new CdonReadStream(decompressed);
return read.cdon() as Type;
}
@@ -19,18 +19,27 @@ export const GUN_TYPE_NAMES: Record<GunDefinition['type'], string> = {
autoLoader: 'Auto loader',
autoReloader: 'Auto reloader',
};
/**
* @deprecated use svg
*/
export const TANK_ICONS: Record<TankClass, string> = {
'AT-SPG': 'https://i.imgur.com/BIHSEH0.png',
lightTank: 'https://i.imgur.com/CSNha5V.png',
mediumTank: 'https://i.imgur.com/wvf3ltm.png',
heavyTank: 'https://i.imgur.com/ECeqlZa.png',
};
/**
* @deprecated use svg
*/
export const TANK_ICONS_PREMIUM: Record<TankClass, string> = {
'AT-SPG': 'https://i.imgur.com/TCu3EdR.png',
lightTank: 'https://i.imgur.com/zdkpTRb.png',
mediumTank: 'https://i.imgur.com/3z7eHX6.png',
heavyTank: 'https://i.imgur.com/P3vbmyA.png',
};
/**
* @deprecated use svg
*/
export const TANK_ICONS_COLLECTOR: Record<TankClass, string> = {
'AT-SPG': 'https://i.imgur.com/WTjeirB.png',
lightTank: 'https://i.imgur.com/EwhtKkU.png',
@@ -197,17 +197,6 @@ export const tankNames = tanksDefinitionsArray.then((tanks) =>
export type Tier = (typeof TIERS)[number];
export const NATIONS = tanksDefinitionsArray.then((tanks) => {
const nations = Array.from(
new Set<string>(Object.values(tanks).map((tank) => tank.nation)),
);
nations.splice(nations.indexOf('other'), 1);
nations.push('other');
return nations;
});
export const flags: Record<string, string> = {
ussr: '<:ussr:1218421042033197197>',
germany: '🇩🇪',
+17
View File
@@ -0,0 +1,17 @@
import { TankopediaFilters } from '../../stores/tankopediaFilters';
import { TankDefinition } from './tankDefinitions';
export function tankopediaFilterTank(
filters: TankopediaFilters,
tank: TankDefinition,
) {
return (
(filters.tier === undefined || filters.tier === tank.tier) &&
(filters.nation === undefined || filters.nation === tank.nation) &&
(filters.class === undefined || filters.class === tank.class) &&
(filters.type === undefined || filters.type === tank.treeType) &&
(filters.testing === 'include' ||
(filters.testing === 'only' && tank.testing) ||
(filters.testing === 'exclude' && !tank.testing))
);
}
+4 -3
View File
@@ -3,7 +3,7 @@ import {
SlashCommandSubcommandBuilder,
SlashCommandSubcommandGroupBuilder,
} from 'discord.js';
import { NATIONS } from '../blitzkit/tankDefinitions';
import { gameDefinitions } from '../blitzkit/gameDefinitions';
import { addFilterOptions } from './addFilterOptions';
import { addPeriodSubCommands } from './addPeriodSubCommands';
@@ -15,9 +15,10 @@ export default async function addPeriodicFilterOptions<
option: SlashCommandSubcommandBuilder,
) => SlashCommandSubcommandBuilder = (option) => option,
): Promise<OptionType> {
const nations = await NATIONS;
const awaitedGameDefinitions = await gameDefinitions;
addPeriodSubCommands(option, (option) =>
addFilterOptions(extra(option), nations),
addFilterOptions(extra(option), awaitedGameDefinitions.nations),
);
return option;
@@ -8,6 +8,7 @@ import {
MessageEditOptions,
} from 'discord.js';
import { InteractionReturnable } from '../../events/interactionCreate';
import { Writeable } from '../../types/writable';
import jsxToPngThreaded from '../blitzkit/jsxToPngThreaded';
import { RenderConfiguration } from '../blitzkit/renderConfiguration';
@@ -30,7 +31,7 @@ export default async function normalizeInteractionReturnable(
reply.content = item;
} else if (item instanceof EmbedBuilder) {
if (!reply.embeds) reply.embeds = [];
reply.embeds.push(item);
(reply.embeds as Writeable<typeof reply.embeds>).push(item);
} else if (item instanceof ButtonBuilder) {
if (!reply.components)
reply.components = [new ActionRowBuilder<ButtonBuilder>()];
@@ -39,7 +40,7 @@ export default async function normalizeInteractionReturnable(
);
} else if (item instanceof AttachmentBuilder) {
if (!reply.files) reply.files = [];
reply.files.push(item);
(reply.files as Writeable<typeof reply.files>).push(item);
} else if (item instanceof RenderConfiguration) {
renderConfiguration = item;
} else if (item === null) {
@@ -54,7 +55,9 @@ export default async function normalizeInteractionReturnable(
if (images.length > 0) {
images.sort(([a], [b]) => b - a);
if (!reply.files) reply.files = [];
images.forEach(([, image]) => reply.files?.push(image));
images.forEach(([, image]) =>
(reply.files as Writeable<typeof reply.files>)?.push(image),
);
}
return reply;
+1 -1
View File
@@ -54,6 +54,6 @@ export class WotbReplayReadStream extends ReadStream {
}
const replay = await readFile('temp/test3.wotbreplay');
const stream = new WotbReplayReadStream(replay.buffer);
const stream = new WotbReplayReadStream(replay.buffer as ArrayBuffer);
stream.wotbReplay();