mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 11:39:50 +02:00
feat: start of proto only
This commit is contained in:
1 parent
d90a3cc010
commit
45dc99e1ce
19 files changed
+365
-891
No files matched your search
@@ -1,7 +0,0 @@
|
||||
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>(buffer));
|
||||
}
|
||||
@@ -13,7 +13,6 @@ export * from './degressiveStat';
|
||||
// export * from './emblemURL';
|
||||
export * from './equipmentDefinitions';
|
||||
export * from './eventManager';
|
||||
// export * from './fetchCdonLz4';
|
||||
// export * from './flagUserActivity';
|
||||
export * from './gameDefinitions';
|
||||
// export * from './getArchivedLatestSeasonNumber';
|
||||
@@ -36,8 +35,6 @@ export * from './resolvePenetrationCoefficient';
|
||||
export * from './reviews';
|
||||
export * from './skillDefinitions';
|
||||
export * from './sum';
|
||||
export * from './superCompress';
|
||||
export * from './superDecompress';
|
||||
export * from './tankDefinitions';
|
||||
export * from './tankIcon';
|
||||
export * from './tankNames';
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { compress } from 'lz4js';
|
||||
import { CdonWriteStream } from '../streams';
|
||||
|
||||
export function superCompress(object: any) {
|
||||
const write = new CdonWriteStream().cdon(object);
|
||||
const compressed = compress(write.uint8Array);
|
||||
return Buffer.from(compressed).toString('base64');
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { decompress } from 'lz4js';
|
||||
import { CdonReadStream } from '../streams';
|
||||
|
||||
export function superDecompress<Type>(buffer: ArrayBuffer) {
|
||||
const decompressed = decompress(new Uint8Array(buffer)).buffer as ArrayBuffer;
|
||||
const read = new CdonReadStream(decompressed);
|
||||
return read.cdon() as Type;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import {
|
||||
CrewMember,
|
||||
CrewType,
|
||||
GunDefinition,
|
||||
ShellType,
|
||||
TankClass,
|
||||
TankType,
|
||||
Tier,
|
||||
TreeType,
|
||||
} from '.';
|
||||
|
||||
export const SHELL_NAMES: Record<ShellType, string> = {
|
||||
@@ -13,7 +13,7 @@ export const SHELL_NAMES: Record<ShellType, string> = {
|
||||
hc: 'HEAT',
|
||||
he: 'HE',
|
||||
};
|
||||
export const CREW_MEMBER_NAMES: Record<CrewMember, string> = {
|
||||
export const CREW_MEMBER_NAMES: Record<CrewType, string> = {
|
||||
commander: 'Commander',
|
||||
radioman: 'Radioman',
|
||||
gunner: 'Gunner',
|
||||
@@ -77,7 +77,7 @@ export const flags: Record<string, string> = {
|
||||
european: '🇪🇺',
|
||||
other: '<:other:1218421572243558482>',
|
||||
};
|
||||
export const TREE_TYPE_ICONS: Record<TreeType, Record<TankClass, string>> = {
|
||||
export const TREE_TYPE_ICONS: Record<TankType, Record<TankClass, string>> = {
|
||||
researchable: TANK_ICONS,
|
||||
premium: TANK_ICONS_PREMIUM,
|
||||
collector: TANK_ICONS_COLLECTOR,
|
||||
|
||||
@@ -1,27 +1,48 @@
|
||||
import { Vector2Tuple } from 'three';
|
||||
import { TANK_CLASSES, TREE_TYPES } from '../../blitz/constants';
|
||||
import { asset } from '../asset';
|
||||
import { fetchCdonLz4 } from '../fetchCdonLz4';
|
||||
import { TIERS } from './constants';
|
||||
|
||||
export type TankClass = (typeof TANK_CLASSES)[number];
|
||||
export type TreeType = (typeof TREE_TYPES)[number];
|
||||
export enum TankClass {
|
||||
Unspecified,
|
||||
Light,
|
||||
Medium,
|
||||
Heavy,
|
||||
TankDestroyer,
|
||||
}
|
||||
export enum TankType {
|
||||
Unspecified,
|
||||
Researchable,
|
||||
Premium,
|
||||
Collector,
|
||||
}
|
||||
|
||||
export enum ShellType {
|
||||
AP = 'ap',
|
||||
APCR = 'ap_cr',
|
||||
HEAT = 'hc',
|
||||
HE = 'he',
|
||||
Unspecified,
|
||||
AP,
|
||||
APCR,
|
||||
HEAT,
|
||||
HE,
|
||||
}
|
||||
|
||||
export enum CrewType {
|
||||
Unspecified,
|
||||
Commander,
|
||||
Radioman,
|
||||
Gunner,
|
||||
Driver,
|
||||
Loader,
|
||||
}
|
||||
|
||||
export type CrewMember =
|
||||
| 'commander'
|
||||
| 'radioman'
|
||||
| 'gunner'
|
||||
| 'driver'
|
||||
| 'loader';
|
||||
export type TankDefinitions = Record<number, TankDefinition>;
|
||||
export type ModuleType = 'vehicle' | 'engine' | 'chassis' | 'turret' | 'gun';
|
||||
export enum ModuleType {
|
||||
Unspecified,
|
||||
Vehicle,
|
||||
Engine,
|
||||
Tracks,
|
||||
Turret,
|
||||
Gun,
|
||||
}
|
||||
|
||||
export interface Unlock {
|
||||
type: ModuleType;
|
||||
id: number;
|
||||
@@ -32,9 +53,9 @@ export interface Unlock {
|
||||
};
|
||||
}
|
||||
export interface Crew {
|
||||
type: CrewMember;
|
||||
type: CrewType;
|
||||
count?: number;
|
||||
substitute?: CrewMember[];
|
||||
substitute?: CrewType[];
|
||||
}
|
||||
export type ModuleDefinition =
|
||||
| TrackDefinition
|
||||
@@ -45,18 +66,18 @@ export interface TankDefinition {
|
||||
id: number;
|
||||
roles: Record<number, number>;
|
||||
description?: string;
|
||||
fixedCamouflage?: boolean;
|
||||
camouflages?: number[];
|
||||
ancestors?: number[];
|
||||
successors?: number[];
|
||||
fixed_camouflage: boolean;
|
||||
camouflages: number[];
|
||||
ancestors: number[];
|
||||
successors: number[];
|
||||
crew: Crew[];
|
||||
health: number;
|
||||
nation: string;
|
||||
name: string;
|
||||
nameFull?: string;
|
||||
treeType: TreeType;
|
||||
consumables: number;
|
||||
provisions: number;
|
||||
type: TankType;
|
||||
max_consumables: number;
|
||||
max_provisions: number;
|
||||
tier: Tier;
|
||||
class: TankClass;
|
||||
testing: boolean;
|
||||
@@ -66,16 +87,12 @@ export interface TankDefinition {
|
||||
tracks: TrackDefinition[];
|
||||
price: TankPrice;
|
||||
xp?: number;
|
||||
speed: {
|
||||
forwards: number;
|
||||
backwards: number;
|
||||
};
|
||||
camouflage: {
|
||||
still: number;
|
||||
moving: number;
|
||||
onFire: number;
|
||||
};
|
||||
equipment: string;
|
||||
speed_forwards: number;
|
||||
speed_backwards: number;
|
||||
camouflage_still: number;
|
||||
camouflage_moving: number;
|
||||
camouflage_onFire: number;
|
||||
equipment_preset: string;
|
||||
weight: number;
|
||||
}
|
||||
export interface TrackDefinition {
|
||||
@@ -83,17 +100,13 @@ export interface TrackDefinition {
|
||||
tier: Tier;
|
||||
name: string;
|
||||
weight: number;
|
||||
traverseSpeed: number;
|
||||
traverse_speed: number;
|
||||
xp?: number;
|
||||
dispersion: {
|
||||
move: number;
|
||||
traverse: number;
|
||||
};
|
||||
resistance: {
|
||||
hard: number;
|
||||
medium: number;
|
||||
soft: number;
|
||||
};
|
||||
dispersion_move: number;
|
||||
dispersion_traverse: number;
|
||||
resistance_hard: number;
|
||||
resistance_medium: number;
|
||||
resistance_soft: number;
|
||||
unlocks?: Unlock[];
|
||||
}
|
||||
export interface EngineDefinition {
|
||||
@@ -101,18 +114,24 @@ export interface EngineDefinition {
|
||||
name: string;
|
||||
xp?: number;
|
||||
tier: Tier;
|
||||
fireChance: number;
|
||||
fire_chance: number;
|
||||
power: number;
|
||||
weight: number;
|
||||
unlocks?: Unlock[];
|
||||
}
|
||||
export type TankPrice =
|
||||
| { type: 'credits'; value: number }
|
||||
| { type: 'gold'; value: number };
|
||||
export type TankPrice = {
|
||||
type: TankPriceType;
|
||||
value: number;
|
||||
};
|
||||
enum TankPriceType {
|
||||
Unspecified,
|
||||
Credits,
|
||||
Gold,
|
||||
}
|
||||
export interface TurretDefinition {
|
||||
health: number;
|
||||
viewRange: number;
|
||||
traverseSpeed: number;
|
||||
view_range: number;
|
||||
traverse_speed: number;
|
||||
xp?: number;
|
||||
id: number;
|
||||
name: string;
|
||||
@@ -126,52 +145,60 @@ export type GunDefinition =
|
||||
| GunDefinitionAutoLoader
|
||||
| GunDefinitionAutoReloader;
|
||||
interface GunDefinitionBase {
|
||||
rotationSpeed: number;
|
||||
rotation_speed: number;
|
||||
xp?: number;
|
||||
weight: number;
|
||||
id: number;
|
||||
name: string;
|
||||
tier: Tier;
|
||||
shells: ShellDefinition[];
|
||||
camouflageLoss: number;
|
||||
aimTime: number;
|
||||
dispersion: {
|
||||
base: number;
|
||||
traverse: number;
|
||||
shot: number;
|
||||
damaged: number;
|
||||
};
|
||||
camouflage_loss: number;
|
||||
aim_time: number;
|
||||
dispersion_base: number;
|
||||
dispersion_traverse: number;
|
||||
dispersion_shot: number;
|
||||
dispersion_damaged: number;
|
||||
unlocks?: Unlock[];
|
||||
}
|
||||
interface GunDefinitionRegular extends GunDefinitionBase {
|
||||
type: 'regular';
|
||||
interface GunDefinitionRegular {
|
||||
gun: GunDefinitionBase;
|
||||
regular: GunDefinitionRegularProperties;
|
||||
}
|
||||
interface GunDefinitionRegularProperties {
|
||||
reload: number;
|
||||
}
|
||||
interface GunDefinitionAutoLoader extends GunDefinitionBase {
|
||||
type: 'autoLoader';
|
||||
interface GunDefinitionAutoLoader {
|
||||
gun: GunDefinitionBase;
|
||||
auto_loader: GunDefinitionAutoLoaderProperties;
|
||||
}
|
||||
interface GunDefinitionAutoLoaderProperties {
|
||||
reload: number;
|
||||
intraClip: number;
|
||||
intra_clip: number;
|
||||
count: number;
|
||||
}
|
||||
interface GunDefinitionAutoReloader extends GunDefinitionBase {
|
||||
type: 'autoReloader';
|
||||
interface GunDefinitionAutoReloader {
|
||||
gun: GunDefinitionBase;
|
||||
auto_reloader: GunDefinitionAutoReloaderProperties;
|
||||
}
|
||||
interface GunDefinitionAutoReloaderProperties {
|
||||
reload: number[];
|
||||
intraClip: number;
|
||||
count: number;
|
||||
}
|
||||
export type ShellDefinition = {
|
||||
export interface ShellDefinition {
|
||||
id: number;
|
||||
name: string;
|
||||
speed: number;
|
||||
damage: { armor: number; module: number };
|
||||
velocity: number;
|
||||
armor_damage: number;
|
||||
module_damage: number;
|
||||
caliber: number;
|
||||
icon: string;
|
||||
penetration: number | Vector2Tuple;
|
||||
type: ShellType;
|
||||
normalization?: number;
|
||||
ricochet?: number;
|
||||
explosionRadius?: number;
|
||||
};
|
||||
explosion_radius?: number;
|
||||
}
|
||||
|
||||
export const tankDefinitions = fetchCdonLz4<TankDefinitions>(
|
||||
asset('definitions/tanks.cdon.lz4'),
|
||||
@@ -180,6 +207,18 @@ export const tankDefinitions = fetchCdonLz4<TankDefinitions>(
|
||||
export const tankDefinitionsArray = tankDefinitions.then((tanks) =>
|
||||
Object.values(tanks),
|
||||
);
|
||||
export type Tier = (typeof TIERS)[number];
|
||||
export enum Tier {
|
||||
Unspecified,
|
||||
I,
|
||||
II,
|
||||
III,
|
||||
IV,
|
||||
V,
|
||||
VI,
|
||||
VII,
|
||||
VIII,
|
||||
IX,
|
||||
X,
|
||||
}
|
||||
|
||||
export * from './constants';
|
||||
@@ -1,10 +1,11 @@
|
||||
import protobuf from 'protobufjs';
|
||||
import average_definitions from '../../protos/average_definitions.proto?raw';
|
||||
import reviews from '../../protos/reviews.proto?raw';
|
||||
import average_definitions from '../../protos/average_definitions.proto';
|
||||
import reviews from '../../protos/reviews.proto';
|
||||
import tank_definitions from '../../protos/tank_definitions.proto';
|
||||
|
||||
export type ProtoSource = keyof typeof protos;
|
||||
|
||||
const protos = { reviews, average_definitions };
|
||||
const protos = { reviews, average_definitions, tank_definitions };
|
||||
|
||||
export function lookupProtobufType(source: ProtoSource, type: string) {
|
||||
return protobuf.parse(protos[source]).root.lookupType(type);
|
||||
|
||||
@@ -1,375 +0,0 @@
|
||||
import { times } from 'lodash-es';
|
||||
import { ReadStream, WriteStream } from './buffer';
|
||||
|
||||
enum ValueType {
|
||||
Null,
|
||||
Boolean,
|
||||
Uint8,
|
||||
Uint16,
|
||||
Uint32,
|
||||
Uint64,
|
||||
Int8,
|
||||
Int16,
|
||||
Int32,
|
||||
Int64,
|
||||
Float32,
|
||||
Float64,
|
||||
String,
|
||||
FastString,
|
||||
Array,
|
||||
Object,
|
||||
}
|
||||
|
||||
enum FastStringFormat {
|
||||
Format8,
|
||||
Format16,
|
||||
Format32,
|
||||
}
|
||||
|
||||
export type CdonValue =
|
||||
| undefined
|
||||
| null
|
||||
| boolean
|
||||
| number
|
||||
| bigint
|
||||
| string
|
||||
| CdonValue[]
|
||||
| { [key: string]: CdonValue };
|
||||
|
||||
export class CdonReadStream extends ReadStream {
|
||||
cdon() {
|
||||
this.magic();
|
||||
const header = this.header();
|
||||
const body = this.body(header.fastStringFormat, header.stringTable);
|
||||
return body;
|
||||
}
|
||||
|
||||
magic() {
|
||||
const magic = this.utf8(4);
|
||||
|
||||
if (magic !== 'CDON') {
|
||||
throw new Error(`Invalid CDON magic number: "${magic}"`);
|
||||
}
|
||||
}
|
||||
|
||||
header() {
|
||||
const version = this.uint16();
|
||||
const fastStringFormat = this.uint8() as FastStringFormat;
|
||||
|
||||
return {
|
||||
version,
|
||||
fastStringFormat,
|
||||
stringTable: this.stringTable(fastStringFormat),
|
||||
};
|
||||
}
|
||||
|
||||
body(
|
||||
fastStringFormat: FastStringFormat,
|
||||
stringTable: Record<number, string>,
|
||||
) {
|
||||
return this.value(fastStringFormat, stringTable);
|
||||
}
|
||||
|
||||
stringTable(fastStringFormat: FastStringFormat) {
|
||||
let count: number;
|
||||
|
||||
switch (fastStringFormat) {
|
||||
case FastStringFormat.Format8:
|
||||
count = this.uint8();
|
||||
break;
|
||||
|
||||
case FastStringFormat.Format16:
|
||||
count = this.uint16();
|
||||
break;
|
||||
|
||||
case FastStringFormat.Format32:
|
||||
count = this.uint32();
|
||||
break;
|
||||
}
|
||||
|
||||
const strings: string[] = [];
|
||||
|
||||
for (let index = 0; index < count; index++) {
|
||||
strings.push(this.string());
|
||||
}
|
||||
|
||||
const table: Record<number, string> = {};
|
||||
times(count, (index) => (table[index] = strings[index]));
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
string() {
|
||||
const length = this.uint32();
|
||||
const string = this.utf8(length);
|
||||
return string;
|
||||
}
|
||||
|
||||
value(
|
||||
fastStringFormat: FastStringFormat,
|
||||
stringTable: Record<number, string>,
|
||||
): CdonValue {
|
||||
const type = this.uint8() as ValueType;
|
||||
|
||||
switch (type) {
|
||||
case ValueType.Null:
|
||||
return null;
|
||||
|
||||
case ValueType.Boolean:
|
||||
return this.boolean();
|
||||
|
||||
case ValueType.Uint8:
|
||||
return this.uint8();
|
||||
|
||||
case ValueType.Uint16:
|
||||
return this.uint16();
|
||||
|
||||
case ValueType.Uint32:
|
||||
return this.uint32();
|
||||
|
||||
case ValueType.Uint64:
|
||||
return this.uint64();
|
||||
|
||||
case ValueType.Int8:
|
||||
return this.int8();
|
||||
|
||||
case ValueType.Int16:
|
||||
return this.int16();
|
||||
|
||||
case ValueType.Int32:
|
||||
return this.int32();
|
||||
|
||||
case ValueType.Int64:
|
||||
return this.int64();
|
||||
|
||||
case ValueType.Float32:
|
||||
return this.float32();
|
||||
|
||||
case ValueType.Float64:
|
||||
return this.float64();
|
||||
|
||||
case ValueType.String:
|
||||
return this.string();
|
||||
|
||||
case ValueType.FastString: {
|
||||
switch (fastStringFormat) {
|
||||
case FastStringFormat.Format8:
|
||||
return stringTable[this.uint8()];
|
||||
|
||||
case FastStringFormat.Format16:
|
||||
return stringTable[this.uint16()];
|
||||
|
||||
case FastStringFormat.Format32:
|
||||
return stringTable[this.uint32()];
|
||||
}
|
||||
}
|
||||
|
||||
case ValueType.Array:
|
||||
return times(this.uint32(), () =>
|
||||
this.value(fastStringFormat, stringTable),
|
||||
);
|
||||
|
||||
case ValueType.Object: {
|
||||
const count = this.uint32();
|
||||
const keys = times(
|
||||
count,
|
||||
() => this.value(fastStringFormat, stringTable) as string,
|
||||
);
|
||||
const values = times(count, () =>
|
||||
this.value(fastStringFormat, stringTable),
|
||||
);
|
||||
const object: Record<string, CdonValue> = {};
|
||||
|
||||
keys.forEach((string, index) => (object[string] = values[index]));
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`Invalid value type: ${type}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class CdonWriteStream extends WriteStream {
|
||||
cdon(object: CdonValue) {
|
||||
this.magic();
|
||||
const header = this.header(object);
|
||||
this.body(header.fastStringFormat, object, header.stringTable);
|
||||
return this;
|
||||
}
|
||||
|
||||
body(
|
||||
fastStringFormat: FastStringFormat,
|
||||
object: CdonValue,
|
||||
stringTable: Map<string, number>,
|
||||
) {
|
||||
this.value(fastStringFormat, object, stringTable);
|
||||
return this;
|
||||
}
|
||||
|
||||
value(
|
||||
fastStringFormat: FastStringFormat,
|
||||
object: CdonValue,
|
||||
stringTable: Map<string, number>,
|
||||
) {
|
||||
if (object === null || object === undefined) {
|
||||
this.uint8(ValueType.Null);
|
||||
} else if (typeof object === 'boolean') {
|
||||
this.uint8(ValueType.Boolean);
|
||||
this.uint8(object ? 1 : 0);
|
||||
} else if (typeof object === 'number') {
|
||||
if (object % 1 === 0) {
|
||||
if (object < 0) {
|
||||
if (object < -0x80000000) {
|
||||
this.uint8(ValueType.Int64);
|
||||
this.int64(BigInt(object));
|
||||
} else if (object < -0x8000) {
|
||||
this.uint8(ValueType.Int32);
|
||||
this.int32(object);
|
||||
} else if (object < -0x80) {
|
||||
this.uint8(ValueType.Int16);
|
||||
this.int16(object);
|
||||
} else {
|
||||
this.uint8(ValueType.Int8);
|
||||
this.int8(object);
|
||||
}
|
||||
} else {
|
||||
if (object > 0x7fffffff) {
|
||||
this.uint8(ValueType.Uint64);
|
||||
this.uint64(BigInt(object));
|
||||
} else if (object > 0x7fff) {
|
||||
this.uint8(ValueType.Uint32);
|
||||
this.uint32(object);
|
||||
} else if (object > 0x7f) {
|
||||
this.uint8(ValueType.Uint16);
|
||||
this.uint16(object);
|
||||
} else {
|
||||
this.uint8(ValueType.Uint8);
|
||||
this.uint8(object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (object < -0x80000000 || object > 0x7fffffff) {
|
||||
this.uint8(ValueType.Float64);
|
||||
this.float64(object);
|
||||
} else {
|
||||
this.uint8(ValueType.Float32);
|
||||
this.float32(object);
|
||||
}
|
||||
}
|
||||
} else if (typeof object === 'bigint') {
|
||||
if (object < 0) {
|
||||
this.int64(object);
|
||||
} else {
|
||||
this.uint64(object);
|
||||
}
|
||||
} else if (typeof object === 'string') {
|
||||
if (stringTable.has(object)) {
|
||||
this.uint8(ValueType.FastString);
|
||||
const id = stringTable.get(object)!;
|
||||
switch (fastStringFormat) {
|
||||
case FastStringFormat.Format8:
|
||||
this.uint8(id);
|
||||
break;
|
||||
|
||||
case FastStringFormat.Format16:
|
||||
this.uint16(id);
|
||||
break;
|
||||
|
||||
case FastStringFormat.Format32:
|
||||
this.uint32(id);
|
||||
}
|
||||
} else {
|
||||
this.uint8(ValueType.String);
|
||||
this.string(object);
|
||||
}
|
||||
} else if (Array.isArray(object)) {
|
||||
this.uint8(ValueType.Array);
|
||||
this.uint32(object.length);
|
||||
object.forEach((value) =>
|
||||
this.value(fastStringFormat, value, stringTable),
|
||||
);
|
||||
} else {
|
||||
const entries = Object.entries(object).filter(
|
||||
([, value]) => value !== undefined,
|
||||
);
|
||||
|
||||
this.uint8(ValueType.Object);
|
||||
this.uint32(entries.length);
|
||||
entries.forEach(([key]) =>
|
||||
this.value(fastStringFormat, key, stringTable),
|
||||
);
|
||||
entries.forEach(([, value]) =>
|
||||
this.value(fastStringFormat, value, stringTable),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
header(object: CdonValue) {
|
||||
this.uint16(1);
|
||||
return this.stringTable(object);
|
||||
}
|
||||
|
||||
stringTable(object: CdonValue) {
|
||||
const stringTable = this.buildStringTable(
|
||||
this.collectStringCounts(object, new Map()),
|
||||
);
|
||||
let fastStringFormat: FastStringFormat;
|
||||
|
||||
if (stringTable.size <= 0xff) {
|
||||
fastStringFormat = FastStringFormat.Format8;
|
||||
this.uint8(FastStringFormat.Format8);
|
||||
this.uint8(stringTable.size);
|
||||
} else if (stringTable.size <= 0xffff) {
|
||||
fastStringFormat = FastStringFormat.Format16;
|
||||
this.uint8(FastStringFormat.Format16);
|
||||
this.uint16(stringTable.size);
|
||||
} else {
|
||||
fastStringFormat = FastStringFormat.Format32;
|
||||
this.uint8(FastStringFormat.Format32);
|
||||
this.uint32(stringTable.size);
|
||||
}
|
||||
|
||||
stringTable.forEach((_index, string) => this.string(string));
|
||||
|
||||
return { fastStringFormat, stringTable };
|
||||
}
|
||||
|
||||
buildStringTable(stringCounts: Map<string, number>) {
|
||||
const stringTable = new Map<string, number>();
|
||||
|
||||
stringCounts.forEach((count, string) => {
|
||||
if (count > 1) stringTable.set(string, stringTable.size);
|
||||
});
|
||||
|
||||
return stringTable;
|
||||
}
|
||||
|
||||
collectStringCounts(object: CdonValue, stringCounts: Map<string, number>) {
|
||||
if (typeof object === 'string') {
|
||||
if (stringCounts.has(object)) {
|
||||
stringCounts.set(object, stringCounts.get(object)! + 1);
|
||||
} else {
|
||||
stringCounts.set(object, 1);
|
||||
}
|
||||
} else if (object instanceof Array) {
|
||||
object.forEach((value) => this.collectStringCounts(value, stringCounts));
|
||||
} else if (object instanceof Object) {
|
||||
Object.entries(object).forEach((strings) =>
|
||||
this.collectStringCounts(strings, stringCounts),
|
||||
);
|
||||
}
|
||||
|
||||
return stringCounts;
|
||||
}
|
||||
|
||||
string(value: string) {
|
||||
this.uint32(Buffer.byteLength(value));
|
||||
this.utf8(value);
|
||||
}
|
||||
|
||||
magic() {
|
||||
this.utf8('CDON');
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
export * from './bkrl';
|
||||
export * from './buffer';
|
||||
export * from './cdon';
|
||||
export * from './dds';
|
||||
export * from './dids';
|
||||
export * from './pvr';
|
||||
|
||||
Reference in new issue
Block a user