Compare commits

...
4 Commits
Author SHA1 Message Date
tresabhi 1c382022a7 proto3 2026-09-27 17:24:48 -05:00
tresabhi 593ae760e7 proto imports 2026-09-27 17:19:39 -05:00
tresabhi 127c55ec93 migrate to soapstone 2026-09-27 17:04:15 -05:00
tresabhi e5b44d4eb8 flatten armor dir 2026-09-27 16:46:22 -05:00
104 changed files with 465 additions and 594 deletions

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
---
name: proto-workflow
description: Regenerate this repository's TypeScript protobuf outputs after editing .proto schemas.
---
# Proto Workflow
After editing any `.proto` schema in this repository, run `bun run build-protos` from the repository root. Review the generated changes and address any schema or generator errors before finishing the task.
+13
View File
@@ -0,0 +1,13 @@
---
name: repo-boundaries
description: Apply the user's persistent repository boundaries whenever working in their projects.
---
# Repo Boundaries
Apply these boundaries to all work in the user's repositories:
- Read-only Git commands are allowed when useful, including status, diff, log, and show. Do not run Git commands that modify repository state.
- Never edit `bun.lock`, including regenerating or formatting it. When dependency manifests change, leave the lockfile alone; the user will update it by running `bun install`.
These are firm constraints, not preferences to revisit for a task. Continue useful work within them and explain any limitation if a requested result would require crossing either boundary.
@@ -0,0 +1,3 @@
interface:
display_name: "Repo Boundaries"
short_description: "Respect repository editing boundaries"
-1
View File
@@ -13,7 +13,6 @@ If you intend to contribute to the code, note that you may need to check out sen
| [packages/core](packages/core) | | | Mutual internal code shared between all other packages. |
| [packages/i18n](packages/i18n) | | [Crowdin](https://crowdin.com/project/blitzkrieg) | Translations served as JSON shared across all other packages, including some utility code. |
| [packages/scripts](packages/scripts) | | | CLI utilities for the development and deployment of BlitzKit services. |
| [packages/varuna](packages/varuna) | Varuna | [NPM](https://www.npmjs.com/package/varuna) | React and Astro-oriented state management library, awaiting separation from BlitzKit. Unavailable from NPM at this time. |
| [packages/website](packages/website) | BlitzKit | https://blitzkit.app | The BlitzKit website provides a wide range of tools, APIs, and interconnects all other services. |
## Submodules
+9 -12
View File
@@ -93,15 +93,6 @@
"yaml": "^2.8.1",
},
},
"packages/varuna": {
"name": "varuna",
"dependencies": {
"@types/lodash-es": "^4.17.12",
"immer": "^10.1.3",
"lodash-es": "^4.17.21",
"react": "^19.1.1",
},
},
"packages/website": {
"name": "@blitzkit/website",
"dependencies": {
@@ -141,12 +132,12 @@
"react-dom": "^19.2.4",
"react-error-boundary": "^6.1.3",
"react-promise-suspense": "^0.3.4",
"soapstone": "^1.0.0",
"three": "^0.180.0",
"three-stdlib": "^2.36.0",
"transliteration": "^2.6.1",
"typescript": "^5.9.3",
"urlon": "^3.1.0",
"varuna": "workspace:*",
"vite": "^7.1.9",
},
},
@@ -2162,6 +2153,8 @@
"smol-toml": ["[email protected]", "", {}, "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g=="],
"soapstone": ["[email protected]", "", { "dependencies": { "immer": "^11.1.8", "lodash-es": "^4.18.1", "react": "^19.2.7" }, "peerDependencies": { "typescript": "^5" } }, "sha512-Jlf8aCY9aCvgQR3y/aGhkXyC7vAox05J+dply+0wm567UIOYlCiwSR1MhAkZIRIXtOnoUERBrVz4mDYBrQYBDA=="],
"socks": ["[email protected]", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
"socks-proxy-agent": ["[email protected]", "", { "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww=="],
@@ -2392,8 +2385,6 @@
"uzip-module": ["[email protected]", "", {}, "sha512-AMqwWZaknLM77G+VPYNZLEruMGWGzyigPK3/Whg99B3S6vGHuqsyl5ZrOv1UUF3paGK1U6PM0cnayioaryg/fA=="],
"varuna": ["varuna@workspace:packages/varuna"],
"vfile": ["[email protected]", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-location": ["[email protected]", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
@@ -2692,6 +2683,12 @@
"simple-swizzle/is-arrayish": ["[email protected]", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
"soapstone/immer": ["[email protected]", "", {}, "sha512-EQyQtLiYW029lyoczMl/Hh4Xu7cDecSc58JRYpHyL4tIAu3eqd1yJzQX04d2BZHDkzFFvm6qJEJWOtfDSWAXbQ=="],
"soapstone/lodash-es": ["[email protected]", "", {}, "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="],
"soapstone/react": ["[email protected]", "", {}, "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog=="],
"source-map-support/source-map": ["[email protected]", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"stats-gl/three": ["[email protected]", "", {}, "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="],
@@ -1,47 +1,47 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
message AverageDefinitions {
map<uint32, AverageDefinitionsEntry> averages = 1;
required Samples samples = 2;
required uint64 time = 3;
Samples samples = 2;
uint64 time = 3;
}
message AverageDefinitionsEntry {
required AverageDefinitionsAllStats mu = 1;
required AverageDefinitionsAllStats sigma = 2;
required AverageDefinitionsAllStats r = 3;
required Samples samples = 4;
AverageDefinitionsAllStats mu = 1;
AverageDefinitionsAllStats sigma = 2;
AverageDefinitionsAllStats r = 3;
Samples samples = 4;
}
message AverageDefinitionsAllStats {
required float battles = 1;
required float capture_points = 2;
required float damage_dealt = 3;
required float damage_received = 4;
required float dropped_capture_points = 5;
required float frags = 6;
required float frags8p = 7;
required float hits = 8;
required float losses = 9;
required float max_frags = 10;
required float max_xp = 11;
required float shots = 12;
required float spotted = 13;
required float survived_battles = 14;
required float win_and_survived = 15;
required float wins = 16;
required float xp = 17;
required float battle_life_time = 18;
float battles = 1;
float capture_points = 2;
float damage_dealt = 3;
float damage_received = 4;
float dropped_capture_points = 5;
float frags = 6;
float frags8p = 7;
float hits = 8;
float losses = 9;
float max_frags = 10;
float max_xp = 11;
float shots = 12;
float spotted = 13;
float survived_battles = 14;
float win_and_survived = 15;
float wins = 16;
float xp = 17;
float battle_life_time = 18;
}
message Samples {
required uint32 d_1 = 1;
required uint32 d_7 = 2;
required uint32 d_30 = 3;
required uint32 d_60 = 4;
required uint32 d_90 = 5;
required uint32 d_120 = 6;
required uint32 total = 7;
uint32 d_1 = 1;
uint32 d_7 = 2;
uint32 d_30 = 3;
uint32 d_60 = 4;
uint32 d_90 = 5;
uint32 d_120 = 6;
uint32 total = 7;
}
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -9,8 +9,8 @@ message CamouflageDefinitions {
}
message Camouflage {
required uint32 id = 1;
required I18nString name = 2;
uint32 id = 1;
I18nString name = 2;
optional I18nString tank_name = 3;
optional I18nString tank_name_full = 4;
}
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -9,9 +9,9 @@ message ConsumableDefinitions {
}
message Consumable {
required uint32 id = 1;
required I18nString name = 2;
required bool game_mode_exclusive = 5;
uint32 id = 1;
I18nString name = 2;
bool game_mode_exclusive = 5;
repeated TankInclusivityFilter include = 6;
repeated TankInclusivityFilter exclude = 7;
}
@@ -26,8 +26,8 @@ message TankInclusivityFilter {
}
message ConsumableTankTierFilter {
required uint32 min = 1;
required uint32 max = 2;
uint32 min = 1;
uint32 max = 2;
}
message ConsumableTankIdsFilter {
+4 -4
View File
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -9,7 +9,7 @@ message Gallery {
}
message Avatar {
required string id = 1;
required I18nString name = 2;
required string extension = 3;
string id = 1;
I18nString name = 2;
string extension = 3;
}
@@ -1,18 +1,18 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
import "i18n.proto";
message GameDefinitions {
required string version = 1;
string version = 1;
repeated string nations = 2;
map<string, GameMode> gameModes = 3;
map<uint32, GameModeRole> roles = 4;
}
message GameMode {
required I18nString name = 1;
I18nString name = 1;
}
message GameModeRole {
+1 -1
View File
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -9,6 +9,6 @@ message MapDefinitions {
}
message MapDefinition {
required uint32 id = 1;
required I18nString name = 2;
uint32 id = 1;
I18nString name = 2;
}
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -7,12 +7,12 @@ message ModelDefinitions {
}
message ModelDefinition {
required Armor armor = 1;
required Vector3 turret_origin = 2;
Armor armor = 1;
Vector3 turret_origin = 2;
optional InitialTurretRotation initial_turret_rotation = 3;
map<uint32, TurretModelDefinition> turrets = 4;
map<uint32, TrackModelDefinition> tracks = 5;
required BoundingBox bounding_box = 6;
BoundingBox bounding_box = 6;
}
message Armor {
@@ -21,59 +21,59 @@ message Armor {
}
message Vector3 {
required float x = 1;
required float y = 2;
required float z = 3;
float x = 1;
float y = 2;
float z = 3;
}
message InitialTurretRotation {
required float yaw = 1;
required float pitch = 2;
required float roll = 3;
float yaw = 1;
float pitch = 2;
float roll = 3;
}
message TurretModelDefinition {
required BoundingBox bounding_box = 1;
required Armor armor = 2;
required uint32 model_id = 3;
required Vector3 gun_origin = 4;
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 {
required float min = 1;
required float max = 2;
float min = 1;
float max = 2;
}
message BoundingBox {
required Vector3 min = 1;
required Vector3 max = 2;
Vector3 min = 1;
Vector3 max = 2;
}
message TrackModelDefinition {
required float thickness = 1;
required Vector3 origin = 2;
float thickness = 1;
Vector3 origin = 2;
}
message GunModelDefinition {
required Armor armor = 1;
required float thickness = 2;
required uint32 model_id = 3;
required PitchLimits pitch = 4;
optional float mask = 5;
Armor armor = 1;
float thickness = 2;
uint32 model_id = 3;
PitchLimits pitch = 4;
optional float mask = 5;
}
message PitchLimits {
required float min = 1;
required float max = 2;
float min = 1;
float max = 2;
optional PitchLimitsExtrema front = 3;
optional PitchLimitsExtrema back = 4;
optional float transition = 5;
}
message PitchLimitsExtrema {
required float min = 1;
required float max = 2;
required float range = 3;
float min = 1;
float max = 2;
float range = 3;
}
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -7,6 +7,6 @@ message PopularTanks {
}
message PopularTank {
required uint32 id = 1;
required uint32 views = 2; // views in the last 7 days
uint32 id = 1;
uint32 views = 2; // views in the last 7 days
}
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -10,11 +10,10 @@ message ProvisionDefinitions {
}
message Provision {
reserved 3; // crew
required uint32 id = 1;
required I18nString name = 2;
required bool game_mode_exclusive = 5;
repeated TankInclusivityFilter include = 6;
repeated TankInclusivityFilter exclude = 7;
uint32 id = 1;
I18nString name = 2;
bool game_mode_exclusive = 3;
repeated TankInclusivityFilter include = 4;
repeated TankInclusivityFilter exclude = 5;
}
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -14,8 +14,8 @@ message RatingLeaderboardV1 {
}
message RatingLeaderboardEntryV1 {
required uint32 id = 1;
required uint32 score = 2;
uint32 id = 1;
uint32 score = 2;
}
message RatingLeaderboardV2 {
@@ -23,11 +23,11 @@ message RatingLeaderboardV2 {
}
message RatingLeaderboardEntryV2 {
required uint32 id = 1;
required uint32 score = 2;
required uint32 battles = 3;
required uint32 wins = 4;
required uint32 survived = 5;
required uint32 damage = 6;
required uint32 kills = 7;
uint32 id = 1;
uint32 score = 2;
uint32 battles = 3;
uint32 wins = 4;
uint32 survived = 5;
uint32 damage = 6;
uint32 kills = 7;
}
+4 -4
View File
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -7,11 +7,11 @@ message Reviews {
}
message Review {
required float last_updated = 1;
float last_updated = 1;
repeated Video videos = 2;
}
message Video {
required string id = 1;
required string author = 2;
string id = 1;
string author = 2;
}
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -1,4 +1,4 @@
syntax = "proto2";
syntax = "proto3";
package blitzkit;
@@ -9,46 +9,46 @@ message TankDefinitions {
}
message TankDefinition {
required uint32 id = 1;
required string slug = 2;
uint32 id = 1;
string slug = 2;
map<string, uint32> roles = 3;
required bool fixed_camouflage = 5;
bool fixed_camouflage = 5;
repeated int32 camouflages = 6;
repeated int32 ancestors = 7;
repeated int32 successors = 8;
repeated Crew crew = 9;
required uint32 health = 10;
required string nation = 11;
required I18nString name = 12;
required TankType type = 13;
required uint32 max_consumables = 14;
required uint32 max_provisions = 15;
required uint32 tier = 16;
required TankClass class = 17;
required bool testing = 18;
required bool deprecated = 19;
uint32 health = 10;
string nation = 11;
I18nString name = 12;
TankType type = 13;
uint32 max_consumables = 14;
uint32 max_provisions = 15;
uint32 tier = 16;
TankClass class = 17;
bool testing = 18;
bool deprecated = 19;
repeated TurretDefinition turrets = 20;
repeated EngineDefinition engines = 21;
repeated TrackDefinition tracks = 22;
required TankPrice price = 23;
TankPrice price = 23;
optional ResearchCost research_cost = 24;
required float speed_forwards = 25;
required float speed_backwards = 26;
required float camouflage_still = 27;
required float camouflage_moving = 28;
required float camouflage_on_fire = 29;
required string equipment_preset = 30;
required uint32 weight = 31;
required string dev_name = 32;
float speed_forwards = 25;
float speed_backwards = 26;
float camouflage_still = 27;
float camouflage_moving = 28;
float camouflage_on_fire = 29;
string equipment_preset = 30;
uint32 weight = 31;
string dev_name = 32;
optional Equalizer equalizer = 33;
}
message Equalizer {
required float health = 1;
required float penetration = 2;
required float module_health = 3;
required float damage = 4;
required float armor = 5;
float health = 1;
float penetration = 2;
float module_health = 3;
float damage = 4;
float armor = 5;
}
message ResearchCost {
@@ -59,8 +59,8 @@ message ResearchCost {
}
message ResearchCostSeasonalTokens {
required uint32 season = 1;
required uint32 tokens = 2;
uint32 season = 1;
uint32 tokens = 2;
}
enum TankPriceType {
@@ -69,45 +69,45 @@ enum TankPriceType {
}
message TankPrice {
required TankPriceType type = 1;
required uint32 value = 2;
TankPriceType type = 1;
uint32 value = 2;
}
message TrackDefinition {
required uint32 id = 1;
required uint32 tier = 2;
required I18nString name = 3;
required uint32 weight = 4;
required float traverse_speed = 5;
uint32 id = 1;
uint32 tier = 2;
I18nString name = 3;
uint32 weight = 4;
float traverse_speed = 5;
optional ResearchCost research_cost = 6;
required float dispersion_move = 7;
required float dispersion_traverse = 8;
required float resistance_hard = 9;
required float resistance_medium = 10;
required float resistance_soft = 11;
float dispersion_move = 7;
float dispersion_traverse = 8;
float resistance_hard = 9;
float resistance_medium = 10;
float resistance_soft = 11;
repeated Unlock unlocks = 12;
}
message EngineDefinition {
required uint32 id = 1;
required I18nString name = 2;
uint32 id = 1;
I18nString name = 2;
optional ResearchCost research_cost = 3;
required uint32 tier = 4;
required float fire_chance = 5;
required uint32 power = 6;
required uint32 weight = 7;
uint32 tier = 4;
float fire_chance = 5;
uint32 power = 6;
uint32 weight = 7;
repeated Unlock unlocks = 8;
}
message TurretDefinition {
required uint32 id = 1;
required uint32 health = 2;
required uint32 view_range = 3;
required float traverse_speed = 4;
uint32 id = 1;
uint32 health = 2;
uint32 view_range = 3;
float traverse_speed = 4;
optional ResearchCost research_cost = 5;
required I18nString name = 6;
required uint32 tier = 7;
required uint32 weight = 8;
I18nString name = 6;
uint32 tier = 7;
uint32 weight = 8;
repeated GunDefinition guns = 9;
repeated Unlock unlocks = 10;
}
@@ -119,44 +119,44 @@ message GunDefinition {
GunDefinitionAutoReloader auto_reloader = 3;
}
required uint32 id = 4;
required float rotation_speed = 5;
uint32 id = 4;
float rotation_speed = 5;
optional ResearchCost research_cost = 6;
required uint32 weight = 7;
required I18nString name = 8;
required uint32 tier = 9;
uint32 weight = 7;
I18nString name = 8;
uint32 tier = 9;
repeated ShellDefinition shells = 10;
required float camouflage_loss = 11;
required float aim_time = 12;
required float dispersion_base = 13;
required float dispersion_traverse = 14;
required float dispersion_shot = 15;
required float dispersion_damaged = 16;
float camouflage_loss = 11;
float aim_time = 12;
float dispersion_base = 13;
float dispersion_traverse = 14;
float dispersion_shot = 15;
float dispersion_damaged = 16;
repeated Unlock unlocks = 17;
required uint32 shell_capacity = 18;
uint32 shell_capacity = 18;
optional AssaultRanges assault_ranges = 19;
optional Burst burst = 20;
}
message GunDefinitionRegular {
required float reload = 1;
float reload = 1;
}
message GunDefinitionAutoLoader {
required float clip_reload = 1;
required float intra_clip = 2;
required float shell_count = 3;
float clip_reload = 1;
float intra_clip = 2;
float shell_count = 3;
}
message Burst {
required uint32 count = 1;
required float interval = 2;
uint32 count = 1;
float interval = 2;
}
message GunDefinitionAutoReloader {
repeated float shell_reloads = 1;
required float intra_clip = 2;
required float shell_count = 3;
float intra_clip = 2;
float shell_count = 3;
}
message AssaultRanges {
@@ -165,24 +165,24 @@ message AssaultRanges {
}
message AssaultRange {
required float distance = 1;
required float factor = 2;
float distance = 1;
float factor = 2;
}
message ShellDefinition {
required uint32 id = 1;
required I18nString name = 2;
required uint32 velocity = 3;
required uint32 armor_damage = 4;
required uint32 module_damage = 5;
required float caliber = 6;
required string icon = 7;
required ShellPenetration penetration = 8;
required ShellType type = 9;
optional float normalization = 10;
optional float ricochet = 11;
optional float explosion_radius = 12;
required uint32 range = 13;
uint32 id = 1;
I18nString name = 2;
uint32 velocity = 3;
uint32 armor_damage = 4;
uint32 module_damage = 5;
float caliber = 6;
string icon = 7;
ShellPenetration penetration = 8;
ShellType type = 9;
optional float normalization = 10;
optional float ricochet = 11;
optional float explosion_radius = 12;
uint32 range = 13;
}
enum ShellType {
@@ -193,19 +193,19 @@ enum ShellType {
}
message ShellPenetration {
required float near = 1;
required float far = 2;
float near = 1;
float far = 2;
}
message Unlock {
required int32 id = 1;
required ModuleType type = 2;
required UnlockCost cost = 3;
int32 id = 1;
ModuleType type = 2;
UnlockCost cost = 3;
}
message UnlockCost {
required string type = 1;
required int32 value = 2;
string type = 1;
int32 value = 2;
}
enum ModuleType {
@@ -230,8 +230,8 @@ enum TankType {
}
message Crew {
required CrewType type = 1;
required uint32 count = 2;
CrewType type = 1;
uint32 count = 2;
repeated CrewType substitute = 3;
}
+2 -1
View File
@@ -1,5 +1,6 @@
import { asset, Reviews, Video, youtubers } from "@blitzkit/core";
import { asset, youtubers } from "@blitzkit/core";
import locales from "@blitzkit/i18n/locales.json";
import { Reviews, Video } from "@blitzkit/protos";
import { google } from "googleapis";
import { cloneDeep, uniqBy } from "lodash-es";
import { AssetUploader } from "./core/github/assetUploader";
-11
View File
@@ -1,11 +0,0 @@
{
"name": "varuna",
"type": "module",
"main": "src/index.ts",
"dependencies": {
"@types/lodash-es": "^4.17.12",
"immer": "^10.1.3",
"lodash-es": "^4.17.21",
"react": "^19.1.1"
}
}
-125
View File
@@ -1,125 +0,0 @@
import { produce } from "immer";
import { debounce, merge } from "lodash-es";
import { useEffect, useRef, useState } from "react";
export class Varuna<Type, Arguments = void> {
private listeners = new Set<(state: Type) => void>();
private initialized = false;
private _initial?: Type;
private _state?: Type;
constructor(
private creator: Type | ((...args: Arguments[]) => Type),
private persistence?: string
) {
if (typeof creator !== "function") this.initialize(creator);
}
private initialize(initial: Type) {
let data = initial;
if (this.persistence && typeof localStorage !== "undefined") {
const dehydrated = localStorage.getItem(this.persistence);
if (dehydrated) {
const rehydrated = JSON.parse(dehydrated) as unknown;
data = merge(data, rehydrated);
}
window.addEventListener("beforeunload", this.store.bind(this));
}
this.initialized = true;
this._initial = data;
this._state = data;
}
useInitialization(...args: Arguments[]) {
const initializedThisMount = useRef(false);
if (initializedThisMount.current) return;
if (typeof this.creator !== "function") {
throw new Error("Provider must be used with a function creator");
}
this.initialize((this.creator as (...args: Arguments[]) => Type)(...args));
initializedThisMount.current = true;
}
private dispatch() {
const state = this.state;
this.listeners.forEach((callback) => callback(state));
}
on<Slice>(slicer: (state: Type) => Slice, callback: (state: Slice) => void) {
let last = slicer(this.state);
function listener(state: Type) {
const next = slicer(state);
if (next !== last) {
callback(next);
last = next;
}
}
this.listeners.add(listener);
return () => {
this.listeners.delete(listener);
};
}
mutate(mutator: (state: Type) => void) {
this.set(produce(this.state, mutator));
}
private assertInitialized() {
if (!this.initialized) {
throw new Error("Varuna store used before initialization");
}
}
get state() {
this.assertInitialized();
return this._state as Type;
}
set(state: Type) {
this.assertInitialized();
this._state = state;
this.dispatch();
this.storeDeferred();
}
get initial() {
this.assertInitialized();
return this._initial as Type;
}
use<Slice = Type>(
slicer: (state: Type) => Slice = (state) => state as unknown as Slice
) {
return this.useDeferred(slicer, slicer(this.state));
}
useDeferred<Slice = Type>(slicer: (state: Type) => Slice, initial: Slice) {
const instance = this;
const [slice, setSlice] = useState(initial);
useEffect(() => {
setSlice(slicer(instance.state));
return instance.on(slicer, setSlice);
}, []);
return slice;
}
store() {
localStorage.setItem(this.persistence!, JSON.stringify(this.state));
}
storeDeferred = debounce(this.store.bind(this), 500);
}
-3
View File
@@ -1,3 +0,0 @@
{
"extends": "../../tsconfig.json"
}
+1 -1
View File
@@ -45,12 +45,12 @@
"react-dom": "^19.2.4",
"react-error-boundary": "^6.1.3",
"react-promise-suspense": "^0.3.4",
"soapstone": "^1.0.0",
"three": "^0.180.0",
"three-stdlib": "^2.36.0",
"transliteration": "^2.6.1",
"typescript": "^5.9.3",
"urlon": "^3.1.0",
"varuna": "workspace:*",
"vite": "^7.1.9"
}
}
@@ -1,8 +0,0 @@
import { forwardRef, type ComponentProps } from "react";
import { Group } from "three";
export const ModelTankWrapper = forwardRef<Group, ComponentProps<"group">>(
(props, ref) => {
return <group rotation={[-Math.PI / 2, 0, 0]} ref={ref} {...props} />;
}
);
@@ -10,11 +10,11 @@ import {
import { Html } from "@react-three/drei";
import { useRef } from "react";
import { radToDeg } from "three/src/math/MathUtils.js";
import { resolveArmorIndex } from "../../../core/blitzkit/resolveArmorIndex";
import { LocaleProvider, useLocale } from "../../../hooks/useLocale";
import { App } from "../../../stores/app";
import { Duel } from "../../../stores/duel";
import { Tankopedia } from "../../../stores/tankopedia";
import { resolveArmorIndex } from "../core/blitzkit/resolveArmorIndex";
import { LocaleProvider, useLocale } from "../hooks/useLocale";
import { App } from "../stores/app";
import { Duel } from "../stores/duel";
import { Tankopedia } from "../stores/tankopedia";
import { layerTypeNames } from "./ShotDisplayCard";
import { ArmorType } from "./SpacedArmorScene";
@@ -1,4 +1,5 @@
import { alias, Avatar } from "@blitzkit/core";
import { alias } from "@blitzkit/core";
import { Avatar } from "@blitzkit/protos";
import { Cross1Icon, DownloadIcon } from "@radix-ui/react-icons";
import { useRef } from "react";
import { useIntersection } from "../hooks/useIntersection";
@@ -1,4 +1,5 @@
import { type TankDefinition, tankIcon } from "@blitzkit/core";
import { tankIcon } from "@blitzkit/core";
import type { TankDefinition } from "@blitzkit/protos";
import { useEffect, useRef } from "react";
import { Vector2 } from "three";
import { useLocale } from "../../hooks/useLocale";
@@ -1,4 +1,4 @@
import type { Consumable } from "@blitzkit/core";
import type { Consumable } from "@blitzkit/protos";
import { Flex, type FlexProps } from "@radix-ui/themes";
import { ConsumableButton } from "./ModuleButtons/ConsumableButton";
@@ -1,11 +1,11 @@
import { createPortal, useFrame, useThree } from "@react-three/fiber";
import { memo, useState } from "react";
import { DepthTexture, Scene, Vector2 } from "three";
import { PrimaryArmorScene } from "./components/PrimaryArmorScene";
import { spacedArmorRenderTarget } from "./components/PrimaryArmorSceneComponent/target";
import { SpacedArmorScene } from "./components/SpacedArmorScene";
import { spacedArmorRenderTarget } from "./PrimaryArmorRenderTarget";
import { PrimaryArmorScene } from "./PrimaryArmorScene";
import { SpacedArmorScene } from "./SpacedArmorScene";
export const Armor = memo(() => {
export const DynamicArmor = memo(() => {
const rootScene = useThree((state) => state.scene);
const [spacedArmorScene] = useState(() => new Scene());
const [primaryArmorScene] = useState(() => {
@@ -1,9 +1,9 @@
import type { EquipmentPreset } from '@blitzkit/core';
import { Flex } from '@radix-ui/themes';
import { chunk, cloneDeep } from 'lodash-es';
import type { EquipmentMatrix } from '../../stores/duel';
import { EquipmentButton } from '../ModuleButtons/EquipmentButton';
import './index.css';
import type { EquipmentPreset } from "@blitzkit/protos";
import { Flex } from "@radix-ui/themes";
import { chunk, cloneDeep } from "lodash-es";
import type { EquipmentMatrix } from "../../stores/duel";
import { EquipmentButton } from "../ModuleButtons/EquipmentButton";
import "./index.css";
interface EquipmentManagerProps {
preset: EquipmentPreset;
+2 -6
View File
@@ -1,10 +1,6 @@
import {
alias,
SEARCH_KEYS,
TankDefinition,
TIER_ROMAN_NUMERALS,
} from "@blitzkit/core";
import { alias, SEARCH_KEYS, TIER_ROMAN_NUMERALS } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n";
import { TankDefinition } from "@blitzkit/protos";
import {
ArrowRightIcon,
EyeOpenIcon,
@@ -1,12 +1,12 @@
import {
TIER_ROMAN_NUMERALS,
type EngineDefinition,
type GunDefinition,
type ShellDefinition,
type TankDefinition,
type TrackDefinition,
type TurretDefinition,
} from "@blitzkit/core";
import { TIER_ROMAN_NUMERALS } from "@blitzkit/core";
import type {
EngineDefinition,
GunDefinition,
ShellDefinition,
TankDefinition,
TrackDefinition,
TurretDefinition,
} from "@blitzkit/protos";
import { DropdownMenu, Flex } from "@radix-ui/themes";
import { useState } from "react";
import { useLocale } from "../hooks/useLocale";
@@ -1,4 +1,5 @@
import { TankDefinition, formatCompact } from "@blitzkit/core";
import { formatCompact } from "@blitzkit/core";
import { TankDefinition } from "@blitzkit/protos";
import { Table } from "@radix-ui/themes";
import { memo } from "react";
import { awaitableAverageDefinitions } from "../../core/awaitables/averageDefinitions";
@@ -1,10 +1,10 @@
import { memo, useRef } from "react";
import { Group } from "three";
import { correctZYTuple } from "../../../core/blitz/correctZYTuple";
import { nameToArmorId } from "../../../core/blitzkit/nameToArmorId";
import { resolveArmor } from "../../../core/blitzkit/resolveThickness";
import { useArmor } from "../../../hooks/useArmor";
import { DuelModule, useDuel } from "../../../hooks/useDuel";
import { correctZYTuple } from "../core/blitz/correctZYTuple";
import { nameToArmorId } from "../core/blitzkit/nameToArmorId";
import { resolveArmor } from "../core/blitzkit/resolveThickness";
import { useArmor } from "../hooks/useArmor";
import { DuelModule, useDuel } from "../hooks/useDuel";
import { ModelTankWrapper } from "./ModelTankWrapper";
import { PrimaryArmorSceneComponent } from "./PrimaryArmorSceneComponent";
@@ -17,15 +17,15 @@ import {
Vector2,
} from "three";
import { degToRad } from "three/src/math/MathUtils.js";
import { jsxTree } from "../../../../core/blitzkit/jsxTree";
import { DuelModule, getDuel } from "../../../../hooks/useDuel";
import { hasEquipment } from "../../../../hooks/useEquipment";
import { Tankopedia } from "../../../../stores/tankopedia";
import { TankopediaPersistent } from "../../../../stores/tankopediaPersistent";
import { transitionEvent } from "../../../Lighting";
import { jsxTree } from "../../core/blitzkit/jsxTree";
import { DuelModule, getDuel } from "../../hooks/useDuel";
import { hasEquipment } from "../../hooks/useEquipment";
import { Tankopedia } from "../../stores/tankopedia";
import { TankopediaPersistent } from "../../stores/tankopediaPersistent";
import { transitionEvent } from "../Lighting";
import fragmentShader from "./shaders/fragment.glsl?raw";
import vertexShader from "./shaders/vertex.glsl?raw";
import { spacedArmorRenderTarget } from "./target";
import { spacedArmorRenderTarget } from "./PrimaryArmorRenderTarget";
interface PrimaryArmorSceneComponentProps {
thickness: number;
@@ -16,13 +16,13 @@ import {
Path,
Quaternion,
} from "three";
import { isHalloween } from "../../../core/blitzkit/isHalloween";
import { LocaleProvider, useLocale } from "../../../hooks/useLocale";
import { isHalloween } from "../core/blitzkit/isHalloween";
import { LocaleProvider, useLocale } from "../hooks/useLocale";
import {
Tankopedia,
type ShotLayerNonExternal,
type ShotStatus,
} from "../../../stores/tankopedia";
} from "../stores/tankopedia";
import { ShotDisplayCard } from "./ShotDisplayCard";
export const shotStatusColors: Record<
@@ -9,8 +9,8 @@ import {
} from "@radix-ui/themes";
import type { ComponentProps } from "react";
import { radToDeg } from "three/src/math/MathUtils.js";
import { useLocale } from "../../../hooks/useLocale";
import type { Shot, ShotLayer } from "../../../stores/tankopedia";
import { useLocale } from "../hooks/useLocale";
import type { Shot, ShotLayer } from "../stores/tankopedia";
import { shotStatusColors } from "./ShotDisplay";
import { ArmorType } from "./SpacedArmorScene";
@@ -1,13 +1,13 @@
import { memo, useRef } from "react";
import { Group, Plane, Scene, Vector3 } from "three";
import { correctZYTuple } from "../../../core/blitz/correctZYTuple";
import { nameToArmorId } from "../../../core/blitzkit/nameToArmorId";
import { resolveArmor } from "../../../core/blitzkit/resolveThickness";
import { useArmor } from "../../../hooks/useArmor";
import { useModel } from "../../../hooks/useModel";
import { useTankModelDefinition } from "../../../hooks/useTankModelDefinition";
import { useTankTransform } from "../../../hooks/useTankTransform";
import { Duel } from "../../../stores/duel";
import { correctZYTuple } from "../core/blitz/correctZYTuple";
import { nameToArmorId } from "../core/blitzkit/nameToArmorId";
import { resolveArmor } from "../core/blitzkit/resolveThickness";
import { useArmor } from "../hooks/useArmor";
import { useModel } from "../hooks/useModel";
import { useTankModelDefinition } from "../hooks/useTankModelDefinition";
import { useTankTransform } from "../hooks/useTankTransform";
import { Duel } from "../stores/duel";
import { ModelTankWrapper } from "./ModelTankWrapper";
import { SpacedArmorSceneComponent } from "./SpacedArmorSceneComponent";
@@ -1,8 +1,5 @@
import {
ShellType,
isExplosive,
resolvePenetrationCoefficient,
} from "@blitzkit/core";
import { isExplosive, resolvePenetrationCoefficient } from "@blitzkit/core";
import { ShellType } from "@blitzkit/protos";
import { useThree } from "@react-three/fiber";
import { useCallback } from "react";
import {
@@ -16,20 +13,20 @@ import {
Vector3,
} from "three";
import { degToRad } from "three/src/math/MathUtils.js";
import { hasEquipment } from "../../../../core/blitzkit/hasEquipment";
import { jsxTree } from "../../../../core/blitzkit/jsxTree";
import { defaultEqualizer } from "../../../../core/blitzkit/tankToDuelMember";
import { discardClippingPlane } from "../../../../core/three/discardClippingPlane";
import { Duel } from "../../../../stores/duel";
import { hasEquipment } from "../core/blitzkit/hasEquipment";
import { jsxTree } from "../core/blitzkit/jsxTree";
import { defaultEqualizer } from "../core/blitzkit/tankToDuelMember";
import { discardClippingPlane } from "../core/three/discardClippingPlane";
import { Duel } from "../stores/duel";
import {
type Shot,
type ShotLayerBase,
type ShotLayerNonExternal,
Tankopedia,
} from "../../../../stores/tankopedia";
import { ArmorType } from "../SpacedArmorScene";
import { SpacedArmorSubExternal } from "./components/SpacedArmorSubExternal";
import { SpacedArmorSubSpaced } from "./components/SpacedArmorSubSpaced";
} from "../stores/tankopedia";
import { ArmorType } from "./SpacedArmorScene";
import { SpacedArmorSubExternal } from "./SpacedArmorSubExternal";
import { SpacedArmorSubSpaced } from "./SpacedArmorSubSpaced";
type SpacedArmorSceneComponentProps = {
node: Object3D;
@@ -7,12 +7,12 @@ import {
Plane,
ShaderMaterial,
} from "three";
import type { ArmorUserData, ExternalModuleVariant } from "../..";
import { hasEquipment } from "../../../../../../core/blitzkit/hasEquipment";
import { jsxTree } from "../../../../../../core/blitzkit/jsxTree";
import { Duel } from "../../../../../../stores/duel";
import { Tankopedia } from "../../../../../../stores/tankopedia";
import { ArmorType } from "../../../SpacedArmorScene";
import type { ArmorUserData, ExternalModuleVariant } from "../SpacedArmorSceneComponent";
import { hasEquipment } from "../../core/blitzkit/hasEquipment";
import { jsxTree } from "../../core/blitzkit/jsxTree";
import { Duel } from "../../stores/duel";
import { Tankopedia } from "../../stores/tankopedia";
import { ArmorType } from "./SpacedArmorScene";
import fragmentShader from "./shaders/fragment.glsl?raw";
import vertexShader from "./shaders/vertex.glsl?raw";
@@ -7,12 +7,12 @@ import {
type Object3D,
} from "three";
import { degToRad } from "three/src/math/MathUtils.js";
import type { ArmorUserData } from "../..";
import { hasEquipment } from "../../../../../../core/blitzkit/hasEquipment";
import { jsxTree } from "../../../../../../core/blitzkit/jsxTree";
import { Duel } from "../../../../../../stores/duel";
import { Tankopedia } from "../../../../../../stores/tankopedia";
import { ArmorType } from "../../../SpacedArmorScene";
import type { ArmorUserData } from "../SpacedArmorSceneComponent";
import { hasEquipment } from "../../core/blitzkit/hasEquipment";
import { jsxTree } from "../../core/blitzkit/jsxTree";
import { Duel } from "../../stores/duel";
import { Tankopedia } from "../../stores/tankopedia";
import { ArmorType } from "./SpacedArmorScene";
import fragmentShader from "./shaders/fragment.glsl?raw";
import vertexShader from "./shaders/vertex.glsl?raw";
@@ -1,20 +1,20 @@
import { useThree, type ThreeEvent } from "@react-three/fiber";
import { memo, useRef } from "react";
import { Group, Plane, Vector2, Vector3 } from "three";
import { applyPitchYawLimits } from "../../../core/blitz/applyPitchYawLimits";
import { correctZYTuple } from "../../../core/blitz/correctZYTuple";
import { hasEquipment } from "../../../core/blitzkit/hasEquipment";
import { modelTransformEvent } from "../../../core/blitzkit/modelTransform";
import { nameToArmorId } from "../../../core/blitzkit/nameToArmorId";
import { resolveArmor } from "../../../core/blitzkit/resolveThickness";
import { controlsEnabledEvent } from "../../../core/controlsEnabled";
import { useArmor } from "../../../hooks/useArmor";
import { useModel } from "../../../hooks/useModel";
import { useTankModelDefinition } from "../../../hooks/useTankModelDefinition";
import { useTankTransform } from "../../../hooks/useTankTransform";
import { Duel } from "../../../stores/duel";
import { Tankopedia } from "../../../stores/tankopedia";
import { TankopediaPersistent } from "../../../stores/tankopediaPersistent";
import { applyPitchYawLimits } from "../core/blitz/applyPitchYawLimits";
import { correctZYTuple } from "../core/blitz/correctZYTuple";
import { hasEquipment } from "../core/blitzkit/hasEquipment";
import { modelTransformEvent } from "../core/blitzkit/modelTransform";
import { nameToArmorId } from "../core/blitzkit/nameToArmorId";
import { resolveArmor } from "../core/blitzkit/resolveThickness";
import { controlsEnabledEvent } from "../core/controlsEnabled";
import { useArmor } from "../hooks/useArmor";
import { useModel } from "../hooks/useModel";
import { useTankModelDefinition } from "../hooks/useTankModelDefinition";
import { useTankTransform } from "../hooks/useTankTransform";
import { Duel } from "../stores/duel";
import { Tankopedia } from "../stores/tankopedia";
import { TankopediaPersistent } from "../stores/tankopediaPersistent";
import { ModelTankWrapper } from "./ModelTankWrapper";
import { ArmorType } from "./SpacedArmorScene";
import { StaticArmorSceneComponent } from "./StaticArmorSceneComponent";
@@ -16,18 +16,18 @@ import {
Quaternion,
Vector3,
} from "three";
import { unrotateDavaVector } from "../../../core/blitz/unrotateDavaVector";
import { jsxTree } from "../../../core/blitzkit/jsxTree";
import { unrotateDavaVector } from "../core/blitz/unrotateDavaVector";
import { jsxTree } from "../core/blitzkit/jsxTree";
import {
modelTransformEvent,
type ModelTransformEventData,
} from "../../../core/blitzkit/modelTransform";
import { defaultEqualizer } from "../../../core/blitzkit/tankToDuelMember";
import { discardClippingPlane } from "../../../core/three/discardClippingPlane";
import { useEquipment } from "../../../hooks/useEquipment";
import { Duel } from "../../../stores/duel";
import { Tankopedia } from "../../../stores/tankopedia";
import { transitionEvent } from "../../Lighting";
} from "../core/blitzkit/modelTransform";
import { defaultEqualizer } from "../core/blitzkit/tankToDuelMember";
import { discardClippingPlane } from "../core/three/discardClippingPlane";
import { useEquipment } from "../hooks/useEquipment";
import { Duel } from "../stores/duel";
import { Tankopedia } from "../stores/tankopedia";
import { transitionEvent } from "./Lighting";
import { ArmorType } from "./SpacedArmorScene";
import type {
ArmorUserData,
@@ -12,7 +12,7 @@ import { useModel } from "../hooks/useModel";
import { useTankTransform } from "../hooks/useTankTransform";
import { Tankopedia } from "../stores/tankopedia";
import { TankopediaDisplay } from "../stores/tankopediaPersistent/constants";
import { ModelTankWrapper } from "./Armor/components/ModelTankWrapper";
import { ModelTankWrapper } from "./ModelTankWrapper";
export function TankModel() {
const protagonist = Duel.use((draft) => draft.protagonist);
@@ -1,4 +1,5 @@
import { type TankDefinition, tankIcon, TankType } from "@blitzkit/core";
import { tankIcon } from "@blitzkit/core";
import { type TankDefinition, TankType } from "@blitzkit/protos";
import { Box, Flex } from "@radix-ui/themes";
import { useLocale } from "../hooks/useLocale";
import { classIcons } from "./ClassIcon";
@@ -2,8 +2,8 @@ import {
normalizeBoundingBox,
resolveDpm,
unionBoundingBox,
type TankDefinition,
} from "@blitzkit/core";
import type { TankDefinition } from "@blitzkit/protos";
import { useMemo } from "react";
import { api } from "../../../api/dynamic";
import { resolveReload } from "../../../core/blitzkit/resolveReload";
@@ -1,4 +1,4 @@
import { type TankDefinition } from "@blitzkit/core";
import type { TankDefinition } from "@blitzkit/protos";
import { CaretRightIcon } from "@radix-ui/react-icons";
import { useLocale } from "../../../hooks/useLocale";
import { TankFilters } from "../../../stores/tankFilters";
@@ -1,5 +1,5 @@
import type { AssaultRanges } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n";
import type { AssaultRanges } from "@blitzkit/protos";
import { Box, Flex, Text } from "@radix-ui/themes";
import { clamp } from "three/src/math/MathUtils.js";
import {
@@ -68,7 +68,7 @@ export function AssaultRangesVisualizer({ ranges: _ranges, stats }: Props) {
>
{literals(strings.common.units.hp, {
value: Math.round(
stats.damageWithoutAssault * range.factor
stats.damageWithoutAssault * range.factor,
),
})}
</Text>
@@ -1,5 +1,6 @@
import { CREW_MEMBER_NAMES, CrewType } from "@blitzkit/core";
import { CREW_MEMBER_NAMES } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n";
import { CrewType } from "@blitzkit/protos";
import { AccessibilityIcon, InfoCircledIcon } from "@radix-ui/react-icons";
import { Flex, Heading, IconButton, Popover, Text } from "@radix-ui/themes";
import { Fragment } from "react/jsx-runtime";
@@ -1,16 +1,18 @@
import {
alias,
EngineDefinition,
formatCompact,
GunDefinition,
ModuleType,
tankIcon,
TIER_ROMAN_NUMERALS,
} from "@blitzkit/core";
import {
EngineDefinition,
GunDefinition,
ModuleType,
TrackDefinition,
TurretDefinition,
type TankDefinition,
type Unlock,
} from "@blitzkit/core";
} from "@blitzkit/protos";
import {
Button,
ChevronDownIcon,
@@ -1,5 +1,5 @@
import { ShellType } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n/src/literals";
import { ShellType } from "@blitzkit/protos";
import {
Button,
Flex,
@@ -7,7 +7,7 @@ import { Tankopedia } from "../../../../../../stores/tankopedia";
import { TankopediaPersistent } from "../../../../../../stores/tankopediaPersistent";
import { TankopediaDisplay } from "../../../../../../stores/tankopediaPersistent/constants";
import type { MaybeSkeletonComponentProps } from "../../../../../../types/maybeSkeletonComponentProps";
import type { ThicknessRange } from "../../../../../Armor/components/StaticArmor";
import type { ThicknessRange } from "../../../../../StaticArmor";
import { DynamicArmorSwitcher } from "./DynamicArmorSwitcher";
type ThicknessesProps = MaybeSkeletonComponentProps & {
@@ -37,7 +37,7 @@ import { Tankopedia } from "../../../../../stores/tankopedia";
import { TankopediaPersistent } from "../../../../../stores/tankopediaPersistent";
import { TankopediaDisplay } from "../../../../../stores/tankopediaPersistent/constants";
import type { MaybeSkeletonComponentProps } from "../../../../../types/maybeSkeletonComponentProps";
import type { ThicknessRange } from "../../../../Armor/components/StaticArmor";
import type { ThicknessRange } from "../../../../StaticArmor";
import { EqualIcon } from "../../../../EqualIcon";
import { ModuleButton } from "../../../../ModuleButtons/ModuleButton";
import { ScreenshotButton } from "../../../../ScreenshotButton";
@@ -7,7 +7,7 @@ import { useModel } from "../../../../../../../hooks/useModel";
import { useTankModelDefinition } from "../../../../../../../hooks/useTankModelDefinition";
import { useTankTransform } from "../../../../../../../hooks/useTankTransform";
import { Duel } from "../../../../../../../stores/duel";
import { ModelTankWrapper } from "../../../../../../Armor/components/ModelTankWrapper";
import { ModelTankWrapper } from "../../../../../../ModelTankWrapper";
import fragmentShader from "./shaders/fragment.glsl?raw";
import vertexShader from "./shaders/vertex.glsl?raw";
@@ -7,7 +7,7 @@ import { useFullScreen } from "../../../hooks/useFullScreen";
import { Duel } from "../../../stores/duel";
import { Tankopedia } from "../../../stores/tankopedia";
import type { MaybeSkeletonComponentProps } from "../../../types/maybeSkeletonComponentProps";
import type { ThicknessRange } from "../../Armor/components/StaticArmor";
import type { ThicknessRange } from "../../StaticArmor";
import { Options } from "./components/Options";
import { TankSandbox } from "./components/TankSandbox";
import { Title } from "./components/TankSandbox/Title";
@@ -1,9 +1,5 @@
import {
alias,
TankPriceType,
TankType,
TIER_ROMAN_NUMERALS,
} from "@blitzkit/core";
import { alias, TIER_ROMAN_NUMERALS } from "@blitzkit/core";
import { TankPriceType, TankType } from "@blitzkit/protos";
import { Box, Flex } from "@radix-ui/themes";
import { Var } from "../../../core/radix/var";
import { useLocale } from "../../../hooks/useLocale";
@@ -1,5 +1,6 @@
import { alias, TankType } from "@blitzkit/core";
import { alias } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n/src/literals";
import { TankType } from "@blitzkit/protos";
import { CaretLeftIcon, CaretRightIcon, PlusIcon } from "@radix-ui/react-icons";
import { Flex, Heading, IconButton, ScrollArea, Text } from "@radix-ui/themes";
import { Fragment, useEffect, useMemo, useRef, useState } from "react";
@@ -14,19 +14,16 @@ import { useModel } from "../../hooks/useModel";
import { Tankopedia } from "../../stores/tankopedia";
import { TankopediaPersistent } from "../../stores/tankopediaPersistent";
import { TankopediaDisplay } from "../../stores/tankopediaPersistent/constants";
import { Armor } from "../Armor";
import { ArmorPlateDisplay } from "../Armor/components/ArmorPlateDisplay";
import { ShotDisplay } from "../Armor/components/ShotDisplay";
import {
StaticArmor,
type ThicknessRange,
} from "../Armor/components/StaticArmor";
import { ArmorPlateDisplay } from "../ArmorPlateDisplay";
import { CanvasAutoClear } from "../CanvasAutoClear";
import { CanvasControl } from "../CanvasControl";
import { DynamicArmor } from "../DynamicArmor";
import { InitialCameraAligner } from "../InitialCameraAligner";
import { Lighting } from "../Lighting";
import { SceneProps } from "../SceneProps";
import { ShotDisplay } from "../ShotDisplay";
import { SmartCanvas } from "../SmartCanvas";
import { StaticArmor, type ThicknessRange } from "../StaticArmor";
import { TankModel } from "../TankModel";
import styles from "./index.module.css";
@@ -187,7 +184,7 @@ export const TankopediaSandbox = forwardRef<
{/* Controls within Suspense to allow for frame-perfect start of camera auto-rotate */}
<CanvasControl />
{display === TankopediaDisplay.DynamicArmor && <Armor />}
{display === TankopediaDisplay.DynamicArmor && <DynamicArmor />}
{display === TankopediaDisplay.StaticArmor && (
<StaticArmor thicknessRange={thicknessRange} />
)}
@@ -1,12 +1,14 @@
import {
formatCompositeStat,
TankClass,
TankDefinition,
TankType,
type CompositeStats,
type CompositeStatsKey,
} from "@blitzkit/core";
import strings from "@blitzkit/i18n/strings/en.json";
import {
TankClass,
TankDefinition,
TankType,
} from "@blitzkit/protos";
import { amberDark, blueDark } from "@radix-ui/colors";
import { Flex, Text, type FlexProps } from "@radix-ui/themes";
import { times } from "lodash-es";
@@ -1,4 +1,4 @@
import type { TankDefinition } from "@blitzkit/core";
import type { TankDefinition } from "@blitzkit/protos";
import { Box } from "@radix-ui/themes";
import {
useCallback,
@@ -1,8 +1,5 @@
import {
normalizeAngleRad,
type PitchLimits,
type YawLimits,
} from "@blitzkit/core";
import { normalizeAngleRad } from "@blitzkit/core";
import type { PitchLimits, YawLimits } from "@blitzkit/protos";
import { clamp } from "lodash-es";
import { degToRad } from "three/src/math/MathUtils.js";
@@ -1,6 +1,6 @@
import type { Vector3 as BlitzkitVector3 } from '@blitzkit/core';
import { Vector3 as THREEVector3 } from 'three';
import { rotateDavaVector } from './rotateDavaVector';
import type { Vector3 as BlitzkitVector3 } from "@blitzkit/protos";
import { Vector3 as THREEVector3 } from "three";
import { rotateDavaVector } from "./rotateDavaVector";
export function correctZYTuple(tuple: BlitzkitVector3) {
return rotateDavaVector(new THREEVector3(tuple.x, tuple.y, -tuple.z));
@@ -1,9 +1,9 @@
import type { GunDefinition } from '@blitzkit/core';
import type { GunDefinition } from "@blitzkit/protos";
export function resolveReload(gun: GunDefinition) {
if (gun.gun_type!.$case === 'regular') {
if (gun.gun_type!.$case === "regular") {
return gun.gun_type!.value.reload;
} else if (gun.gun_type!.$case === 'auto_loader') {
} else if (gun.gun_type!.$case === "auto_loader") {
return (
gun.gun_type!.value.clip_reload +
(gun.gun_type!.value.shell_count - 1) * gun.gun_type!.value.intra_clip
@@ -1,4 +1,4 @@
import type { Armor } from '@blitzkit/core';
import type { Armor } from "@blitzkit/protos";
export function resolveArmor(armor: Armor, index: number) {
const spaced = armor.spaced?.includes(index) ?? false;
@@ -1,15 +1,18 @@
import {
CrewType,
degressiveStat,
isExplosive,
normalizeBoundingBox,
progressiveStat,
resolveDpm,
resolvePenetrationCoefficient,
ShellType,
sum,
TankClass,
unionBoundingBox,
} from "@blitzkit/core";
import { coefficient } from "@blitzkit/core/src/blitzkit/coefficient";
import {
CrewType,
ShellType,
TankClass,
type EngineDefinition,
type EquipmentDefinitions,
type GunDefinition,
@@ -19,8 +22,7 @@ import {
type TankDefinition,
type TrackDefinition,
type TurretDefinition,
} from "@blitzkit/core";
import { coefficient } from "@blitzkit/core/src/blitzkit/coefficient";
} from "@blitzkit/protos";
import type { EquipmentMatrix } from "../../stores/duel";
import { defaultEqualizer } from "./tankToDuelMember";
@@ -1,7 +1,7 @@
import type { ProvisionDefinitions, TankDefinition } from '@blitzkit/core';
import { uniqueId } from 'lodash-es';
import type { CompareMember } from '../../stores/compareEphemeral';
import { tankToDuelMember } from './tankToDuelMember';
import type { ProvisionDefinitions, TankDefinition } from "@blitzkit/protos";
import { uniqueId } from "lodash-es";
import type { CompareMember } from "../../stores/compareEphemeral";
import { tankToDuelMember } from "./tankToDuelMember";
export function tankToCompareMember(
tank: TankDefinition,
@@ -1,5 +1,5 @@
import { EquipmentPreset } from '@blitzkit/core';
import type { EquipmentMatrix } from '../stores/duel';
import { EquipmentPreset } from "@blitzkit/protos";
import type { EquipmentMatrix } from "../stores/duel";
export function useAppliedEquipments(
matrix: EquipmentMatrix,
@@ -7,6 +7,6 @@ export function useAppliedEquipments(
) {
const flatMatrix = matrix.flat();
return preset.slots.map(
(options, index) => options[flatMatrix[index] == 1 ? 'right' : 'left'],
(options, index) => options[flatMatrix[index] == 1 ? "right" : "left"],
);
}
@@ -1,4 +1,4 @@
import { TankDefinition } from "@blitzkit/core";
import { TankDefinition } from "@blitzkit/protos";
import { sumBy } from "lodash-es";
import { useMemo } from "react";
import { api } from "../api/dynamic";
@@ -1,10 +1,5 @@
import {
I_HAT,
J_HAT,
K_HAT,
TrackDefinition,
TurretDefinition,
} from "@blitzkit/core";
import { I_HAT, J_HAT, K_HAT } from "@blitzkit/core";
import { TrackDefinition, TurretDefinition } from "@blitzkit/protos";
import { invalidate } from "@react-three/fiber";
import type { QuicklimeEvent } from "quicklime";
import { type RefObject, useEffect } from "react";
@@ -1,4 +1,4 @@
import { EquipmentDefinitions } from "@blitzkit/core";
import { EquipmentDefinitions } from "@blitzkit/protos";
import { api } from "../../../api/dynamic";
export { getStaticPaths } from "../_index";
@@ -1,4 +1,4 @@
import { Gallery } from "@blitzkit/core";
import { Gallery } from "@blitzkit/protos";
import { api } from "../../../api/dynamic";
export { getStaticPaths } from "../_index";
@@ -1,4 +1,4 @@
import { MapDefinitions } from "@blitzkit/core";
import { MapDefinitions } from "@blitzkit/protos";
import { api } from "../../../api/dynamic";
export { getStaticPaths } from "../_index";
@@ -1,4 +1,4 @@
import { SkillDefinitions } from "@blitzkit/core";
import { SkillDefinitions } from "@blitzkit/protos";
import { api } from "../../../api/dynamic";
export { getStaticPaths } from "../_index";
@@ -1,5 +1,6 @@
import { fetchGlossary, type Avatar } from "@blitzkit/core";
import { fetchGlossary } from "@blitzkit/core";
import locales from "@blitzkit/i18n/locales.json";
import type { Avatar } from "@blitzkit/protos";
import type { APIContext, GetStaticPathsItem } from "astro";
import { extname } from "path";
import { mixStaticPaths } from "../../../../astro/mixStaticPaths";
@@ -1,11 +1,13 @@
import {
alias,
GunDefinition,
TankDefinition,
TIER_ROMAN_NUMERALS,
TurretDefinition,
} from "@blitzkit/core";
import { literals } from "@blitzkit/i18n";
import {
GunDefinition,
TankDefinition,
TurretDefinition,
} from "@blitzkit/protos";
import { CaretRightIcon, CaretUpIcon, UpdateIcon } from "@radix-ui/react-icons";
import {
Box,
+2 -2
View File
@@ -1,4 +1,4 @@
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
export interface WargamingLogin {
token: string;
@@ -14,7 +14,7 @@ export interface App {
};
}
export const App = new Varuna<App>(
export const App = new Soapstone<App>(
{
developerMode: false,
policiesAgreementIndex: -1,
@@ -1,4 +1,4 @@
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
import type { DuelMember } from "./duel";
export interface CompareMember extends DuelMember {
@@ -15,9 +15,9 @@ export interface CompareEphemeral {
};
}
export const CompareEphemeral = new Varuna<
export const CompareEphemeral = new Soapstone<
CompareEphemeral,
Record<string, number>
[Record<string, number>]
>((crewSkills) => ({
crewSkills,
equalize: false,
@@ -1,4 +1,4 @@
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
export type DeltaMode = "none" | "percentage" | "absolute";
@@ -6,7 +6,7 @@ export interface ComparePersistent {
deltaMode: DeltaMode;
}
export const ComparePersistent = new Varuna<ComparePersistent>(
export const ComparePersistent = new Soapstone<ComparePersistent>(
{ deltaMode: "none" },
"compare-2"
);
@@ -1,9 +1,9 @@
import { type IndividualTankStats } from "@blitzkit/core";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
type EmbedBreakdown = Record<number, IndividualTankStats[]>;
export const EmbedBreakdown = new Varuna<EmbedBreakdown>(
export const EmbedBreakdown = new Soapstone<EmbedBreakdown>(
{},
"embed-breakdown-2"
);
@@ -1,5 +1,5 @@
import * as radixColors from "@radix-ui/colors";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
import {
type EmbedConfigItemType,
EmbedItemType,
@@ -103,6 +103,6 @@ export type EmbedConfigItem = (
export type EmbedStateStore = Record<string, EmbedConfigItem["default"]>;
export const EmbedState = new Varuna<EmbedStateStore, EmbedStateStore>(
export const EmbedState = new Soapstone<EmbedStateStore, [EmbedStateStore]>(
(data) => data
);
+2 -2
View File
@@ -1,7 +1,7 @@
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
interface Gallery {
search?: string;
}
export const Gallery = new Varuna<Gallery>({});
export const Gallery = new Soapstone<Gallery>({});
+3 -3
View File
@@ -1,6 +1,6 @@
import type { TankDefinition } from "@blitzkit/core";
import type { TankDefinition } from "@blitzkit/protos";
import { times } from "lodash-es";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
export enum GuessState {
Correct,
@@ -18,7 +18,7 @@ export interface Guess {
tiers: number[];
}
export const Guess = new Varuna<Guess, TankDefinition>((tank) => ({
export const Guess = new Soapstone<Guess, [TankDefinition]>((tank) => ({
tank,
guessState: GuessState.NotGuessed,
totalGuesses: 0,
+3 -3
View File
@@ -2,8 +2,8 @@ import type {
GunDefinition,
TankDefinition,
TurretDefinition,
} from "@blitzkit/core";
import { Varuna } from "varuna";
} from "@blitzkit/protos";
import { Soapstone } from "soapstone";
export interface Mixer {
hull: TankDefinition;
@@ -18,4 +18,4 @@ export interface Mixer {
};
}
export const Mixer = new Varuna<Mixer, Mixer>((data) => data);
export const Mixer = new Soapstone<Mixer, [Mixer]>((data) => data);
+3 -3
View File
@@ -1,5 +1,5 @@
import type { Samples } from "@blitzkit/core";
import { Varuna } from "varuna";
import type { Samples } from "@blitzkit/protos";
import { Soapstone } from "soapstone";
export interface Performance {
playerCountPeriod: PlayerCountPeriod;
@@ -7,6 +7,6 @@ export interface Performance {
export type PlayerCountPeriod = keyof Samples;
export const Performance = new Varuna<Performance>({
export const Performance = new Soapstone<Performance>({
playerCountPeriod: "total",
});
+2 -2
View File
@@ -1,4 +1,4 @@
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
export interface PlaylistEntry {
id: number;
@@ -11,4 +11,4 @@ export interface Playlist {
list?: PlaylistEntry[];
}
export const Playlist = new Varuna<Playlist>({}, "playlist");
export const Playlist = new Soapstone<Playlist>({}, "playlist");
+2 -2
View File
@@ -3,7 +3,7 @@ import type {
IndividualTankStats,
Region,
} from "@blitzkit/core";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
interface SessionBase {
columns: CompositeStatsKey[];
@@ -25,7 +25,7 @@ interface SessionNotTracking extends SessionBase {
type Session = SessionTracking | SessionNotTracking;
export const Session = new Varuna<Session>(
export const Session = new Soapstone<Session>(
{
columns: [
"cumulative_battles",
+2 -2
View File
@@ -5,7 +5,7 @@ import type {
TankClass,
TankType,
} from "@blitzkit/protos";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
export interface TankFilters {
tiers: number[];
@@ -26,7 +26,7 @@ export interface TankFilters {
showUnowned: boolean;
}
export const TankFilters = new Varuna<TankFilters>({
export const TankFilters = new Soapstone<TankFilters>({
tiers: [],
nations: [],
classes: [],
@@ -1,5 +1,5 @@
import type en from "@blitzkit/i18n/strings/en.json";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
export type TankPerformanceSortType =
keyof typeof en.website.tools.performance.table.stats;
@@ -9,7 +9,7 @@ export interface TankPerformanceSort {
direction: -1 | 1;
}
export const TankPerformanceSort = new Varuna<TankPerformanceSort>({
export const TankPerformanceSort = new Soapstone<TankPerformanceSort>({
type: "winrate",
direction: -1,
});
+4 -4
View File
@@ -5,10 +5,10 @@ import type {
TankDefinition,
} from "@blitzkit/protos";
import type { Vector3 } from "three";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
import { api } from "../api/dynamic";
import type { ArmorType } from "../components/Armor/components/SpacedArmorScene";
import type { ExternalModuleVariant } from "../components/Armor/components/SpacedArmorSceneComponent";
import type { ArmorType } from "../components/SpacedArmorScene";
import type { ExternalModuleVariant } from "../components/SpacedArmorSceneComponent";
import type { XP_MULTIPLIERS } from "../components/Tankopedia/TechTreeSection";
import { createTankState } from "../tankopedia/createTankState";
import type { TankState } from "../tankopedia/tankState";
@@ -117,7 +117,7 @@ interface Tankopedia {
const skills = await api.skills();
const models = await api.models();
export const Tankopedia = new Varuna<Tankopedia, TankDefinition>((tank) => ({
export const Tankopedia = new Soapstone<Tankopedia, [TankDefinition]>((tank) => ({
disturbed: false,
revealed: false,
@@ -1,5 +1,5 @@
import type en from "@blitzkit/i18n/strings/en.json";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
export type TankopediaSortBy = keyof typeof en.website.common.tank_search.sort;
export type TankopediaSortDirection = "ascending" | "descending";
@@ -23,7 +23,7 @@ export interface TankopediaPersistent {
};
}
export const TankopediaPersistent = new Varuna<TankopediaPersistent>(
export const TankopediaPersistent = new Soapstone<TankopediaPersistent>(
{
hideTankModelUnderArmor: false,
wireframe: false,
@@ -1,4 +1,4 @@
import { Varuna } from 'varuna';
import { Soapstone } from 'soapstone';
import {
type TankopediaSortBy,
type TankopediaSortDirection,
@@ -9,7 +9,7 @@ export interface TankSort {
direction: TankopediaSortDirection;
}
export const TankSort = new Varuna<TankSort>({
export const TankSort = new Soapstone<TankSort>({
by: 'meta.none',
direction: 'descending',
});
+2 -2
View File
@@ -1,5 +1,5 @@
import { enableMapSet } from "immer";
import { Varuna } from "varuna";
import { Soapstone } from "soapstone";
import { tierListRows } from "../components/TierList/Table/constants";
export interface TierList {
@@ -8,7 +8,7 @@ export interface TierList {
placedTanks: Set<number>;
}
export const TierList = new Varuna<TierList>({
export const TierList = new Soapstone<TierList>({
dragging: false,
rows: tierListRows.map((row) => ({ name: row.name, tanks: [] })),
placedTanks: new Set(),
Loaded 100 of 104 files, more files were not shown because too many files have changed in this diff. Show more