mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 03:29:51 +02:00
Merge branch 'main' into dev
This commit is contained in:
commit
2928db2727
75 files changed
+1732
-7937
No files matched your search
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { fetchCdonLz4 } from './fetchCdonLz4';
|
||||
|
||||
export interface GameDefinitions {
|
||||
version: string;
|
||||
nations: string[];
|
||||
}
|
||||
|
||||
export const gameDefinitions = fetchCdonLz4<GameDefinitions>(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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: {
|
||||
|
||||
@@ -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: '🇩🇪',
|
||||
|
||||
@@ -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))
|
||||
);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
Reference in new issue
Block a user