Compare commits

..
67 Commits
Author SHA1 Message Date
TrèsAbhi 05648ea040 Merge pull request #353 from Hitjack007/remove-imgur-references
Fix: migrate Imgur images to BlitzKit hosting
2026-10-18 14:12:50 -05:00
TrèsAbhi 73080fd60a Merge branch 'main' into remove-imgur-references 2026-10-18 14:03:19 -05:00
TrèsAbhi 14be326c41 Merge pull request #368 from Hitjack007/calculated-bounding-boxes 2026-10-18 14:02:34 -05:00
TrèsAbhi 8132f2d91e Merge branch 'main' into calculated-bounding-boxes 2026-10-18 13:59:49 -05:00
TrèsAbhi 1258cd1fa2 New Crowdin updates (#399) 2026-10-18 13:59:07 -05:00
tresabhi 7f7d0cc499 remove outdated docs 2026-10-10 16:41:57 -05:00
TrèsAbhi 0c91ee3600 New Crowdin updates (#389)
* New translations en.json (Ukrainian)

[ci skip]

* New translations en.json (Chinese Simplified)

[ci skip]

* New translations en.json (French)

[ci skip]

* New translations en.json (Spanish)

[ci skip]

* New translations en.json (Japanese)

[ci skip]

* New translations en.json (Polish)

[ci skip]

* New translations en.json (Portuguese)

[ci skip]

* New translations en.json (Russian)

[ci skip]
2026-10-09 23:33:06 -05:00
tresabhi 1988ecff92 smaller titles 2026-10-09 18:20:11 -05:00
tresabhi ff03f8ffb2 remove bold 2026-10-09 18:17:56 -05:00
tresabhi d050776628 format 2026-10-09 18:14:59 -05:00
tresabhi 78bff2cdd2 logs 2026-10-09 18:13:22 -05:00
tresabhi 072174ad45 promote version 2026-10-09 18:01:10 -05:00
TrèsAbhi 03f2bcdc1a Merge pull request #366 from Hitjack007/track-repair-time 2026-10-09 17:29:38 -05:00
TrèsAbhi b6ae34dafa Merge pull request #377 from Hitjack007/armor-penetration-chance 2026-10-09 17:28:05 -05:00
TrèsAbhi 2e10052732 Merge pull request #282 from Hitjack007/armor-controls-edge 2026-10-09 17:06:22 -05:00
TrèsAbhi 9a95306b37 Merge pull request #284 from Hitjack007/mixer-mobile 2026-10-09 17:03:52 -05:00
tresabhi fbc4355984 remove clamped vw 2026-10-09 17:02:54 -05:00
TrèsAbhi 24026a95ee Merge pull request #359 from Hitjack007/flag-offset 2026-10-09 16:57:27 -05:00
TrèsAbhi 8f4a43fc8a Merge pull request #357 from Hitjack007/playlist-filters-layout 2026-10-09 16:55:20 -05:00
tresabhi 646d6fa7d5 center align and max width 32rem 2026-10-09 16:54:37 -05:00
TrèsAbhi 37fae7477d Merge branch 'main' into playlist-filters-layout 2026-10-09 16:53:35 -05:00
Mark Greene a365fa5e50 Fix: migrate Imgur images to BlitzKit hosting 2026-10-08 20:28:02 +13:00
Mark Greene 57d77bf2b4 Fix: calculate tank dimensions from collision models 2026-10-08 20:25:03 +13:00
Mark Greene 940c3c537b Feature: track repair time in Tankopedia
Adds track repair time to the Tankopedia survivability stats, matching the value the game lists.

- Added a required `repair_time` to track definitions, filled from each chassis's hysteresis health divided by its health regen per second
- Applied the toolbox, the repair crew skill and the protective kit as multiplicative repair speed bonuses
- Added a Track repair time row under fire chance; it appears once the definitions are regenerated on the next build

Fixes #308
2026-10-08 18:02:05 +13:00
Mark Greene fbdfa2c063 Feature: Penetration chance in the armor shot card
Shows the chance a shot penetrates in the dynamic armor shot card, right-aligned on the shot's result line.

- Penetration varies by ±5% (the same randomisation the armor highlighter shader uses), so the chance is the share of that range where the shot's final outcome is a penetration
- Re-runs the existing shot calculation at different penetration values, so spaced armor, HEAT gap losses and ricochets are taken into account
- For ricochets the chance is shown on the ricocheted shot's line; HE splashes don't count as penetrations
- Adds the `shot_card.stats.penetration_chance` string

Fixes #342
2026-10-08 18:00:57 +13:00
tresabhi 7234c39ad8 move credits back 2026-10-07 21:32:38 -05:00
TrèsAbhi c292adac41 Merge pull request #356 from Hitjack007/track-texture-scroll-rates 2026-10-07 17:05:52 -05:00
TrèsAbhi 1af104d4d6 Merge branch 'main' into track-texture-scroll-rates 2026-10-07 17:01:58 -05:00
TrèsAbhi 7b7513f227 Merge pull request #355 from Hitjack007/restore-locale-redirect 2026-10-07 17:01:01 -05:00
tresabhi 02f5cc0686 remove redundant logic 2026-10-07 17:00:47 -05:00
TrèsAbhi 6f1d653d54 Merge branch 'main' into restore-locale-redirect 2026-10-07 16:59:43 -05:00
tresabhi 92c8b90bb3 remove api check 2026-10-07 16:56:40 -05:00
TrèsAbhi 1b807e6d0e Merge pull request #360 from Hitjack007/equalizer-background-sliver 2026-10-07 16:48:29 -05:00
tresabhi 0e7b020d60 fix sliver 2026-10-07 16:48:08 -05:00
TrèsAbhi eda5d10290 Merge branch 'main' into equalizer-background-sliver 2026-10-07 16:37:48 -05:00
TrèsAbhi 85e93cd827 Merge pull request #361 from Hitjack007/contact-shadows-low-angles 2026-10-07 16:36:58 -05:00
TrèsAbhi bc2dd8c7b7 Merge branch 'main' into contact-shadows-low-angles 2026-10-07 16:35:43 -05:00
TrèsAbhi 904d50f4c3 New Crowdin updates (#379) 2026-10-07 16:35:15 -05:00
TrèsAbhi 112472762d Merge pull request #362 from Hitjack007/discover-ids-await-loop 2026-10-07 16:34:49 -05:00
TrèsAbhi f6e5fabb65 Merge pull request #363 from Hitjack007/stable-tank-sort-order 2026-10-07 16:33:25 -05:00
tresabhi e19d0d5895 revert tank exclusion 2026-10-07 16:32:48 -05:00
TrèsAbhi aa6268a86b Merge branch 'main' into stable-tank-sort-order 2026-10-07 16:30:42 -05:00
TrèsAbhi 0f878485b3 Merge pull request #364 from Hitjack007/tier-eleven-compatibility 2026-10-07 16:28:33 -05:00
tresabhi 0e119b6ba8 optimize awaitable tiers 2026-10-07 16:27:38 -05:00
tresabhi 3397e7f67b truthy array 2026-10-07 16:25:34 -05:00
TrèsAbhi de03a2ab95 Merge branch 'main' into tier-eleven-compatibility 2026-10-07 16:23:11 -05:00
tresabhi d4e649804e add astro cleaning script 2026-10-07 16:15:07 -05:00
TrèsAbhi c31d5705eb Merge pull request #367 from Hitjack007/tank-model-auto-load 2026-10-07 16:11:04 -05:00
tresabhi 16be5faae6 use UpdateIcon 2026-10-07 16:08:56 -05:00
tresabhi e1b079ca02 high contrast button 2026-10-07 16:06:52 -05:00
tresabhi 00149a3d9d simplify strings 2026-10-07 16:03:41 -05:00
TrèsAbhi e3e94e2b49 Merge branch 'main' into tank-model-auto-load 2026-10-07 15:59:34 -05:00
tresabhi 5ce927be4e force bun even with node installed 2026-10-07 10:14:44 -05:00
tresabhi c70fae8162 game strings 2026-10-05 11:24:29 -05:00
tresabhi d79e0ddb5d caching for strings 2026-10-05 11:24:01 -05:00
Mark Greene 541da65bfc Feature: option to turn off automatic tank model loading
Lets people on limited data stop the Tankopedia from downloading 3D models automatically.

- Added an Automatically load 3D models switch to the settings page, on by default
- When off, the tank page hero shows a Load 3D model button where the loading bar sits
- Held back every model download on the tank page until requested, including the dynamic armor switcher and the gun flexibility visualizer
- Wrapped the tank sandbox in its own suspense boundary so the loading bar shows real progress instead of the whole page waiting on the model
- Measured loading progress from when each loading bar appears so it always starts empty
- Added the English strings; other languages fall back until translated

Fixes #311
2026-10-05 19:52:46 +13:00
Mark Greene e4e92d76b4 Feature: tier XI compatibility
Prepares BlitzKit for tier XI tanks ahead of their release. Tier X was hardcoded as the maximum in the tank search filters, the guesser and the tech tree, and had no roman numeral beyond X.

- Added `XI` to `TIER_ROMAN_NUMERALS`
- Added an awaitable tier list derived from the highest tier in the tank definitions, so nothing changes until tier XI tanks exist
- Used it for the tank search tier filters and the guesser tier picker and defaults
- Made the tech tree check for successors instead of assuming tier X is the last tier

Fixes #302
2026-10-05 18:18:19 +13:00
Mark Greene 273881c460 Fix: keep tank order stable on select
Tanks sharing the same tier, nation, class and type were shown in an arbitrary order that changed after selecting a tank. The meta sort had no tiebreaker, and the filtered list was sorted and reversed in place, so each re-sort started from the previous reversed order and flipped tied tanks around.

- Added tank ID as the first sort key in `metaSortTank` so tied tanks always come out in the same order
- Sorted a copy of the tank search results, pre-sorted by ID, instead of the cached list
- Added an `exclude` option to tank search and used it in Compare so tanks already being compared can't be added again, including through select all or by swapping another slot

Fixes #313
2026-10-05 18:00:43 +13:00
Mark Greene 3aefe7d985 Fix: await the ID discovery loop so it runs to completion
The ID discovery script exited about a second after starting. Since the switch to `atMaxRate`, neither the discovery loop nor the request loop was awaited, and `atMaxRate` didn't await its callback, so the script went straight to `save()`, committed and exited while overlapping duplicate requests failed in the background.

- Awaited both `atMaxRate` loops and the callback inside `atMaxRate`
- Moved the ID range exhaustion check out of the retry loop so retries can't remove extra regions
- Treated network and JSON errors as failed API calls so a long run retries instead of crashing without saving

Fixes #306
2026-10-05 17:33:01 +13:00
Mark Greene bfe31053a9 Fix: keep contact shadows visible at low camera angles
Contact shadows under the tank disappeared when the camera orbited low enough to look up at it. The shadow plane and the ground disc are both transparent and centred on the origin, so three.js sorts them by camera depth. Looking upward flips that order, and because the shadow doesn't write depth, the ground disc was drawn over it.

- Gave `ContactShadows` a `renderOrder` of 1 so it always renders after the ground disc

Fixes #299
2026-10-05 17:28:01 +13:00
Mark Greene a5eac5572e Fix: remove background sliver under equalizer toggle gradient
On some browsers a thin sliver of the Insanity banner showed through along the rounded edges of the equalizer toggle, most visibly on the right where the gradient is opaque. The banner and the gradient were painted on two separately clipped elements, so their anti-aliased edges didn't line up.

- Moved the gradient onto the outer box as the top layer of its `backgroundImage`, above the banner
- Removed the separate gradient layer from the inner flex

Fixes #297
2026-10-05 17:20:52 +13:00
Mark Greene 643e1dd352 Fix: crop transparent padding from fade flags
The fade flag images are 2:1 but the flag only fills the left part, with the rest transparent. That made `cover` + `center` in the tech tree node crop and offset the visible flag.

- Trim the transparent border from the fade flag in the `/flags/fade/[id].webp` route using `sharp`
- Revert the tech tree node back to `cover` + `center`, since the image is now just the flag
2026-10-05 08:10:52 +13:00
Mark Greene fbba0bf13b Fix: constrain playlist filter width
The filters on the playlist page stretched into one long strip beside the tank pool, squeezing the pool into the remaining space.

**Changes**
- Place the filters and the generate button in a fixed-width column (`22rem`) on medium screens and up so the filter buttons wrap compactly
- Stretch the generate button to the column width
- Let the tank pool take the remaining width
- Tighten the gap between the two columns
- Keep the existing stacked layout on small screens
2026-10-04 20:07:52 +13:00
Mark Greene c2c586c2e7 Fix: scroll track textures at the same rate
Dragging a tank's track scrolled its roughness/metalness texture at twice the speed of the base color and normal textures, so highlights drifted off the track links.

**Cause**
- `translateTexture` added the scroll offset to `roughnessMap` and `metalnessMap` separately
- glTF has a single metallic-roughness texture, and the loader assigns that same texture object to both slots, so it received the offset twice

**Changes**
- Collect the track's maps in a `Set` before scrolling so a texture shared between slots is offset exactly once
2026-10-04 20:00:51 +13:00
Mark Greene aaf0e52be4 Fix: restore redirect to the user's preferred locale
Users were no longer sent to their preferred locale. `LocaleRedirector` was emptied in `115fa5aca` after its previous versions caused repeated redirects, and nothing replaced it.

**Cause**
- The earlier logic compared the best locale (a string) against the current locale entry (an object), so the check was always true on non-default locale pages
- That made the redirect fire repeatedly, which led to the logic being removed entirely

**Changes**
- Derive the current locale from the URL, treating the default locale as unprefixed to match how pages are generated
- Redirect only when the best locale differs from the current locale, so it stops after one hop
- Redirect users with a saved `preferred-locale` from any page
- Redirect users without a saved preference from default-locale URLs only, using their browser language, so shared locale links are respected
- Preserve the rest of the path when swapping the locale prefix
- Skip `/api` paths
2026-10-04 19:47:20 +13:00
Mark Greene 6907e5fb7a Fix: mixer buttons clipping at the screen edges on small phones
The mixer's hull/turret/gun row is about 440px wide at its fixed sizes and is centered with `left: 50%` and `translateX(-50%)`, so on phones narrower than that it overflowed past both edges.

Use smaller button sizes on phones and scale the tank images with the viewport (`clamp(2rem, 11vw, 4em)`), with smaller separators and gaps. From 520px up the layout is unchanged.
2026-10-04 15:17:51 +13:00
Mark Greene e5e2f2505c Fix: static armor controls peeking in at the screen edge
The static armor panel hid itself with a fixed `right: -6rem`. In languages with longer labels (e.g. Spanish) the panel is wider than that, so part of it stayed visible at the edge.

Anchor the panel at `right: 0` and slide it out with a transform based on its own width (`translateX(calc(100% + var(--space-4)))`) when static armor isn't active, so it always clears the edge regardless of label length.
2026-10-04 14:50:10 +13:00
495 changed files with 16636 additions and 8371 deletions

No files matched your search

-8
View File
@@ -1,8 +0,0 @@
---
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
@@ -1,13 +0,0 @@
---
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.
@@ -1,3 +0,0 @@
interface:
display_name: "Repo Boundaries"
short_description: "Respect repository editing boundaries"
-2
View File
@@ -1,5 +1,3 @@
packages/protos/src/*/*.ts
node_modules
_node_modules
package-lock.json
+1 -4
View File
@@ -254,8 +254,5 @@
"youtubers",
"zoomable"
],
"typescript.tsdk": "node_modules\\typescript\\lib",
"cSpell.enabledFileTypes": {
"proto": true
}
"typescript.tsdk": "node_modules\\typescript\\lib"
}
+93 -99
View File
@@ -26,7 +26,6 @@
"name": "@blitzkit/core",
"dependencies": {
"@blitzkit/i18n": "workspace:*",
"@blitzkit/protos": "workspace:*",
"@bufbuild/protobuf": "^2.9.0",
"@octokit/plugin-throttling": "^11.0.1",
"@octokit/rest": "^22.0.0",
@@ -53,9 +52,6 @@
"ts-deepmerge": "^7.0.3",
},
},
"packages/protos": {
"name": "@blitzkit/protos",
},
"packages/scripts": {
"name": "@blitzkit/scripts",
"dependencies": {
@@ -93,6 +89,15 @@
"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": {
@@ -102,18 +107,17 @@
"@astrolib/seo": "^1.0.0-beta.8",
"@blitzkit/core": "workspace:*",
"@blitzkit/i18n": "workspace:*",
"@fontsource-variable/jetbrains-mono": "^5.3.0",
"@fontsource-variable/roboto-flex": "^5.3.0",
"@fontsource/inter": "^5.2.8",
"@gltf-transform/core": "^4.4.2",
"@gltf-transform/functions": "^4.4.2",
"@radix-ui/colors": "^3.0.0",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/themes": "^3.2.1",
"@react-three/drei": "^10.7.6",
"@react-three/fiber": "^9.4.0",
"@types/lodash-es": "^4.17.12",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@types/three": "^0.180.0",
"@vite-pwa/astro": "^1.1.0",
"astro": "^5.14.4",
@@ -127,17 +131,15 @@
"markdown-to-jsx": "^7.7.13",
"pwa-install-handler": "^2.6.3",
"quicklime": "^1.2.0",
"radix-ui": "^1.6.7",
"react": "^19.3.0",
"react-dom": "^19.3.0",
"react-error-boundary": "^6.1.3",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-promise-suspense": "^0.3.4",
"soapstone": "^1.0.1",
"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",
},
},
@@ -395,8 +397,6 @@
"@blitzkit/i18n": ["@blitzkit/i18n@workspace:packages/i18n"],
"@blitzkit/protos": ["@blitzkit/protos@workspace:packages/protos"],
"@blitzkit/scripts": ["@blitzkit/scripts@workspace:packages/scripts"],
"@blitzkit/website": ["@blitzkit/website@workspace:packages/website"],
@@ -481,17 +481,13 @@
"@esbuild/win32-x64": ["@esbuild/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="],
"@floating-ui/core": ["@floating-ui/core@1.8.0", "", { "dependencies": { "@floating-ui/utils": "^0.2.12" } }, "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ=="],
"@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="],
"@floating-ui/dom": ["@floating-ui/dom@1.8.0", "", { "dependencies": { "@floating-ui/core": "^1.8.0", "@floating-ui/utils": "^0.2.12" } }, "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg=="],
"@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="],
"@floating-ui/react-dom": ["@floating-ui/[email protected].9", "", { "dependencies": { "@floating-ui/dom": "^1.8.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg=="],
"@floating-ui/react-dom": ["@floating-ui/[email protected].6", "", { "dependencies": { "@floating-ui/dom": "^1.7.4" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw=="],
"@floating-ui/utils": ["@floating-ui/[email protected]2", "", {}, "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww=="],
"@fontsource-variable/jetbrains-mono": ["@fontsource-variable/[email protected]", "", {}, "sha512-F32xpS2NsGYoQi2ADSkKTgpJj7ozajsGgDJ8woTnqjmIB+dxDIqImjl4pXZVEExu8UFZ2ndhmX18EBS/hdz3Lw=="],
"@fontsource-variable/roboto-flex": ["@fontsource-variable/[email protected]", "", {}, "sha512-bOxckUy0qXNRjhV6e4pcHGSvptix4ZRD1uaj5Za8h+p3qrb2GL4U4TQdpVmPSy0SmqwldfD+JJqEKdF68EyiAw=="],
"@floating-ui/utils": ["@floating-ui/[email protected]0", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
"@fontsource/inter": ["@fontsource/[email protected]", "", {}, "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg=="],
@@ -681,127 +677,129 @@
"@radix-ui/colors": ["@radix-ui/[email protected]", "", {}, "sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg=="],
"@radix-ui/number": ["@radix-ui/[email protected].3", "", {}, "sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA=="],
"@radix-ui/number": ["@radix-ui/[email protected].1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
"@radix-ui/primitive": ["@radix-ui/[email protected].7", "", {}, "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q=="],
"@radix-ui/primitive": ["@radix-ui/[email protected].3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
"@radix-ui/react-accessible-icon": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/react-visually-hidden": "1.2.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-WTQwcAvQf5sOcuUyi90lKPbhwcvQ+j55cjrSmeaN+L2vKU3DooOvlKw2MDeiJ5IkV5N905KW0/fGojKOBhD11A=="],
"@radix-ui/react-accessible-icon": ["@radix-ui/[email protected].7", "", { "dependencies": { "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A=="],
"@radix-ui/react-accordion": ["@radix-ui/[email protected]0", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collapsible": "1.1.20", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg=="],
"@radix-ui/react-accordion": ["@radix-ui/[email protected].12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA=="],
"@radix-ui/react-alert-dialog": ["@radix-ui/[email protected].23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dialog": "1.1.23", "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-VAYOiQRqj3GPpYJE0I9J+X8Ip05cyVlNdKOFeiGS2Ou1HHGfpl0BxOyZm6nmVDyU+W+NF3/XLzmjHmVGydhwgA=="],
"@radix-ui/react-alert-dialog": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw=="],
"@radix-ui/react-arrow": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA=="],
"@radix-ui/react-arrow": ["@radix-ui/[email protected].7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
"@radix-ui/react-aspect-ratio": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-fy+dyVR+90nelK8rqIznFlxzx7uPcGbhxH8Nfr2bHb4UfSe+e3hklOC0luK0hDwVwnRX7xTRySpsrQVeW+/oNQ=="],
"@radix-ui/react-aspect-ratio": ["@radix-ui/[email protected].7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g=="],
"@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-4ULOTJ/mqy2hT9GlWa/MFHxHSvH3nJzHnZM1waNsc5Bonv7i70aNenghXmD97S6OJ81ekXONGGt4nT1r0PfEdA=="],
"@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.10", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog=="],
"@radix-ui/react-checkbox": ["@radix-ui/[email protected].11", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-size": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Gnptr9pDDQxD3hgq2dtPbtrp/c2qH1mBwIzw3X/ivrMb2e1t0jMTi606fVEqFPaQR1ggXIVQWKj3P2WW9v7zGQ=="],
"@radix-ui/react-checkbox": ["@radix-ui/[email protected].3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw=="],
"@radix-ui/react-collapsible": ["@radix-ui/[email protected]0", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q=="],
"@radix-ui/react-collapsible": ["@radix-ui/[email protected].12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="],
"@radix-ui/react-collection": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA=="],
"@radix-ui/react-collection": ["@radix-ui/[email protected].7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
"@radix-ui/react-compose-refs": ["@radix-ui/[email protected].5", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA=="],
"@radix-ui/react-compose-refs": ["@radix-ui/[email protected].2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
"@radix-ui/react-context": ["@radix-ui/react-context@1.2.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA=="],
"@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
"@radix-ui/react-context-menu": ["@radix-ui/react-context-menu@2.3.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-CtXP35dxaB5T3zXSd+E3uHe/QpXcpYnZmxp6OaIbfthtfW4wyb77M23BG+bwIJDtsMwEP/YssdsmNyZu7jhWew=="],
"@radix-ui/react-context-menu": ["@radix-ui/react-context-menu@2.2.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww=="],
"@radix-ui/react-dialog": ["@radix-ui/[email protected].23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA=="],
"@radix-ui/react-dialog": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="],
"@radix-ui/react-direction": ["@radix-ui/[email protected].4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg=="],
"@radix-ui/react-direction": ["@radix-ui/[email protected].1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
"@radix-ui/react-dismissable-layer": ["@radix-ui/[email protected]9", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-effect-event": "0.0.5" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w=="],
"@radix-ui/react-dismissable-layer": ["@radix-ui/[email protected]1", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
"@radix-ui/react-dropdown-menu": ["@radix-ui/[email protected].24", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-geq8l2rJkxvkXsT9RMgtUE3P8pITFpTsvYpbySi1IH4fZEABD/Gp85myayFgxk0ktljGMJnCbeFkyTusvSvv7g=="],
"@radix-ui/react-dropdown-menu": ["@radix-ui/[email protected].16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw=="],
"@radix-ui/react-focus-guards": ["@radix-ui/[email protected].6", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ=="],
"@radix-ui/react-focus-guards": ["@radix-ui/[email protected].3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
"@radix-ui/react-focus-scope": ["@radix-ui/[email protected].16", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ=="],
"@radix-ui/react-focus-scope": ["@radix-ui/[email protected].7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
"@radix-ui/react-form": ["@radix-ui/[email protected].16", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-label": "2.1.15", "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Q4TLEn2A7TAypxwmd6R9EwrlXDvkfYSDMrq9/887AXAGh+G1rH+kYJKSTv+Si9Y0JPKTwKYv6PviAJosysNimA=="],
"@radix-ui/react-form": ["@radix-ui/[email protected].8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-label": "2.1.7", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ=="],
"@radix-ui/react-hover-card": ["@radix-ui/[email protected].23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-H8qONfZd3ltrU3+jHCIgITbWo6e1iTKvP9DHdrvYbX48ooRM5FjEDTn16AMwdfuOGkWdZEhpl3PLL/Wk/AnHDQ=="],
"@radix-ui/react-hover-card": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg=="],
"@radix-ui/react-icons": ["@radix-ui/[email protected]", "", { "peerDependencies": { "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" } }, "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g=="],
"@radix-ui/react-id": ["@radix-ui/[email protected].4", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA=="],
"@radix-ui/react-id": ["@radix-ui/[email protected].1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
"@radix-ui/react-label": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-o/rdYEwZTTo5tjknnPeyQFU45kUC4i/XyeDPP+HGyi6XqpOP6Zf5Ya5vh/Yfe9Id5JiuWnnAx2XqIeD3UYZt0g=="],
"@radix-ui/react-label": ["@radix-ui/[email protected].7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="],
"@radix-ui/react-menu": ["@radix-ui/[email protected].24", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-callback-ref": "1.1.4", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-uW7RVuU6Lp/ZtfeY4b3kL32zccgEWvPv1+cf17ubYzHa9cL8AHokmk36cG/XEiH/smbQvumnieXX9j/e9RqJWA=="],
"@radix-ui/react-menu": ["@radix-ui/[email protected].16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg=="],
"@radix-ui/react-menubar": ["@radix-ui/[email protected].24", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-eeVs0vf7cuqXaM0qLQCPcufImiJNVBXdJDLu7ZGYl2732UH23Qat/foNGrr6vYV3/DdTsBqASoggUFgH14OcZA=="],
"@radix-ui/react-menubar": ["@radix-ui/[email protected].16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA=="],
"@radix-ui/react-navigation-menu": ["@radix-ui/[email protected].22", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-previous": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ou7iLEJ+yrhQndkkA4U21XIdS/CS45F4iXIkTZcb6/Ne9EMsOuDudVmCwmDnfFZZ+y1FZqXRNSIgBy+YMvZVZg=="],
"@radix-ui/react-navigation-menu": ["@radix-ui/[email protected].14", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w=="],
"@radix-ui/react-one-time-password-field": ["@radix-ui/[email protected].16", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Tj9P6ntAJEw52oq/F0AGknXR4XncxEt7XU47O3xJQOiWfLzEy3d9gtgKfvjSzGxzHkfL+VzvxGu2KTFsloJqXw=="],
"@radix-ui/react-one-time-password-field": ["@radix-ui/[email protected].8", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg=="],
"@radix-ui/react-password-toggle-field": ["@radix-ui/[email protected].11", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-is-hydrated": "0.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-4gvFnmDXu3dgj21CqsufzIameRvlRd4SBqaWhcrlrNhRo0Y5i/49AmRJYe1fdAM3G2VNBbmin4b0D6cdQocwgw=="],
"@radix-ui/react-password-toggle-field": ["@radix-ui/[email protected].3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-is-hydrated": "0.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw=="],
"@radix-ui/react-popover": ["@radix-ui/[email protected].23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ=="],
"@radix-ui/react-popover": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA=="],
"@radix-ui/react-popper": ["@radix-ui/react-popper@1.3.7", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-rect": "1.1.4", "@radix-ui/react-use-size": "1.1.4", "@radix-ui/rect": "1.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg=="],
"@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="],
"@radix-ui/react-portal": ["@radix-ui/[email protected].17", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ=="],
"@radix-ui/react-portal": ["@radix-ui/[email protected].9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
"@radix-ui/react-presence": ["@radix-ui/[email protected].10", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw=="],
"@radix-ui/react-presence": ["@radix-ui/[email protected].5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
"@radix-ui/react-primitive": ["@radix-ui/[email protected].10", "", { "dependencies": { "@radix-ui/react-slot": "1.3.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg=="],
"@radix-ui/react-primitive": ["@radix-ui/[email protected].3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
"@radix-ui/react-progress": ["@radix-ui/[email protected].16", "", { "dependencies": { "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5XnomAsoZZCY+KNTxbIghpGqPruZvKFNlvcAljVAOdDRDsH4/OZQxhtwo5wdtoDM5R6MhJBb2sPnDuRFep3lzg=="],
"@radix-ui/react-progress": ["@radix-ui/[email protected].7", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg=="],
"@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.4.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-size": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-cgYFEkntCxppHZgtSZ+7vh0wbZQ+IC7PPMw8DSnRG27B6kDd32/Zw0OJt7dGDigCoprMuWHjg2PvUn3PYvPFoQ=="],
"@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.3.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ=="],
"@radix-ui/react-roving-focus": ["@radix-ui/[email protected]9", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ=="],
"@radix-ui/react-roving-focus": ["@radix-ui/[email protected]1", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="],
"@radix-ui/react-scroll-area": ["@radix-ui/[email protected]8", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA=="],
"@radix-ui/react-scroll-area": ["@radix-ui/[email protected]0", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="],
"@radix-ui/react-select": ["@radix-ui/react-select@2.3.7", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-previous": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-WFGImkmbzcfxeIwq/+4HvRN0pizBwbwQUED4I13ezQsDdfl38ZntN6TmR8XaSzPBqoCToe8rF75j6NPNDSzhbg=="],
"@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="],
"@radix-ui/react-separator": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-jOLO4lssEzWpoDu7G+Ze4VjwMRUBt291pnZD0gmalREZipnTX3wadQo7Fy48GCTfe14/YRN6rw/rOJqrE85Wxw=="],
"@radix-ui/react-separator": ["@radix-ui/[email protected].7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="],
"@radix-ui/react-slider": ["@radix-ui/react-slider@1.4.7", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-previous": "1.1.4", "@radix-ui/react-use-size": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mTSLf1GC/C0moWjTbvCM6Qn/gBjvlFt1azuWF2v7MN5C3Zq2U2J2lN3ZEYkpujuOU5Ro7A28wkviSxaKnG0BYg=="],
"@radix-ui/react-slider": ["@radix-ui/react-slider@1.3.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw=="],
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q=="],
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
"@radix-ui/react-switch": ["@radix-ui/react-switch@1.3.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-size": "1.1.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-48tB/4dn2UVLBCYhTu9AuR63IHl73l/qLbLgxd86noTUor4/K4LFDAcYjK+isP5313qxaFpjPVogE7+Y0/V3Kw=="],
"@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ=="],
"@radix-ui/react-tabs": ["@radix-ui/[email protected].21", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog=="],
"@radix-ui/react-tabs": ["@radix-ui/[email protected]3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
"@radix-ui/react-toast": ["@radix-ui/[email protected].23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ofhyAsYaocRGOs/n0XWdUOSVzEAG6BfrMVM8z0c0kLEWY38w/0WuMFPTJP/HVaZPYkMvHZoKIIhNcjbTCBILPg=="],
"@radix-ui/react-toast": ["@radix-ui/[email protected].15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g=="],
"@radix-ui/react-toggle": ["@radix-ui/[email protected]8", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7lonPlKfSacd20GlOBx2ltuVKz9oqWYZz+oMQyOltw6t1y2nyftj2ZmwwUHYn49kqfDWcp8dNZm5NgV+5Z+mug=="],
"@radix-ui/react-toggle": ["@radix-ui/[email protected]0", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ=="],
"@radix-ui/react-toggle-group": ["@radix-ui/[email protected]9", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-toggle": "1.1.18", "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-OtnwuSVjd1Ofi+AdnvhsjQdyuhCDwYs1w9RyB5BN/OavXOVQo42SYqQjwUnbPnaiPFBpQ9aX70dWeee+v2oBLA=="],
"@radix-ui/react-toggle-group": ["@radix-ui/[email protected]1", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q=="],
"@radix-ui/react-toolbar": ["@radix-ui/[email protected]9", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-separator": "1.1.15", "@radix-ui/react-toggle-group": "1.1.19" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ph0IvtYw4VB12ZnZg+YtrGs8yJQsnizwo/zu0R4Y/nWugtJzA7Pg1eWeuDR9+LSqn+xjamss+UOSOJJJ4gx8jw=="],
"@radix-ui/react-toolbar": ["@radix-ui/[email protected]1", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-separator": "1.1.7", "@radix-ui/react-toggle-group": "1.1.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg=="],
"@radix-ui/react-tooltip": ["@radix-ui/[email protected].16", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg=="],
"@radix-ui/react-tooltip": ["@radix-ui/[email protected].8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="],
"@radix-ui/react-use-callback-ref": ["@radix-ui/[email protected].4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ=="],
"@radix-ui/react-use-callback-ref": ["@radix-ui/[email protected].1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
"@radix-ui/react-use-controllable-state": ["@radix-ui/[email protected].6", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ=="],
"@radix-ui/react-use-controllable-state": ["@radix-ui/[email protected].2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
"@radix-ui/react-use-effect-event": ["@radix-ui/[email protected].5", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg=="],
"@radix-ui/react-use-effect-event": ["@radix-ui/[email protected].2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
"@radix-ui/react-use-escape-keydown": ["@radix-ui/[email protected].5", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ge3ipobwSXTj4JyVtswQ7qZj0ZHdtbGuOno/LrgAAeSxtsJ6Vs4Gz5IkPH2bmqpjcLUFoqGhA/mueuIf63UXlA=="],
"@radix-ui/react-use-escape-keydown": ["@radix-ui/[email protected].1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
"@radix-ui/react-use-is-hydrated": ["@radix-ui/[email protected].3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw=="],
"@radix-ui/react-use-is-hydrated": ["@radix-ui/[email protected].0", "", { "dependencies": { "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA=="],
"@radix-ui/react-use-layout-effect": ["@radix-ui/[email protected].4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw=="],
"@radix-ui/react-use-layout-effect": ["@radix-ui/[email protected].1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
"@radix-ui/react-use-previous": ["@radix-ui/[email protected].4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg=="],
"@radix-ui/react-use-previous": ["@radix-ui/[email protected].1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="],
"@radix-ui/react-use-rect": ["@radix-ui/[email protected].4", "", { "dependencies": { "@radix-ui/rect": "1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ=="],
"@radix-ui/react-use-rect": ["@radix-ui/[email protected].1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
"@radix-ui/react-use-size": ["@radix-ui/[email protected].4", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw=="],
"@radix-ui/react-use-size": ["@radix-ui/[email protected].1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="],
"@radix-ui/react-visually-hidden": ["@radix-ui/[email protected].11", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ=="],
"@radix-ui/react-visually-hidden": ["@radix-ui/[email protected].3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="],
"@radix-ui/rect": ["@radix-ui/[email protected].3", "", {}, "sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw=="],
"@radix-ui/rect": ["@radix-ui/[email protected].1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
"@radix-ui/themes": ["@radix-ui/[email protected]", "", { "dependencies": { "@radix-ui/colors": "^3.0.0", "classnames": "^2.3.2", "radix-ui": "^1.1.3", "react-remove-scroll-bar": "^2.3.8" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I0/h2CRNTpYNB7Mi3xFIvSsQq5a108d7kK8dTO5zp5b9HR5QJXKag6B8tjpz2ITkVYkFdkGk45doNkSr7OxwNw=="],
"@react-three/drei": ["@react-three/[email protected]", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@mediapipe/tasks-vision": "0.10.17", "@monogrid/gainmap-js": "^3.0.6", "@use-gesture/react": "^10.3.1", "camera-controls": "^3.1.0", "cross-env": "^7.0.3", "detect-gpu": "^5.0.56", "glsl-noise": "^0.0.0", "hls.js": "^1.5.17", "maath": "^0.10.8", "meshline": "^3.3.1", "stats-gl": "^2.2.8", "stats.js": "^0.17.0", "suspend-react": "^0.1.3", "three-mesh-bvh": "^0.8.3", "three-stdlib": "^2.35.6", "troika-three-text": "^0.52.4", "tunnel-rat": "^0.1.2", "use-sync-external-store": "^1.4.0", "utility-types": "^3.11.0", "zustand": "^5.0.1" }, "peerDependencies": { "@react-three/fiber": "^9.0.0", "react": "^19", "react-dom": "^19", "three": ">=0.159" }, "optionalPeers": ["react-dom"] }, "sha512-ZSFwRlRaa4zjtB7yHO6Q9xQGuyDCzE7whXBhum92JslcMRC3aouivp0rAzszcVymIoJx6PXmibyP+xr+zKdwLg=="],
@@ -939,9 +937,9 @@
"@types/progress": ["@types/[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-iadjw02vte8qWx7U0YM++EybBha2CQLPGu9iJ97whVgJUT5Zq9MjAPYUnbfRI2Kpehimf1QjFJYxD0t8nqzu5w=="],
"@types/react": ["@types/react@19.3.0", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg=="],
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
"@types/react-dom": ["@types/react-dom@19.3.0", "", { "peerDependencies": { "@types/react": "^19.3.0" } }, "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q=="],
"@types/react-dom": ["@types/react-dom@19.2.2", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw=="],
"@types/react-reconciler": ["@types/[email protected]", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-RsqPttsBQ+6af0nATFXJJpemYQH7kL9+xLNm1z+0MjQFDKBZDM2R6SBrjdvRmHu9i9fM6povACj57Ft+pKRNOA=="],
@@ -1153,6 +1151,8 @@
"ci-info": ["[email protected]", "", {}, "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ=="],
"classnames": ["[email protected]", "", {}, "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="],
"cli-boxes": ["[email protected]", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
"cliui": ["[email protected]", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
@@ -1687,7 +1687,7 @@
"lodash": ["[email protected]", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
"lodash-es": ["[email protected]8.1", "", {}, "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="],
"lodash-es": ["[email protected]7.23", "", {}, "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg=="],
"lodash.debounce": ["[email protected]", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
@@ -1995,7 +1995,7 @@
"quicklime": ["[email protected]", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-uPFHeb+1L4o0D5V4TtLfvoMtLbv2dUq7d9dco47khUZilsdS0ugBD1RfhvdsdpMr4UWbOUkJOUCetUrMIDST1A=="],
"radix-ui": ["radix-ui@1.6.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-accessible-icon": "1.1.15", "@radix-ui/react-accordion": "1.2.20", "@radix-ui/react-alert-dialog": "1.1.23", "@radix-ui/react-arrow": "1.1.15", "@radix-ui/react-aspect-ratio": "1.1.15", "@radix-ui/react-avatar": "1.2.6", "@radix-ui/react-checkbox": "1.3.11", "@radix-ui/react-collapsible": "1.1.20", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-context-menu": "2.3.7", "@radix-ui/react-dialog": "1.1.23", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-dropdown-menu": "2.1.24", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-form": "0.1.16", "@radix-ui/react-hover-card": "1.1.23", "@radix-ui/react-label": "2.1.15", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-menubar": "1.1.24", "@radix-ui/react-navigation-menu": "1.2.22", "@radix-ui/react-one-time-password-field": "0.1.16", "@radix-ui/react-password-toggle-field": "0.1.11", "@radix-ui/react-popover": "1.1.23", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-progress": "1.1.16", "@radix-ui/react-radio-group": "1.4.7", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-scroll-area": "1.2.18", "@radix-ui/react-select": "2.3.7", "@radix-ui/react-separator": "1.1.15", "@radix-ui/react-slider": "1.4.7", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-switch": "1.3.7", "@radix-ui/react-tabs": "1.1.21", "@radix-ui/react-toast": "1.2.23", "@radix-ui/react-toggle": "1.1.18", "@radix-ui/react-toggle-group": "1.1.19", "@radix-ui/react-toolbar": "1.1.19", "@radix-ui/react-tooltip": "1.2.16", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-escape-keydown": "1.1.5", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-size": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-QBdhh1arIEUvPC0dQ5+nwWAxt7+N+oP/9jPwjJkGFoSk/sqxg32gJtSXGtFh8frAIcS6oC9cx2Q+7KYCQLOAeA=="],
"radix-ui": ["radix-ui@1.4.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-accessible-icon": "1.1.7", "@radix-ui/react-accordion": "1.2.12", "@radix-ui/react-alert-dialog": "1.1.15", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-aspect-ratio": "1.1.7", "@radix-ui/react-avatar": "1.1.10", "@radix-ui/react-checkbox": "1.3.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-context-menu": "2.2.16", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-dropdown-menu": "2.1.16", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-form": "0.1.8", "@radix-ui/react-hover-card": "1.1.15", "@radix-ui/react-label": "2.1.7", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-menubar": "1.1.16", "@radix-ui/react-navigation-menu": "1.2.14", "@radix-ui/react-one-time-password-field": "0.1.8", "@radix-ui/react-password-toggle-field": "0.1.3", "@radix-ui/react-popover": "1.1.15", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-progress": "1.1.7", "@radix-ui/react-radio-group": "1.3.8", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-scroll-area": "1.2.10", "@radix-ui/react-select": "2.2.6", "@radix-ui/react-separator": "1.1.7", "@radix-ui/react-slider": "1.3.6", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-switch": "1.2.6", "@radix-ui/react-tabs": "1.1.13", "@radix-ui/react-toast": "1.2.15", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-toggle-group": "1.1.11", "@radix-ui/react-toolbar": "1.1.11", "@radix-ui/react-tooltip": "1.2.8", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-escape-keydown": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA=="],
"radix3": ["[email protected]", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="],
@@ -2003,11 +2003,9 @@
"range-parser": ["[email protected]", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
"react": ["react@19.3.0", "", {}, "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog=="],
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
"react-dom": ["react-dom@19.3.0", "", { "dependencies": { "scheduler": "^0.28.0" }, "peerDependencies": { "react": "^19.3.0" } }, "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q=="],
"react-error-boundary": ["[email protected]", "", { "peerDependencies": { "@types/react": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-GnSKpCohFi2nQmJCWwP8O8wub7zexlePvpsejvQr35vS5RTouS1+utTNOmyc540yw5vyOXnSL1rBWsCQDmkyUA=="],
"react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
"react-promise-suspense": ["[email protected]", "", { "dependencies": { "fast-deep-equal": "^2.0.1" } }, "sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ=="],
@@ -2015,7 +2013,7 @@
"react-refresh": ["[email protected]", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
"react-remove-scroll": ["[email protected].2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="],
"react-remove-scroll": ["[email protected].1", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA=="],
"react-remove-scroll-bar": ["[email protected]", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
@@ -2153,8 +2151,6 @@
"smol-toml": ["[email protected]", "", {}, "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g=="],
"soapstone": ["[email protected]", "", { "dependencies": { "immer": "^11.1.8", "lodash-es": "^4.18.1" }, "peerDependencies": { "react": "^19.3.0", "typescript": "^5" } }, "sha512-5f6iW2Hybjqcvmn+P+X1gH1NKDhry+ePk4F1rqK0yeFjNICx7tqy0X315tQD0Lhv/zUTNA9dV+8BLW9/o7Wlpw=="],
"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=="],
@@ -2385,6 +2381,8 @@
"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=="],
@@ -2563,8 +2561,6 @@
"@babel/preset-env/semver": ["[email protected]", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@blitzkit/scripts/lodash-es": ["[email protected]", "", {}, "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg=="],
"@jimp/core/file-type": ["[email protected]", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="],
"@octokit/endpoint/@octokit/types": ["@octokit/[email protected]", "", { "dependencies": { "@octokit/openapi-types": "^25.1.0" } }, "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g=="],
@@ -2673,7 +2669,7 @@
"proxy-agent/socks-proxy-agent": ["[email protected]", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
"react-dom/scheduler": ["[email protected]8.0", "", {}, "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw=="],
"react-dom/scheduler": ["[email protected]7.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
"readable-stream/safe-buffer": ["[email protected]", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
@@ -2685,8 +2681,6 @@
"simple-swizzle/is-arrayish": ["[email protected]", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
"soapstone/immer": ["[email protected]", "", {}, "sha512-EQyQtLiYW029lyoczMl/Hh4Xu7cDecSc58JRYpHyL4tIAu3eqd1yJzQX04d2BZHDkzFFvm6qJEJWOtfDSWAXbQ=="],
"source-map-support/source-map": ["[email protected]", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"stats-gl/three": ["[email protected]", "", {}, "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="],
+1 -6
View File
@@ -1,11 +1,6 @@
{
"words": [
"Debuff",
"words": [
"gamemodes",
"Passability",
"Recoverkit",
"Repairkit",
"Respawns",
"Tankopedia"
]
}
+2 -2
View File
@@ -5,10 +5,10 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions
## Features
- Combined game mode passive and active abilities into a single dropdown
- [Mark Greene] Added tier filters to the Guess game
- Added tier filters to the Guess game [Mark Greene]
- Changing tiers will break your streak
## Fixes
- [Mark Greene] module damage is now properly shown when sorting with it in the tank search
- module damage is now properly shown when sorting with it in the tank search [Mark Greene]
- Duplicate abilities in the tank filters are now removed
+1 -1
View File
@@ -4,7 +4,7 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions
## Fixes
- [GonnaHetzMe] The turret for Centurion I is no longer offset from the body
- The turret for Centurion I is no longer offset from the body [GonnaHetzMe]
- Please allow up to 24 hours for the model to update
- Vertical Stabilizers now give the correct 12% buff instead of 15%
- Re-ordering tanks in Compare now works once again
+1 -1
View File
@@ -15,5 +15,5 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions
## Fixes
- The Tankopedia now smoothly resizes when enlarging on interaction
- [Mark Greene] Stock turrets now correctly mount the corresponding stock gun
- Stock turrets now correctly mount the corresponding stock gun [Mark Greene]
- The consumable and provision buttons in Compare are no longer tiny
+2 -2
View File
@@ -5,10 +5,10 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions
## Features
- Reworked tank search filters to be far more compact to make way for new filters
- [Mark Greene] Added the ability to filter tanks by consumables
- Added the ability to filter tanks by consumables [Mark Greene]
- Added the ability to filter tanks by provisions and game-mode abilities and powers
## Fixes
- Consumable and provision icons in Compare are now properly sized
- [Mark Greene] Provisions now properly affect terrain resistances
- Provisions now properly affect terrain resistances [Mark Greene]
+5 -5
View File
@@ -13,11 +13,11 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions
## Technical Features
- [GonnaHetzMe] Enabling dev mode now displays the tank's non-numerical id
- [GonnaHetzMe] The dev id and the new dev name are now copyable on click
- Enabling dev mode now displays the tank's non-numerical id [GonnaHetzMe]
- The dev id and the new dev name are now copyable on click [GonnaHetzMe]
## Fixes
- [GonnaHetzMe] Tech trees that start at tiers higher than tier 1 like the Blitz Nation ones now properly render their trees in Tankopedia
- [GonnaHetzMe] The tank pitch/yaw inputs in the Tank Sandbox now initialize with the correct values instead of 0
- [GonnaHetzMe] Large Repair Kits once again use the correct modern icon
- Tech trees that start at tiers higher than tier 1 like the Blitz Nation ones now properly render their trees in Tankopedia [GonnaHetzMe]
- The tank pitch/yaw inputs in the Tank Sandbox now initialize with the correct values instead of 0 [GonnaHetzMe]
- Large Repair Kits once again use the correct modern icon [GonnaHetzMe]
+1 -1
View File
@@ -4,5 +4,5 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions
## Fixes
- [GonnaHetzMe] Tank hit points in Equalizer mode is now accurate to the game
- Tank hit points in Equalizer mode is now accurate to the game [GonnaHetzMe]
- Armor highlighting now reflects the actual thicknesses of tanks in Equalizer mode
+3 -3
View File
@@ -4,9 +4,9 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions
## Fixes
- [GonnaHetzMe] Tungsten shells are now properly cropped
- Tungsten shells are now properly cropped [GonnaHetzMe]
- Equalizer no longer gives insanely high penetration values
- The tank reveal animation no longer repeats when you scroll away and back to the tank sandbox
- [GonnaHetzMe] The RHM. Pzw.'s turret no longer has the floating plate
- The RHM. Pzw.'s turret no longer has the floating plate [GonnaHetzMe]
- Please give BlitzKit up to 1 hour to update the model
- [GonnaHetzMe] Tanks with inclined turret rings like the Minotauro now display the correct pitch in the tank sandbox inputs
- Tanks with inclined turret rings like the Minotauro now display the correct pitch in the tank sandbox inputs [GonnaHetzMe]
+5 -5
View File
@@ -4,7 +4,7 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions
## Features
- [GonnaHetzMe] Added tooltips to the module selector in Tankopedia
- Added tooltips to the module selector in Tankopedia [GonnaHetzMe]
## Fixes
@@ -12,7 +12,7 @@ Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions
- Removed tank visual and collision model caching
- Guesser once again breaks streaks if not all tiers are selected
- BlitzKit now properly unloads tank models from memory when visually hidden in Guesser
- [GonnaHetzMe] Tanks with complex transparency like the Herdbreaker once again handle opacity correctly
- [GonnaHetzMe] Pieces of tank models that have transparency now handle culling properly (they're visible from both sides)
- [GonnaHetzMe] Tanks with "cardboard" textures have been fixed, thanks to better PVR file parsing
- [GonnaHetzMe] Tank icons are now scaled correctly so small tanks are now properly zoomed out in contrast to bigger ones
- Tanks with complex transparency like the Herdbreaker once again handle opacity correctly [GonnaHetzMe]
- Pieces of tank models that have transparency now handle culling properly (they're visible from both sides) [GonnaHetzMe]
- Tanks with "cardboard" textures have been fixed, thanks to better PVR file parsing [GonnaHetzMe]
- Tank icons are now scaled correctly so small tanks are now properly zoomed out in contrast to bigger ones [GonnaHetzMe]
+4 -4
View File
@@ -8,13 +8,13 @@ Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions
## Fixes
- [Mark Greene] Clicking on the armor multiple times with HE no longer crashes BlitzKit
- [Mark Greene] Ricochets that later intersect with external modules no longer falsely claim a successful damaging penetration
- Clicking on the armor multiple times with HE no longer crashes BlitzKit [Mark Greene]
- Ricochets that later intersect with external modules no longer falsely claim a successful damaging penetration [Mark Greene]
- The lighting animation no longer stops prematurely when BlitzKit is unfocused
- The spot light angle has been increased to more evenly light up larger tanks
- BlitzKit once again uses soft shadows, reducing the pixelated shadows
- Fixed the weird patterns that formed on the tracks of tanks under self-shadows
- Increased the floor size and light decay to create the illusion that the floor is infinite
- [Mark Greene] Safari no longer crashes when unloading textures for unloaded tanks
- Safari no longer crashes when unloading textures for unloaded tanks [Mark Greene]
- The gun depression transition between two constraints (like often behind tanks) now uses a gentler zoned and can never be 0
- [Mark Greene] Armor plate names in Static Armor are now properly capitalized in English and translated to other languages
- Armor plate names in Static Armor are now properly capitalized in English and translated to other languages [Mark Greene]
-41
View File
@@ -1,41 +0,0 @@
# BlitzKit 1.31.4
Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions this update.
## Features
- [Mark Greene] Added Peekaboo DPM
- Your Peekaboo DPM is lower than your normal DPM if your reload is faster than 10s as you'll have to wait for the remaining 10s for you to get unspotted before you can poke and shoot
- [Mark Greene] The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off
- [Mark Greene] Added a spall liner button to the Tankopedia beside the other equipment
## Fixes
- [Mark Greene] BlitzKit Session now properly handles tanks removed from the game
- [Mark Greene] Removed the Beta badge from the Equalizer button
- Updated the background image for the Equalizer button to the actual banner of the new game mode
- [Mark Greene] The armor no longer disappears when you turn on Dynamic Armor System
- [Mark Greene] Camouflage values in Tankopedia are now more descriptive when shooting
- [Mark Greene] The contact shadows on the ground no longer grow & darken when switching between tabs
- The "Help Translate BlitzKit" text on the home page is now properly centered vertically
- [Mark Greene] The footer now says "Branch" instead of "CDN"
- [Mark Greene] The game version in the footer now displays a shorthand version instead of the entire version number
- [Mark Greene] The reload visualizer now displays just 1 decimal place
- [Mark Greene] The search bar no longer redirects to a seemingly random tank when clicking enter when searching
- [Mark Greene] Tank search now properly handles the full names of tanks like the Super Pershing
- [Mark Greene] The loading bar below the name of the tanks in Tankopedia is now sufficiently spaced below
- [Mark Greene] The gun depression visualizer now properly handles the inherent tilt of tanks like the Minotauro
## Technical Features
- Added documentation to the README on setting up and developing BlitzKit locally
- Added bug report and feature request forms to GitHub
- Switched to the GNU AGPLv3 license
## Technical Fixes
- BlitzKit now handles the new ID system for game-modes in WoTB
- The directory which preview versions of the game are downloaded to are now created properly
- This was the last bug standing in the way of BlitzKit Previews
- Welcome back, BlitzKit Previews!
- Removed some dead code from the BlitzKit model mangler
+98
View File
@@ -0,0 +1,98 @@
# BlitzKit 1.32.0
Thank you to [Mark Greene](https://github.com/Hitjack007) for your contributions this update.
## Features
### Tankopedia & Armor
- Added a spall liner button to the Tankopedia beside the other equipment [Mark Greene]
- Listed track repair times in the Tankopedia [Mark Greene]
- The penetration chance is now displayed when penetration testing armor [Mark Greene]
- Added a new setting to disable automatically loading tanks in Tankopedia [Mark Greene]
### Tank Performance & Mechanics
- Added Peekaboo DPM [Mark Greene]
- Your Peekaboo DPM is lower than your normal DPM if your reload is faster than 10s as you'll have to wait for the remaining 10s for you to get unspotted before you can poke and shoot
### Tank Filters
- The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene]
### Game Compatibility
- Added compatibility for tier XI tanks [Mark Greene]
## Fixes
### Tankopedia & Armor
- The armor no longer disappears when you turn on Dynamic Armor System [Mark Greene]
- Camouflage values in Tankopedia are now more descriptive when shooting [Mark Greene]
- The penetration chance is now displayed when penetration testing armor [Mark Greene]
- Listed track repair times in the Tankopedia [Mark Greene]
- Added a spall liner button to the Tankopedia beside the other equipment [Mark Greene]
- The flags in the Tankopedia tech tree are no longer offset to the top left [Mark Greene]
- The loading bar below the name of the tanks in Tankopedia is now sufficiently spaced below [Mark Greene]
- Removed the vertical sliver of pixels found to the right of the Equalizer toggle in Tankopedia
### Tank Search & Filters
- The search bar no longer redirects to a seemingly random tank when clicking enter when searching [Mark Greene]
- Tank search now properly handles the full names of tanks like the Super Pershing [Mark Greene]
- The tank search now remains consistent in order even when an added filter does not add/remove tanks from the list [Mark Greene]
- The test and owned tank filters are now more intuitive as clicking on them now turns the clicked option on instead of off [Mark Greene]
### Visuals & UI
- Removed the Beta badge from the Equalizer button [Mark Greene]
- Updated the background image for the Equalizer button to the actual banner of the new game mode
- The contact shadows on the ground no longer grow & darken when switching between tabs [Mark Greene]
- Additionally, the contact shadows stays visible at low angles [Mark Greene]
- The "Help Translate BlitzKit" text on the home page is now properly centered vertically
- The footer now says "Branch" instead of "CDN" [Mark Greene]
- The game version in the footer now displays a shorthand version instead of the entire version number [Mark Greene]
- The reload visualizer now displays just 1 decimal place [Mark Greene]
- Plot controls for the Static armor tab no longer pokes in from the right on non-Static armor tabs in some languages [Mark Greene]
- Mixer's controllers now scale better on smaller screens [Mark Greene]
- The list of available tanks in the Playlist is no longer excessively wide [Mark Greene]
### Tank Mechanics & Models
- The gun depression visualizer now properly handles the inherent tilt of tanks like the Minotauro [Mark Greene]
- When moving the tracks of tanks, the textures no longer move at different rates [Mark Greene]
### Localization
- Users with a preference on a language are once again redirected to the correct localized pages [Mark Greene]
### Session & Game Compatibility
- BlitzKit Session now properly handles tanks removed from the game [Mark Greene]
## Technical Fixes
- BlitzKit now handles the new ID system for game-modes in WoTB
- The directory which preview versions of the game are downloaded to are now created properly
- This was the last bug standing in the way of BlitzKit Previews
- Welcome back, BlitzKit Previews!
- Removed some dead code from the BlitzKit model mangler
- The player discovery loop now persists for longer than 1 iteration [Mark Greene]
- Bun is now forced to run scripts with the `--bun` flag
## Technical Features
- Added documentation to the README on setting up and developing BlitzKit locally
- Added bug report and feature request forms to GitHub
- Switched to the GNU AGPLv3 license
## Technical Fixes
- BlitzKit now handles the new ID system for game-modes in WoTB
- The directory which preview versions of the game are downloaded to are now created properly
- This was the last bug standing in the way of BlitzKit Previews
- Welcome back, BlitzKit Previews!
- Removed some dead code from the BlitzKit model mangler
- The player discovery loop now persists for longer than 1 iteration [Mark Greene]
- Bun is now forced to run scripts with the `--bun` flag
-9
View File
@@ -1,9 +0,0 @@
# Timezones
What is considered a "day's worth of games" is determined by the reset time. The reset time is generally at midnight everyday after which newer games are counted towards the next day. Reset times vary from region to region:
- North America: `UTC-5:00` (Central North American Time midnight)
- Europe: `UTC+1:00` (Central European Time midnight)
- Asia: `UTC+7:00` (Central Asia Standard Time midnight)
**Reset times are different from Blitz Stars** (Blitz Stars resets at 5:00 am locally relative to the user opening their website). Inconsistencies with Blitz Stars only occur with sleep-deprived players and players who play in the wrong region.
-45
View File
@@ -1,45 +0,0 @@
# Blitzkit Rating Leaderboard
A straightforward way of storing the entire World of Tanks Blitz rating leaderboard to disk.
```cpp
primary BlitzkitRatingLeaderboard {
utf8"BKRL" magic;
Header header;
primary Body<header> body;
}
Header {
uint16 version; // always 1
Format format;
uint32 count;
}
Format enum<uint8> {
Base,
Superset1,
}
Body<Header header> match<header.format> {
Base {
primary {
uint32 id;
uint16 score;
}[header.count] entries;
};
Superset1 {
primary {
uint32 id;
uint16 score;
uint32 battles;
uint32 wins;
uint32 survived;
uint32 damage;
uint32 kills;
}[header.count] entries;
};
}
```
-18
View File
@@ -1,18 +0,0 @@
# Discovered Ids
```c
primary DiscoveredIds {
utf8"DIDS" magic;
Header header;
primary Body body;
}
Header {
uint16 version; // always 1
}
Body {
uint32 count;
uint32[count] ids;
}
```
+1 -170
View File
@@ -1,172 +1,3 @@
# KitScore
## Memo
KitScore is a performance metric that makes sense. This metric can be applied to any game, virtual or real. Specific pieces of information relating directly to World of Tanks Blitz will be provided within parentheses and with a "WoTB:" prefix.
## Consumption of Observations
KitScore is driven solely by the behavior of other players and finding meaning of a new observation within a pool of condensed data based on previously observed data. Generally, we will be provided with a number of statistics (the $x_i$ of an observation) per player (WoTB: $x_\text{frags}$, $x_\text{xp}$, $x_\text{spots}$, etc.) including a target statistic (the $x_j$ of an observation) that all other statistics try to maximize (WoTB: "winrate" which we will defined later as $x_j$).
If the statistics are cumulative, they will have to be normalized (WoTB: statistics fetched from Wargaming are indeed cumulative even for a single player; $x_\text{frags}=\frac{\Sigma x_\text{frags}}{\Sigma x_\text{battles}}$, $x_\text{spots}=\frac{\Sigma x_\text{spots}}{\Sigma x_\text{battles}}$, $x_j=\frac{\Sigma x_\text{wins}}{\Sigma x_\text{battles}}$, etc.). Each player will have such average statistics, giving us many points of data to work with. If the statistics are not cumulative, then you will be dealing with multiple observations per player which will only help improve accuracy.
## It's Impossible to "Find What Makes the Metric Tick"
WN8, a widely adopted metric in the World of Tanks and World of Tanks Blitz communities is plagued with problems. One of them being that people often find and exploit "what makes the metric tick." In other words, people easily exploit the rudimentary nature of WN8 to score undeservedly high.
In WN8, the gains of some rewarding categories overshadow the losses of others though that may not necessarily be in the best interest in maximizing winrate. KitScore makes this nearly impossible as it punishes a player for scoring well solely high in a certain category. You will never exploit KitScore. Period.
## Generating Reasonable Values
TODO: there's like no runaway cases
## Symbol Interpretation
| Symbol | Interpretation |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| $A_\text{human}$ | The human readable version of the raw score $A$. |
| $A$ | The raw KitScore. |
| $C$ | An arbitrary coefficient. |
| $I$ | The number of statistics including the target statistic. This means that there are $I-1$ entries for $x_i$ and $1$ entry for $y$ for each observation. |
| $i$ | The statistic index of where there are $I$ entries. |
| $j$ | A discriminator for the target statistic. There may never be more than $1$ entries for $j$. |
| $m$ | The degree of the polynomial regression. |
| $n$ | The number of observations. |
| $a$ | An "atomic" score which is a function of the $i$th statistic. |
| $w$ | The weight of the $i$th atomic statistic. |
## Computing the Score
The final metric $A_\text{human}$ is an arbitrarily scaled value of the raw score $A$ where $C$ is any coefficient of your liking. BlitzKit uses $C=10^3$.
$$
A_\text{human}=CA
$$
The final metric $A$ is the weighted average of individual scores $a$ which are functions of the $i$th statistic excluding the target statistic $j$ itself.
$$
A=\frac{\sum_{i \neq j} w_{i}a_{i}}{\sum_{i \neq j} w_{i}}
$$
The "atomic" score $a$ is the difference between the predicted target statistic $P_{i \leftrightarrow j}(x_i)$ acquired using a polynomial regression of degree $m$ and the actual newly observed $x_j$.
$$
a_i=x_j-P_{i \leftrightarrow j}(x_i)
$$
The polynomial regression of $m$th degree can be written as follows:
$$
P(x)=\beta_0x^0+\beta_1x^1+\beta_2x^2+\dots+\beta_mx^m
$$
Polynomial regression coefficients $\beta$ can be acquired through basic linear algebra where an $m \times m$ of constants is multiplied with $m \times 1$ of unknowns which equals another $m \times 1$ of constants.
```math
\begin{bmatrix}
\sum_{k=1}^n x_i^0 & \sum_{k=1}^n x_i^1 & \sum_{k=1}^n x_i^2 & \dots & \sum_{k=1}^n x_i^m \\
\sum_{k=1}^n x_i^1 & \sum_{k=1}^n x_i^2 & \sum_{k=1}^n x_i^3 & \dots & \sum_{k=1}^n x_i^{m+1} \\
\sum_{k=1}^n x_i^2 & \sum_{k=1}^n x_i^3 & \sum_{k=1}^n x_i^4 & \dots & \sum_{k=1}^n x_i^{m+2} \\
\vdots & \vdots & \vdots & \ddots & \vdots \\
\sum_{k=1}^n x_i^m & \sum_{k=1}^n x_i^{m+1} & \sum_{k=1}^n x_i^{m+1} & \dots & \sum_{k=1}^n x_i^{2m} \\
\end{bmatrix}
\begin{bmatrix}
\beta_0 \\
\beta_1 \\
\beta_2 \\
\vdots \\
\beta_m
\end{bmatrix}
=
\begin{bmatrix}
\sum_{k=1}^n x_jx_i^0 \\
\sum_{k=1}^n x_jx_i^1 \\
\sum_{k=1}^n x_jx_i^2 \\
\vdots \\
\sum_{k=1}^n x_jx_i^m
\end{bmatrix}
```
The weight $w$ is a slice of the Pearson corelation matrix. The numerator is the corelation between the $i$th statistic and the target statistic $j$ while the denominator the sum of the corelations between the $i$th statistic and all statistics but the target statistic $j$.
$$
w_{i}=\frac{r_{i\leftrightarrow j}^2}{\sum_{i_{k}\neq j}r_{i\leftrightarrow i_{k}}^2}
$$
## Understanding the Corelation Matrix
Forming the corelation matrix will create an $I \times I$ matrix where. This matrix is best represented as a table. The example below illustrates a matrix/table for $I=4$ which includes $3$ entries for $i$ statistics and $1$ entry for the $j$ target statistic.
| | $x_1$ | $x_2$ | $x_3$ | $x_j$ |
| ----- | --------------------------- | --------------------------- | --------------------------- | --------------------------- |
| $x_1$ | $1$ | $r_{1 \leftrightarrow 2}^2$ | $r_{1 \leftrightarrow 3}^2$ | $r_{1 \leftrightarrow j}^2$ |
| $x_2$ | $r_{1 \leftrightarrow 2}^2$ | $1$ | $r_{2 \leftrightarrow 3}^2$ | $r_{2 \leftrightarrow j}^2$ |
| $x_3$ | $r_{1 \leftrightarrow 3}^2$ | $r_{2 \leftrightarrow 3}^2$ | $1$ | $r_{3 \leftrightarrow j}^2$ |
| $x_j$ | $r_{1 \leftrightarrow j}^2$ | $r_{2 \leftrightarrow j}^2$ | $r_{3 \leftrightarrow j}^2$ | $1$ |
It should not be a surprise to find $r_{i \leftrightarrow i}^2=1$ which forms a neat diagonal across the table. Note that there are many duplicates within the $I^2$ entries. The "bottom-right triangle" can be eliminated to remove redundancies leaving us with only $\frac{I(I+1)}{2}$ fields occupied.
| | $x_1$ | $x_2$ | $x_3$ | $x_j$ |
| ----- | ----- | --------------------------- | --------------------------- | --------------------------- |
| $x_1$ | $1$ | $r_{1 \leftrightarrow 2}^2$ | $r_{1 \leftrightarrow 3}^2$ | $r_{1 \leftrightarrow j}^2$ |
| $x_2$ | | $1$ | $r_{2 \leftrightarrow 3}^2$ | $r_{2 \leftrightarrow j}^2$ |
| $x_3$ | | | $1$ | $r_{3 \leftrightarrow j}^2$ |
| $x_j$ | | | | $1$ |
When programming this matrix into an array, $r_{i \leftrightarrow i}^2=1$ will be redundant. I recommend condensing the matrix into an array of size $\frac{I(I+1)}{2}+I=\frac{I(I-1)}{2}$ to avoid all redundant entries. For $I=4$, the array will look something like the one illustrated below (here, $j=4$).
$$
[r_{1 \leftrightarrow 2}^2, r_{1 \leftrightarrow 3}^2, r_{1 \leftrightarrow 4}^2, r_{2 \leftrightarrow 3}^2, r_{2 \leftrightarrow 4}^2, r_{3 \leftrightarrow 4}^2]
$$
## Understanding the Weights
Some may find the weight equation arbitrary; it evidently isn't. The goal of $w$ is to eliminate over-rewarding the same behavior represented in multiple statistics. It makes all atomic statistics concurrent by leveraging the Pearson corelation matrix.
A simplified example will clarify the idea. First, we compute a Pearson corelation matrix for $I=3$ statistics. We have $x_1$ and $x_2$, the statistics that are trying to maximize $x_j$. Reminder: a Pearson corelation matrix finds the $r$ value not only between $x_i$ and $x_j$ but also between all combinations of $x_i$ and themselves. Here, $r^2$ is calculated using polynomial regression corelation analysis to the $m$th degree.
| | $x_1$ | $x_2$ | $x_3$ | $x_j$ |
| ----- | ----- | ----------- | ----- | ----- |
| $x_1$ | $1$ | $\boxed{0}$ | $0$ | $1$ |
| $x_2$ | | $1$ | $0$ | $1$ |
| $x_3$ | | | $1$ | $1$ |
| $x_j$ | | | | $1$ |
In the case above, $r^2_{1 \leftrightarrow 2}=0$ meaning that both statistics have absolutely nothing to do with each other. Hence, the player will be awarded for optimizing both individually. And since $r^2_{1 \leftrightarrow j}=r^2_{2 \leftrightarrow j}$, they should both be rewarded equally; in other words, they should have equal weights.
$$
w_{1}=\frac{1}{1 + 0 + 0}=1
$$
$$
w_{2}=\frac{1}{0 + 1 + 0}=1
$$
$$
w_{3}=\frac{1}{0 + 0 + 1}=1
$$
Now consider a case where $x_1$ and $x_2$ are fully correlated. It would be a bad idea to reward them equally; hence, their weights suffer.
| | $x_1$ | $x_2$ | $x_3$ | $x_j$ |
| ----- | ----- | ----------- | ----- | ----- |
| $x_1$ | $1$ | $\boxed{1}$ | $0$ | $1$ |
| $x_2$ | | $1$ | $0$ | $1$ |
| $x_3$ | | | $1$ | $1$ |
| $x_j$ | | | | $1$ |
$$
w_{1}=\frac{1}{1 + 1 + 0}=0.5
$$
$$
w_{2}=\frac{1}{1 + 1 + 0}=0.5
$$
$$
w_{3}=\frac{1}{0 + 0 + 1}=1
$$
Remind me to write out the linearized model!
-71
View File
@@ -1,71 +0,0 @@
# BlitzKit Regular Tank Stats
A straightforward way of storing the entire World of Tanks Blitz tank statistics for players to disk.
## Manifest `manifest.rtsm`
```cpp
primary RegularTankStatisticsManifest {
utf8"RTSM" magic;
Header header;
primary Body body;
}
Header {
uint16 version; // always 1
}
Body {
uint32 time;
uint8 base;
}
```
## Chunk `*.rtsc`
```cpp
primary RegularTankStatisticsChunk {
utf8"RTSC" magic;
Header header;
primary Body body<header.playerCount>;
}
Header {
uint16 version; // always 1
uint32 playerCount;
}
Body<uint32 playerCount> {
Player[playerCount] players;
}
Player {
uint32 id;
uint16 tankCount;
Tank[tankCount] tanks;
}
Tank {
uint32 id;
uint32 battleLifeTime;
uint32 lastBattleTime;
uint8 markOfMastery;
uint32 battles;
uint32 capturePoints;
uint32 damageDealt;
uint32 damageReceived;
uint32 droppedCapturePoints;
uint32 frags;
uint32 frags8p;
uint32 hits;
uint32 losses;
uint8 maxFrags;
uint16 maxXp;
uint32 shots;
uint32 spotted;
uint32 survivedBattles;
uint32 winAndSurvived;
uint32 wins;
uint32 xp;
}
```
+4 -3
View File
@@ -1,15 +1,16 @@
{
"name": "blitzkit",
"version": "1.31.4",
"version": "1.32.0",
"license": "BlitzKit License",
"private": true,
"scripts": {
"dev": "cd packages/website && bun run dev",
"dev": "cd packages/website && bun --bun run dev",
"build": "cd packages/website && bun run build",
"discover-ids": "cd packages/scripts && bun run discover-ids",
"build-protos": "cd packages/scripts && bun run build-protos",
"record-performance": "cd packages/scripts && bun run record-performance",
"download-client": "cd packages/scripts && bun run download-client"
"download-client": "cd packages/scripts && bun run download-client",
"clean-astro": "rm -rf packages/website/.astro packages/website/node_modules/.astro packages/website/node_modules/.vite"
},
"type": "module",
"workspaces": [
-1
View File
@@ -5,7 +5,6 @@
"main": "src/index.ts",
"dependencies": {
"@blitzkit/i18n": "workspace:*",
"@blitzkit/protos": "workspace:*",
"@bufbuild/protobuf": "^2.9.0",
"@octokit/plugin-throttling": "^11.0.1",
"@octokit/rest": "^22.0.0",
-5
View File
@@ -1,5 +0,0 @@
export async function fetchJSON<Type>(url: string) {
const response = await fetch(url);
const json = await response.json();
return json as Type;
}
-2
View File
@@ -1,2 +0,0 @@
export * from "./fetchJSON";
export * from "./fetchPB";
@@ -1,16 +0,0 @@
import { ShellType } from "@blitzkit/protos";
import { ShellKind } from "../types";
export const blitzShellKindToBlitzkit: Record<ShellKind, ShellType> = {
ARMOR_PIERCING: ShellType.SHELL_TYPE_AP,
ARMOR_PIERCING_CR: ShellType.SHELL_TYPE_APCR,
HIGH_EXPLOSIVE: ShellType.SHELL_TYPE_HE,
HOLLOW_CHARGE: ShellType.SHELL_TYPE_HEAT,
};
// @ts-ignore
export const blitzkitToBlitzShellKind: Record<ShellType, ShellKind> = {};
for (const [key, value] of Object.entries(blitzShellKindToBlitzkit)) {
blitzkitToBlitzShellKind[value] = key as ShellKind;
}
+2
View File
@@ -1,3 +1,5 @@
import { ShellDefinition, ShellType } from "../protos";
export function canSplash(
type: ShellDefinition["type"],
): type is ShellType.SHELL_TYPE_HE {
+41
View File
@@ -0,0 +1,41 @@
import { TankClass, TankType } from "../protos";
import type { BlitzStats } from "../statistics";
export const TANK_TYPES = [
TankType.TANK_TYPE_RESEARCHABLE,
TankType.TANK_TYPE_PREMIUM,
TankType.TANK_TYPE_COLLECTOR,
];
export const TANK_TYPE_COMMAND_NAMES = {
[TankType.TANK_TYPE_RESEARCHABLE]: "researchable",
[TankType.TANK_TYPE_PREMIUM]: "premium",
[TankType.TANK_TYPE_COLLECTOR]: "collector",
};
export const TANK_CLASSES = [
TankClass.TANK_CLASS_LIGHT,
TankClass.TANK_CLASS_MEDIUM,
TankClass.TANK_CLASS_HEAVY,
TankClass.TANK_CLASS_TANK_DESTROYER,
];
export const emptyAllStats: BlitzStats = {
battles: 0,
capture_points: 0,
damage_dealt: 0,
damage_received: 0,
dropped_capture_points: 0,
frags: 0,
frags8p: 0,
hits: 0,
losses: 0,
max_frags: 0,
max_xp: 0,
shots: 0,
spotted: 0,
survived_battles: 0,
xp: 0,
win_and_survived: 0,
wins: 0,
};
+1 -1
View File
@@ -1,7 +1,7 @@
export * from "./blitzShellKindToBlitzkit";
export * from "./canSplash";
export * from "./clans";
export * from "./classes";
export * from "./constants";
export * from "./equipmentPrice";
export * from "./fetchBlitz";
export * from "./fetchGlossary";
@@ -1,40 +0,0 @@
import { Strings } from "@blitzkit/i18n";
import {
CamouflageDefinitions,
ConsumableDefinitions,
EquipmentDefinitions,
Gallery,
GameDefinitions,
MapDefinitions,
ModelDefinitions,
ProvisionDefinitions,
SkillDefinitions,
TankDefinitions,
} from "@blitzkit/protos";
import { BlitzScripts } from "../../types/blitzScripts";
export abstract class AbstractBlitzKitAPI {
abstract skills(): Promise<SkillDefinitions>;
abstract provisions(): Promise<ProvisionDefinitions>;
abstract consumables(): Promise<ConsumableDefinitions>;
abstract equipment(): Promise<EquipmentDefinitions>;
abstract maps(): Promise<MapDefinitions>;
abstract models(): Promise<ModelDefinitions>;
abstract camouflages(): Promise<CamouflageDefinitions>;
abstract tanks(): Promise<TankDefinitions>;
abstract game(): Promise<GameDefinitions>;
abstract gallery(): Promise<Gallery>;
abstract scripts(): Promise<BlitzScripts>;
abstract strings(locale: string): Promise<Strings>;
async tank(id: number) {
const tanks = await this.tanks();
return tanks.tanks[id];
}
async model(id: number) {
const models = await this.models();
return models.models[id];
}
}
+25
View File
@@ -0,0 +1,25 @@
import {
CamouflageDefinitions,
ConsumableDefinitions,
EquipmentDefinitions,
Gallery,
GameDefinitions,
MapDefinitions,
ModelDefinitions,
ProvisionDefinitions,
SkillDefinitions,
TankDefinitions,
} from "@blitzkit/core";
export abstract class BlitzKitAPI {
abstract skillDefinitions(): Promise<SkillDefinitions>;
abstract provisionDefinitions(): Promise<ProvisionDefinitions>;
abstract consumableDefinitions(): Promise<ConsumableDefinitions>;
abstract equipmentDefinitions(): Promise<EquipmentDefinitions>;
abstract mapDefinitions(): Promise<MapDefinitions>;
abstract modelDefinitions(): Promise<ModelDefinitions>;
abstract camouflageDefinitions(): Promise<CamouflageDefinitions>;
abstract tankDefinitions(): Promise<TankDefinitions>;
abstract gameDefinitions(): Promise<GameDefinitions>;
abstract galleryDefinitions(): Promise<Gallery>;
}
+14 -25
View File
@@ -1,5 +1,5 @@
import { alias } from "@blitzkit/core";
import { Strings } from "@blitzkit/i18n";
import { fetchPB } from "../../protobuf";
import {
CamouflageDefinitions,
ConsumableDefinitions,
@@ -11,70 +11,59 @@ import {
ProvisionDefinitions,
SkillDefinitions,
TankDefinitions,
} from "@blitzkit/protos";
import { fetchPB } from "../../api";
import { fetchJSON } from "../../api/fetchJSON";
import { BlitzScripts } from "../../types/blitzScripts";
import { AbstractBlitzKitAPI } from "./abstract";
} from "../../protos";
import { BlitzKitAPI } from "./base";
export class ClientBlitzKitAPI extends AbstractBlitzKitAPI {
game() {
export class ClientBlitzKitAPI extends BlitzKitAPI {
gameDefinitions() {
return fetchPB(alias("api", "/definitions/game.pb"), GameDefinitions);
}
consumables() {
consumableDefinitions() {
return fetchPB(
alias("api", "/definitions/consumables.pb"),
ConsumableDefinitions,
);
}
tanks() {
tankDefinitions() {
return fetchPB(alias("api", "/definitions/tanks.pb"), TankDefinitions);
}
camouflages() {
camouflageDefinitions() {
return fetchPB(
alias("api", "/definitions/camouflage.pb"),
CamouflageDefinitions,
);
}
provisions() {
provisionDefinitions() {
return fetchPB(
alias("api", "/definitions/provisions.pb"),
ProvisionDefinitions,
);
}
models() {
modelDefinitions() {
return fetchPB(alias("api", "/definitions/models.pb"), ModelDefinitions);
}
skills() {
skillDefinitions() {
return fetchPB(alias("api", "/definitions/skills.pb"), SkillDefinitions);
}
equipment() {
equipmentDefinitions() {
return fetchPB(
alias("api", "/definitions/equipment.pb"),
EquipmentDefinitions,
);
}
gallery() {
galleryDefinitions() {
return fetchPB(alias("api", "/definitions/gallery.pb"), Gallery);
}
maps() {
mapDefinitions() {
return fetchPB(alias("api", "/definitions/maps.pb"), MapDefinitions);
}
scripts() {
return fetchJSON<BlitzScripts>(alias("api", "/definitions/scripts.json"));
}
strings(locale: string) {
return fetchJSON<Strings>(alias("api", `/strings/${locale}.json`));
}
}
-21
View File
@@ -1,21 +0,0 @@
import { AbstractBlitzKitAPI, AbstractVFS } from "@blitzkit/core";
export async function createDynamicAPI(vfs: () => Promise<AbstractVFS>) {
let _api: AbstractBlitzKitAPI;
if (import.meta.env.SSR) {
const { ServerBlitzKitAPI } = await import(
"@blitzkit/core/src/blitzkit/api/server/index"
);
_api = await new ServerBlitzKitAPI(await vfs()).init();
} else {
const { ClientBlitzKitAPI } = await import(
"@blitzkit/core/src/blitzkit/api/client"
);
_api = new ClientBlitzKitAPI();
}
return _api;
}
-4
View File
@@ -1,4 +0,0 @@
export * from "./abstract";
export * from "./client";
export * from "./dynamic";
export * from "./server";
+42 -38
View File
@@ -8,34 +8,30 @@ import {
CamouflagesYaml,
CombatRolesYaml,
ConsumablesCommon,
ConsumableTankCategoryFilterCategory,
CrewType,
I18nString,
MapsYaml,
ModuleType,
OptionalDevices,
OptionalDeviceSlots,
ProvisionsCommon,
ShellKind,
ShellType,
SquadBattleTypeStylesYaml,
TankClass,
TankmenAvatar,
toUniqueId,
VehicleDefinitionList,
} from "@blitzkit/core";
import { AbstractVFS } from "@blitzkit/core/src/blitzkit/vfs/abstract";
import locales from "@blitzkit/i18n/locales.json";
import {
ConsumableTankCategoryFilterCategory,
CrewType,
I18nString,
ModuleType,
TankClass,
} from "@blitzkit/protos";
import type { extname, parse } from "node:path";
import { SUPPORTED_LOCALE_BLITZ_MAP } from "@blitzkit/i18n/src/strings";
import { parse as parseYaml } from "yaml";
import { AbstractBlitzKitAPI } from "../abstract";
export abstract class ServerBlitzKitAPI0 extends AbstractBlitzKitAPI {
// TODO: move most of these to their respective constructors
import { BlitzKitAPI } from "../base";
export abstract class ServerBlitzKitAPI0 extends BlitzKitAPI {
protected vfs: AbstractVFS;
protected parsePath?: typeof parse;
protected extname?: typeof extname;
protected nationSlugDiscriminators = {
china: "cn",
@@ -78,6 +74,12 @@ export abstract class ServerBlitzKitAPI0 extends AbstractBlitzKitAPI {
heavyTank: TankClass.TANK_CLASS_HEAVY,
mediumTank: TankClass.TANK_CLASS_MEDIUM,
};
protected blitzShellKindToBlitzkit: Record<ShellKind, ShellType> = {
ARMOR_PIERCING: ShellType.SHELL_TYPE_AP,
ARMOR_PIERCING_CR: ShellType.SHELL_TYPE_APCR,
HIGH_EXPLOSIVE: ShellType.SHELL_TYPE_HE,
HOLLOW_CHARGE: ShellType.SHELL_TYPE_HEAT,
};
protected blitzTankFilterDefinitionCategoryToBlitzkit: Record<
BlitzTankFilterDefinitionCategory,
ConsumableTankCategoryFilterCategory
@@ -107,18 +109,14 @@ export abstract class ServerBlitzKitAPI0 extends AbstractBlitzKitAPI {
constructor(vfs: AbstractVFS) {
super();
this.vfs = vfs;
}
async init() {
const { existsSync } = await import("fs");
const { readFile, writeFile, mkdir } = await import("fs/promises");
console.log("Initializing virtual file system...");
const path = await import("node:path");
this.extname = path.extname;
this.parsePath = path.parse;
await this.vfs.init();
console.log("Fetching game data...");
@@ -160,31 +158,37 @@ export abstract class ServerBlitzKitAPI0 extends AbstractBlitzKitAPI {
console.log("Fetching game localizations...");
if (import.meta.env.DEV) {
locales.supported = [locales.supported[0]];
}
let fetchedLocalizations = 0;
await Promise.all(
locales.supported.map(async (locale) => {
const blitzLocale = locale.variant_blitz_cdn ?? locale.locale;
const cache = await fetch(
locales.supported.map(async ({ locale }) => {
const root = "../../temp/game-strings";
const cachePath = `${root}/${locale}.json`;
if (existsSync(cachePath)) {
console.log(` Cache hit for ${locale}`);
const content = await readFile(cachePath, "utf-8");
this.stringsI18n[locale] = JSON.parse(content) as BlitzStrings;
return;
}
console.log(` Cache miss for ${locale} (this will take a while...)`);
const blitzLocale = SUPPORTED_LOCALE_BLITZ_MAP[locale];
const networkStrings = (await fetch(
`https://stufficons.wgcdn.co/localizations/${blitzLocale}.yaml`,
)
.then((response) => response.text())
.then((string) => parseYaml(string) as BlitzStrings);
const preInstalled = await this.vfs.yaml<BlitzStrings>(
.then(parseYaml)) as BlitzStrings;
const localStrings = await this.vfs.yaml<BlitzStrings>(
`Data/Strings/${blitzLocale}.yaml`,
);
const combined = { ...networkStrings, ...localStrings };
this.stringsI18n[locale.locale] = {
...cache,
...preInstalled,
};
await mkdir(root, { recursive: true });
await writeFile(cachePath, JSON.stringify(combined));
console.log(
`Fetched localizations for ${locale} (${++fetchedLocalizations}/${locales.supported.length})`,
);
this.stringsI18n[locale] = combined;
}),
);
@@ -1,18 +1,18 @@
import { fetchGlossary } from "@blitzkit/core";
import { Avatar, fetchGlossary, Gallery } from "@blitzkit/core";
import locales from "@blitzkit/i18n/locales.json";
import { Avatar, Gallery } from "@blitzkit/protos";
import { extname } from "path";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI9 } from "./9_game";
import { ServerBlitzKitAPI9 } from "./9_gameDefinitions";
export abstract class ServerBlitzKitAPI10 extends ServerBlitzKitAPI9 {
@Cache()
async gallery() {
async galleryDefinitions() {
const avatars: Record<string, { avatar: Avatar; url: string }> = {};
await Promise.all(
locales.supported.map(async (supported) => {
const glossary = await fetchGlossary(
supported.variant_blitz_local ?? supported.locale,
supported.blitz ?? supported.locale,
);
console.log(
@@ -34,7 +34,7 @@ export abstract class ServerBlitzKitAPI10 extends ServerBlitzKitAPI9 {
avatars[key].avatar.name!.locales[supported.locale] =
glossaryEntry.title;
} else {
const extension = this.extname!(glossaryEntry.image_url);
const extension = extname(glossaryEntry.image_url);
avatars[key] = {
url: glossaryEntry.image_url,
@@ -1,72 +0,0 @@
import { ConsumablesCommon, OptionalDevices } from "../../../types";
import { BlitzEffectScript } from "../../../types/blitzEffectScript";
import { BlitzScripts } from "../../../types/blitzScripts";
import { AbstractVFS } from "../../vfs";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI10 } from "./10_avatars";
function assignNormalizedScript(
target: Record<string, BlitzEffectScript>,
key: number,
script?: BlitzEffectScript,
) {
if (script === undefined) return;
if (script["#text"] === "StaticFactorDevice") {
script["#text"] = script.attribute!;
}
target[key] = script;
}
export abstract class ServerBlitzKitAPI11 extends ServerBlitzKitAPI10 {
@Cache()
async scripts() {
const scripts: BlitzScripts = {
consumables: {},
equipment: {},
provisions: {},
};
const optionalDevices = await this.vfs.xml<{
root: OptionalDevices;
}>("Data/XML/item_defs/vehicles/common/optional_devices.xml");
for (const key in optionalDevices.root) {
const equipment = optionalDevices.root[key];
assignNormalizedScript(scripts.equipment, equipment.id, equipment.script);
}
async function assign(
vfs: AbstractVFS,
dir: string,
target: keyof BlitzScripts,
) {
const root = `Data/XML/item_defs/vehicles/common/${dir}`;
const list = await vfs.text(`${root}/list.xml`);
const pattern = /<items path="(\w+)\.xml"\/>/gm;
for (const match of list.matchAll(pattern)) {
const group = match[1];
const path = `${root}/${group}.xml`;
const things = await vfs.xml<{ root: ConsumablesCommon }>(path);
for (const key in things.root) {
const thing = things.root[key];
assignNormalizedScript(
scripts[target],
thing.id,
things.root[key].script,
);
}
}
}
await assign(this.vfs, "consumables", "consumables");
await assign(this.vfs, "provisions", "provisions");
return scripts;
}
}
@@ -1,26 +0,0 @@
import { Strings } from "@blitzkit/i18n";
import locales from "@blitzkit/i18n/locales.json";
import { DeepPartial } from "@blitzkit/protos";
import { merge } from "lodash-es";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI11 } from "./11_scripts";
export abstract class ServerBlitzKitAPI12 extends ServerBlitzKitAPI11 {
private globbedStrings = import.meta.glob(
"../../../../../i18n/strings/*.json",
{ import: "default" },
);
@Cache()
async strings(locale: string) {
const localized = (await this.globbedStrings[
`../../../../../i18n/strings/${locale}.json`
]()) as DeepPartial<Strings>;
const defaults = (await this.globbedStrings[
`../../../../../i18n/strings/${locales.default}.json`
]()) as Strings;
const strings = merge({}, defaults, localized);
return strings;
}
}
@@ -1,33 +1,30 @@
import {
AssaultRanges,
BlitzCrewType,
BlitzModuleType,
blitzShellKindToBlitzkit,
BlitzTankClass,
ChassisDefinitionsList,
Crew,
EngineDefinitionsList,
Equalizer,
GunDefinition,
GunDefinitionsList,
ModuleType,
ResearchCost,
ShellDefinitionsList,
ShellKind,
sluggify,
toUniqueId,
TurretDefinitionsList,
UnlocksListing,
VehicleDefinitionList,
VehicleDefinitions,
} from "@blitzkit/core";
import {
AssaultRanges,
Crew,
Equalizer,
GunDefinition,
ModuleType,
ResearchCost,
TankDefinitions,
TankPrice,
TankPriceType,
TankType,
toUniqueId,
TurretDefinitionsList,
Unlock,
} from "@blitzkit/protos";
UnlocksListing,
VehicleDefinitionList,
VehicleDefinitions,
} from "@blitzkit/core";
import { Cache, ServerBlitzKitAPI0 } from "./0_base";
export abstract class ServerBlitzKitAPI1 extends ServerBlitzKitAPI0 {
@@ -50,7 +47,7 @@ export abstract class ServerBlitzKitAPI1 extends ServerBlitzKitAPI0 {
}
@Cache()
async tanks() {
async tankDefinitions() {
const tankDefinitions = TankDefinitions.create();
const gameModeNativeNames: Record<string, string> = {};
@@ -437,6 +434,7 @@ export abstract class ServerBlitzKitAPI1 extends ServerBlitzKitAPI0 {
resistance_hard: terrainResistances[0],
resistance_medium: terrainResistances[1],
resistance_soft: terrainResistances[2],
repair_time: track.hysteresisHealth / track.healthRegenPerSec,
tier: track.level,
unlocks: resolveUnlocks(
this.blitzModuleTypeToBlitzkit,
@@ -510,8 +508,8 @@ export abstract class ServerBlitzKitAPI1 extends ServerBlitzKitAPI0 {
.map((string) => {
const trimmed = string.trim();
if (trimmed in blitzShellKindToBlitzkit) {
return blitzShellKindToBlitzkit[trimmed as ShellKind];
if (trimmed in this.blitzShellKindToBlitzkit) {
return this.blitzShellKindToBlitzkit[trimmed as ShellKind];
}
throw new SyntaxError(`Invalid shell kind: ${trimmed}`);
@@ -615,7 +613,7 @@ export abstract class ServerBlitzKitAPI1 extends ServerBlitzKitAPI0 {
caliber: shell.caliber,
normalization: shell.normalizationAngle,
ricochet: shell.ricochetAngle,
type: blitzShellKindToBlitzkit[shell.kind],
type: this.blitzShellKindToBlitzkit[shell.kind],
explosion_radius:
shell.kind === "HIGH_EXPLOSIVE"
? (shell.explosionRadius ?? 0)
@@ -1,10 +1,10 @@
import { CamouflageDefinitions } from "@blitzkit/protos";
import { CamouflageDefinitions } from "@blitzkit/core";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI1 } from "./1_tanks";
import { ServerBlitzKitAPI1 } from "./1_tankDefinitions";
export abstract class ServerBlitzKitAPI2 extends ServerBlitzKitAPI1 {
@Cache()
async camouflages() {
async camouflageDefinitions() {
const camouflageDefinitions = CamouflageDefinitions.create();
for (const camoKey in this.camouflagesXml!.root.camouflages) {
@@ -1,22 +1,114 @@
import {
Armor,
BlitzCrewType,
ChassisDefinitionsList,
Crew,
GunDefinitionsList,
I_HAT,
J_HAT,
K_HAT,
ModelDefinitions,
parseHierarchies,
Sc2ReadStream,
ScgReadStream,
TankParameters,
toUniqueId,
TurretDefinitionsList,
Vector3,
VehicleDefinitionArmor,
VehicleDefinitionList,
VehicleDefinitions,
VertexAttribute,
} from "@blitzkit/core";
import { Armor, Crew, ModelDefinitions, Vector3 } from "@blitzkit/protos";
import { Vector3Tuple } from "three";
import { parse as parsePath } from "path";
import { MathUtils, Vector3 as THREEVector3, Vector3Tuple } from "three";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI2 } from "./2_camouflages";
import { ServerBlitzKitAPI2 } from "./2_camouflageDefinitions";
export abstract class ServerBlitzKitAPI3 extends ServerBlitzKitAPI2 {
private vector3TupleToBlitzkit(tuple: Vector3Tuple) {
return { x: tuple[0], y: tuple[1], z: -tuple[2] } satisfies Vector3;
return { x: tuple[0], y: tuple[1], z: tuple[2] } satisfies Vector3;
}
private async collisionBoundingBoxes(
nation: string,
tankKey: string,
turretRotation?: { yaw: number; pitch: number; roll: number },
) {
const boundingBoxes: Record<
string,
{ min: Vector3Tuple; max: Vector3Tuple }
> = {};
const path = `Data/3d/Tanks/CollisionMeshes/${nation}-${tankKey}`;
if (!(await this.vfs.resolve(`${path}.sc2`))) {
throw new Error(`Missing collision mesh for ${nation}-${tankKey}`);
}
const sc2 = new Sc2ReadStream(
(await this.vfs.file(`${path}.sc2`)).buffer as ArrayBuffer,
).sc2();
const scg = new ScgReadStream(
(await this.vfs.file(`${path}.scg`)).buffer as ArrayBuffer,
).scg();
parseHierarchies(sc2["#hierarchy"], null, (hierarchy, components) => {
for (const component of components) {
if (component["comp.typename"] !== "RenderComponent") continue;
const polygonGroup = scg.get(
component["rc.renderObj"]["ro.batches"]["0000"]["rb.datasource"],
);
if (!polygonGroup) continue;
const min: Vector3Tuple = [Infinity, Infinity, Infinity];
const max: Vector3Tuple = [-Infinity, -Infinity, -Infinity];
const rotate =
turretRotation && hierarchy.name.toLowerCase().startsWith("turret");
polygonGroup.vertices.forEach((vertex) => {
vertex.forEach(({ attribute, value }) => {
if (attribute !== VertexAttribute.VERTEX) return;
const position = new THREEVector3(...value);
if (rotate) {
position
.applyAxisAngle(
I_HAT,
-MathUtils.degToRad(turretRotation.pitch),
)
.applyAxisAngle(
J_HAT,
-MathUtils.degToRad(turretRotation.roll),
)
.applyAxisAngle(
K_HAT,
-MathUtils.degToRad(turretRotation.yaw),
);
}
const coordinates = position.toArray();
for (let axis = 0; axis < 3; axis++) {
min[axis] = Math.min(min[axis], coordinates[axis]);
max[axis] = Math.max(max[axis], coordinates[axis]);
}
});
});
boundingBoxes[hierarchy.name.toLowerCase()] = { min, max };
}
return null;
});
if (!boundingBoxes.hull) {
throw new Error(`Missing hull collision mesh for ${nation}-${tankKey}`);
}
return boundingBoxes;
}
private assignArmor(
@@ -36,7 +128,7 @@ export abstract class ServerBlitzKitAPI3 extends ServerBlitzKitAPI2 {
}
@Cache()
async models() {
async modelDefinitions() {
const modelDefinitions = ModelDefinitions.create();
for (const nation of this.nationsDir!) {
@@ -63,6 +155,12 @@ export abstract class ServerBlitzKitAPI3 extends ServerBlitzKitAPI2 {
const tankParameters = await this.vfs.yaml<TankParameters>(
`Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`,
);
const collisionBoundingBoxes = await this.collisionBoundingBoxes(
nation,
tankKey,
tankDefinition.root.hull.turretInitialRotation,
);
const hullBoundingBox = collisionBoundingBoxes.hull;
const turretOrigin = tankDefinition.root.hull.turretPositions.turret
.split(" ")
.map(Number) as Vector3Tuple;
@@ -137,12 +235,8 @@ export abstract class ServerBlitzKitAPI3 extends ServerBlitzKitAPI2 {
}
: undefined,
bounding_box: {
min: this.vector3TupleToBlitzkit(
tankParameters.collision.hull.bbox.min,
),
max: this.vector3TupleToBlitzkit(
tankParameters.collision.hull.bbox.max,
),
min: this.vector3TupleToBlitzkit(hullBoundingBox.min),
max: this.vector3TupleToBlitzkit(hullBoundingBox.max),
},
turrets: {},
tracks: {},
@@ -168,7 +262,7 @@ export abstract class ServerBlitzKitAPI3 extends ServerBlitzKitAPI2 {
Object.keys(tankDefinition.root.turrets0).forEach((turretKey) => {
const turret = tankDefinition.root.turrets0[turretKey];
const turretModel = Number(
this.parsePath!(turret.models.undamaged).name.split("_")[1],
parsePath(turret.models.undamaged).name.split("_")[1],
);
const turretId = toUniqueId(nation, turretList.root.ids[turretKey]);
const turretYaw = (
@@ -204,30 +298,35 @@ export abstract class ServerBlitzKitAPI3 extends ServerBlitzKitAPI2 {
turret.userString;
const turretCollisionName = parsePath(
turret.hitTester.collisionModel,
).name.toLowerCase();
const isFullYaw = -turretYaw[0] + turretYaw[1] === 360;
if (!collisionBoundingBoxes[turretCollisionName] && isFullYaw) {
throw new Error(
`Missing turret collision mesh for ${nation}-${tankKey} ${turretKey}`,
);
}
const turretBoundingBox = collisionBoundingBoxes[
turretCollisionName
] ?? {
min: [0, 0, 0] as Vector3Tuple,
max: [0, 0, 0] as Vector3Tuple,
};
modelDefinitions.models[tankId].turrets[turretId] = {
armor: turretArmor,
gun_origin: this.vector3TupleToBlitzkit(gunOrigin),
model_id: turretModel,
yaw:
-turretYaw[0] + turretYaw[1] === 360
? undefined
: { min: turretYaw[0], max: turretYaw[1] },
yaw: isFullYaw
? undefined
: { min: turretYaw[0], max: turretYaw[1] },
guns: {},
bounding_box: {
min: this.vector3TupleToBlitzkit(
tankParameters.collision[
this.parsePath!(
turret.hitTester.collisionModel,
).name.toLowerCase()
].bbox.min,
),
max: this.vector3TupleToBlitzkit(
tankParameters.collision[
this.parsePath!(
turret.hitTester.collisionModel,
).name.toLowerCase()
].bbox.max,
),
min: this.vector3TupleToBlitzkit(turretBoundingBox.min),
max: this.vector3TupleToBlitzkit(turretBoundingBox.max),
},
};
@@ -244,7 +343,7 @@ export abstract class ServerBlitzKitAPI3 extends ServerBlitzKitAPI2 {
.split(" ")
.map(Number) as [number, number];
const gunModel = Number(
this.parsePath!(gun.models.undamaged).name.split("_")[1],
parsePath(gun.models.undamaged).name.split("_")[1],
);
const front = gun.extraPitchLimits?.front
? gun.extraPitchLimits.front.split(" ").map(Number)
@@ -1,10 +1,10 @@
import { MapDefinitions } from "@blitzkit/protos";
import { MapDefinitions } from "@blitzkit/core";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI3 } from "./3_models";
import { ServerBlitzKitAPI3 } from "./3_modelDefinitions";
export abstract class ServerBlitzKitAPI4 extends ServerBlitzKitAPI3 {
@Cache()
async maps() {
async mapDefinitions() {
const mapDefinitions = MapDefinitions.create();
for (const key in this.mapsYaml!.maps) {
@@ -1,10 +1,10 @@
import { EquipmentDefinitions, EquipmentSlot } from "@blitzkit/protos";
import { EquipmentDefinitions, EquipmentSlot } from "@blitzkit/core";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI4 } from "./4_maps";
import { ServerBlitzKitAPI4 } from "./4_mapDefinitions";
export abstract class ServerBlitzKitAPI5 extends ServerBlitzKitAPI4 {
@Cache()
async equipment() {
async equipmentDefinitions() {
const equipmentDefinitions = EquipmentDefinitions.create();
Object.entries(this.optionalDevices!.root).forEach(
@@ -27,10 +27,8 @@ export abstract class ServerBlitzKitAPI5 extends ServerBlitzKitAPI4 {
.map((level) => {
return Object.values(level).map((options) => {
return {
options: [
this.optionalDevices!.root[options.device0].id,
this.optionalDevices!.root[options.device1].id,
],
left: this.optionalDevices!.root[options.device0].id,
right: this.optionalDevices!.root[options.device1].id,
} satisfies EquipmentSlot;
});
})
@@ -1,17 +1,22 @@
import { BlitzTankFilterDefinitionCategory } from "@blitzkit/core";
import { Consumable, ConsumableDefinitions } from "@blitzkit/protos";
import {
BlitzTankFilterDefinitionCategory,
Consumable,
ConsumableDefinitions,
} from "@blitzkit/core";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI5 } from "./5_equipments";
import { ServerBlitzKitAPI5 } from "./5_equipmentDefinitions";
export abstract class ServerBlitzKitAPI6 extends ServerBlitzKitAPI5 {
@Cache()
async consumables() {
async consumableDefinitions() {
const consumableDefinitions = ConsumableDefinitions.create();
Object.entries(this.consumablesCommon).forEach(([, consumable]) => {
Object.entries(this.consumablesCommon).forEach(([key, consumable]) => {
const entry: Consumable = {
id: consumable.id,
game_mode_exclusive: "gameModeFilter" in consumable,
cooldown: consumable.script.cooldown,
duration: consumable.script.duration,
name: this.getString(consumable.userString),
exclude: [],
include: [],
@@ -1,21 +1,24 @@
import { BlitzTankFilterDefinitionCategory } from "@blitzkit/core";
import { Provision, ProvisionDefinitions } from "@blitzkit/protos";
import {
BlitzTankFilterDefinitionCategory,
Provision,
ProvisionDefinitions,
} from "@blitzkit/core";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI6 } from "./6_consumables";
import { ServerBlitzKitAPI6 } from "./6_consumableDefinitions";
export abstract class ServerBlitzKitAPI7 extends ServerBlitzKitAPI6 {
@Cache()
async provisions() {
async provisionDefinitions() {
const provisionDefinitions = ProvisionDefinitions.create();
Object.entries(this.provisionsCommon).forEach(([, provision]) => {
const entry = Provision.create({
const entry: Provision = {
id: provision.id,
exclude: [],
include: [],
game_mode_exclusive: "gameModeFilter" in provision,
name: this.getString(provision.userString),
});
};
provisionDefinitions.provisions[provision.id] = entry;
const includeRaw = provision.vehicleFilter?.include.vehicle;
@@ -102,6 +105,11 @@ export abstract class ServerBlitzKitAPI7 extends ServerBlitzKitAPI6 {
});
}
}
if (provision.script.bonusValues?.crewLevelIncrease !== undefined) {
provisionDefinitions.provisions[provision.id].crew =
provision.script.bonusValues?.crewLevelIncrease;
}
});
return provisionDefinitions;
@@ -1,12 +1,11 @@
import { BlitzTankClass } from "@blitzkit/core";
import { BlitzTankClass, SkillDefinitions } from "@blitzkit/core";
import { SkillDefinitions } from "@blitzkit/protos";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI7 } from "./7_provisions";
import { ServerBlitzKitAPI7 } from "./7_provisionDefinitions";
export abstract class ServerBlitzKitAPI8 extends ServerBlitzKitAPI7 {
@Cache()
async skills() {
async skillDefinitions() {
const skillDefinitions = SkillDefinitions.create();
for (const tankClass in this.tankmenAvatar!.root.skillsByClasses) {
@@ -1,12 +1,11 @@
import { AvailableNationsYaml } from "@blitzkit/core";
import { AvailableNationsYaml, GameDefinitions } from "@blitzkit/core";
import { GameDefinitions } from "@blitzkit/protos";
import { Cache } from "./0_base";
import { ServerBlitzKitAPI8 } from "./8_skills";
import { ServerBlitzKitAPI8 } from "./8_skillDefinitions";
export abstract class ServerBlitzKitAPI9 extends ServerBlitzKitAPI8 {
@Cache()
async game() {
async gameDefinitions() {
const gameDefinitions = GameDefinitions.create();
const consumableNativeNames: Record<string, number> = {};
@@ -1,3 +1,3 @@
import { ServerBlitzKitAPI12 } from "./12_strings";
import { ServerBlitzKitAPI10 } from "@blitzkit/core/src/blitzkit/api/server/10_galleryDefinitions";
export class ServerBlitzKitAPI extends ServerBlitzKitAPI12 {}
export class ServerBlitzKitAPI extends ServerBlitzKitAPI10 {}
@@ -1,16 +1,12 @@
import {
GunDefinition,
ProvisionDefinitions,
TankDefinition,
} from "../../../protos/src/blitzkit";
import { isTankCompatible } from "../tankopedia";
import { GunDefinition, ProvisionDefinitions, TankDefinition } from "../protos";
import { checkConsumableProvisionInclusivity } from "./checkConsumableProvisionInclusivity";
export function availableProvisions(
tank: TankDefinition,
gun: GunDefinition,
provisionDefinitions: ProvisionDefinitions,
provisionDefinitions: ProvisionDefinitions
) {
return Object.values(provisionDefinitions.provisions).filter((provision) =>
isTankCompatible(tank, gun, provision.include, provision.exclude),
checkConsumableProvisionInclusivity(provision, tank, gun)
);
}
@@ -0,0 +1,22 @@
import { emptyAllStats } from '../../blitz/constants';
import { Samples } from '../../protos';
import type { BlitzkitStats } from '../../statistics';
export const emptyAverageDefinitionsAllStats: BlitzkitStats = {
...emptyAllStats,
battle_life_time: 0,
};
export const averageDefinitionsAllStatsKeys = Object.keys(
emptyAverageDefinitionsAllStats,
) as (keyof BlitzkitStats)[];
export const emptySamples: Samples = {
d_1: 0,
d_7: 0,
d_30: 0,
d_60: 0,
d_90: 0,
d_120: 0,
total: 0,
};
@@ -0,0 +1,17 @@
import { staticAsset } from "@blitzkit/core";
import { fetchPB } from "../../protobuf";
import { AverageDefinitions } from "../../protos";
export interface AverageDefinitionsManifest {
version: 1;
/**
* epoch in days
*/
latest: number;
}
export async function fetchAverageDefinitions() {
return await fetchPB(staticAsset("averages.pb"), AverageDefinitions);
}
export * from "./constants";
@@ -1,17 +1,17 @@
import {
Consumable,
ConsumableTankCategoryFilterCategory,
GunDefinition,
Provision,
TankDefinition,
TankInclusivityFilter,
} from "@blitzkit/protos";
} from "../protos";
export function isTankCompatible(
export function checkConsumableProvisionInclusivity(
consumableProvision: Consumable | Provision,
tank: TankDefinition,
gun: GunDefinition,
include?: TankInclusivityFilter[],
exclude?: TankInclusivityFilter[],
) {
const included = include?.every((rule) => {
const included = consumableProvision.include?.every((rule) => {
switch (rule.filter_type!.$case) {
case "tiers":
return (
@@ -29,7 +29,7 @@ export function isTankCompatible(
throw new SyntaxError("Category filtering found in include rule");
}
});
const excluded = exclude?.some((rule) => {
const excluded = consumableProvision.exclude?.some((rule) => {
switch (rule.filter_type!.$case) {
case "tiers":
return (
@@ -53,5 +53,5 @@ export function isTankCompatible(
}
});
return include !== undefined && include?.length > 0 && included && !excluded;
return consumableProvision.include?.length > 0 && included && !excluded;
}
@@ -1,10 +1,5 @@
import {
GunDefinition,
ProvisionDefinitions,
TankDefinition,
} from "@blitzkit/protos";
import { BlitzScripts } from "../types/blitzScripts";
import { availableProvisions } from "./availableProvisions";
import { GunDefinition, ProvisionDefinitions, TankDefinition } from '../protos';
import { availableProvisions } from './availableProvisions';
const PROVISION_PREFERENCES = [
19, // improved fuel
@@ -19,10 +14,9 @@ function infinityFallback(value: number) {
export function createDefaultProvisions(
tank: TankDefinition,
gun: GunDefinition,
provisions: ProvisionDefinitions,
scripts: BlitzScripts,
provisionDefinitions: ProvisionDefinitions,
) {
const provisionsList = availableProvisions(tank, gun, provisions);
const provisionsList = availableProvisions(tank, gun, provisionDefinitions);
return provisionsList
.sort(
@@ -30,11 +24,7 @@ export function createDefaultProvisions(
infinityFallback(PROVISION_PREFERENCES.indexOf(a.id)) -
infinityFallback(PROVISION_PREFERENCES.indexOf(b.id)),
)
.sort(
(a, b) =>
(scripts.provisions[b.id].bonusValues?.crewLevelIncrease ?? 0) -
(scripts.provisions[a.id].bonusValues?.crewLevelIncrease ?? 0),
)
.sort((a, b) => (b.crew ?? 0) - (a.crew ?? 0))
.slice(0, tank.max_provisions)
.map(({ id }) => id);
}
@@ -6,7 +6,7 @@ export interface DiscoveredIdsDefinitions {
count: number;
}
export async function fetchDiscoveredIds() {
export async function fetchDiscoveredIdsDefinitions() {
const response = await fetch(staticAsset("ids/manifest.json"));
return response.json() as Promise<DiscoveredIdsDefinitions>;
}
+2 -2
View File
@@ -1,7 +1,7 @@
export * from "./alias";
export * from "./api";
export * from "./assertSecret";
export * from "./availableProvisions";
export * from "./averageDefinitions";
export * from "./coefficient";
export * from "./createDefaultProvisions";
export * from "./createDefaultSkills";
@@ -25,11 +25,11 @@ export * from "./sluggify";
export * from "./staticAsset";
export * from "./sum";
export * from "./tankDefinitions";
export * from "./tankBoundingBox";
export * from "./tankIcon";
export * from "./tankNames";
export * from "./unionBoundingBox";
export * from "./uniqueGuns";
export * from "./unwrapBlitzkitResponse";
export * from "./vfs";
export * from "./votes";
export * from "./youtubers";
+1 -1
View File
@@ -1,4 +1,4 @@
import { ShellDefinition, ShellType } from "../../../protos/src/blitzkit";
import { ShellDefinition, ShellType } from "../protos";
export function isExplosive(
type: ShellDefinition["type"],
+10 -5
View File
@@ -1,19 +1,24 @@
import { GameDefinitions, TankDefinition } from "@blitzkit/protos";
import { tankClassOrder } from "../config/tankClassOrder";
import { treeTypeOrder } from "../config/treeTypeOrder";
import { TANK_CLASSES } from "../blitz/constants";
import { GameDefinitions, TankDefinition, TankType } from "../protos";
const treeTypeOrder = [
TankType.TANK_TYPE_RESEARCHABLE,
TankType.TANK_TYPE_PREMIUM,
TankType.TANK_TYPE_COLLECTOR,
];
export function metaSortTank(
tanks: TankDefinition[],
gameDefinitions: GameDefinitions,
) {
return tanks
.sort((a, b) => a.id - b.id)
.sort((a, b) => b.tier - a.tier)
.sort(
(a, b) => treeTypeOrder.indexOf(b.type) - treeTypeOrder.indexOf(a.type),
)
.sort(
(a, b) =>
tankClassOrder.indexOf(b.class) - tankClassOrder.indexOf(a.class),
(a, b) => TANK_CLASSES.indexOf(b.class) - TANK_CLASSES.indexOf(a.class),
)
.sort(
(a, b) =>
@@ -1,4 +1,4 @@
import { BoundingBox, Vector3 } from "../../../protos/src/blitzkit";
import { BoundingBox, Vector3 } from "../protos";
export function normalizeBoundingBox(boundingBox: BoundingBox) {
return {
+2 -2
View File
@@ -1,6 +1,6 @@
import { staticAsset } from "@blitzkit/core";
import { PopularTanks } from "../../../protos/src/blitzkit";
import { fetchPB } from "../api";
import { fetchPB } from "../protobuf";
import { PopularTanks } from "../protos";
export function fetchPopularTanks() {
return fetchPB(staticAsset("definitions/popular-tanks.pb"), PopularTanks);
@@ -1,4 +1,4 @@
import { Equalizer, ShellType } from "@blitzkit/protos";
import { Equalizer, ShellType } from "../protos";
export function resolvePenetrationCoefficient(
calibratedShells: boolean,
+2 -2
View File
@@ -1,6 +1,6 @@
import { staticAsset } from "@blitzkit/core";
import { Reviews } from "../../../protos/src/blitzkit";
import { fetchPB } from "../api";
import { fetchPB } from "../protobuf";
import { Reviews } from "../protos";
export function fetchReviews() {
return fetchPB(staticAsset("definitions/reviews.pb"), Reviews);
@@ -0,0 +1,32 @@
import { ModelDefinition, TurretModelDefinition } from "../protos";
import { unionBoundingBox } from "./unionBoundingBox";
export function tankBoundingBox(
tankModelDefinition: ModelDefinition,
turretModelDefinition: TurretModelDefinition,
) {
const hull = tankModelDefinition.bounding_box!;
const turret = turretModelDefinition.bounding_box!;
const origin = tankModelDefinition.turret_origin!;
if (
turret.min!.x === turret.max!.x &&
turret.min!.y === turret.max!.y &&
turret.min!.z === turret.max!.z
) {
return unionBoundingBox(hull, hull);
}
return unionBoundingBox(hull, {
min: {
x: turret.min!.x + origin.x,
y: turret.min!.y + origin.z,
z: turret.min!.z + origin.y,
},
max: {
x: turret.max!.x + origin.x,
y: turret.max!.y + origin.z,
z: turret.max!.z + origin.y,
},
});
}
@@ -1,5 +1,5 @@
import { CrewType, ShellType, TankClass, TankType } from "@blitzkit/protos";
import { times } from "lodash-es";
import { CrewType, ShellType } from "../../protos";
export const SHELL_NAMES: Record<ShellType, string> = {
[ShellType.SHELL_TYPE_AP]: "AP",
@@ -15,33 +15,6 @@ export const CREW_MEMBER_NAMES = {
[CrewType.CREW_TYPE_RADIOMAN]: "radioman",
} as const;
/**
* @deprecated use svg
*/
export const TANK_ICONS: Record<TankClass, string> = {
[TankClass.TANK_CLASS_TANK_DESTROYER]: "https://i.imgur.com/BIHSEH0.png",
[TankClass.TANK_CLASS_LIGHT]: "https://i.imgur.com/CSNha5V.png",
[TankClass.TANK_CLASS_MEDIUM]: "https://i.imgur.com/wvf3ltm.png",
[TankClass.TANK_CLASS_HEAVY]: "https://i.imgur.com/ECeqlZa.png",
};
/**
* @deprecated use svg
*/
export const TANK_ICONS_PREMIUM: Record<TankClass, string> = {
[TankClass.TANK_CLASS_TANK_DESTROYER]: "https://i.imgur.com/TCu3EdR.png",
[TankClass.TANK_CLASS_LIGHT]: "https://i.imgur.com/zdkpTRb.png",
[TankClass.TANK_CLASS_MEDIUM]: "https://i.imgur.com/3z7eHX6.png",
[TankClass.TANK_CLASS_HEAVY]: "https://i.imgur.com/P3vbmyA.png",
};
/**
* @deprecated use svg
*/
export const TANK_ICONS_COLLECTOR: Record<TankClass, string> = {
[TankClass.TANK_CLASS_TANK_DESTROYER]: "https://i.imgur.com/WTjeirB.png",
[TankClass.TANK_CLASS_LIGHT]: "https://i.imgur.com/EwhtKkU.png",
[TankClass.TANK_CLASS_MEDIUM]: "https://i.imgur.com/u8YDMBh.png",
[TankClass.TANK_CLASS_HEAVY]: "https://i.imgur.com/8xRf3nc.png",
};
export const TIERS = times(10, (index) => index + 1);
export const TIER_ROMAN_NUMERALS: Record<number, string> = {
1: "I",
@@ -54,6 +27,7 @@ export const TIER_ROMAN_NUMERALS: Record<number, string> = {
8: "VIII",
9: "IX",
10: "X",
11: "XI",
};
export const flags: Record<string, string> = {
@@ -67,8 +41,3 @@ export const flags: Record<string, string> = {
european: "🇪🇺",
other: "<:other:1218421572243558482>",
};
export const TREE_TYPE_ICONS: Record<TankType, Record<TankClass, string>> = {
[TankType.TANK_TYPE_RESEARCHABLE]: TANK_ICONS,
[TankType.TANK_TYPE_PREMIUM]: TANK_ICONS_PREMIUM,
[TankType.TANK_TYPE_COLLECTOR]: TANK_ICONS_COLLECTOR,
};
+32 -41
View File
@@ -1,37 +1,25 @@
import { BlitzKitAPI } from "@blitzkit/core";
import locales from "@blitzkit/i18n/locales.json";
import { I18nString } from "@blitzkit/protos";
import { deburr, times } from "lodash-es";
import { AbstractBlitzKitAPI } from "./api";
import { deburr } from "lodash-es";
import { I18nString } from "../protos";
export async function fetchTankNames(api: AbstractBlitzKitAPI) {
export async function fetchTankNames(api: BlitzKitAPI) {
const [tankDefinitions, camouflageDefinitions] = await Promise.all([
api.tanks(),
api.camouflages(),
api.tankDefinitions(),
api.camouflageDefinitions(),
]);
const tankDefinitionsArray = Object.values(tankDefinitions.tanks);
return await Promise.all(
tankDefinitionsArray.map(async (tank) => {
const name_deburr: I18nString = I18nString.create();
const camouflages_deburr: I18nString[] = [];
const camouflages = tank.camouflages.map(
(id) => camouflageDefinitions.camouflages[id].name!,
);
const searchableNameDeburr: I18nString = { locales: {} };
Object.entries(tank.name!).forEach(([key, value]) => {
name_deburr.locales[key] = deburr(value);
});
camouflages.forEach((camouflage, index) => {
camouflages_deburr[index] = I18nString.create();
Object.entries(camouflage).forEach(([key, value]) => {
camouflages_deburr[index].locales[key] = deburr(value);
});
searchableNameDeburr.locales[key] = deburr(value);
});
const searchableNameFull: I18nString = {
locales: { ...(tank.name_full?.locales ?? tank.name!.locales) },
locales: { ...tank.name_full?.locales },
};
const searchableNameFullDeburr: I18nString = { locales: {} };
@@ -41,33 +29,36 @@ export async function fetchTankNames(api: AbstractBlitzKitAPI) {
return {
id: tank.id,
slug: tank.slug,
dev_name: tank.dev_name,
name: tank.name!,
name_deburr,
camouflages,
camouflages_deburr,
name: tank.name,
searchableName: tank.name,
searchableNameDeburr,
searchableNameFull,
searchableNameFullDeburr,
camouflages: tank.camouflages
?.map((id) =>
locales.supported.map(
({ locale }) =>
camouflageDefinitions.camouflages[id]?.name!.locales[locale],
),
)
.flat()
.filter(Boolean)
.map(deburr)
.join(" "),
treeType: tank.type,
};
}),
);
}
export const SEARCH_KEYS = [
"id",
"slug",
"dev_name",
...locales.supported
.map(({ locale }) => [
`name.locales.${locale}`,
`name_deburr.locales.${locale}`,
...times(8, (index) => [
`camouflages.${index}.locales.${locale}`,
`camouflages_deburr.${index}.locales.${locale}`,
]),
`searchableName.locales.${locale}`,
`searchableNameDeburr.locales.${locale}`,
`searchableNameFull.locales.${locale}`,
`searchableNameFullDeburr.locales.${locale}`,
])
.flat(2),
.flat(),
"camouflages",
];
@@ -1,4 +1,4 @@
import { BoundingBox } from "../../../protos/src/blitzkit";
import { BoundingBox } from "../protos";
export function unionBoundingBox(a: BoundingBox, b: BoundingBox) {
return {
+1 -1
View File
@@ -1,5 +1,5 @@
import { forEachRight } from 'lodash-es';
import { GunDefinition, TurretDefinition } from '../../../protos/src/blitzkit';
import { GunDefinition, TurretDefinition } from '../protos';
export function uniqueGuns(turrets: TurretDefinition[]) {
const gunIds = new Set<number>();
+4 -13
View File
@@ -1,23 +1,14 @@
import { readDVPL } from "@blitzkit/core";
import { Options, parse as parseCSV } from "csv-parse/browser/esm/sync";
import { Options, parse as parseCSV } from "csv-parse/sync";
import { XMLParser } from "fast-xml-parser";
import type { normalize } from "node:path/posix";
import { normalize } from "path/posix";
import { parse as parseYaml } from "yaml";
export abstract class AbstractVFS {
textDecoder = new TextDecoder();
private xmlParser = new XMLParser();
protected normalizePath?: typeof normalize;
async init() {
const path = await import("node:path/posix");
this.normalizePath = path.normalize;
await this._init();
}
protected abstract _init(): Promise<typeof this>;
abstract init(): Promise<typeof this>;
abstract dispose(): void;
@@ -26,7 +17,7 @@ export abstract class AbstractVFS {
abstract raw(path: string): Promise<Uint8Array<ArrayBuffer>>;
async resolve(path: string) {
const normalized = this.normalizePath!(path);
const normalized = normalize(path);
if (await this.has(normalized)) return normalized;
const dvplPath = `${normalized}.dvpl`;
-5
View File
@@ -1,5 +0,0 @@
export * from "./abstract";
export * from "./local";
export * from "./mixed";
export * from "./steam";
export * from "./zip";
+3 -11
View File
@@ -1,20 +1,12 @@
import type { readdir } from "node:fs/promises";
import { readdir } from "node:fs/promises";
import { AbstractVFS } from "./abstract";
export class LocalVFS extends AbstractVFS {
protected readdir?: typeof readdir;
constructor(private base: string) {
super();
}
async _init() {
const path = await import("node:path/posix");
const fs = await import("node:fs/promises");
this.normalizePath = path.normalize;
this.readdir = fs.readdir;
async init() {
return this;
}
@@ -33,7 +25,7 @@ export class LocalVFS extends AbstractVFS {
async _dir(path: string) {
try {
return await this.readdir!(`${this.base}/${path}`);
return await readdir(`${this.base}/${path}`);
} catch (_) {
return [];
}
+1 -1
View File
@@ -5,7 +5,7 @@ export class MixedVFS extends AbstractVFS {
super();
}
async _init() {
async init() {
for (const vfs of this.vfses) {
await vfs.init();
}
+6 -10
View File
@@ -1,4 +1,4 @@
import type SteamUser from "steam-user";
import SteamUser, { EConnectionProtocol } from "steam-user";
import { AbstractVFS } from "./abstract";
interface SteamManifestFile {
@@ -31,7 +31,7 @@ interface SteamManifest {
}
export class SteamVFS extends AbstractVFS {
private steam?: SteamUser;
private steam = new SteamUser({ protocol: EConnectionProtocol.TCP });
private manifest: Map<string, SteamManifestFile> = new Map();
constructor(
@@ -43,18 +43,13 @@ export class SteamVFS extends AbstractVFS {
super();
}
async _init() {
const steamUser = await import("steam-user");
this.steam = new steamUser.default({
protocol: steamUser.EConnectionProtocol.TCP,
});
async init() {
this.steam.logOn({
accountName: this.username,
password: this.password,
});
await new Promise((resolve) => this.steam!.once("loggedOn", resolve));
await new Promise((resolve) => this.steam.once("loggedOn", resolve));
const productInfo = await this.steam.getProductInfo([this.app], []);
const manifest: SteamManifest = await new Promise((resolve) => {
@@ -62,6 +57,7 @@ export class SteamVFS extends AbstractVFS {
this.steam.getManifest(
this.app,
this.depot,
// @ts-expect-error
productInfo.apps[this.app].appinfo.depots[this.depot].manifests.public
.gid,
"public",
@@ -110,6 +106,6 @@ export class SteamVFS extends AbstractVFS {
}
dispose() {
this.steam!.logOff();
this.steam.logOff();
}
}
+3 -4
View File
@@ -1,3 +1,4 @@
import { normalize } from "path/posix";
import { HTTPRangeReader, unzip, ZipEntry } from "unzipit";
import { AbstractVFS } from "./abstract";
@@ -11,14 +12,12 @@ export class ZipVFS extends AbstractVFS {
super();
}
async _init() {
async init() {
const reader = new HTTPRangeReader(this.url);
const { entries } = await unzip(reader);
for (const entry of Object.values(entries)) {
const normalized = this.normalizePath!(
entry.name.slice(this.root.length),
);
const normalized = normalize(entry.name.slice(this.root.length));
this.entries.set(normalized, entry);
}
-8
View File
@@ -1,8 +0,0 @@
import { GunDefinition } from "@blitzkit/protos";
import { CaseType } from "../types";
export const gunTypeOrder: CaseType<GunDefinition>[] = [
"regular",
"auto_loader",
"auto_reloader",
];
-3
View File
@@ -1,3 +0,0 @@
export * from "./gunTypeOrder";
export * from "./tankClassOrder";
export * from "./treeTypeOrder";
@@ -1,8 +0,0 @@
import { TankClass } from "@blitzkit/protos";
export const tankClassOrder = [
TankClass.TANK_CLASS_LIGHT,
TankClass.TANK_CLASS_MEDIUM,
TankClass.TANK_CLASS_HEAVY,
TankClass.TANK_CLASS_TANK_DESTROYER,
];
@@ -1,7 +0,0 @@
import { TankType } from "@blitzkit/protos";
export const treeTypeOrder = [
TankType.TANK_TYPE_RESEARCHABLE,
TankType.TANK_TYPE_PREMIUM,
TankType.TANK_TYPE_COLLECTOR,
];
-50
View File
@@ -1,50 +0,0 @@
export enum ImgurSize {
/**
* The default size
*/
Default = '',
/**
* Unknown size but really really small
*/
UltraSmall = 'ss',
/**
* 90x90
*/
SmallSquare = 's',
/**
* 160x160
*/
BigSquare = 'b',
/**
* 160x160
*/
SmallThumbnail = 't',
/**
* 320x320
*/
MediumThumbnail = 'm',
/**
* 640x640
*/
LargeThumbnail = 'l',
/**
* 1024x1024
*/
HugeThumbnail = 'h',
}
interface ImgurOptions {
format: 'jpeg' | 'png';
size: ImgurSize;
}
const defaultImgurOptions: ImgurOptions = {
format: 'png',
size: ImgurSize.Default,
};
export function imgur(id: string, imgurOptions?: Partial<ImgurOptions>) {
const options = { ...defaultImgurOptions, ...imgurOptions };
return `https://i.imgur.com/${id}${options.size}.${options.format}`;
}
-1
View File
@@ -1 +0,0 @@
export * from './imgur';
+2 -4
View File
@@ -1,11 +1,9 @@
export * from "./api";
export * from "./blitz";
export * from "./blitzkit";
export * from "./config";
export * from "./imgur";
export * from "./math";
export * from "./patreon";
export * from "./protobuf";
export * from "./protos";
export * from "./statistics";
export * from "./streams";
export * from "./tankopedia";
export * from "./types";
@@ -1,4 +1,4 @@
import type { MessageFns } from "@blitzkit/protos/src/blitzkit";
import type { MessageFns } from '../protos';
export async function fetchPB<Type>(url: string, message: MessageFns<Type>) {
const response = await fetch(url);
+2
View File
@@ -0,0 +1,2 @@
export * from './fetchPB';
export * from './pbMap';
+1
View File
@@ -0,0 +1 @@
export type PBMap<T> = T[keyof T] extends number ? T[keyof T] : never;
@@ -0,0 +1,47 @@
syntax = "proto2";
package blitzkit;
message AverageDefinitions {
map<uint32, AverageDefinitionsEntry> averages = 1;
required Samples samples = 2;
required uint64 time = 3;
}
message AverageDefinitionsEntry {
required AverageDefinitionsAllStats mu = 1;
required AverageDefinitionsAllStats sigma = 2;
required AverageDefinitionsAllStats r = 3;
required 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;
}
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;
}
@@ -0,0 +1,923 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.7
// protoc v3.19.6
// source: average_definitions.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
export const protobufPackage = "blitzkit";
export interface AverageDefinitions {
averages: { [key: number]: AverageDefinitionsEntry };
samples: Samples | undefined;
time: number;
}
export interface AverageDefinitions_AveragesEntry {
key: number;
value: AverageDefinitionsEntry | undefined;
}
export interface AverageDefinitionsEntry {
mu: AverageDefinitionsAllStats | undefined;
sigma: AverageDefinitionsAllStats | undefined;
r: AverageDefinitionsAllStats | undefined;
samples: Samples | undefined;
}
export interface AverageDefinitionsAllStats {
battles: number;
capture_points: number;
damage_dealt: number;
damage_received: number;
dropped_capture_points: number;
frags: number;
frags8p: number;
hits: number;
losses: number;
max_frags: number;
max_xp: number;
shots: number;
spotted: number;
survived_battles: number;
win_and_survived: number;
wins: number;
xp: number;
battle_life_time: number;
}
export interface Samples {
d_1: number;
d_7: number;
d_30: number;
d_60: number;
d_90: number;
d_120: number;
total: number;
}
function createBaseAverageDefinitions(): AverageDefinitions {
return { averages: {}, samples: undefined, time: 0 };
}
export const AverageDefinitions: MessageFns<AverageDefinitions> = {
encode(message: AverageDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
Object.entries(message.averages).forEach(([key, value]) => {
AverageDefinitions_AveragesEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join();
});
if (message.samples !== undefined) {
Samples.encode(message.samples, writer.uint32(18).fork()).join();
}
if (message.time !== 0) {
writer.uint32(24).uint64(message.time);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): AverageDefinitions {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseAverageDefinitions();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
const entry1 = AverageDefinitions_AveragesEntry.decode(reader, reader.uint32());
if (entry1.value !== undefined) {
message.averages[entry1.key] = entry1.value;
}
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.samples = Samples.decode(reader, reader.uint32());
continue;
}
case 3: {
if (tag !== 24) {
break;
}
message.time = longToNumber(reader.uint64());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): AverageDefinitions {
return {
averages: isObject(object.averages)
? Object.entries(object.averages).reduce<{ [key: number]: AverageDefinitionsEntry }>((acc, [key, value]) => {
acc[globalThis.Number(key)] = AverageDefinitionsEntry.fromJSON(value);
return acc;
}, {})
: {},
samples: isSet(object.samples) ? Samples.fromJSON(object.samples) : undefined,
time: isSet(object.time) ? globalThis.Number(object.time) : 0,
};
},
toJSON(message: AverageDefinitions): unknown {
const obj: any = {};
if (message.averages) {
const entries = Object.entries(message.averages);
if (entries.length > 0) {
obj.averages = {};
entries.forEach(([k, v]) => {
obj.averages[k] = AverageDefinitionsEntry.toJSON(v);
});
}
}
if (message.samples !== undefined) {
obj.samples = Samples.toJSON(message.samples);
}
if (message.time !== 0) {
obj.time = Math.round(message.time);
}
return obj;
},
create<I extends Exact<DeepPartial<AverageDefinitions>, I>>(base?: I): AverageDefinitions {
return AverageDefinitions.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<AverageDefinitions>, I>>(object: I): AverageDefinitions {
const message = createBaseAverageDefinitions();
message.averages = Object.entries(object.averages ?? {}).reduce<{ [key: number]: AverageDefinitionsEntry }>(
(acc, [key, value]) => {
if (value !== undefined) {
acc[globalThis.Number(key)] = AverageDefinitionsEntry.fromPartial(value);
}
return acc;
},
{},
);
message.samples = (object.samples !== undefined && object.samples !== null)
? Samples.fromPartial(object.samples)
: undefined;
message.time = object.time ?? 0;
return message;
},
};
function createBaseAverageDefinitions_AveragesEntry(): AverageDefinitions_AveragesEntry {
return { key: 0, value: undefined };
}
export const AverageDefinitions_AveragesEntry: MessageFns<AverageDefinitions_AveragesEntry> = {
encode(message: AverageDefinitions_AveragesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== 0) {
writer.uint32(8).uint32(message.key);
}
if (message.value !== undefined) {
AverageDefinitionsEntry.encode(message.value, writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): AverageDefinitions_AveragesEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseAverageDefinitions_AveragesEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.key = reader.uint32();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.value = AverageDefinitionsEntry.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): AverageDefinitions_AveragesEntry {
return {
key: isSet(object.key) ? globalThis.Number(object.key) : 0,
value: isSet(object.value) ? AverageDefinitionsEntry.fromJSON(object.value) : undefined,
};
},
toJSON(message: AverageDefinitions_AveragesEntry): unknown {
const obj: any = {};
if (message.key !== 0) {
obj.key = Math.round(message.key);
}
if (message.value !== undefined) {
obj.value = AverageDefinitionsEntry.toJSON(message.value);
}
return obj;
},
create<I extends Exact<DeepPartial<AverageDefinitions_AveragesEntry>, I>>(
base?: I,
): AverageDefinitions_AveragesEntry {
return AverageDefinitions_AveragesEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<AverageDefinitions_AveragesEntry>, I>>(
object: I,
): AverageDefinitions_AveragesEntry {
const message = createBaseAverageDefinitions_AveragesEntry();
message.key = object.key ?? 0;
message.value = (object.value !== undefined && object.value !== null)
? AverageDefinitionsEntry.fromPartial(object.value)
: undefined;
return message;
},
};
function createBaseAverageDefinitionsEntry(): AverageDefinitionsEntry {
return { mu: undefined, sigma: undefined, r: undefined, samples: undefined };
}
export const AverageDefinitionsEntry: MessageFns<AverageDefinitionsEntry> = {
encode(message: AverageDefinitionsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.mu !== undefined) {
AverageDefinitionsAllStats.encode(message.mu, writer.uint32(10).fork()).join();
}
if (message.sigma !== undefined) {
AverageDefinitionsAllStats.encode(message.sigma, writer.uint32(18).fork()).join();
}
if (message.r !== undefined) {
AverageDefinitionsAllStats.encode(message.r, writer.uint32(26).fork()).join();
}
if (message.samples !== undefined) {
Samples.encode(message.samples, writer.uint32(34).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): AverageDefinitionsEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseAverageDefinitionsEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.mu = AverageDefinitionsAllStats.decode(reader, reader.uint32());
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.sigma = AverageDefinitionsAllStats.decode(reader, reader.uint32());
continue;
}
case 3: {
if (tag !== 26) {
break;
}
message.r = AverageDefinitionsAllStats.decode(reader, reader.uint32());
continue;
}
case 4: {
if (tag !== 34) {
break;
}
message.samples = Samples.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): AverageDefinitionsEntry {
return {
mu: isSet(object.mu) ? AverageDefinitionsAllStats.fromJSON(object.mu) : undefined,
sigma: isSet(object.sigma) ? AverageDefinitionsAllStats.fromJSON(object.sigma) : undefined,
r: isSet(object.r) ? AverageDefinitionsAllStats.fromJSON(object.r) : undefined,
samples: isSet(object.samples) ? Samples.fromJSON(object.samples) : undefined,
};
},
toJSON(message: AverageDefinitionsEntry): unknown {
const obj: any = {};
if (message.mu !== undefined) {
obj.mu = AverageDefinitionsAllStats.toJSON(message.mu);
}
if (message.sigma !== undefined) {
obj.sigma = AverageDefinitionsAllStats.toJSON(message.sigma);
}
if (message.r !== undefined) {
obj.r = AverageDefinitionsAllStats.toJSON(message.r);
}
if (message.samples !== undefined) {
obj.samples = Samples.toJSON(message.samples);
}
return obj;
},
create<I extends Exact<DeepPartial<AverageDefinitionsEntry>, I>>(base?: I): AverageDefinitionsEntry {
return AverageDefinitionsEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<AverageDefinitionsEntry>, I>>(object: I): AverageDefinitionsEntry {
const message = createBaseAverageDefinitionsEntry();
message.mu = (object.mu !== undefined && object.mu !== null)
? AverageDefinitionsAllStats.fromPartial(object.mu)
: undefined;
message.sigma = (object.sigma !== undefined && object.sigma !== null)
? AverageDefinitionsAllStats.fromPartial(object.sigma)
: undefined;
message.r = (object.r !== undefined && object.r !== null)
? AverageDefinitionsAllStats.fromPartial(object.r)
: undefined;
message.samples = (object.samples !== undefined && object.samples !== null)
? Samples.fromPartial(object.samples)
: undefined;
return message;
},
};
function createBaseAverageDefinitionsAllStats(): AverageDefinitionsAllStats {
return {
battles: 0,
capture_points: 0,
damage_dealt: 0,
damage_received: 0,
dropped_capture_points: 0,
frags: 0,
frags8p: 0,
hits: 0,
losses: 0,
max_frags: 0,
max_xp: 0,
shots: 0,
spotted: 0,
survived_battles: 0,
win_and_survived: 0,
wins: 0,
xp: 0,
battle_life_time: 0,
};
}
export const AverageDefinitionsAllStats: MessageFns<AverageDefinitionsAllStats> = {
encode(message: AverageDefinitionsAllStats, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.battles !== 0) {
writer.uint32(13).float(message.battles);
}
if (message.capture_points !== 0) {
writer.uint32(21).float(message.capture_points);
}
if (message.damage_dealt !== 0) {
writer.uint32(29).float(message.damage_dealt);
}
if (message.damage_received !== 0) {
writer.uint32(37).float(message.damage_received);
}
if (message.dropped_capture_points !== 0) {
writer.uint32(45).float(message.dropped_capture_points);
}
if (message.frags !== 0) {
writer.uint32(53).float(message.frags);
}
if (message.frags8p !== 0) {
writer.uint32(61).float(message.frags8p);
}
if (message.hits !== 0) {
writer.uint32(69).float(message.hits);
}
if (message.losses !== 0) {
writer.uint32(77).float(message.losses);
}
if (message.max_frags !== 0) {
writer.uint32(85).float(message.max_frags);
}
if (message.max_xp !== 0) {
writer.uint32(93).float(message.max_xp);
}
if (message.shots !== 0) {
writer.uint32(101).float(message.shots);
}
if (message.spotted !== 0) {
writer.uint32(109).float(message.spotted);
}
if (message.survived_battles !== 0) {
writer.uint32(117).float(message.survived_battles);
}
if (message.win_and_survived !== 0) {
writer.uint32(125).float(message.win_and_survived);
}
if (message.wins !== 0) {
writer.uint32(133).float(message.wins);
}
if (message.xp !== 0) {
writer.uint32(141).float(message.xp);
}
if (message.battle_life_time !== 0) {
writer.uint32(149).float(message.battle_life_time);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): AverageDefinitionsAllStats {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseAverageDefinitionsAllStats();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 13) {
break;
}
message.battles = reader.float();
continue;
}
case 2: {
if (tag !== 21) {
break;
}
message.capture_points = reader.float();
continue;
}
case 3: {
if (tag !== 29) {
break;
}
message.damage_dealt = reader.float();
continue;
}
case 4: {
if (tag !== 37) {
break;
}
message.damage_received = reader.float();
continue;
}
case 5: {
if (tag !== 45) {
break;
}
message.dropped_capture_points = reader.float();
continue;
}
case 6: {
if (tag !== 53) {
break;
}
message.frags = reader.float();
continue;
}
case 7: {
if (tag !== 61) {
break;
}
message.frags8p = reader.float();
continue;
}
case 8: {
if (tag !== 69) {
break;
}
message.hits = reader.float();
continue;
}
case 9: {
if (tag !== 77) {
break;
}
message.losses = reader.float();
continue;
}
case 10: {
if (tag !== 85) {
break;
}
message.max_frags = reader.float();
continue;
}
case 11: {
if (tag !== 93) {
break;
}
message.max_xp = reader.float();
continue;
}
case 12: {
if (tag !== 101) {
break;
}
message.shots = reader.float();
continue;
}
case 13: {
if (tag !== 109) {
break;
}
message.spotted = reader.float();
continue;
}
case 14: {
if (tag !== 117) {
break;
}
message.survived_battles = reader.float();
continue;
}
case 15: {
if (tag !== 125) {
break;
}
message.win_and_survived = reader.float();
continue;
}
case 16: {
if (tag !== 133) {
break;
}
message.wins = reader.float();
continue;
}
case 17: {
if (tag !== 141) {
break;
}
message.xp = reader.float();
continue;
}
case 18: {
if (tag !== 149) {
break;
}
message.battle_life_time = reader.float();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): AverageDefinitionsAllStats {
return {
battles: isSet(object.battles) ? globalThis.Number(object.battles) : 0,
capture_points: isSet(object.capture_points) ? globalThis.Number(object.capture_points) : 0,
damage_dealt: isSet(object.damage_dealt) ? globalThis.Number(object.damage_dealt) : 0,
damage_received: isSet(object.damage_received) ? globalThis.Number(object.damage_received) : 0,
dropped_capture_points: isSet(object.dropped_capture_points)
? globalThis.Number(object.dropped_capture_points)
: 0,
frags: isSet(object.frags) ? globalThis.Number(object.frags) : 0,
frags8p: isSet(object.frags8p) ? globalThis.Number(object.frags8p) : 0,
hits: isSet(object.hits) ? globalThis.Number(object.hits) : 0,
losses: isSet(object.losses) ? globalThis.Number(object.losses) : 0,
max_frags: isSet(object.max_frags) ? globalThis.Number(object.max_frags) : 0,
max_xp: isSet(object.max_xp) ? globalThis.Number(object.max_xp) : 0,
shots: isSet(object.shots) ? globalThis.Number(object.shots) : 0,
spotted: isSet(object.spotted) ? globalThis.Number(object.spotted) : 0,
survived_battles: isSet(object.survived_battles) ? globalThis.Number(object.survived_battles) : 0,
win_and_survived: isSet(object.win_and_survived) ? globalThis.Number(object.win_and_survived) : 0,
wins: isSet(object.wins) ? globalThis.Number(object.wins) : 0,
xp: isSet(object.xp) ? globalThis.Number(object.xp) : 0,
battle_life_time: isSet(object.battle_life_time) ? globalThis.Number(object.battle_life_time) : 0,
};
},
toJSON(message: AverageDefinitionsAllStats): unknown {
const obj: any = {};
if (message.battles !== 0) {
obj.battles = message.battles;
}
if (message.capture_points !== 0) {
obj.capture_points = message.capture_points;
}
if (message.damage_dealt !== 0) {
obj.damage_dealt = message.damage_dealt;
}
if (message.damage_received !== 0) {
obj.damage_received = message.damage_received;
}
if (message.dropped_capture_points !== 0) {
obj.dropped_capture_points = message.dropped_capture_points;
}
if (message.frags !== 0) {
obj.frags = message.frags;
}
if (message.frags8p !== 0) {
obj.frags8p = message.frags8p;
}
if (message.hits !== 0) {
obj.hits = message.hits;
}
if (message.losses !== 0) {
obj.losses = message.losses;
}
if (message.max_frags !== 0) {
obj.max_frags = message.max_frags;
}
if (message.max_xp !== 0) {
obj.max_xp = message.max_xp;
}
if (message.shots !== 0) {
obj.shots = message.shots;
}
if (message.spotted !== 0) {
obj.spotted = message.spotted;
}
if (message.survived_battles !== 0) {
obj.survived_battles = message.survived_battles;
}
if (message.win_and_survived !== 0) {
obj.win_and_survived = message.win_and_survived;
}
if (message.wins !== 0) {
obj.wins = message.wins;
}
if (message.xp !== 0) {
obj.xp = message.xp;
}
if (message.battle_life_time !== 0) {
obj.battle_life_time = message.battle_life_time;
}
return obj;
},
create<I extends Exact<DeepPartial<AverageDefinitionsAllStats>, I>>(base?: I): AverageDefinitionsAllStats {
return AverageDefinitionsAllStats.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<AverageDefinitionsAllStats>, I>>(object: I): AverageDefinitionsAllStats {
const message = createBaseAverageDefinitionsAllStats();
message.battles = object.battles ?? 0;
message.capture_points = object.capture_points ?? 0;
message.damage_dealt = object.damage_dealt ?? 0;
message.damage_received = object.damage_received ?? 0;
message.dropped_capture_points = object.dropped_capture_points ?? 0;
message.frags = object.frags ?? 0;
message.frags8p = object.frags8p ?? 0;
message.hits = object.hits ?? 0;
message.losses = object.losses ?? 0;
message.max_frags = object.max_frags ?? 0;
message.max_xp = object.max_xp ?? 0;
message.shots = object.shots ?? 0;
message.spotted = object.spotted ?? 0;
message.survived_battles = object.survived_battles ?? 0;
message.win_and_survived = object.win_and_survived ?? 0;
message.wins = object.wins ?? 0;
message.xp = object.xp ?? 0;
message.battle_life_time = object.battle_life_time ?? 0;
return message;
},
};
function createBaseSamples(): Samples {
return { d_1: 0, d_7: 0, d_30: 0, d_60: 0, d_90: 0, d_120: 0, total: 0 };
}
export const Samples: MessageFns<Samples> = {
encode(message: Samples, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.d_1 !== 0) {
writer.uint32(8).uint32(message.d_1);
}
if (message.d_7 !== 0) {
writer.uint32(16).uint32(message.d_7);
}
if (message.d_30 !== 0) {
writer.uint32(24).uint32(message.d_30);
}
if (message.d_60 !== 0) {
writer.uint32(32).uint32(message.d_60);
}
if (message.d_90 !== 0) {
writer.uint32(40).uint32(message.d_90);
}
if (message.d_120 !== 0) {
writer.uint32(48).uint32(message.d_120);
}
if (message.total !== 0) {
writer.uint32(56).uint32(message.total);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): Samples {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseSamples();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.d_1 = reader.uint32();
continue;
}
case 2: {
if (tag !== 16) {
break;
}
message.d_7 = reader.uint32();
continue;
}
case 3: {
if (tag !== 24) {
break;
}
message.d_30 = reader.uint32();
continue;
}
case 4: {
if (tag !== 32) {
break;
}
message.d_60 = reader.uint32();
continue;
}
case 5: {
if (tag !== 40) {
break;
}
message.d_90 = reader.uint32();
continue;
}
case 6: {
if (tag !== 48) {
break;
}
message.d_120 = reader.uint32();
continue;
}
case 7: {
if (tag !== 56) {
break;
}
message.total = reader.uint32();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): Samples {
return {
d_1: isSet(object.d_1) ? globalThis.Number(object.d_1) : 0,
d_7: isSet(object.d_7) ? globalThis.Number(object.d_7) : 0,
d_30: isSet(object.d_30) ? globalThis.Number(object.d_30) : 0,
d_60: isSet(object.d_60) ? globalThis.Number(object.d_60) : 0,
d_90: isSet(object.d_90) ? globalThis.Number(object.d_90) : 0,
d_120: isSet(object.d_120) ? globalThis.Number(object.d_120) : 0,
total: isSet(object.total) ? globalThis.Number(object.total) : 0,
};
},
toJSON(message: Samples): unknown {
const obj: any = {};
if (message.d_1 !== 0) {
obj.d_1 = Math.round(message.d_1);
}
if (message.d_7 !== 0) {
obj.d_7 = Math.round(message.d_7);
}
if (message.d_30 !== 0) {
obj.d_30 = Math.round(message.d_30);
}
if (message.d_60 !== 0) {
obj.d_60 = Math.round(message.d_60);
}
if (message.d_90 !== 0) {
obj.d_90 = Math.round(message.d_90);
}
if (message.d_120 !== 0) {
obj.d_120 = Math.round(message.d_120);
}
if (message.total !== 0) {
obj.total = Math.round(message.total);
}
return obj;
},
create<I extends Exact<DeepPartial<Samples>, I>>(base?: I): Samples {
return Samples.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<Samples>, I>>(object: I): Samples {
const message = createBaseSamples();
message.d_1 = object.d_1 ?? 0;
message.d_7 = object.d_7 ?? 0;
message.d_30 = object.d_30 ?? 0;
message.d_60 = object.d_60 ?? 0;
message.d_90 = object.d_90 ?? 0;
message.d_120 = object.d_120 ?? 0;
message.total = object.total ?? 0;
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial<T["value"]> }
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
function longToNumber(int64: { toString(): string }): number {
const num = globalThis.Number(int64.toString());
if (num > globalThis.Number.MAX_SAFE_INTEGER) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
}
if (num < globalThis.Number.MIN_SAFE_INTEGER) {
throw new globalThis.Error("Value is smaller than Number.MIN_SAFE_INTEGER");
}
return num;
}
function isObject(value: any): boolean {
return typeof value === "object" && value !== null;
}
function isSet(value: any): boolean {
return value !== null && value !== undefined;
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T;
fromJSON(object: any): T;
toJSON(message: T): unknown;
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
}
@@ -1,4 +1,4 @@
syntax = "proto3";
syntax = "proto2";
package blitzkit;
@@ -9,8 +9,8 @@ message CamouflageDefinitions {
}
message Camouflage {
uint32 id = 1;
I18nString name = 2;
required uint32 id = 1;
required I18nString name = 2;
optional I18nString tank_name = 3;
optional I18nString tank_name_full = 4;
}
@@ -0,0 +1,335 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.7
// protoc v3.19.6
// source: camouflage_definitions.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import { I18nString } from "./i18n";
export const protobufPackage = "blitzkit";
export interface CamouflageDefinitions {
camouflages: { [key: number]: Camouflage };
}
export interface CamouflageDefinitions_CamouflagesEntry {
key: number;
value: Camouflage | undefined;
}
export interface Camouflage {
id: number;
name: I18nString | undefined;
tank_name?: I18nString | undefined;
tank_name_full?: I18nString | undefined;
}
function createBaseCamouflageDefinitions(): CamouflageDefinitions {
return { camouflages: {} };
}
export const CamouflageDefinitions: MessageFns<CamouflageDefinitions> = {
encode(message: CamouflageDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
Object.entries(message.camouflages).forEach(([key, value]) => {
CamouflageDefinitions_CamouflagesEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join();
});
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): CamouflageDefinitions {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseCamouflageDefinitions();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
const entry1 = CamouflageDefinitions_CamouflagesEntry.decode(reader, reader.uint32());
if (entry1.value !== undefined) {
message.camouflages[entry1.key] = entry1.value;
}
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): CamouflageDefinitions {
return {
camouflages: isObject(object.camouflages)
? Object.entries(object.camouflages).reduce<{ [key: number]: Camouflage }>((acc, [key, value]) => {
acc[globalThis.Number(key)] = Camouflage.fromJSON(value);
return acc;
}, {})
: {},
};
},
toJSON(message: CamouflageDefinitions): unknown {
const obj: any = {};
if (message.camouflages) {
const entries = Object.entries(message.camouflages);
if (entries.length > 0) {
obj.camouflages = {};
entries.forEach(([k, v]) => {
obj.camouflages[k] = Camouflage.toJSON(v);
});
}
}
return obj;
},
create<I extends Exact<DeepPartial<CamouflageDefinitions>, I>>(base?: I): CamouflageDefinitions {
return CamouflageDefinitions.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<CamouflageDefinitions>, I>>(object: I): CamouflageDefinitions {
const message = createBaseCamouflageDefinitions();
message.camouflages = Object.entries(object.camouflages ?? {}).reduce<{ [key: number]: Camouflage }>(
(acc, [key, value]) => {
if (value !== undefined) {
acc[globalThis.Number(key)] = Camouflage.fromPartial(value);
}
return acc;
},
{},
);
return message;
},
};
function createBaseCamouflageDefinitions_CamouflagesEntry(): CamouflageDefinitions_CamouflagesEntry {
return { key: 0, value: undefined };
}
export const CamouflageDefinitions_CamouflagesEntry: MessageFns<CamouflageDefinitions_CamouflagesEntry> = {
encode(message: CamouflageDefinitions_CamouflagesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== 0) {
writer.uint32(8).uint32(message.key);
}
if (message.value !== undefined) {
Camouflage.encode(message.value, writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): CamouflageDefinitions_CamouflagesEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseCamouflageDefinitions_CamouflagesEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.key = reader.uint32();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.value = Camouflage.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): CamouflageDefinitions_CamouflagesEntry {
return {
key: isSet(object.key) ? globalThis.Number(object.key) : 0,
value: isSet(object.value) ? Camouflage.fromJSON(object.value) : undefined,
};
},
toJSON(message: CamouflageDefinitions_CamouflagesEntry): unknown {
const obj: any = {};
if (message.key !== 0) {
obj.key = Math.round(message.key);
}
if (message.value !== undefined) {
obj.value = Camouflage.toJSON(message.value);
}
return obj;
},
create<I extends Exact<DeepPartial<CamouflageDefinitions_CamouflagesEntry>, I>>(
base?: I,
): CamouflageDefinitions_CamouflagesEntry {
return CamouflageDefinitions_CamouflagesEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<CamouflageDefinitions_CamouflagesEntry>, I>>(
object: I,
): CamouflageDefinitions_CamouflagesEntry {
const message = createBaseCamouflageDefinitions_CamouflagesEntry();
message.key = object.key ?? 0;
message.value = (object.value !== undefined && object.value !== null)
? Camouflage.fromPartial(object.value)
: undefined;
return message;
},
};
function createBaseCamouflage(): Camouflage {
return { id: 0, name: undefined, tank_name: undefined, tank_name_full: undefined };
}
export const Camouflage: MessageFns<Camouflage> = {
encode(message: Camouflage, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.id !== 0) {
writer.uint32(8).uint32(message.id);
}
if (message.name !== undefined) {
I18nString.encode(message.name, writer.uint32(18).fork()).join();
}
if (message.tank_name !== undefined) {
I18nString.encode(message.tank_name, writer.uint32(26).fork()).join();
}
if (message.tank_name_full !== undefined) {
I18nString.encode(message.tank_name_full, writer.uint32(34).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): Camouflage {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseCamouflage();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.id = reader.uint32();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.name = I18nString.decode(reader, reader.uint32());
continue;
}
case 3: {
if (tag !== 26) {
break;
}
message.tank_name = I18nString.decode(reader, reader.uint32());
continue;
}
case 4: {
if (tag !== 34) {
break;
}
message.tank_name_full = I18nString.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): Camouflage {
return {
id: isSet(object.id) ? globalThis.Number(object.id) : 0,
name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined,
tank_name: isSet(object.tank_name) ? I18nString.fromJSON(object.tank_name) : undefined,
tank_name_full: isSet(object.tank_name_full) ? I18nString.fromJSON(object.tank_name_full) : undefined,
};
},
toJSON(message: Camouflage): unknown {
const obj: any = {};
if (message.id !== 0) {
obj.id = Math.round(message.id);
}
if (message.name !== undefined) {
obj.name = I18nString.toJSON(message.name);
}
if (message.tank_name !== undefined) {
obj.tank_name = I18nString.toJSON(message.tank_name);
}
if (message.tank_name_full !== undefined) {
obj.tank_name_full = I18nString.toJSON(message.tank_name_full);
}
return obj;
},
create<I extends Exact<DeepPartial<Camouflage>, I>>(base?: I): Camouflage {
return Camouflage.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<Camouflage>, I>>(object: I): Camouflage {
const message = createBaseCamouflage();
message.id = object.id ?? 0;
message.name = (object.name !== undefined && object.name !== null)
? I18nString.fromPartial(object.name)
: undefined;
message.tank_name = (object.tank_name !== undefined && object.tank_name !== null)
? I18nString.fromPartial(object.tank_name)
: undefined;
message.tank_name_full = (object.tank_name_full !== undefined && object.tank_name_full !== null)
? I18nString.fromPartial(object.tank_name_full)
: undefined;
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial<T["value"]> }
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
function isObject(value: any): boolean {
return typeof value === "object" && value !== null;
}
function isSet(value: any): boolean {
return value !== null && value !== undefined;
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T;
fromJSON(object: any): T;
toJSON(message: T): unknown;
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
}
@@ -1,4 +1,4 @@
syntax = "proto3";
syntax = "proto2";
package blitzkit;
@@ -9,14 +9,16 @@ message ConsumableDefinitions {
}
message Consumable {
uint32 id = 1;
I18nString name = 2;
bool game_mode_exclusive = 5;
repeated TankInclusivityFilter include = 6;
repeated TankInclusivityFilter exclude = 7;
required uint32 id = 1;
required I18nString name = 2;
required uint32 cooldown = 3;
optional float duration = 4;
required bool game_mode_exclusive = 5;
repeated ConsumableTankFilter include = 6;
repeated ConsumableTankFilter exclude = 7;
}
message TankInclusivityFilter {
message ConsumableTankFilter {
oneof filter_type {
ConsumableTankTierFilter tiers = 1;
ConsumableTankIdsFilter ids = 2;
@@ -26,8 +28,8 @@ message TankInclusivityFilter {
}
message ConsumableTankTierFilter {
uint32 min = 1;
uint32 max = 2;
required uint32 min = 1;
required uint32 max = 2;
}
message ConsumableTankIdsFilter {
@@ -0,0 +1,861 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.7
// protoc v3.19.6
// source: consumable_definitions.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import { I18nString } from "./i18n";
export const protobufPackage = "blitzkit";
export enum ConsumableTankCategoryFilterCategory {
CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP = 0,
}
export function consumableTankCategoryFilterCategoryFromJSON(object: any): ConsumableTankCategoryFilterCategory {
switch (object) {
case 0:
case "CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP":
return ConsumableTankCategoryFilterCategory.CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP;
default:
throw new globalThis.Error(
"Unrecognized enum value " + object + " for enum ConsumableTankCategoryFilterCategory",
);
}
}
export function consumableTankCategoryFilterCategoryToJSON(object: ConsumableTankCategoryFilterCategory): string {
switch (object) {
case ConsumableTankCategoryFilterCategory.CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP:
return "CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP";
default:
throw new globalThis.Error(
"Unrecognized enum value " + object + " for enum ConsumableTankCategoryFilterCategory",
);
}
}
export interface ConsumableDefinitions {
consumables: { [key: number]: Consumable };
}
export interface ConsumableDefinitions_ConsumablesEntry {
key: number;
value: Consumable | undefined;
}
export interface Consumable {
id: number;
name: I18nString | undefined;
cooldown: number;
duration?: number | undefined;
game_mode_exclusive: boolean;
include: ConsumableTankFilter[];
exclude: ConsumableTankFilter[];
}
export interface ConsumableTankFilter {
filter_type?:
| { $case: "tiers"; value: ConsumableTankTierFilter }
| { $case: "ids"; value: ConsumableTankIdsFilter }
| { $case: "categories"; value: ConsumableTankCategoryFilter }
| { $case: "nations"; value: ConsumableTankNationFilter }
| undefined;
}
export interface ConsumableTankTierFilter {
min: number;
max: number;
}
export interface ConsumableTankIdsFilter {
ids: number[];
}
export interface ConsumableTankCategoryFilter {
categories: ConsumableTankCategoryFilterCategory[];
}
export interface ConsumableTankNationFilter {
nations: string[];
}
function createBaseConsumableDefinitions(): ConsumableDefinitions {
return { consumables: {} };
}
export const ConsumableDefinitions: MessageFns<ConsumableDefinitions> = {
encode(message: ConsumableDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
Object.entries(message.consumables).forEach(([key, value]) => {
ConsumableDefinitions_ConsumablesEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join();
});
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ConsumableDefinitions {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseConsumableDefinitions();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
const entry1 = ConsumableDefinitions_ConsumablesEntry.decode(reader, reader.uint32());
if (entry1.value !== undefined) {
message.consumables[entry1.key] = entry1.value;
}
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): ConsumableDefinitions {
return {
consumables: isObject(object.consumables)
? Object.entries(object.consumables).reduce<{ [key: number]: Consumable }>((acc, [key, value]) => {
acc[globalThis.Number(key)] = Consumable.fromJSON(value);
return acc;
}, {})
: {},
};
},
toJSON(message: ConsumableDefinitions): unknown {
const obj: any = {};
if (message.consumables) {
const entries = Object.entries(message.consumables);
if (entries.length > 0) {
obj.consumables = {};
entries.forEach(([k, v]) => {
obj.consumables[k] = Consumable.toJSON(v);
});
}
}
return obj;
},
create<I extends Exact<DeepPartial<ConsumableDefinitions>, I>>(base?: I): ConsumableDefinitions {
return ConsumableDefinitions.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<ConsumableDefinitions>, I>>(object: I): ConsumableDefinitions {
const message = createBaseConsumableDefinitions();
message.consumables = Object.entries(object.consumables ?? {}).reduce<{ [key: number]: Consumable }>(
(acc, [key, value]) => {
if (value !== undefined) {
acc[globalThis.Number(key)] = Consumable.fromPartial(value);
}
return acc;
},
{},
);
return message;
},
};
function createBaseConsumableDefinitions_ConsumablesEntry(): ConsumableDefinitions_ConsumablesEntry {
return { key: 0, value: undefined };
}
export const ConsumableDefinitions_ConsumablesEntry: MessageFns<ConsumableDefinitions_ConsumablesEntry> = {
encode(message: ConsumableDefinitions_ConsumablesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== 0) {
writer.uint32(8).uint32(message.key);
}
if (message.value !== undefined) {
Consumable.encode(message.value, writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ConsumableDefinitions_ConsumablesEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseConsumableDefinitions_ConsumablesEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.key = reader.uint32();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.value = Consumable.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): ConsumableDefinitions_ConsumablesEntry {
return {
key: isSet(object.key) ? globalThis.Number(object.key) : 0,
value: isSet(object.value) ? Consumable.fromJSON(object.value) : undefined,
};
},
toJSON(message: ConsumableDefinitions_ConsumablesEntry): unknown {
const obj: any = {};
if (message.key !== 0) {
obj.key = Math.round(message.key);
}
if (message.value !== undefined) {
obj.value = Consumable.toJSON(message.value);
}
return obj;
},
create<I extends Exact<DeepPartial<ConsumableDefinitions_ConsumablesEntry>, I>>(
base?: I,
): ConsumableDefinitions_ConsumablesEntry {
return ConsumableDefinitions_ConsumablesEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<ConsumableDefinitions_ConsumablesEntry>, I>>(
object: I,
): ConsumableDefinitions_ConsumablesEntry {
const message = createBaseConsumableDefinitions_ConsumablesEntry();
message.key = object.key ?? 0;
message.value = (object.value !== undefined && object.value !== null)
? Consumable.fromPartial(object.value)
: undefined;
return message;
},
};
function createBaseConsumable(): Consumable {
return { id: 0, name: undefined, cooldown: 0, duration: 0, game_mode_exclusive: false, include: [], exclude: [] };
}
export const Consumable: MessageFns<Consumable> = {
encode(message: Consumable, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.id !== 0) {
writer.uint32(8).uint32(message.id);
}
if (message.name !== undefined) {
I18nString.encode(message.name, writer.uint32(18).fork()).join();
}
if (message.cooldown !== 0) {
writer.uint32(24).uint32(message.cooldown);
}
if (message.duration !== undefined && message.duration !== 0) {
writer.uint32(37).float(message.duration);
}
if (message.game_mode_exclusive !== false) {
writer.uint32(40).bool(message.game_mode_exclusive);
}
for (const v of message.include) {
ConsumableTankFilter.encode(v!, writer.uint32(50).fork()).join();
}
for (const v of message.exclude) {
ConsumableTankFilter.encode(v!, writer.uint32(58).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): Consumable {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseConsumable();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.id = reader.uint32();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.name = I18nString.decode(reader, reader.uint32());
continue;
}
case 3: {
if (tag !== 24) {
break;
}
message.cooldown = reader.uint32();
continue;
}
case 4: {
if (tag !== 37) {
break;
}
message.duration = reader.float();
continue;
}
case 5: {
if (tag !== 40) {
break;
}
message.game_mode_exclusive = reader.bool();
continue;
}
case 6: {
if (tag !== 50) {
break;
}
message.include.push(ConsumableTankFilter.decode(reader, reader.uint32()));
continue;
}
case 7: {
if (tag !== 58) {
break;
}
message.exclude.push(ConsumableTankFilter.decode(reader, reader.uint32()));
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): Consumable {
return {
id: isSet(object.id) ? globalThis.Number(object.id) : 0,
name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined,
cooldown: isSet(object.cooldown) ? globalThis.Number(object.cooldown) : 0,
duration: isSet(object.duration) ? globalThis.Number(object.duration) : 0,
game_mode_exclusive: isSet(object.game_mode_exclusive) ? globalThis.Boolean(object.game_mode_exclusive) : false,
include: globalThis.Array.isArray(object?.include)
? object.include.map((e: any) => ConsumableTankFilter.fromJSON(e))
: [],
exclude: globalThis.Array.isArray(object?.exclude)
? object.exclude.map((e: any) => ConsumableTankFilter.fromJSON(e))
: [],
};
},
toJSON(message: Consumable): unknown {
const obj: any = {};
if (message.id !== 0) {
obj.id = Math.round(message.id);
}
if (message.name !== undefined) {
obj.name = I18nString.toJSON(message.name);
}
if (message.cooldown !== 0) {
obj.cooldown = Math.round(message.cooldown);
}
if (message.duration !== undefined && message.duration !== 0) {
obj.duration = message.duration;
}
if (message.game_mode_exclusive !== false) {
obj.game_mode_exclusive = message.game_mode_exclusive;
}
if (message.include?.length) {
obj.include = message.include.map((e) => ConsumableTankFilter.toJSON(e));
}
if (message.exclude?.length) {
obj.exclude = message.exclude.map((e) => ConsumableTankFilter.toJSON(e));
}
return obj;
},
create<I extends Exact<DeepPartial<Consumable>, I>>(base?: I): Consumable {
return Consumable.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<Consumable>, I>>(object: I): Consumable {
const message = createBaseConsumable();
message.id = object.id ?? 0;
message.name = (object.name !== undefined && object.name !== null)
? I18nString.fromPartial(object.name)
: undefined;
message.cooldown = object.cooldown ?? 0;
message.duration = object.duration ?? 0;
message.game_mode_exclusive = object.game_mode_exclusive ?? false;
message.include = object.include?.map((e) => ConsumableTankFilter.fromPartial(e)) || [];
message.exclude = object.exclude?.map((e) => ConsumableTankFilter.fromPartial(e)) || [];
return message;
},
};
function createBaseConsumableTankFilter(): ConsumableTankFilter {
return { filter_type: undefined };
}
export const ConsumableTankFilter: MessageFns<ConsumableTankFilter> = {
encode(message: ConsumableTankFilter, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
switch (message.filter_type?.$case) {
case "tiers":
ConsumableTankTierFilter.encode(message.filter_type.value, writer.uint32(10).fork()).join();
break;
case "ids":
ConsumableTankIdsFilter.encode(message.filter_type.value, writer.uint32(18).fork()).join();
break;
case "categories":
ConsumableTankCategoryFilter.encode(message.filter_type.value, writer.uint32(26).fork()).join();
break;
case "nations":
ConsumableTankNationFilter.encode(message.filter_type.value, writer.uint32(34).fork()).join();
break;
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ConsumableTankFilter {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseConsumableTankFilter();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.filter_type = { $case: "tiers", value: ConsumableTankTierFilter.decode(reader, reader.uint32()) };
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.filter_type = { $case: "ids", value: ConsumableTankIdsFilter.decode(reader, reader.uint32()) };
continue;
}
case 3: {
if (tag !== 26) {
break;
}
message.filter_type = {
$case: "categories",
value: ConsumableTankCategoryFilter.decode(reader, reader.uint32()),
};
continue;
}
case 4: {
if (tag !== 34) {
break;
}
message.filter_type = { $case: "nations", value: ConsumableTankNationFilter.decode(reader, reader.uint32()) };
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): ConsumableTankFilter {
return {
filter_type: isSet(object.tiers)
? { $case: "tiers", value: ConsumableTankTierFilter.fromJSON(object.tiers) }
: isSet(object.ids)
? { $case: "ids", value: ConsumableTankIdsFilter.fromJSON(object.ids) }
: isSet(object.categories)
? { $case: "categories", value: ConsumableTankCategoryFilter.fromJSON(object.categories) }
: isSet(object.nations)
? { $case: "nations", value: ConsumableTankNationFilter.fromJSON(object.nations) }
: undefined,
};
},
toJSON(message: ConsumableTankFilter): unknown {
const obj: any = {};
if (message.filter_type?.$case === "tiers") {
obj.tiers = ConsumableTankTierFilter.toJSON(message.filter_type.value);
} else if (message.filter_type?.$case === "ids") {
obj.ids = ConsumableTankIdsFilter.toJSON(message.filter_type.value);
} else if (message.filter_type?.$case === "categories") {
obj.categories = ConsumableTankCategoryFilter.toJSON(message.filter_type.value);
} else if (message.filter_type?.$case === "nations") {
obj.nations = ConsumableTankNationFilter.toJSON(message.filter_type.value);
}
return obj;
},
create<I extends Exact<DeepPartial<ConsumableTankFilter>, I>>(base?: I): ConsumableTankFilter {
return ConsumableTankFilter.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<ConsumableTankFilter>, I>>(object: I): ConsumableTankFilter {
const message = createBaseConsumableTankFilter();
switch (object.filter_type?.$case) {
case "tiers": {
if (object.filter_type?.value !== undefined && object.filter_type?.value !== null) {
message.filter_type = {
$case: "tiers",
value: ConsumableTankTierFilter.fromPartial(object.filter_type.value),
};
}
break;
}
case "ids": {
if (object.filter_type?.value !== undefined && object.filter_type?.value !== null) {
message.filter_type = { $case: "ids", value: ConsumableTankIdsFilter.fromPartial(object.filter_type.value) };
}
break;
}
case "categories": {
if (object.filter_type?.value !== undefined && object.filter_type?.value !== null) {
message.filter_type = {
$case: "categories",
value: ConsumableTankCategoryFilter.fromPartial(object.filter_type.value),
};
}
break;
}
case "nations": {
if (object.filter_type?.value !== undefined && object.filter_type?.value !== null) {
message.filter_type = {
$case: "nations",
value: ConsumableTankNationFilter.fromPartial(object.filter_type.value),
};
}
break;
}
}
return message;
},
};
function createBaseConsumableTankTierFilter(): ConsumableTankTierFilter {
return { min: 0, max: 0 };
}
export const ConsumableTankTierFilter: MessageFns<ConsumableTankTierFilter> = {
encode(message: ConsumableTankTierFilter, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.min !== 0) {
writer.uint32(8).uint32(message.min);
}
if (message.max !== 0) {
writer.uint32(16).uint32(message.max);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ConsumableTankTierFilter {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseConsumableTankTierFilter();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.min = reader.uint32();
continue;
}
case 2: {
if (tag !== 16) {
break;
}
message.max = reader.uint32();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): ConsumableTankTierFilter {
return {
min: isSet(object.min) ? globalThis.Number(object.min) : 0,
max: isSet(object.max) ? globalThis.Number(object.max) : 0,
};
},
toJSON(message: ConsumableTankTierFilter): unknown {
const obj: any = {};
if (message.min !== 0) {
obj.min = Math.round(message.min);
}
if (message.max !== 0) {
obj.max = Math.round(message.max);
}
return obj;
},
create<I extends Exact<DeepPartial<ConsumableTankTierFilter>, I>>(base?: I): ConsumableTankTierFilter {
return ConsumableTankTierFilter.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<ConsumableTankTierFilter>, I>>(object: I): ConsumableTankTierFilter {
const message = createBaseConsumableTankTierFilter();
message.min = object.min ?? 0;
message.max = object.max ?? 0;
return message;
},
};
function createBaseConsumableTankIdsFilter(): ConsumableTankIdsFilter {
return { ids: [] };
}
export const ConsumableTankIdsFilter: MessageFns<ConsumableTankIdsFilter> = {
encode(message: ConsumableTankIdsFilter, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.ids) {
writer.uint32(8).uint32(v!);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ConsumableTankIdsFilter {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseConsumableTankIdsFilter();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag === 8) {
message.ids.push(reader.uint32());
continue;
}
if (tag === 10) {
const end2 = reader.uint32() + reader.pos;
while (reader.pos < end2) {
message.ids.push(reader.uint32());
}
continue;
}
break;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): ConsumableTankIdsFilter {
return { ids: globalThis.Array.isArray(object?.ids) ? object.ids.map((e: any) => globalThis.Number(e)) : [] };
},
toJSON(message: ConsumableTankIdsFilter): unknown {
const obj: any = {};
if (message.ids?.length) {
obj.ids = message.ids.map((e) => Math.round(e));
}
return obj;
},
create<I extends Exact<DeepPartial<ConsumableTankIdsFilter>, I>>(base?: I): ConsumableTankIdsFilter {
return ConsumableTankIdsFilter.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<ConsumableTankIdsFilter>, I>>(object: I): ConsumableTankIdsFilter {
const message = createBaseConsumableTankIdsFilter();
message.ids = object.ids?.map((e) => e) || [];
return message;
},
};
function createBaseConsumableTankCategoryFilter(): ConsumableTankCategoryFilter {
return { categories: [] };
}
export const ConsumableTankCategoryFilter: MessageFns<ConsumableTankCategoryFilter> = {
encode(message: ConsumableTankCategoryFilter, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.categories) {
writer.uint32(8).int32(v!);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ConsumableTankCategoryFilter {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseConsumableTankCategoryFilter();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag === 8) {
message.categories.push(reader.int32() as any);
continue;
}
if (tag === 10) {
const end2 = reader.uint32() + reader.pos;
while (reader.pos < end2) {
message.categories.push(reader.int32() as any);
}
continue;
}
break;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): ConsumableTankCategoryFilter {
return {
categories: globalThis.Array.isArray(object?.categories)
? object.categories.map((e: any) => consumableTankCategoryFilterCategoryFromJSON(e))
: [],
};
},
toJSON(message: ConsumableTankCategoryFilter): unknown {
const obj: any = {};
if (message.categories?.length) {
obj.categories = message.categories.map((e) => consumableTankCategoryFilterCategoryToJSON(e));
}
return obj;
},
create<I extends Exact<DeepPartial<ConsumableTankCategoryFilter>, I>>(base?: I): ConsumableTankCategoryFilter {
return ConsumableTankCategoryFilter.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<ConsumableTankCategoryFilter>, I>>(object: I): ConsumableTankCategoryFilter {
const message = createBaseConsumableTankCategoryFilter();
message.categories = object.categories?.map((e) => e) || [];
return message;
},
};
function createBaseConsumableTankNationFilter(): ConsumableTankNationFilter {
return { nations: [] };
}
export const ConsumableTankNationFilter: MessageFns<ConsumableTankNationFilter> = {
encode(message: ConsumableTankNationFilter, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.nations) {
writer.uint32(10).string(v!);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ConsumableTankNationFilter {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseConsumableTankNationFilter();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.nations.push(reader.string());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): ConsumableTankNationFilter {
return {
nations: globalThis.Array.isArray(object?.nations) ? object.nations.map((e: any) => globalThis.String(e)) : [],
};
},
toJSON(message: ConsumableTankNationFilter): unknown {
const obj: any = {};
if (message.nations?.length) {
obj.nations = message.nations;
}
return obj;
},
create<I extends Exact<DeepPartial<ConsumableTankNationFilter>, I>>(base?: I): ConsumableTankNationFilter {
return ConsumableTankNationFilter.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<ConsumableTankNationFilter>, I>>(object: I): ConsumableTankNationFilter {
const message = createBaseConsumableTankNationFilter();
message.nations = object.nations?.map((e) => e) || [];
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial<T["value"]> }
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
function isObject(value: any): boolean {
return typeof value === "object" && value !== null;
}
function isSet(value: any): boolean {
return value !== null && value !== undefined;
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T;
fromJSON(object: any): T;
toJSON(message: T): unknown;
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
}
@@ -1,4 +1,4 @@
syntax = "proto3";
syntax = "proto2";
package blitzkit;
@@ -10,8 +10,8 @@ message EquipmentDefinitions {
}
message Equipment {
I18nString name = 1;
I18nString description = 2;
required I18nString name = 1;
required I18nString description = 2;
}
message EquipmentPreset {
@@ -19,5 +19,6 @@ message EquipmentPreset {
}
message EquipmentSlot {
repeated uint32 options = 1;
required uint32 left = 1;
required uint32 right = 2;
}
@@ -0,0 +1,570 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.7
// protoc v3.19.6
// source: equipment_definitions.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import { I18nString } from "./i18n";
export const protobufPackage = "blitzkit";
export interface EquipmentDefinitions {
presets: { [key: string]: EquipmentPreset };
equipments: { [key: number]: Equipment };
}
export interface EquipmentDefinitions_PresetsEntry {
key: string;
value: EquipmentPreset | undefined;
}
export interface EquipmentDefinitions_EquipmentsEntry {
key: number;
value: Equipment | undefined;
}
export interface Equipment {
name: I18nString | undefined;
description: I18nString | undefined;
}
export interface EquipmentPreset {
slots: EquipmentSlot[];
}
export interface EquipmentSlot {
left: number;
right: number;
}
function createBaseEquipmentDefinitions(): EquipmentDefinitions {
return { presets: {}, equipments: {} };
}
export const EquipmentDefinitions: MessageFns<EquipmentDefinitions> = {
encode(message: EquipmentDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
Object.entries(message.presets).forEach(([key, value]) => {
EquipmentDefinitions_PresetsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join();
});
Object.entries(message.equipments).forEach(([key, value]) => {
EquipmentDefinitions_EquipmentsEntry.encode({ key: key as any, value }, writer.uint32(18).fork()).join();
});
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): EquipmentDefinitions {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseEquipmentDefinitions();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
const entry1 = EquipmentDefinitions_PresetsEntry.decode(reader, reader.uint32());
if (entry1.value !== undefined) {
message.presets[entry1.key] = entry1.value;
}
continue;
}
case 2: {
if (tag !== 18) {
break;
}
const entry2 = EquipmentDefinitions_EquipmentsEntry.decode(reader, reader.uint32());
if (entry2.value !== undefined) {
message.equipments[entry2.key] = entry2.value;
}
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): EquipmentDefinitions {
return {
presets: isObject(object.presets)
? Object.entries(object.presets).reduce<{ [key: string]: EquipmentPreset }>((acc, [key, value]) => {
acc[key] = EquipmentPreset.fromJSON(value);
return acc;
}, {})
: {},
equipments: isObject(object.equipments)
? Object.entries(object.equipments).reduce<{ [key: number]: Equipment }>((acc, [key, value]) => {
acc[globalThis.Number(key)] = Equipment.fromJSON(value);
return acc;
}, {})
: {},
};
},
toJSON(message: EquipmentDefinitions): unknown {
const obj: any = {};
if (message.presets) {
const entries = Object.entries(message.presets);
if (entries.length > 0) {
obj.presets = {};
entries.forEach(([k, v]) => {
obj.presets[k] = EquipmentPreset.toJSON(v);
});
}
}
if (message.equipments) {
const entries = Object.entries(message.equipments);
if (entries.length > 0) {
obj.equipments = {};
entries.forEach(([k, v]) => {
obj.equipments[k] = Equipment.toJSON(v);
});
}
}
return obj;
},
create<I extends Exact<DeepPartial<EquipmentDefinitions>, I>>(base?: I): EquipmentDefinitions {
return EquipmentDefinitions.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<EquipmentDefinitions>, I>>(object: I): EquipmentDefinitions {
const message = createBaseEquipmentDefinitions();
message.presets = Object.entries(object.presets ?? {}).reduce<{ [key: string]: EquipmentPreset }>(
(acc, [key, value]) => {
if (value !== undefined) {
acc[key] = EquipmentPreset.fromPartial(value);
}
return acc;
},
{},
);
message.equipments = Object.entries(object.equipments ?? {}).reduce<{ [key: number]: Equipment }>(
(acc, [key, value]) => {
if (value !== undefined) {
acc[globalThis.Number(key)] = Equipment.fromPartial(value);
}
return acc;
},
{},
);
return message;
},
};
function createBaseEquipmentDefinitions_PresetsEntry(): EquipmentDefinitions_PresetsEntry {
return { key: "", value: undefined };
}
export const EquipmentDefinitions_PresetsEntry: MessageFns<EquipmentDefinitions_PresetsEntry> = {
encode(message: EquipmentDefinitions_PresetsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== "") {
writer.uint32(10).string(message.key);
}
if (message.value !== undefined) {
EquipmentPreset.encode(message.value, writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): EquipmentDefinitions_PresetsEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseEquipmentDefinitions_PresetsEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.key = reader.string();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.value = EquipmentPreset.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): EquipmentDefinitions_PresetsEntry {
return {
key: isSet(object.key) ? globalThis.String(object.key) : "",
value: isSet(object.value) ? EquipmentPreset.fromJSON(object.value) : undefined,
};
},
toJSON(message: EquipmentDefinitions_PresetsEntry): unknown {
const obj: any = {};
if (message.key !== "") {
obj.key = message.key;
}
if (message.value !== undefined) {
obj.value = EquipmentPreset.toJSON(message.value);
}
return obj;
},
create<I extends Exact<DeepPartial<EquipmentDefinitions_PresetsEntry>, I>>(
base?: I,
): EquipmentDefinitions_PresetsEntry {
return EquipmentDefinitions_PresetsEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<EquipmentDefinitions_PresetsEntry>, I>>(
object: I,
): EquipmentDefinitions_PresetsEntry {
const message = createBaseEquipmentDefinitions_PresetsEntry();
message.key = object.key ?? "";
message.value = (object.value !== undefined && object.value !== null)
? EquipmentPreset.fromPartial(object.value)
: undefined;
return message;
},
};
function createBaseEquipmentDefinitions_EquipmentsEntry(): EquipmentDefinitions_EquipmentsEntry {
return { key: 0, value: undefined };
}
export const EquipmentDefinitions_EquipmentsEntry: MessageFns<EquipmentDefinitions_EquipmentsEntry> = {
encode(message: EquipmentDefinitions_EquipmentsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== 0) {
writer.uint32(8).uint32(message.key);
}
if (message.value !== undefined) {
Equipment.encode(message.value, writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): EquipmentDefinitions_EquipmentsEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseEquipmentDefinitions_EquipmentsEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.key = reader.uint32();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.value = Equipment.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): EquipmentDefinitions_EquipmentsEntry {
return {
key: isSet(object.key) ? globalThis.Number(object.key) : 0,
value: isSet(object.value) ? Equipment.fromJSON(object.value) : undefined,
};
},
toJSON(message: EquipmentDefinitions_EquipmentsEntry): unknown {
const obj: any = {};
if (message.key !== 0) {
obj.key = Math.round(message.key);
}
if (message.value !== undefined) {
obj.value = Equipment.toJSON(message.value);
}
return obj;
},
create<I extends Exact<DeepPartial<EquipmentDefinitions_EquipmentsEntry>, I>>(
base?: I,
): EquipmentDefinitions_EquipmentsEntry {
return EquipmentDefinitions_EquipmentsEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<EquipmentDefinitions_EquipmentsEntry>, I>>(
object: I,
): EquipmentDefinitions_EquipmentsEntry {
const message = createBaseEquipmentDefinitions_EquipmentsEntry();
message.key = object.key ?? 0;
message.value = (object.value !== undefined && object.value !== null)
? Equipment.fromPartial(object.value)
: undefined;
return message;
},
};
function createBaseEquipment(): Equipment {
return { name: undefined, description: undefined };
}
export const Equipment: MessageFns<Equipment> = {
encode(message: Equipment, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.name !== undefined) {
I18nString.encode(message.name, writer.uint32(10).fork()).join();
}
if (message.description !== undefined) {
I18nString.encode(message.description, writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): Equipment {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseEquipment();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.name = I18nString.decode(reader, reader.uint32());
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.description = I18nString.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): Equipment {
return {
name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined,
description: isSet(object.description) ? I18nString.fromJSON(object.description) : undefined,
};
},
toJSON(message: Equipment): unknown {
const obj: any = {};
if (message.name !== undefined) {
obj.name = I18nString.toJSON(message.name);
}
if (message.description !== undefined) {
obj.description = I18nString.toJSON(message.description);
}
return obj;
},
create<I extends Exact<DeepPartial<Equipment>, I>>(base?: I): Equipment {
return Equipment.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<Equipment>, I>>(object: I): Equipment {
const message = createBaseEquipment();
message.name = (object.name !== undefined && object.name !== null)
? I18nString.fromPartial(object.name)
: undefined;
message.description = (object.description !== undefined && object.description !== null)
? I18nString.fromPartial(object.description)
: undefined;
return message;
},
};
function createBaseEquipmentPreset(): EquipmentPreset {
return { slots: [] };
}
export const EquipmentPreset: MessageFns<EquipmentPreset> = {
encode(message: EquipmentPreset, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.slots) {
EquipmentSlot.encode(v!, writer.uint32(10).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): EquipmentPreset {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseEquipmentPreset();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.slots.push(EquipmentSlot.decode(reader, reader.uint32()));
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): EquipmentPreset {
return {
slots: globalThis.Array.isArray(object?.slots) ? object.slots.map((e: any) => EquipmentSlot.fromJSON(e)) : [],
};
},
toJSON(message: EquipmentPreset): unknown {
const obj: any = {};
if (message.slots?.length) {
obj.slots = message.slots.map((e) => EquipmentSlot.toJSON(e));
}
return obj;
},
create<I extends Exact<DeepPartial<EquipmentPreset>, I>>(base?: I): EquipmentPreset {
return EquipmentPreset.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<EquipmentPreset>, I>>(object: I): EquipmentPreset {
const message = createBaseEquipmentPreset();
message.slots = object.slots?.map((e) => EquipmentSlot.fromPartial(e)) || [];
return message;
},
};
function createBaseEquipmentSlot(): EquipmentSlot {
return { left: 0, right: 0 };
}
export const EquipmentSlot: MessageFns<EquipmentSlot> = {
encode(message: EquipmentSlot, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.left !== 0) {
writer.uint32(8).uint32(message.left);
}
if (message.right !== 0) {
writer.uint32(16).uint32(message.right);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): EquipmentSlot {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseEquipmentSlot();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.left = reader.uint32();
continue;
}
case 2: {
if (tag !== 16) {
break;
}
message.right = reader.uint32();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): EquipmentSlot {
return {
left: isSet(object.left) ? globalThis.Number(object.left) : 0,
right: isSet(object.right) ? globalThis.Number(object.right) : 0,
};
},
toJSON(message: EquipmentSlot): unknown {
const obj: any = {};
if (message.left !== 0) {
obj.left = Math.round(message.left);
}
if (message.right !== 0) {
obj.right = Math.round(message.right);
}
return obj;
},
create<I extends Exact<DeepPartial<EquipmentSlot>, I>>(base?: I): EquipmentSlot {
return EquipmentSlot.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<EquipmentSlot>, I>>(object: I): EquipmentSlot {
const message = createBaseEquipmentSlot();
message.left = object.left ?? 0;
message.right = object.right ?? 0;
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial<T["value"]> }
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
function isObject(value: any): boolean {
return typeof value === "object" && value !== null;
}
function isSet(value: any): boolean {
return value !== null && value !== undefined;
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T;
fromJSON(object: any): T;
toJSON(message: T): unknown;
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
}
+15
View File
@@ -0,0 +1,15 @@
syntax = "proto2";
package blitzkit;
import "i18n.proto";
message Gallery {
repeated Avatar avatars = 1;
}
message Avatar {
required string id = 1;
required I18nString name = 2;
required string extension = 3;
}
+201
View File
@@ -0,0 +1,201 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.7
// protoc v3.19.6
// source: gallery.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import { I18nString } from "./i18n";
export const protobufPackage = "blitzkit";
export interface Gallery {
avatars: Avatar[];
}
export interface Avatar {
id: string;
name: I18nString | undefined;
extension: string;
}
function createBaseGallery(): Gallery {
return { avatars: [] };
}
export const Gallery: MessageFns<Gallery> = {
encode(message: Gallery, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.avatars) {
Avatar.encode(v!, writer.uint32(10).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): Gallery {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseGallery();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.avatars.push(Avatar.decode(reader, reader.uint32()));
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): Gallery {
return {
avatars: globalThis.Array.isArray(object?.avatars) ? object.avatars.map((e: any) => Avatar.fromJSON(e)) : [],
};
},
toJSON(message: Gallery): unknown {
const obj: any = {};
if (message.avatars?.length) {
obj.avatars = message.avatars.map((e) => Avatar.toJSON(e));
}
return obj;
},
create<I extends Exact<DeepPartial<Gallery>, I>>(base?: I): Gallery {
return Gallery.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<Gallery>, I>>(object: I): Gallery {
const message = createBaseGallery();
message.avatars = object.avatars?.map((e) => Avatar.fromPartial(e)) || [];
return message;
},
};
function createBaseAvatar(): Avatar {
return { id: "", name: undefined, extension: "" };
}
export const Avatar: MessageFns<Avatar> = {
encode(message: Avatar, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.id !== "") {
writer.uint32(10).string(message.id);
}
if (message.name !== undefined) {
I18nString.encode(message.name, writer.uint32(18).fork()).join();
}
if (message.extension !== "") {
writer.uint32(26).string(message.extension);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): Avatar {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseAvatar();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.id = reader.string();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.name = I18nString.decode(reader, reader.uint32());
continue;
}
case 3: {
if (tag !== 26) {
break;
}
message.extension = reader.string();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): Avatar {
return {
id: isSet(object.id) ? globalThis.String(object.id) : "",
name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined,
extension: isSet(object.extension) ? globalThis.String(object.extension) : "",
};
},
toJSON(message: Avatar): unknown {
const obj: any = {};
if (message.id !== "") {
obj.id = message.id;
}
if (message.name !== undefined) {
obj.name = I18nString.toJSON(message.name);
}
if (message.extension !== "") {
obj.extension = message.extension;
}
return obj;
},
create<I extends Exact<DeepPartial<Avatar>, I>>(base?: I): Avatar {
return Avatar.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<Avatar>, I>>(object: I): Avatar {
const message = createBaseAvatar();
message.id = object.id ?? "";
message.name = (object.name !== undefined && object.name !== null)
? I18nString.fromPartial(object.name)
: undefined;
message.extension = object.extension ?? "";
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial<T["value"]> }
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
function isSet(value: any): boolean {
return value !== null && value !== undefined;
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T;
fromJSON(object: any): T;
toJSON(message: T): unknown;
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
}
@@ -1,18 +1,18 @@
syntax = "proto3";
syntax = "proto2";
package blitzkit;
import "i18n.proto";
message GameDefinitions {
string version = 1;
required string version = 1;
repeated string nations = 2;
map<string, GameMode> gameModes = 3;
map<uint32, GameModeRole> roles = 4;
}
message GameMode {
I18nString name = 1;
required I18nString name = 1;
}
message GameModeRole {
@@ -0,0 +1,534 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.7
// protoc v3.19.6
// source: game_definitions.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import { I18nString } from "./i18n";
export const protobufPackage = "blitzkit";
export interface GameDefinitions {
version: string;
nations: string[];
gameModes: { [key: string]: GameMode };
roles: { [key: number]: GameModeRole };
}
export interface GameDefinitions_GameModesEntry {
key: string;
value: GameMode | undefined;
}
export interface GameDefinitions_RolesEntry {
key: number;
value: GameModeRole | undefined;
}
export interface GameMode {
name: I18nString | undefined;
}
export interface GameModeRole {
provisions: number[];
consumables: number[];
}
function createBaseGameDefinitions(): GameDefinitions {
return { version: "", nations: [], gameModes: {}, roles: {} };
}
export const GameDefinitions: MessageFns<GameDefinitions> = {
encode(message: GameDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.version !== "") {
writer.uint32(10).string(message.version);
}
for (const v of message.nations) {
writer.uint32(18).string(v!);
}
Object.entries(message.gameModes).forEach(([key, value]) => {
GameDefinitions_GameModesEntry.encode({ key: key as any, value }, writer.uint32(26).fork()).join();
});
Object.entries(message.roles).forEach(([key, value]) => {
GameDefinitions_RolesEntry.encode({ key: key as any, value }, writer.uint32(34).fork()).join();
});
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): GameDefinitions {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseGameDefinitions();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.version = reader.string();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.nations.push(reader.string());
continue;
}
case 3: {
if (tag !== 26) {
break;
}
const entry3 = GameDefinitions_GameModesEntry.decode(reader, reader.uint32());
if (entry3.value !== undefined) {
message.gameModes[entry3.key] = entry3.value;
}
continue;
}
case 4: {
if (tag !== 34) {
break;
}
const entry4 = GameDefinitions_RolesEntry.decode(reader, reader.uint32());
if (entry4.value !== undefined) {
message.roles[entry4.key] = entry4.value;
}
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): GameDefinitions {
return {
version: isSet(object.version) ? globalThis.String(object.version) : "",
nations: globalThis.Array.isArray(object?.nations) ? object.nations.map((e: any) => globalThis.String(e)) : [],
gameModes: isObject(object.gameModes)
? Object.entries(object.gameModes).reduce<{ [key: string]: GameMode }>((acc, [key, value]) => {
acc[key] = GameMode.fromJSON(value);
return acc;
}, {})
: {},
roles: isObject(object.roles)
? Object.entries(object.roles).reduce<{ [key: number]: GameModeRole }>((acc, [key, value]) => {
acc[globalThis.Number(key)] = GameModeRole.fromJSON(value);
return acc;
}, {})
: {},
};
},
toJSON(message: GameDefinitions): unknown {
const obj: any = {};
if (message.version !== "") {
obj.version = message.version;
}
if (message.nations?.length) {
obj.nations = message.nations;
}
if (message.gameModes) {
const entries = Object.entries(message.gameModes);
if (entries.length > 0) {
obj.gameModes = {};
entries.forEach(([k, v]) => {
obj.gameModes[k] = GameMode.toJSON(v);
});
}
}
if (message.roles) {
const entries = Object.entries(message.roles);
if (entries.length > 0) {
obj.roles = {};
entries.forEach(([k, v]) => {
obj.roles[k] = GameModeRole.toJSON(v);
});
}
}
return obj;
},
create<I extends Exact<DeepPartial<GameDefinitions>, I>>(base?: I): GameDefinitions {
return GameDefinitions.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<GameDefinitions>, I>>(object: I): GameDefinitions {
const message = createBaseGameDefinitions();
message.version = object.version ?? "";
message.nations = object.nations?.map((e) => e) || [];
message.gameModes = Object.entries(object.gameModes ?? {}).reduce<{ [key: string]: GameMode }>(
(acc, [key, value]) => {
if (value !== undefined) {
acc[key] = GameMode.fromPartial(value);
}
return acc;
},
{},
);
message.roles = Object.entries(object.roles ?? {}).reduce<{ [key: number]: GameModeRole }>((acc, [key, value]) => {
if (value !== undefined) {
acc[globalThis.Number(key)] = GameModeRole.fromPartial(value);
}
return acc;
}, {});
return message;
},
};
function createBaseGameDefinitions_GameModesEntry(): GameDefinitions_GameModesEntry {
return { key: "", value: undefined };
}
export const GameDefinitions_GameModesEntry: MessageFns<GameDefinitions_GameModesEntry> = {
encode(message: GameDefinitions_GameModesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== "") {
writer.uint32(10).string(message.key);
}
if (message.value !== undefined) {
GameMode.encode(message.value, writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): GameDefinitions_GameModesEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseGameDefinitions_GameModesEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.key = reader.string();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.value = GameMode.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): GameDefinitions_GameModesEntry {
return {
key: isSet(object.key) ? globalThis.String(object.key) : "",
value: isSet(object.value) ? GameMode.fromJSON(object.value) : undefined,
};
},
toJSON(message: GameDefinitions_GameModesEntry): unknown {
const obj: any = {};
if (message.key !== "") {
obj.key = message.key;
}
if (message.value !== undefined) {
obj.value = GameMode.toJSON(message.value);
}
return obj;
},
create<I extends Exact<DeepPartial<GameDefinitions_GameModesEntry>, I>>(base?: I): GameDefinitions_GameModesEntry {
return GameDefinitions_GameModesEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<GameDefinitions_GameModesEntry>, I>>(
object: I,
): GameDefinitions_GameModesEntry {
const message = createBaseGameDefinitions_GameModesEntry();
message.key = object.key ?? "";
message.value = (object.value !== undefined && object.value !== null)
? GameMode.fromPartial(object.value)
: undefined;
return message;
},
};
function createBaseGameDefinitions_RolesEntry(): GameDefinitions_RolesEntry {
return { key: 0, value: undefined };
}
export const GameDefinitions_RolesEntry: MessageFns<GameDefinitions_RolesEntry> = {
encode(message: GameDefinitions_RolesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== 0) {
writer.uint32(8).uint32(message.key);
}
if (message.value !== undefined) {
GameModeRole.encode(message.value, writer.uint32(18).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): GameDefinitions_RolesEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseGameDefinitions_RolesEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 8) {
break;
}
message.key = reader.uint32();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.value = GameModeRole.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): GameDefinitions_RolesEntry {
return {
key: isSet(object.key) ? globalThis.Number(object.key) : 0,
value: isSet(object.value) ? GameModeRole.fromJSON(object.value) : undefined,
};
},
toJSON(message: GameDefinitions_RolesEntry): unknown {
const obj: any = {};
if (message.key !== 0) {
obj.key = Math.round(message.key);
}
if (message.value !== undefined) {
obj.value = GameModeRole.toJSON(message.value);
}
return obj;
},
create<I extends Exact<DeepPartial<GameDefinitions_RolesEntry>, I>>(base?: I): GameDefinitions_RolesEntry {
return GameDefinitions_RolesEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<GameDefinitions_RolesEntry>, I>>(object: I): GameDefinitions_RolesEntry {
const message = createBaseGameDefinitions_RolesEntry();
message.key = object.key ?? 0;
message.value = (object.value !== undefined && object.value !== null)
? GameModeRole.fromPartial(object.value)
: undefined;
return message;
},
};
function createBaseGameMode(): GameMode {
return { name: undefined };
}
export const GameMode: MessageFns<GameMode> = {
encode(message: GameMode, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.name !== undefined) {
I18nString.encode(message.name, writer.uint32(10).fork()).join();
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): GameMode {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseGameMode();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.name = I18nString.decode(reader, reader.uint32());
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): GameMode {
return { name: isSet(object.name) ? I18nString.fromJSON(object.name) : undefined };
},
toJSON(message: GameMode): unknown {
const obj: any = {};
if (message.name !== undefined) {
obj.name = I18nString.toJSON(message.name);
}
return obj;
},
create<I extends Exact<DeepPartial<GameMode>, I>>(base?: I): GameMode {
return GameMode.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<GameMode>, I>>(object: I): GameMode {
const message = createBaseGameMode();
message.name = (object.name !== undefined && object.name !== null)
? I18nString.fromPartial(object.name)
: undefined;
return message;
},
};
function createBaseGameModeRole(): GameModeRole {
return { provisions: [], consumables: [] };
}
export const GameModeRole: MessageFns<GameModeRole> = {
encode(message: GameModeRole, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.provisions) {
writer.uint32(8).uint32(v!);
}
for (const v of message.consumables) {
writer.uint32(16).uint32(v!);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): GameModeRole {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseGameModeRole();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag === 8) {
message.provisions.push(reader.uint32());
continue;
}
if (tag === 10) {
const end2 = reader.uint32() + reader.pos;
while (reader.pos < end2) {
message.provisions.push(reader.uint32());
}
continue;
}
break;
}
case 2: {
if (tag === 16) {
message.consumables.push(reader.uint32());
continue;
}
if (tag === 18) {
const end2 = reader.uint32() + reader.pos;
while (reader.pos < end2) {
message.consumables.push(reader.uint32());
}
continue;
}
break;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): GameModeRole {
return {
provisions: globalThis.Array.isArray(object?.provisions)
? object.provisions.map((e: any) => globalThis.Number(e))
: [],
consumables: globalThis.Array.isArray(object?.consumables)
? object.consumables.map((e: any) => globalThis.Number(e))
: [],
};
},
toJSON(message: GameModeRole): unknown {
const obj: any = {};
if (message.provisions?.length) {
obj.provisions = message.provisions.map((e) => Math.round(e));
}
if (message.consumables?.length) {
obj.consumables = message.consumables.map((e) => Math.round(e));
}
return obj;
},
create<I extends Exact<DeepPartial<GameModeRole>, I>>(base?: I): GameModeRole {
return GameModeRole.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<GameModeRole>, I>>(object: I): GameModeRole {
const message = createBaseGameModeRole();
message.provisions = object.provisions?.map((e) => e) || [];
message.consumables = object.consumables?.map((e) => e) || [];
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial<T["value"]> }
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
function isObject(value: any): boolean {
return typeof value === "object" && value !== null;
}
function isSet(value: any): boolean {
return value !== null && value !== undefined;
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T;
fromJSON(object: any): T;
toJSON(message: T): unknown;
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
}
@@ -1,4 +1,4 @@
syntax = "proto3";
syntax = "proto2";
package blitzkit;
+204
View File
@@ -0,0 +1,204 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
// versions:
// protoc-gen-ts_proto v2.7.7
// protoc v3.19.6
// source: i18n.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
export const protobufPackage = "blitzkit";
export interface I18nString {
locales: { [key: string]: string };
}
export interface I18nString_LocalesEntry {
key: string;
value: string;
}
function createBaseI18nString(): I18nString {
return { locales: {} };
}
export const I18nString: MessageFns<I18nString> = {
encode(message: I18nString, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
Object.entries(message.locales).forEach(([key, value]) => {
I18nString_LocalesEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join();
});
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): I18nString {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseI18nString();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
const entry1 = I18nString_LocalesEntry.decode(reader, reader.uint32());
if (entry1.value !== undefined) {
message.locales[entry1.key] = entry1.value;
}
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): I18nString {
return {
locales: isObject(object.locales)
? Object.entries(object.locales).reduce<{ [key: string]: string }>((acc, [key, value]) => {
acc[key] = String(value);
return acc;
}, {})
: {},
};
},
toJSON(message: I18nString): unknown {
const obj: any = {};
if (message.locales) {
const entries = Object.entries(message.locales);
if (entries.length > 0) {
obj.locales = {};
entries.forEach(([k, v]) => {
obj.locales[k] = v;
});
}
}
return obj;
},
create<I extends Exact<DeepPartial<I18nString>, I>>(base?: I): I18nString {
return I18nString.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<I18nString>, I>>(object: I): I18nString {
const message = createBaseI18nString();
message.locales = Object.entries(object.locales ?? {}).reduce<{ [key: string]: string }>((acc, [key, value]) => {
if (value !== undefined) {
acc[key] = globalThis.String(value);
}
return acc;
}, {});
return message;
},
};
function createBaseI18nString_LocalesEntry(): I18nString_LocalesEntry {
return { key: "", value: "" };
}
export const I18nString_LocalesEntry: MessageFns<I18nString_LocalesEntry> = {
encode(message: I18nString_LocalesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== "") {
writer.uint32(10).string(message.key);
}
if (message.value !== "") {
writer.uint32(18).string(message.value);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): I18nString_LocalesEntry {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
const end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseI18nString_LocalesEntry();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1: {
if (tag !== 10) {
break;
}
message.key = reader.string();
continue;
}
case 2: {
if (tag !== 18) {
break;
}
message.value = reader.string();
continue;
}
}
if ((tag & 7) === 4 || tag === 0) {
break;
}
reader.skip(tag & 7);
}
return message;
},
fromJSON(object: any): I18nString_LocalesEntry {
return {
key: isSet(object.key) ? globalThis.String(object.key) : "",
value: isSet(object.value) ? globalThis.String(object.value) : "",
};
},
toJSON(message: I18nString_LocalesEntry): unknown {
const obj: any = {};
if (message.key !== "") {
obj.key = message.key;
}
if (message.value !== "") {
obj.value = message.value;
}
return obj;
},
create<I extends Exact<DeepPartial<I18nString_LocalesEntry>, I>>(base?: I): I18nString_LocalesEntry {
return I18nString_LocalesEntry.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<I18nString_LocalesEntry>, I>>(object: I): I18nString_LocalesEntry {
const message = createBaseI18nString_LocalesEntry();
message.key = object.key ?? "";
message.value = object.value ?? "";
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
: T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial<T["value"]> }
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
function isObject(value: any): boolean {
return typeof value === "object" && value !== null;
}
function isSet(value: any): boolean {
return value !== null && value !== undefined;
}
export interface MessageFns<T> {
encode(message: T, writer?: BinaryWriter): BinaryWriter;
decode(input: BinaryReader | Uint8Array, length?: number): T;
fromJSON(object: any): T;
toJSON(message: T): unknown;
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
}
+16
View File
@@ -0,0 +1,16 @@
// @ts-nocheck
export * from "./average_definitions.ts";
export * from "./camouflage_definitions.ts";
export * from "./consumable_definitions.ts";
export * from "./equipment_definitions.ts";
export * from "./gallery.ts";
export * from "./game_definitions.ts";
export * from "./i18n.ts";
export * from "./map_definitions.ts";
export * from "./model_definitions.ts";
export * from "./popular_tanks.ts";
export * from "./provision_definitions.ts";
export * from "./rating_leaderboard.ts";
export * from "./reviews.ts";
export * from "./skill_definitions.ts";
export * from "./tank_definitions.ts";
@@ -1,4 +1,4 @@
syntax = "proto3";
syntax = "proto2";
package blitzkit;
@@ -9,6 +9,6 @@ message MapDefinitions {
}
message MapDefinition {
uint32 id = 1;
I18nString name = 2;
required uint32 id = 1;
required I18nString name = 2;
}
Loaded 100 of 495 files, more files were not shown because too many files have changed in this diff. Show more