mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-25 11:39:51 +01:00
feat: mode protos
This commit is contained in:
1 parent
370ef2df65
commit
9cced11199
23 files changed
+1789
-1714
No files matched your search
@@ -1,16 +1,10 @@
|
|||||||
|
import { CamouflageDefinitions } from '../protos';
|
||||||
import { asset } from './asset';
|
import { asset } from './asset';
|
||||||
import { fetchCdonLz4 } from './fetchCdonLz4';
|
|
||||||
|
|
||||||
export type CamouflageDefinitions = Record<
|
export async function fetchCamouflageDefinitions() {
|
||||||
number,
|
const response = await fetch(asset('definitions/camoufles.pb'));
|
||||||
{
|
const buffer = await response.arrayBuffer();
|
||||||
id: number;
|
const array = new Uint8Array(buffer);
|
||||||
name: string;
|
|
||||||
tankName?: string;
|
|
||||||
tankNameFull?: string;
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const camouflageDefinitions = fetchCdonLz4<CamouflageDefinitions>(
|
return CamouflageDefinitions.deserializeBinary(array).toObject();
|
||||||
asset('definitions/camouflages.cdon.lz4'),
|
}
|
||||||
);
|
|
||||||
@@ -1,47 +1,10 @@
|
|||||||
|
import { ConsumableDefinitions } from '../protos';
|
||||||
import { asset } from './asset';
|
import { asset } from './asset';
|
||||||
import { fetchCdonLz4 } from './fetchCdonLz4';
|
|
||||||
|
|
||||||
export type TankFilterDefinitionCategory = 'clip';
|
export async function fetchConsumableDefinitions() {
|
||||||
|
const response = await fetch(asset('definitions/consumables.pb'));
|
||||||
|
const buffer = await response.arrayBuffer();
|
||||||
|
const array = new Uint8Array(buffer);
|
||||||
|
|
||||||
export type TankFilterDefinition =
|
return ConsumableDefinitions.deserializeBinary(array).toObject();
|
||||||
| {
|
|
||||||
type: 'tier';
|
|
||||||
min: number;
|
|
||||||
max: number;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'ids';
|
|
||||||
ids: number[];
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'category';
|
|
||||||
categories: TankFilterDefinitionCategory[];
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'nation';
|
|
||||||
nations: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ConsumableEntry = {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
cooldown: number;
|
|
||||||
duration?: number;
|
|
||||||
} & (
|
|
||||||
| {
|
|
||||||
gameMode: false;
|
|
||||||
include: TankFilterDefinition[];
|
|
||||||
exclude?: TankFilterDefinition[];
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
gameMode: true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export interface ConsumableDefinitions {
|
|
||||||
[key: string]: ConsumableEntry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const consumableDefinitions = fetchCdonLz4<ConsumableDefinitions>(
|
|
||||||
asset('definitions/consumables.cdon.lz4'),
|
|
||||||
);
|
|
||||||
@@ -1,28 +1,10 @@
|
|||||||
|
import { EquipmentDefinitions } from '../protos';
|
||||||
import { asset } from './asset';
|
import { asset } from './asset';
|
||||||
import { fetchCdonLz4 } from './fetchCdonLz4';
|
|
||||||
|
|
||||||
type EquipmentOptions = [number, number];
|
export async function fetchEquipmentDefinitions() {
|
||||||
|
const response = await fetch(asset('definitions/equipment.pb'));
|
||||||
|
const buffer = await response.arrayBuffer();
|
||||||
|
const array = new Uint8Array(buffer);
|
||||||
|
|
||||||
export type EquipmentRow = [
|
return EquipmentDefinitions.deserializeBinary(array).toObject();
|
||||||
EquipmentOptions,
|
|
||||||
EquipmentOptions,
|
|
||||||
EquipmentOptions,
|
|
||||||
];
|
|
||||||
|
|
||||||
export type EquipmentPreset = [EquipmentRow, EquipmentRow, EquipmentRow];
|
|
||||||
|
|
||||||
export interface EquipmentDefinitions {
|
|
||||||
presets: {
|
|
||||||
[key: string]: EquipmentPreset;
|
|
||||||
};
|
|
||||||
equipments: {
|
|
||||||
[key: number]: {
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const equipmentDefinitions = fetchCdonLz4<EquipmentDefinitions>(
|
|
||||||
asset('definitions/equipment.cdon.lz4'),
|
|
||||||
);
|
|
||||||
@@ -1,23 +1,10 @@
|
|||||||
|
import { GameDefinitions } from '../protos';
|
||||||
import { asset } from './asset';
|
import { asset } from './asset';
|
||||||
import { fetchCdonLz4 } from './fetchCdonLz4';
|
|
||||||
|
|
||||||
interface GameMode {
|
export async function fetchGameDefinitions() {
|
||||||
name: string;
|
const response = await fetch(asset('definitions/game.pb'));
|
||||||
|
const buffer = await response.arrayBuffer();
|
||||||
|
const array = new Uint8Array(buffer);
|
||||||
|
|
||||||
|
return GameDefinitions.deserializeBinary(array).toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GameDefinitions {
|
|
||||||
version: string;
|
|
||||||
nations: string[];
|
|
||||||
gameModes: Record<number, GameMode>;
|
|
||||||
roles: Record<
|
|
||||||
number,
|
|
||||||
{
|
|
||||||
provisions: number[];
|
|
||||||
consumables: number[];
|
|
||||||
}
|
|
||||||
>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const gameDefinitions = fetchCdonLz4<GameDefinitions>(
|
|
||||||
asset('definitions/game.cdon.lz4'),
|
|
||||||
);
|
|
||||||
@@ -1,64 +1,10 @@
|
|||||||
import { Vector3Tuple } from 'three';
|
import { ModelDefinitions } from '../protos';
|
||||||
import { asset } from './asset';
|
import { asset } from './asset';
|
||||||
import { fetchCdonLz4 } from './fetchCdonLz4';
|
|
||||||
|
|
||||||
export type ModelDefinitions = Record<number, ModelDefinition>;
|
export async function fetchModelDefinitions() {
|
||||||
|
const response = await fetch(asset('definitions/models.pb'));
|
||||||
|
const buffer = await response.arrayBuffer();
|
||||||
|
const array = new Uint8Array(buffer);
|
||||||
|
|
||||||
export interface ModelArmor {
|
return ModelDefinitions.deserializeBinary(array).toObject();
|
||||||
thickness: Record<number, number>;
|
|
||||||
spaced?: number[];
|
|
||||||
// dynamic?: Record<`${boolean}`, number[]>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BoundingBox {
|
|
||||||
min: Vector3Tuple;
|
|
||||||
max: Vector3Tuple;
|
|
||||||
}
|
|
||||||
export interface ModelDefinition {
|
|
||||||
armor: ModelArmor;
|
|
||||||
turretOrigin: Vector3Tuple;
|
|
||||||
turretRotation?: InitialTurretRotation;
|
|
||||||
turrets: Record<number, TurretModelDefinition>;
|
|
||||||
tracks: Record<number, TrackDefinition>;
|
|
||||||
boundingBox: BoundingBox;
|
|
||||||
}
|
|
||||||
interface TrackDefinition {
|
|
||||||
thickness: number;
|
|
||||||
origin: Vector3Tuple;
|
|
||||||
}
|
|
||||||
export interface InitialTurretRotation {
|
|
||||||
yaw: number;
|
|
||||||
pitch: number;
|
|
||||||
roll: number;
|
|
||||||
}
|
|
||||||
interface TurretModelDefinition {
|
|
||||||
boundingBox: BoundingBox;
|
|
||||||
armor: ModelArmor;
|
|
||||||
model: number;
|
|
||||||
gunOrigin: Vector3Tuple;
|
|
||||||
guns: Record<number, GunModelDefinition>;
|
|
||||||
yaw?: YawLimits;
|
|
||||||
}
|
|
||||||
export interface YawLimits {
|
|
||||||
min: number;
|
|
||||||
max: number;
|
|
||||||
}
|
|
||||||
interface GunModelDefinition {
|
|
||||||
armor: ModelArmor;
|
|
||||||
thickness: number;
|
|
||||||
model: number;
|
|
||||||
pitch: PitchLimits;
|
|
||||||
mask?: number;
|
|
||||||
}
|
|
||||||
export interface PitchLimits {
|
|
||||||
min: number;
|
|
||||||
max: number;
|
|
||||||
|
|
||||||
front?: { min: number; max: number; range: number };
|
|
||||||
back?: { min: number; max: number; range: number };
|
|
||||||
transition?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const modelDefinitions = fetchCdonLz4<ModelDefinitions>(
|
|
||||||
asset('definitions/models.cdon.lz4'),
|
|
||||||
);
|
|
||||||
@@ -1,26 +1,10 @@
|
|||||||
|
import { ProvisionDefinitions } from '../protos';
|
||||||
import { asset } from './asset';
|
import { asset } from './asset';
|
||||||
import { TankFilterDefinition } from './consumableDefinitions';
|
|
||||||
import { fetchCdonLz4 } from './fetchCdonLz4';
|
|
||||||
|
|
||||||
export type ProvisionEntry = {
|
export async function fetchProvisionDefinitions() {
|
||||||
id: number;
|
const response = await fetch(asset('definitions/provisions.pb'));
|
||||||
name: string;
|
const buffer = await response.arrayBuffer();
|
||||||
crew?: number;
|
const array = new Uint8Array(buffer);
|
||||||
} & (
|
|
||||||
| {
|
|
||||||
gameMode: false;
|
|
||||||
include: TankFilterDefinition[];
|
|
||||||
exclude?: TankFilterDefinition[];
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
gameMode: true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export interface ProvisionDefinitions {
|
return ProvisionDefinitions.deserializeBinary(array).toObject();
|
||||||
[key: string]: ProvisionEntry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const provisionDefinitions = fetchCdonLz4<ProvisionDefinitions>(
|
|
||||||
asset('definitions/provisions.cdon.lz4'),
|
|
||||||
);
|
|
||||||
@@ -6,5 +6,5 @@ export async function fetchReviews() {
|
|||||||
const buffer = await response.arrayBuffer();
|
const buffer = await response.arrayBuffer();
|
||||||
const array = new Uint8Array(buffer);
|
const array = new Uint8Array(buffer);
|
||||||
|
|
||||||
return Reviews.deserializeBinary(array);
|
return Reviews.deserializeBinary(array).toObject();
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
|
import { SkillDefinitions } from '../protos';
|
||||||
import { asset } from './asset';
|
import { asset } from './asset';
|
||||||
import { fetchCdonLz4 } from './fetchCdonLz4';
|
|
||||||
import { TankClass } from './tankDefinitions';
|
|
||||||
|
|
||||||
export interface SkillDefinitions {
|
export async function fetchSkillDefinitions() {
|
||||||
classes: Record<TankClass, string[]>;
|
const response = await fetch(asset('definitions/skills.pb'));
|
||||||
|
const buffer = await response.arrayBuffer();
|
||||||
|
const array = new Uint8Array(buffer);
|
||||||
|
|
||||||
|
return SkillDefinitions.deserializeBinary(array).toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
export const skillDefinitions = fetchCdonLz4<SkillDefinitions>(
|
|
||||||
asset('definitions/skills.cdon.lz4'),
|
|
||||||
);
|
|
||||||
@@ -6,7 +6,7 @@ export async function fetchTankDefinitions() {
|
|||||||
const buffer = await response.arrayBuffer();
|
const buffer = await response.arrayBuffer();
|
||||||
const array = new Uint8Array(buffer);
|
const array = new Uint8Array(buffer);
|
||||||
|
|
||||||
return TankDefinitions.deserializeBinary(array);
|
return TankDefinitions.deserializeBinary(array).toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
export * from './constants';
|
export * from './constants';
|
||||||
@@ -8,4 +8,4 @@ export * from './math';
|
|||||||
export * from './patreon';
|
export * from './patreon';
|
||||||
export * from './statistics';
|
export * from './statistics';
|
||||||
// export * from './streams';
|
// export * from './streams';
|
||||||
// export * from './types';
|
export * from './types';
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package blitzkit;
|
||||||
|
|
||||||
|
message CamouflageDefinitions {
|
||||||
|
map<uint32, Camouflage> camouflages = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Camouflage {
|
||||||
|
uint32 id = 1;
|
||||||
|
string name = 2;
|
||||||
|
optional string tank_name = 3;
|
||||||
|
optional string tank_name_full = 4;
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package blitzkit;
|
||||||
|
|
||||||
|
import "packages/core/src/protos/raw/tank_definitions.proto";
|
||||||
|
|
||||||
|
message ConsumableDefinitions {
|
||||||
|
map<uint32, Consumable> consumables = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Consumable {
|
||||||
|
uint32 id = 1;
|
||||||
|
string name = 2;
|
||||||
|
uint32 cooldown = 3;
|
||||||
|
optional uint32 duration = 4;
|
||||||
|
bool game_mode_exclusive = 5;
|
||||||
|
repeated ConsumableTankFilter include = 6;
|
||||||
|
repeated ConsumableTankFilter exclude = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConsumableTankFilter {
|
||||||
|
oneof filter_type {
|
||||||
|
ConsumableTankTierFilter tier = 1;
|
||||||
|
ConsumableTankIdsFilter ids = 2;
|
||||||
|
ConsumableTankCategoryFilter category = 3;
|
||||||
|
ConsumableTankNationFilter nation = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConsumableTankTierFilter {
|
||||||
|
Tier min = 1;
|
||||||
|
Tier max = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConsumableTankIdsFilter {
|
||||||
|
repeated uint32 ids = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConsumableTankCategoryFilter {
|
||||||
|
repeated ConsumableTankCategoryFilterCategory categories = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ConsumableTankCategoryFilterCategory {
|
||||||
|
TANK_CATEGORY_UNSPECIFIED = 0;
|
||||||
|
TANK_CATEGORY_CLIP = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConsumableTankNationFilter {
|
||||||
|
repeated string nations = 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package blitzkit;
|
||||||
|
|
||||||
|
message EquipmentDefinitions {
|
||||||
|
map<string, EquipmentPreset> presets = 1;
|
||||||
|
map<uint32, Equipment> equipments = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Equipment {
|
||||||
|
string name = 1;
|
||||||
|
string description = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EquipmentPreset {
|
||||||
|
repeated EquipmentSlot slots = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EquipmentSlot {
|
||||||
|
uint32 left = 1;
|
||||||
|
uint32 right = 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package blitzkit;
|
||||||
|
|
||||||
|
message GameDefinitions {
|
||||||
|
string version = 1;
|
||||||
|
repeated string nations = 2;
|
||||||
|
map<uint32, GameMode> gameModes = 3;
|
||||||
|
map<uint32, GameModeRole> roles = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GameMode {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GameModeRole {
|
||||||
|
repeated uint32 provisions = 1;
|
||||||
|
repeated uint32 consumables = 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package blitzkit;
|
||||||
|
|
||||||
|
message ModelDefinitions {
|
||||||
|
map<uint32, ModelDefinition> models = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ModelDefinition {
|
||||||
|
Armor armor = 1;
|
||||||
|
Vector3 turret_origin = 2;
|
||||||
|
optional InitialTurretRotation initial_turret_rotation = 3;
|
||||||
|
map<uint32, TurretModelDefinition> turrets = 4;
|
||||||
|
map<uint32, TrackModelDefinition> tracks = 5;
|
||||||
|
BoundingBox bounding_box = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Armor {
|
||||||
|
map<uint32, uint32> thickness = 1;
|
||||||
|
repeated uint32 spaced = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Vector3 {
|
||||||
|
float x = 1;
|
||||||
|
float y = 2;
|
||||||
|
float z = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InitialTurretRotation {
|
||||||
|
float yaw = 1;
|
||||||
|
float pitch = 2;
|
||||||
|
float roll = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TurretModelDefinition {
|
||||||
|
BoundingBox bounding_box = 1;
|
||||||
|
Armor armor = 2;
|
||||||
|
uint32 model_id = 3;
|
||||||
|
Vector3 gun_origin = 4;
|
||||||
|
map<uint32, GunModelDefinition> guns = 5;
|
||||||
|
optional YawLimits yaw = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message YawLimits {
|
||||||
|
float min = 1;
|
||||||
|
float max = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BoundingBox {
|
||||||
|
Vector3 min = 1;
|
||||||
|
Vector3 max = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrackModelDefinition {
|
||||||
|
uint32 thickness = 1;
|
||||||
|
Vector3 origin = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GunModelDefinition {
|
||||||
|
Armor armor = 1;
|
||||||
|
uint32 thickness = 2;
|
||||||
|
uint32 model_id = 3;
|
||||||
|
PitchLimits pitch = 4;
|
||||||
|
optional float mask = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PitchLimits {
|
||||||
|
float min = 1;
|
||||||
|
float max = 2;
|
||||||
|
optional PitchLimitsExtrema front = 3;
|
||||||
|
optional PitchLimitsExtrema back = 4;
|
||||||
|
optional float transition = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PitchLimitsExtrema {
|
||||||
|
float min = 1;
|
||||||
|
float max = 2;
|
||||||
|
float range = 3;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package blitzkit;
|
||||||
|
|
||||||
|
import "packages/core/src/protos/raw/consumable_definitions.proto";
|
||||||
|
|
||||||
|
message ProvisionDefinitions {
|
||||||
|
map<uint32, Provision> provisions = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Provision {
|
||||||
|
uint32 id = 1;
|
||||||
|
string name = 2;
|
||||||
|
optional float crew = 3;
|
||||||
|
bool game_mode_exclusive = 5;
|
||||||
|
repeated ConsumableTankFilter include = 6;
|
||||||
|
repeated ConsumableTankFilter exclude = 7;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package blitzkit;
|
||||||
|
|
||||||
|
message SkillDefinitions {
|
||||||
|
// enums are disallowed as keys so using uint32; convert run-time
|
||||||
|
map<uint32, Skill> classes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Skill {
|
||||||
|
repeated string skills = 1;
|
||||||
|
}
|
||||||
@@ -84,7 +84,7 @@ message TurretDefinition {
|
|||||||
float traverse_speed = 4;
|
float traverse_speed = 4;
|
||||||
optional uint32 xp = 5;
|
optional uint32 xp = 5;
|
||||||
string name = 6;
|
string name = 6;
|
||||||
uint32 tier = 7;
|
Tier tier = 7;
|
||||||
uint32 weight = 8;
|
uint32 weight = 8;
|
||||||
repeated GunDefinition guns = 9;
|
repeated GunDefinition guns = 9;
|
||||||
repeated Unlock unlocks = 10;
|
repeated Unlock unlocks = 10;
|
||||||
@@ -135,7 +135,7 @@ message GunDefinitionBase {
|
|||||||
optional uint32 xp = 3;
|
optional uint32 xp = 3;
|
||||||
uint32 weight = 4;
|
uint32 weight = 4;
|
||||||
string name = 5;
|
string name = 5;
|
||||||
uint32 tier = 6;
|
Tier tier = 6;
|
||||||
repeated ShellDefinition shells = 7;
|
repeated ShellDefinition shells = 7;
|
||||||
float camouflage_loss = 8;
|
float camouflage_loss = 8;
|
||||||
float aim_time = 9;
|
float aim_time = 9;
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
export * from './pbMap';
|
||||||
export * from './tanksStats';
|
export * from './tanksStats';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export type PBMap<T> = T[keyof T] extends number ? T[keyof T] : never;
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
"decompress": "^4.2.1",
|
"decompress": "^4.2.1",
|
||||||
"csv-parse": "^5.5.6",
|
"csv-parse": "^5.5.6",
|
||||||
"googleapis": "^134.0.0",
|
"googleapis": "^134.0.0",
|
||||||
|
"@blitzkit/core": "workspace:*",
|
||||||
"fast-xml-parser": "^4.4.1"
|
"fast-xml-parser": "^4.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user