diff --git a/.github/workflows/cd-assets.yml b/.github/workflows/cd-assets.yml index 4842f0a5d..b54481736 100644 --- a/.github/workflows/cd-assets.yml +++ b/.github/workflows/cd-assets.yml @@ -27,13 +27,27 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event.inputs.cdn_branch }} cancel-in-progress: true +env: + DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} + DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} + VIDEOS_SHEET: ${{ secrets.VIDEOS_SHEET }} + GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} + WOTB_GLOSSARY: ${{ secrets.WOTB_GLOSSARY }} + WOTB_DLC_CDN: ${{ secrets.WOTB_DLC_CDN }} + PUBLIC_WARGAMING_APPLICATION_ID: ${{ secrets.PUBLIC_WARGAMING_APPLICATION_ID }} + PUBLIC_ASSET_REPO: ${{ secrets.PUBLIC_ASSET_REPO }} + PUBLIC_ASSET_BRANCH: ${{ github.event.inputs.cdn_branch || secrets.PUBLIC_ASSET_BRANCH }} + jobs: download_client: name: Download client runs-on: ubuntu-latest steps: - - name: Maximize build space + - name: (ZIP) Maximize build space + if: github.event.inputs.zip_url != '' uses: easimon/maximize-build-space@master with: root-reserve-mb: 512 @@ -55,23 +69,17 @@ jobs: - name: (Steam) Setup DepotDownloader if: github.event.inputs.zip_url == '' - run: bun scripts/setupDepotDownloader.ts + run: bun run setup:depotdownloader - name: (Steam) Download client if: github.event.inputs.zip_url == '' run: | chmod +x ./temp/depotDownloader/DepotDownloader - ./temp/depotDownloader/DepotDownloader -os windows -app 444200 -username ${{ secrets.DEPOT_DOWNLOADER_USERNAME }} -password "${{ secrets.DEPOT_DOWNLOADER_PASSWORD }}" + ./temp/depotDownloader/DepotDownloader -q -os windows -app 444200 -username ${{ secrets.DEPOT_DOWNLOADER_USERNAME }} -password "${{ secrets.DEPOT_DOWNLOADER_PASSWORD }}" - name: (Steam) Apply patches if: github.event.inputs.zip_url == '' - env: - DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} - GH_TOKEN: ${{ secrets.GH_TOKEN }} - DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} - DATABASE_URL: ${{ secrets.DATABASE_URL }} - WOTB_DLC_CDN: ${{ secrets.WOTB_DLC_CDN }} - run: bun scripts/applyPatches.ts --depot + run: bun setup:patches --depot - name: (ZIP) Download client if: github.event.inputs.zip_url != '' @@ -112,13 +120,4 @@ jobs: path: depots - name: Build assets - env: - DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} - GH_TOKEN: ${{ secrets.GH_TOKEN }} - DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} - DATABASE_URL: ${{ secrets.DATABASE_URL }} - VIDEOS_SHEET: ${{ secrets.VIDEOS_SHEET }} - GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} - NEXT_PUBLIC_ASSET_BRANCH: ${{ github.event.inputs.cdn_branch }} - WOTB_GLOSSARY: ${{ secrets.WOTB_GLOSSARY }} - run: bun build:assets --all-targets --depot --production + run: bun run build:assets --all-targets --depot --production diff --git a/.github/workflows/cd-averages.yml b/.github/workflows/cd-averages.yml index 855dd3229..33ee4e9c1 100644 --- a/.github/workflows/cd-averages.yml +++ b/.github/workflows/cd-averages.yml @@ -9,6 +9,10 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +env: + PUBLIC_ASSET_REPO: ${{ secrets.PUBLIC_ASSET_REPO }} + PUBLIC_WARGAMING_APPLICATION_ID: ${{ secrets.PUBLIC_WARGAMING_APPLICATION_ID }} + jobs: build: runs-on: ubuntu-latest @@ -22,10 +26,11 @@ jobs: - name: Build averages env: + PUBLIC_ASSET_BRANCH: main DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} GH_TOKEN: ${{ secrets.GH_TOKEN }} DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} DATABASE_URL: ${{ secrets.DATABASE_URL }} VIDEOS_SHEET: ${{ secrets.VIDEOS_SHEET }} GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} - run: bun scripts/averages.ts --production + run: bun run build:averages --production diff --git a/.github/workflows/cd-docs.yml b/.github/workflows/cd-docs.yml deleted file mode 100644 index 68f9e23e6..000000000 --- a/.github/workflows/cd-docs.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: CD Docs - -on: - push: - branches: main - -jobs: - build: - name: Build - runs-on: ubuntu-latest - permissions: - pages: write - id-token: write - - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - - steps: - - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v1 - - - name: Install dependencies - run: bun install - - - name: Build docs - run: bun build:docs - - - uses: actions/configure-pages@v2 - - uses: actions/upload-pages-artifact@v1 - with: - path: dist/docs - - - id: deployment - uses: actions/deploy-pages@v1 - - uses: actions/upload-artifact@v4 - with: - name: dist - path: docs/.vitepress/dist diff --git a/.github/workflows/cd-rating-asia.yml b/.github/workflows/cd-rating-asia.yml index 6036b64aa..ece687b9c 100644 --- a/.github/workflows/cd-rating-asia.yml +++ b/.github/workflows/cd-rating-asia.yml @@ -17,6 +17,7 @@ jobs: - name: Generate leaderboard env: + PUBLIC_ASSET_BRANCH: main DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} GH_TOKEN: ${{ secrets.GH_TOKEN }} DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} diff --git a/.github/workflows/cd-rating-eu.yml b/.github/workflows/cd-rating-eu.yml index f54d68e6e..b719dbcdc 100644 --- a/.github/workflows/cd-rating-eu.yml +++ b/.github/workflows/cd-rating-eu.yml @@ -17,6 +17,7 @@ jobs: - name: Generate leaderboard env: + PUBLIC_ASSET_BRANCH: main DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} GH_TOKEN: ${{ secrets.GH_TOKEN }} DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} diff --git a/.github/workflows/cd-rating-latest.yml b/.github/workflows/cd-rating-latest.yml index b09d9bd1f..802a4ee82 100644 --- a/.github/workflows/cd-rating-latest.yml +++ b/.github/workflows/cd-rating-latest.yml @@ -17,6 +17,7 @@ jobs: - name: Generate all leaderboards env: + PUBLIC_ASSET_BRANCH: main DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} GH_TOKEN: ${{ secrets.GH_TOKEN }} DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} diff --git a/.github/workflows/cd-rating-na.yml b/.github/workflows/cd-rating-na.yml index 352d128e6..b9b2e4795 100644 --- a/.github/workflows/cd-rating-na.yml +++ b/.github/workflows/cd-rating-na.yml @@ -17,6 +17,7 @@ jobs: - name: Generate leaderboard env: + PUBLIC_ASSET_BRANCH: main DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} GH_TOKEN: ${{ secrets.GH_TOKEN }} DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} diff --git a/.github/workflows/cd-website.yml b/.github/workflows/cd-website.yml new file mode 100644 index 000000000..5b9dcf48c --- /dev/null +++ b/.github/workflows/cd-website.yml @@ -0,0 +1,54 @@ +name: CD Website + +on: + push: + branches: main + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + PUBLIC_WARGAMING_APPLICATION_ID: ${{ secrets.PUBLIC_WARGAMING_APPLICATION_ID }} + PUBLIC_ASSET_REPO: ${{ secrets.PUBLIC_ASSET_REPO }} + PUBLIC_ASSET_BRANCH: ${{ secrets.PUBLIC_ASSET_BRANCH }} + PUBLIC_PROMOTE_OPENTEST: ${{ secrets.PUBLIC_PROMOTE_OPENTEST }} + ALLOW_ROBOTS: ${{ secrets.ALLOW_ROBOTS }} + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v1 + - uses: actions/configure-pages@v5 + + - name: Install dependencies + run: bun install + + - name: Build website + run: bun run build:website + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: dist/website + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 6a7316df2..7cb0c5661 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ depots public/sitemap* /firebase.json target +# packages/core/src/protos/* +# !packages/core/src/protos/*.proto +/.vercel +/.astro diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..22a15055d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..d64220976 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 330c73a83..87682defe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,8 +11,8 @@ "apcr", "applypatches", "artefacts", + "astrojs", "atgm", - "Avearges", "AYUV", "battleresults", "bbox", @@ -28,7 +28,10 @@ "blitzkit", "blitzrinth", "blitzstars", + "cacheable", + "Callouts", "Camo", + "CCPAOPTOUT", "CDON", "classname", "cleandist", @@ -61,9 +64,11 @@ "DVPLCRC", "dvpm", "dxgi", + "echarts", "Everytime", "FASTNAME", "FOURCC", + "frameloop", "fsformat", "Fullscreen", "fullstats", @@ -101,9 +106,11 @@ "mmnow", "modeltransform", "MURICA", + "nanostores", "NEGATIVEX", "NEGATIVEY", "NEGATIVEZ", + "NITROPAY", "nivo", "nmatname", "noout", @@ -198,5 +205,6 @@ "deno.enable": false, "deno.unstable": false, "cSpell.enableFiletypes": ["glsl", "proto3"], - "typescript.tsdk": "node_modules\\typescript\\lib" + "typescript.tsdk": "node_modules\\typescript\\lib", + "liveServer.settings.multiRootWorkspaceName": "blitzkit" } diff --git a/bun.lockb b/bun.lockb index 90302990d..b56042612 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts deleted file mode 100644 index 902f7d8b3..000000000 --- a/docs/.vitepress/config.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { compareVersions } from 'compare-versions'; -import { readdirSync } from 'fs'; -import { parse } from 'path'; -import { defineConfig } from 'vitepress'; -import { getSidebar } from 'vitepress-plugin-auto-sidebar'; - -export default defineConfig({ - title: 'BlitzKit', - description: 'πŸŽ‰ All-in-one Discord bot for everything World of Tanks Blitz', - base: '/blitzkit/', - outDir: '../dist/docs', - - themeConfig: { - nav: [ - { text: 'Home', link: '/' }, - { text: 'Guide', link: '/guide/introduction' }, - ], - - sidebar: [ - ...getSidebar({ - collapsed: false, - contentDirs: ['guide', 'legal'], - contentRoot: '/docs/', - }), - - { - text: 'Changelogs', - items: readdirSync('./docs/changelogs') - .map((file) => parse(file).name) - .sort(compareVersions) - .map((name) => ({ text: name, link: `/changelogs/${name}.html` })), - }, - ], - - socialLinks: [ - { icon: 'github', link: 'https://github.com/tresabhi/blitzkit' }, - ], - }, -}); diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts deleted file mode 100644 index 107d0ae71..000000000 --- a/docs/.vitepress/theme/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -// https://vitepress.dev/guide/custom-theme -import { h } from 'vue'; -import Theme from 'vitepress/theme'; -import './style.css'; - -export default { - extends: Theme, - Layout: () => { - return h(Theme.Layout, null, { - // https://vitepress.dev/guide/extending-default-theme#layout-slots - }); - }, - enhanceApp({ app, router, siteData }) { - // ... - }, -}; diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css deleted file mode 100644 index 45d673a9e..000000000 --- a/docs/.vitepress/theme/style.css +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Customize default theme styling by overriding CSS variables: - * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css - */ - -/** - * Colors - * -------------------------------------------------------------------------- */ - -:root { - --vp-c-brand: #646cff; - --vp-c-brand-light: #747bff; - --vp-c-brand-lighter: #9499ff; - --vp-c-brand-lightest: #bcc0ff; - --vp-c-brand-dark: #535bf2; - --vp-c-brand-darker: #454ce1; - --vp-c-brand-dimm: rgba(100, 108, 255, 0.08); -} - -/** - * Component: Button - * -------------------------------------------------------------------------- */ - -:root { - --vp-button-brand-border: var(--vp-c-brand-light); - --vp-button-brand-text: var(--vp-c-white); - --vp-button-brand-bg: var(--vp-c-brand); - --vp-button-brand-hover-border: var(--vp-c-brand-light); - --vp-button-brand-hover-text: var(--vp-c-white); - --vp-button-brand-hover-bg: var(--vp-c-brand-light); - --vp-button-brand-active-border: var(--vp-c-brand-light); - --vp-button-brand-active-text: var(--vp-c-white); - --vp-button-brand-active-bg: var(--vp-button-brand-bg); -} - -/** - * Component: Home - * -------------------------------------------------------------------------- */ - -:root { - --vp-home-hero-name-color: transparent; - --vp-home-hero-name-background: -webkit-linear-gradient( - 120deg, - #bd34fe 30%, - #41d1ff - ); - - --vp-home-hero-image-background-image: linear-gradient( - -45deg, - #bd34fe 50%, - #47caff 50% - ); - --vp-home-hero-image-filter: blur(40px); -} - -@media (min-width: 640px) { - :root { - --vp-home-hero-image-filter: blur(56px); - } -} - -@media (min-width: 960px) { - :root { - --vp-home-hero-image-filter: blur(72px); - } -} - -/** - * Component: Custom Block - * -------------------------------------------------------------------------- */ - -:root { - --vp-custom-block-tip-border: var(--vp-c-brand); - --vp-custom-block-tip-text: var(--vp-c-brand-darker); - --vp-custom-block-tip-bg: var(--vp-c-brand-dimm); -} - -.dark { - --vp-custom-block-tip-border: var(--vp-c-brand); - --vp-custom-block-tip-text: var(--vp-c-brand-lightest); - --vp-custom-block-tip-bg: var(--vp-c-brand-dimm); -} - -/** - * Component: Algolia - * -------------------------------------------------------------------------- */ - -.DocSearch { - --docsearch-primary-color: var(--vp-c-brand) !important; -} diff --git a/docs/changelogs/1.22.5.md b/docs/changelogs/1.22.5.md new file mode 100644 index 000000000..6b6f1789c --- /dev/null +++ b/docs/changelogs/1.22.5.md @@ -0,0 +1,27 @@ +# BlitzKit 1.22.5 + +This update only affects the website. + +## Features + +- CDN branch names are now outline +- Added an "unaffiliated to Wargaming" note to the footer +- Added a warning when viewing deprecated tanks +- Added partial support for dynamic armor + - The armor behaves properly in both dynamic and static armor modes but the visual 3D model doesn't update as of yet + - I'm working on it! +- Reworked the hero and meta information section of the tankopedia pages +- The grid is now more visible at steeper angles +- Re-introduced the "swap" tanks button in the tankopedia +- Added an opentest plug at homepage (you'll see what this is soonβ„’) + +## Fixes + +- Titles for a few pages are once again static +- Some links that opened in a new tab even though they were BlitzKit links now once again behave properly +- Missing page titles for documentation pages now work properly +- Toggling equipments through the tank canvas now update the render properly +- The sorting feature in tank search properly updates once again +- Dragging on the tracks to move them once again renders properly +- Correct tier I tanks are now shown in tech trees where deprecated tanks previously occupied the slot +- Reward icons once again display properly for archived rating seasons diff --git a/docs/changelogs/1.22.6.md b/docs/changelogs/1.22.6.md new file mode 100644 index 000000000..60982d232 --- /dev/null +++ b/docs/changelogs/1.22.6.md @@ -0,0 +1,21 @@ +# BlitzKit 1.22.6 + +This update only affects the website. + +## Features + +- Added a "cool projects" section at the bottom of the homepage + - If you have any other cool projects, feel free to let me know +- Added raw terrain coefficients along side the percentage values +- The account name is displayed instead of "Wargaming" when logged in +- Added an opentest button to the Tankopedia pages + +## Fixes + +- Protobuf files are now loaded more deterministically on both the server and client which resolves one of the issues that caused Error 500 +- Removed a server-side incompatible method which fixes the other issue that caused Error 500 +- Shot penetration is now displayed properly on mobile devices again +- Center aligned Wargaming login regions buttons on smaller screen sizes +- The dynamic armor button is no longer inverted +- BlitzKit opentest is not longer promoted on opentest +- The settings link in the navbar no longer open in a new tab diff --git a/docs/changelogs/1.23.0.md b/docs/changelogs/1.23.0.md new file mode 100644 index 000000000..0c05eb0d5 --- /dev/null +++ b/docs/changelogs/1.23.0.md @@ -0,0 +1,17 @@ +# BlitzKit 1.23.0 + +I rewrote the whole website for performance and lower bandwidth. This update does not affect the bot. If I did my job right, you should not notice a difference. + +## Changes + +- Removed documentation website, all the docs are now available within https://blitzkit.app/ +- Removed the Rating tool +- Removed the ability to log in with Patreon +- Removed all ads + +## Technical Changes + +- Converted BlitzKit to a monorepo +- The whole website is now static with no server-side rendering + - Gotta go fast ⚑ +- All structural data is now stored in protocol buffers diff --git a/docs/changelogs/1.23.1.md b/docs/changelogs/1.23.1.md new file mode 100644 index 000000000..bc6d7b521 --- /dev/null +++ b/docs/changelogs/1.23.1.md @@ -0,0 +1,12 @@ +# BlitzKit 1.23.1 + +Some critical fixes. This update only affects the website. + +## Features + +- Added a cool new interactive banner to the homepage + - This was primary done to reduce load times due to the high-definition image behind the "BlitzKit" heading + +## Fixes + +- The Session tool once again works diff --git a/docs/changelogs/1.3.0.md b/docs/changelogs/1.3.0.md index 209438f62..6161ab211 100644 --- a/docs/changelogs/1.3.0.md +++ b/docs/changelogs/1.3.0.md @@ -2,7 +2,7 @@ This release of Blitzkrieg focuses mainly on **performance**. Blitzkrieg now uses **Satori** and **resvg** under the hood to render images resulting in a solid **2x to 8x performance boost** depending on the situation. -This only applies to `/today` and /stats` as they're the only commands that render an image currently. +This only applies to `/today` and `/stats` as they're the only commands that render an image currently. We're working further on **performance optimizations**. Our goal is to deliver a message within **3 seconds or less**. We're close and we'll get there! diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 81b94c75d..000000000 --- a/docs/index.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -# https://vitepress.dev/reference/default-theme-home-page -layout: home - -hero: - name: 'BlitzKit' - text: Everything Blitz, right in Discord - tagline: All-in-one Discord bot for everything World of Tanks Blitz - image: - src: '/assets/images/hero.png' - alt: 'blitzkit' - actions: - - theme: brand - text: Add to Discord Server - link: /guide/invite - - theme: alt - text: Guide - link: /guide/introduction - -features: - - title: Clean and Efficient UI - icon: πŸš€ - details: BlitzKit is where concise meets efficient. Get the information you need in the way you want. - - title: Endless Possibilities - icon: πŸ›  - details: With endless ways to customize the output, it's guaranteed that you'll always get the information you need. - - title: Easy to Use - icon: πŸ’» - details: Leveraging Discord's, Blitz Stars', and Wargaming's powerful APIS, Blitzkit does all the hard work for you. ---- diff --git a/docs/legal/privacy-policy.md b/docs/legal/privacy-policy.md index 40eb44845..14616fac5 100644 --- a/docs/legal/privacy-policy.md +++ b/docs/legal/privacy-policy.md @@ -130,6 +130,23 @@ Your consent to this Privacy Policy followed by Your submission of such informat The Company will take all steps reasonably necessary to ensure that Your data is treated securely and in accordance with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or a country unless there are adequate controls in place including the security of Your data and other personal information. +### California Consumer Privacy Act (CCPA) + +If you are a California resident, you have specific rights regarding your personal information under the California Consumer Privacy Act (CCPA). This section describes your CCPA rights and explains how to exercise those rights. + +#### Rights under CCPA + +Under CCPA, California residents have the following rights: + +1. Right to Know: You have the right to request that we disclose certain information to you about our collection and use of your personal information over the past 12 months. +2. Right to Delete: You have the right to request that we delete any of your personal information that we collected from you and retained, subject to certain exceptions. +3. Right to Opt-Out of Sale: You have the right to opt-out of the sale of your personal information. Note that we do not sell personal information as defined by the CCPA. +4. Right to Non-Discrimination: You have the right not to be discriminated against for exercising any of your CCPA rights. + +#### Exercising Your CCPA Rights + +To exercise your rights under CCPA and to opt-out of the sale of your personal information, you can click on the "Do not sell my personal information" link in the footer of any page on our website. + ### Delete Your Personal Data You have the right to delete or request that We assist in deleting the Personal Data that We have collected about You. @@ -188,4 +205,4 @@ You are advised to review this Privacy Policy periodically for any changes. Chan If you have any questions about this Privacy Policy, You can contact us: -- By visiting this page on our website: [https://discord.gg/nDt7AjGJQH](https://discord.gg/nDt7AjGJQH) +- By emailing blitzkriegautomation@gmail.com diff --git a/docs/public/assets/images/hero.png b/docs/public/assets/images/hero.png deleted file mode 100644 index 722f5bf0a..000000000 Binary files a/docs/public/assets/images/hero.png and /dev/null differ diff --git a/docs/technical/cdon.md b/docs/technical/cdon.md deleted file mode 100644 index ddb36bed5..000000000 --- a/docs/technical/cdon.md +++ /dev/null @@ -1,99 +0,0 @@ -# Cedilla Object Notation - -1. JSON compressed as CDON, written directly to disk (a direct 50% reduction). -2. CDON further compressed with LZ4 (a clean 90% reduction). -3. The raw JSON file as fetched from a random data source. -4. CDON decompressed once again to JSON. Note that this file is a little larger than the original JSON file as it contains a lot more decimal places due to float precision (this shouldn't affect the size in memory). - -![an image of file sizes](https://i.imgur.com/AHJiFpq.png) - -FS stands for "Fast String". - -```cpp -primary CedillaObjectNotation { - utf8"CDON" magic; - Header header; - primary Body body; -} - -Header { - uint16 version; // always 1 - FSFormat fsFormat; - StringTable stringTable; -} - -FSFormat enum { - Format8, - Format16, - Format32, -} - -FSPrimitive match(fsFormat) { - Format8: uint8; - Format16: uint16; - Format32: uint32; -} - -StringTable { - FSPrimitive count; - String[count] strings; -} - -Body { - primary Value object; -} - -ValueType enum { - Null, - Boolean, - Uint8, - Uint16, - Uint32, - Uint64, - Int8, - Int16, - Int32, - Int64, - Float32, - Float64, - String, - FS, - Array, - Object, -} - -String { - uint32 length; - primary utf8 value; -} - -StringValue Value & { (ValueType.String | ValueType.FS) type } - -Value { - ValueType type; - match { - Boolean: { uint8 value; } - Uint8: { uint8 value; } - Uint16: { uint16 value; } - Uint32: { uint32 value; } - Uint64: { uint64 value; } - Int8: { int8 value; } - Int16: { int16 value; } - Int32: { int32 value; } - Int64: { int64 value; } - Float32: { float32 value; } - Float64: { float64 value; } - String: { String value; } - FS: { FSPrimitive index; } - Array: { - uint32 count; - Value[count] values; - } - Object: { - uint32 count; - StringValue[count] keys; - Value[count] values; - } - } -} -``` diff --git a/next-env.d.ts b/next-env.d.ts deleted file mode 100644 index 4f11a03dc..000000000 --- a/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/next.config.js b/next.config.js deleted file mode 100644 index ea23ed45c..000000000 --- a/next.config.js +++ /dev/null @@ -1,47 +0,0 @@ -import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin'; -import { readdirSync, writeFileSync } from 'fs'; - -const withVanillaExtract = createVanillaExtractPlugin({ tests: /\.css$/ }); - -/** @type {import('next').NextConfig} */ -const nextConfig = { - ...withVanillaExtract({ - webpack: (config, { isServer }) => { - config.module.rules.push({ - test: /\.glsl$/, - type: 'asset/source', - }); - - if (isServer) { - writeFileSync( - 'public/assets/versions.json', - JSON.stringify( - readdirSync('docs/changelogs').map((file) => - file.replace('.md', ''), - ), - ), - ); - } - - return config; - }, - }), - - async headers() { - return [ - { - source: '/(.*)?', - headers: [{ key: 'X-Frame-Options', value: 'DENY' }], - }, - ]; - }, - - distDir: 'dist/website', - reactStrictMode: true, - - experimental: { - workerThreads: false, - }, -}; - -export default nextConfig; diff --git a/package.json b/package.json index 0ab054c7d..a8629cf91 100644 --- a/package.json +++ b/package.json @@ -1,113 +1,51 @@ { "name": "blitzkit", - "version": "1.22.4", + "private": true, + "version": "1.23.1", "description": "πŸŽ‰ Tools for everything World of Tanks Blitz", - "main": "src/server.ts", "type": "module", + "types": "./types.d.ts", + "workspaces": [ + "packages/*" + ], "scripts": { - "build:assets": "bun scripts/buildAssets/index.ts", - "build:averages": "bun scripts/averages", + "build:assets": "bun --filter=@blitzkit/scripts run build:assets", + "build:averages": "bun --filter=@blitzkit/scripts run build:averages", "build:bot": "rm -rf dist/bot && mkdir -p dist/bot/prisma && bun build src/index.ts src/workers/bot.ts src/workers/render.ts --outdir dist/bot --target=bun --splitting --sourcemap=inline --external sharp && cp -R src/lang dist/bot/lang && prisma generate && cp prisma/schema.prisma dist/bot/prisma/schema.prisma && cp -R node_modules/prisma/*.node dist/bot/prisma && cd dist/bot && bun init -y && bun add sharp", - "build:website": "bun build:sitemap && next build", + "build:website": "bun build:prisma && bun --filter=@blitzkit/website run build", + "build:prisma": "prisma generate", "build:sitemap": "bun scripts/sitemap.ts", "build:docs": "vitepress build docs", "build:ratingleaderboard": "bun --script scripts/buildRatingLeaderboard.ts", "dev:bot": "bun build:bot && bun start:bot", "dev:docs": "vitepress dev docs", - "dev:website": "next dev", + "dev:website": "cd packages/website && bun run dev", + "dev:api": "bun --filter=@blitzkit/api run dev", "start:bot": "bun dist/bot/index.js", - "start:website": "next start", + "setup:depotdownloader": "bun --filter=@blitzkit/scripts run setup:depotdownloader", + "setup:patches": "bun --filter=@blitzkit/scripts run setup:patches", + "start:website": "bun --filter=@blitzkit/website run start", "host:docs": "vitepress preview docs", "lint": "tsc", - "lint:website": "next lint", + "lint:website": "cd packages/website && bun run lint", "format": "prettier --write \"**/*.@(json|js|jsx|css|md|ts|tsx|html|xml|yml|gltf)\"", - "knip": "knip", "update": "yarn upgrade --latest", "tunnel": "cloudflared tunnel --url http://localhost:3000", - "discoverids": "scripts/discoverIds.ts" + "discoverids": "scripts/discoverIds.ts", + "build:protos": "bun packages/scripts/src/protos.ts", + "preview:website": "cd packages/website && bun run preview" }, "license": "MIT", "dependencies": { - "@gltf-transform/core": "^3.10.1", - "@nivo/bar": "^0.87.0", - "@octokit/plugin-throttling": "^8.2.0", - "@octokit/rest": "^20.1.1", - "@prisma/client": "^5.16.2", - "@radix-ui/colors": "^3.0.0", - "@radix-ui/react-icons": "^1.3.0", - "@radix-ui/themes": "^3.1.1", - "@react-three/drei": "^9.108.3", - "@react-three/fiber": "^8.16.8", - "@resvg/resvg-js": "^2.6.2", - "@types/three": "^0.160.0", - "@vanilla-extract/css": "^1.15.3", - "@vanilla-extract/dynamic": "^2.1.1", - "adm-zip": "^0.5.14", - "bepaint": "^0.1.0-beta.3", - "csv-parse": "^5.5.6", - "decompress": "^4.2.1", - "discord.js": "^14.15.3", - "dotenv": "^16.4.5", - "esbuild": "^0.19.12", - "express": "^4.19.2", - "false": "^0.0.4", - "fuzzysort": "^2.0.4", - "googleapis": "^134.0.0", - "immer": "^10.1.1", - "js-yaml": "^4.1.0", - "lodash": "^4.17.21", - "lz4js": "^0.2.0", - "markdown-escape": "^2.0.0", - "markdown-to-jsx": "^7.4.7", - "next": "^14.2.5", - "parse-dds": "^1.2.1", - "pickleparser": "^0.2.1", - "postprocessing": "^6.35.6", - "progress": "^2.0.3", - "protobufjs": "^7.3.2", - "react": "^18.3.1", - "react-device-detect": "^2.2.3", - "react-dom": "^18.3.1", - "react-fuzzysort": "^1.0.1", - "react-promise-suspense": "^0.3.4", - "satori": "^0.10.14", - "sharp": "^0.33.4", - "three": "0.159.0", - "three-stdlib": "^2.30.4", - "urlon": "^3.1.0", - "vitepress": "^1.3.0", - "vitepress-plugin-auto-sidebar": "^1.2.0", - "yaml": "^2.4.5", - "zustand": "^4.5.4" + "lodash-es": "^4.17.21" }, "devDependencies": { - "@total-typescript/ts-reset": "^0.5.1", - "@types/adm-zip": "^0.5.5", - "@types/bun": "^1.1.6", - "@types/decompress": "^4.2.7", - "@types/escape-html": "^1.0.4", - "@types/express": "^4.17.21", - "@types/js-yaml": "^4.0.9", - "@types/lodash": "^4.17.6", - "@types/lz4": "^0.6.4", - "@types/lz4js": "^0.2.1", - "@types/markdown-escape": "^1.1.3", - "@types/node": "^20.14.10", - "@types/parse-dds": "^1.0.3", - "@types/pngjs": "^6.0.5", - "@types/progress": "^2.0.7", - "@types/react": "^18.3.3", - "@vanilla-extract/next-plugin": "^2.4.3", - "compare-versions": "^6.1.0", - "crc": "^4.3.2", - "fast-xml-parser": "^4.4.0", - "knip": "^3.13.2", - "prettier": "^3.3.2", - "prisma": "^5.16.2", + "@types/bun": "latest", + "@types/lodash-es": "^4.17.12", + "@types/node": "^22.5.4", + "esbuild": "^0.19.12", + "prettier": "^3.3.3", + "prisma": "^5.19.1", "typescript": "^5.5.4" - }, - "packageManager": "yarn@1.22.1", - "trustedDependencies": [ - "protobufjs" - ] + } } diff --git a/packages/..temp/depotDownloader.zip b/packages/..temp/depotDownloader.zip new file mode 100644 index 000000000..8b7d370bf Binary files /dev/null and b/packages/..temp/depotDownloader.zip differ diff --git a/packages/..temp/depotDownloader/DepotDownloader b/packages/..temp/depotDownloader/DepotDownloader new file mode 100644 index 000000000..5e959e611 Binary files /dev/null and b/packages/..temp/depotDownloader/DepotDownloader differ diff --git a/packages/..temp/depotDownloader/LICENSE b/packages/..temp/depotDownloader/LICENSE new file mode 100644 index 000000000..d159169d1 --- /dev/null +++ b/packages/..temp/depotDownloader/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/packages/bot/package.json b/packages/bot/package.json new file mode 100644 index 000000000..3bc03a78a --- /dev/null +++ b/packages/bot/package.json @@ -0,0 +1,21 @@ +{ + "name": "@blitzkit/bot", + "private": true, + "type": "module", + "types": "src/types.d.ts", + "dependencies": { + "@blitzkit/core": "workspace:*", + "satori": "^0.10.14", + "@resvg/resvg-js": "^2.6.2", + "discord.js": "^14.15.3", + "react": "^18.3.1", + "@radix-ui/colors": "^3.0.0", + "fuzzysort": "^2.0.4", + "bepaint": "^0.1.0-beta.3", + "dotenv": "^16.4.5", + "markdown-escape": "^2.0.0" + }, + "devDependencies": { + "@types/markdown-escape": "^1.1.3" + } +} diff --git a/src/commands/about.ts b/packages/bot/src/commands/about.ts similarity index 100% rename from src/commands/about.ts rename to packages/bot/src/commands/about.ts diff --git a/src/commands/breakdown/index.tsx b/packages/bot/src/commands/breakdown/index.tsx similarity index 74% rename from src/commands/breakdown/index.tsx rename to packages/bot/src/commands/breakdown/index.tsx index 5acd2237a..c282e6dde 100644 --- a/src/commands/breakdown/index.tsx +++ b/packages/bot/src/commands/breakdown/index.tsx @@ -1,18 +1,18 @@ import { getBlitzStarsLinkButton } from '../../core/blitzstars/getBlitzStarsLinkButton'; -import addPeriodicFilterOptions from '../../core/discord/addPeriodicFilterOptions'; -import addUsernameChoices from '../../core/discord/addUsernameChoices'; -import autocompleteTanks from '../../core/discord/autocompleteTanks'; -import autocompleteUsername from '../../core/discord/autocompleteUsername'; +import { addPeriodicFilterOptions } from '../../core/discord/addPeriodicFilterOptions'; +import { addUsernameChoices } from '../../core/discord/addUsernameChoices'; +import { autocompleteTanks } from '../../core/discord/autocompleteTanks'; +import { autocompleteUsername } from '../../core/discord/autocompleteUsername'; import { buttonRefresh } from '../../core/discord/buttonRefresh'; -import commandToURL from '../../core/discord/commandToURL'; +import { commandToURL } from '../../core/discord/commandToURL'; import { createLocalizedCommand } from '../../core/discord/createLocalizedCommand'; import { getCustomPeriodParams } from '../../core/discord/getCustomPeriodParams'; import { getFiltersFromButton } from '../../core/discord/getFiltersFromButton'; import { getFiltersFromCommand } from '../../core/discord/getFiltersFromCommand'; -import resolvePeriodFromButton from '../../core/discord/resolvePeriodFromButton'; -import resolvePeriodFromCommand from '../../core/discord/resolvePeriodFromCommand'; -import resolvePlayerFromButton from '../../core/discord/resolvePlayerFromButton'; -import resolvePlayerFromCommand from '../../core/discord/resolvePlayerFromCommand'; +import { resolvePeriodFromButton } from '../../core/discord/resolvePeriodFromButton'; +import { resolvePeriodFromCommand } from '../../core/discord/resolvePeriodFromCommand'; +import { resolvePlayerFromButton } from '../../core/discord/resolvePlayerFromButton'; +import { resolvePlayerFromCommand } from '../../core/discord/resolvePlayerFromCommand'; import { CommandRegistry } from '../../events/interactionCreate'; import { renderBreakdown } from './render'; diff --git a/src/commands/breakdown/render.tsx b/packages/bot/src/commands/breakdown/render.tsx similarity index 88% rename from src/commands/breakdown/render.tsx rename to packages/bot/src/commands/breakdown/render.tsx index 727ba5a06..13f8e6e11 100644 --- a/src/commands/breakdown/render.tsx +++ b/packages/bot/src/commands/breakdown/render.tsx @@ -1,27 +1,27 @@ -import { Locale } from 'discord.js'; -import { chunk } from 'lodash'; -import * as Breakdown from '../../components/Breakdown'; -import CommandWrapper from '../../components/CommandWrapper'; -import NoData from '../../components/NoData'; -import TitleBar from '../../components/TitleBar'; -import { getAccountInfo } from '../../core/blitz/getAccountInfo'; -import { getClanAccountInfo } from '../../core/blitz/getClanAccountInfo'; -import getTankStats from '../../core/blitz/getTankStats'; -import { filtersToDescription } from '../../core/blitzkit/filtersToDescription'; import { + BlitzStats, + calculateWN8, + getAccountInfo, + getClanAccountInfo, + getTankStats, + getWN8Percentile, TankDefinition, - tankDefinitions, -} from '../../core/blitzkit/tankDefinitions'; -import getStatsInPeriod from '../../core/blitzstars/getStatsInPeriod'; -import { tankAverages } from '../../core/blitzstars/tankAverages'; +} from '@blitzkit/core'; +import { Locale } from 'discord.js'; +import { chunk } from 'lodash-es'; +import * as Breakdown from '../../components/Breakdown'; +import { CommandWrapper } from '../../components/CommandWrapper'; +import { NoData } from '../../components/NoData'; +import { TitleBar } from '../../components/TitleBar'; +import { filtersToDescription } from '../../core/blitzkit/filtersToDescription'; +import { tankDefinitions } from '../../core/blitzkit/nonBlockingPromises'; +import { UserError } from '../../core/blitzkit/userError'; +import { filterStats, StatFilters } from '../../core/blitzstars/filterStats'; +import { getStatsInPeriod } from '../../core/blitzstars/getStatsInPeriod'; +import { blitzStarsTankAverages } from '../../core/blitzstars/tankAverages'; import { ResolvedPeriod } from '../../core/discord/resolvePeriodFromCommand'; import { ResolvedPlayer } from '../../core/discord/resolvePlayerFromCommand'; import { translator } from '../../core/localization/translator'; -import calculateWN8 from '../../core/statistics/calculateWN8'; -import { BlitzStats } from '../../core/statistics/compositeStats/constants'; -import { StatFilters, filterStats } from '../../core/statistics/filterStats'; -import getWN8Percentile from '../../core/statistics/getWN8Percentile'; -import { UserError } from '../../hooks/userError'; const ROWS_PER_PAGE = 8; const MAX_PAGES = 9; @@ -34,7 +34,7 @@ export async function renderBreakdown( ) { const { t, translate } = translator(locale); const awaitedTankDefinitions = await tankDefinitions; - const awaitedTankAverages = await tankAverages; + const awaitedTankAverages = await blitzStarsTankAverages; const statsInPeriod = await getStatsInPeriod(region, id, start, end, locale); const { filteredOrder } = await filterStats(statsInPeriod, filters); const accountInfo = await getAccountInfo(region, id); @@ -135,7 +135,7 @@ export async function renderBreakdown( children.push( { - const tankDefinition = awaitedTankDefinitions[id] as + const tankDefinition = awaitedTankDefinitions.tanks[id] as | TankDefinition | undefined; const current = orderedCurrentStats[index]; @@ -186,9 +186,9 @@ export async function renderBreakdown( children.push( ((resolve) => { {!hasInactiveMembers && ( diff --git a/src/commands/link.tsx b/packages/bot/src/commands/link.tsx similarity index 91% rename from src/commands/link.tsx rename to packages/bot/src/commands/link.tsx index 159b9b107..314177f5b 100644 --- a/src/commands/link.tsx +++ b/packages/bot/src/commands/link.tsx @@ -1,14 +1,16 @@ +import { + getAccountInfo, + getClanAccountInfo, + linkBlitzAndDiscord, +} from '@blitzkit/core'; import { teal } from '@radix-ui/colors'; import { Glow } from '../components/AllStatsOverview/components/HeroStat/components/Glow'; -import CommandWrapper from '../components/CommandWrapper'; -import { getAccountInfo } from '../core/blitz/getAccountInfo'; -import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; -import { linkBlitzAndDiscord } from '../core/blitzkit/discordBlitzLink'; -import addUsernameChoices from '../core/discord/addUsernameChoices'; -import autocompleteUsername from '../core/discord/autocompleteUsername'; +import { CommandWrapper } from '../components/CommandWrapper'; +import { addUsernameChoices } from '../core/discord/addUsernameChoices'; +import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; -import embedInfo from '../core/discord/embedInfo'; -import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand'; +import { embedInfo } from '../core/discord/embedInfo'; +import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { translator } from '../core/localization/translator'; import { CommandRegistry } from '../events/interactionCreate'; import { theme } from '../stitches.config'; diff --git a/src/commands/ownedTanks.tsx b/packages/bot/src/commands/ownedTanks.tsx similarity index 75% rename from src/commands/ownedTanks.tsx rename to packages/bot/src/commands/ownedTanks.tsx index d7f6c9cb1..e428c329a 100644 --- a/src/commands/ownedTanks.tsx +++ b/packages/bot/src/commands/ownedTanks.tsx @@ -1,21 +1,23 @@ -import { chunk } from 'lodash'; -import markdownEscape from 'markdown-escape'; -import { TANK_CLASSES } from '../components/Tanks/components/Item/constants'; -import { getAccountInfo } from '../core/blitz/getAccountInfo'; -import getTankStats from '../core/blitz/getTankStats'; -import { gameDefinitions } from '../core/blitzkit/gameDefinitions'; import { + TANK_CLASSES, + TIER_ROMAN_NUMERALS, TankDefinition, Tier, flags, + getAccountInfo, + getTankStats, +} from '@blitzkit/core'; +import { chunk } from 'lodash-es'; +import markdownEscape from 'markdown-escape'; +import { + gameDefinitions, tankDefinitions, -} from '../core/blitzkit/tankDefinitions'; -import { TIER_ROMAN_NUMERALS } from '../core/blitzkit/tankDefinitions/constants'; -import addTierChoices from '../core/discord/addTierChoices'; -import addUsernameChoices from '../core/discord/addUsernameChoices'; -import autocompleteUsername from '../core/discord/autocompleteUsername'; +} from '../core/blitzkit/nonBlockingPromises'; +import { addTierChoices } from '../core/discord/addTierChoices'; +import { addUsernameChoices } from '../core/discord/addUsernameChoices'; +import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; -import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand'; +import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { translator } from '../core/localization/translator'; import { CommandRegistry } from '../events/interactionCreate'; @@ -41,7 +43,7 @@ export const ownedTanksCommand = new Promise((resolve) => { const filteredTanks = ( await Promise.all( tankStats.map(async (tankData) => ({ - tankDefinitions: (await tankDefinitions)[tankData.tank_id]!, + tankDefinitions: (await tankDefinitions).tanks[tankData.tank_id]!, id: tankData.tank_id, })), ) @@ -61,7 +63,7 @@ export const ownedTanksCommand = new Promise((resolve) => { const awaitedTankDefinitions = await tankDefinitions; const awaitedGameDefinitions = await gameDefinitions; const lines = tankStats - .map(({ tank_id }) => awaitedTankDefinitions[tank_id]) + .map(({ tank_id }) => awaitedTankDefinitions.tanks[tank_id]) .filter((tank) => tank.tier === tier) .sort( (a, b) => diff --git a/src/commands/permissions.ts b/packages/bot/src/commands/permissions.ts similarity index 100% rename from src/commands/permissions.ts rename to packages/bot/src/commands/permissions.ts diff --git a/src/commands/ping.ts b/packages/bot/src/commands/ping.ts similarity index 100% rename from src/commands/ping.ts rename to packages/bot/src/commands/ping.ts diff --git a/src/commands/playerInfo.ts b/packages/bot/src/commands/playerInfo.ts similarity index 83% rename from src/commands/playerInfo.ts rename to packages/bot/src/commands/playerInfo.ts index f6af4a6dc..cdb7d7d72 100644 --- a/src/commands/playerInfo.ts +++ b/packages/bot/src/commands/playerInfo.ts @@ -1,11 +1,11 @@ +import { getAccountInfo } from '@blitzkit/core'; import markdownEscape from 'markdown-escape'; -import { getAccountInfo } from '../core/blitz/getAccountInfo'; -import addUsernameChoices from '../core/discord/addUsernameChoices'; -import autocompleteUsername from '../core/discord/autocompleteUsername'; +import { addUsernameChoices } from '../core/discord/addUsernameChoices'; +import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; -import embedInfo from '../core/discord/embedInfo'; -import markdownTable from '../core/discord/markdownTable'; -import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand'; +import { embedInfo } from '../core/discord/embedInfo'; +import { markdownTable } from '../core/discord/markdownTable'; +import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { translator } from '../core/localization/translator'; import { CommandRegistry } from '../events/interactionCreate'; diff --git a/src/commands/rating.tsx b/packages/bot/src/commands/rating.tsx similarity index 93% rename from src/commands/rating.tsx rename to packages/bot/src/commands/rating.tsx index fc62d2465..afbe9a0c4 100644 --- a/src/commands/rating.tsx +++ b/packages/bot/src/commands/rating.tsx @@ -1,24 +1,26 @@ +import { + BkrlFormat, + deltaBkrlBlitzStats, + emblemURL, + getAccountInfo, + getArchivedRatingMidnightLeaderboard, + getClanAccountInfo, + getLeagueFromScore, + getRatingInfo, + getRatingNeighbors, +} from '@blitzkit/core'; import { SlashCommandSubcommandBuilder } from 'discord.js'; import markdownEscape from 'markdown-escape'; import { Glow } from '../components/AllStatsOverview/components/HeroStat/components/Glow'; -import CommandWrapper from '../components/CommandWrapper'; +import { CommandWrapper } from '../components/CommandWrapper'; import { DeltaCaret } from '../components/DeltaCaret'; -import TitleBar from '../components/TitleBar'; -import { getAccountInfo } from '../core/blitz/getAccountInfo'; -import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; -import { getLeagueFromScore } from '../core/blitz/getLeagueFromScore'; -import getRatingInfo from '../core/blitz/getRatingInfo'; -import { getRatingNeighbors } from '../core/blitz/getRatingNeighbors'; +import { TitleBar } from '../components/TitleBar'; import { normalizeLeagueIcon } from '../core/blitz/normalizeLeagueIcon'; -import { emblemURL } from '../core/blitzkit/emblemURL'; -import getArchivedRatingMidnightLeaderboard from '../core/blitzkit/getArchivedRatingMidnightLeaderboard'; import { iconPng } from '../core/blitzkit/iconPng'; -import addUsernameChoices from '../core/discord/addUsernameChoices'; +import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; -import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand'; +import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { translator } from '../core/localization/translator'; -import { deltaBkrlBlitzStats } from '../core/statistics/deltaBkrlBlitzStats'; -import { BkrlFormat } from '../core/streams/bkrl'; import { CommandRegistry } from '../events/interactionCreate'; import { theme } from '../stitches.config'; @@ -122,9 +124,9 @@ export const ratingCommand = new Promise((resolve) => {
((resolve) => { padding: 16, backgroundColor: theme.colors[`appBackground2${leagueTheme}`], borderRadius: 4, - border: `1px solid ${theme.colors[`componentInteractive${leagueTheme}`]}`, + border: `1px solid ${ + theme.colors[`componentInteractive${leagueTheme}`] + }`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', diff --git a/src/commands/ratingLeaderboard.tsx b/packages/bot/src/commands/ratingLeaderboard.tsx similarity index 83% rename from src/commands/ratingLeaderboard.tsx rename to packages/bot/src/commands/ratingLeaderboard.tsx index 50f75f4eb..3eca65e3f 100644 --- a/src/commands/ratingLeaderboard.tsx +++ b/packages/bot/src/commands/ratingLeaderboard.tsx @@ -1,123 +1,39 @@ +import { + BkrlDiscriminatedEntries, + FIRST_MINIMAL_ARCHIVED_RATING_SEASON, + getAccountInfo, + getArchivedLatestSeasonNumber, + getArchivedRatingInfo, + getArchivedRatingLeaderboard, + getArchivedRatingMidnightLeaderboard, + getClanAccountInfo, + getRatingInfo, + getRatingLeague, + getRatingNeighbors, + isOnGoingRatingSeason, + LEAGUES, + RatingInfo, + Region, +} from '@blitzkit/core'; import { APIApplicationCommandOptionChoice, Locale, SlashCommandSubcommandBuilder, } from 'discord.js'; -import { range } from 'lodash'; +import { range } from 'lodash-es'; import markdownEscape from 'markdown-escape'; -import CommandWrapper from '../components/CommandWrapper'; +import { CommandWrapper } from '../components/CommandWrapper'; import * as Leaderboard from '../components/Leaderboard'; -import TitleBar from '../components/TitleBar'; -import { LEAGUES } from '../constants/leagues'; -import { FIRST_MINIMAL_ARCHIVED_RATING_SEASON } from '../constants/rating'; -import { Region } from '../constants/regions'; -import { getAccountInfo } from '../core/blitz/getAccountInfo'; -import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; -import getRatingInfo from '../core/blitz/getRatingInfo'; -import { getRatingLeague } from '../core/blitz/getRatingLeague'; -import { getRatingNeighbors } from '../core/blitz/getRatingNeighbors'; -import { isOnGoingRatingSeason } from '../core/blitz/isOnGoingRatingSeason'; -import { getArchivedLatestSeasonNumber } from '../core/blitzkit/getArchivedLatestSeasonNumber'; -import getArchivedRatingInfo from '../core/blitzkit/getArchivedRatingInfo'; -import { getArchivedRatingLeaderboard } from '../core/blitzkit/getArchivedRatingLeaderboard'; -import getArchivedRatingMidnightLeaderboard from '../core/blitzkit/getArchivedRatingMidnightLeaderboard'; -import addRegionChoices from '../core/discord/addRegionChoices'; -import addUsernameChoices from '../core/discord/addUsernameChoices'; -import autocompleteUsername from '../core/discord/autocompleteUsername'; +import { TitleBar } from '../components/TitleBar'; +import { UserError } from '../core/blitzkit/userError'; +import { addRegionChoices } from '../core/discord/addRegionChoices'; +import { addUsernameChoices } from '../core/discord/addUsernameChoices'; +import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { localizationObject } from '../core/discord/localizationObject'; -import resolvePlayerFromCommand from '../core/discord/resolvePlayerFromCommand'; +import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { translator } from '../core/localization/translator'; -import { BkrlDiscriminatedEntries } from '../core/streams/bkrl'; import { CommandRegistry } from '../events/interactionCreate'; -import { UserError } from '../hooks/userError'; - -export interface RatingPlayer { - spa_id: number; - mmr: number; - season_number: number; - calibrationBattlesLeft: number; - number: number; - percentile: number; - skip: boolean; - updated_at: string; - score: number; - nickname: string; - clan_tag: string; -} - -export interface LeagueTop { - result: RatingPlayer[]; -} - -export type RatingReward = { - from_position: number; - to_position: number; - count: number; -} & ( - | { - type: 'vehicle'; - - vehicle: { - id: number; - name: string; - nation: string; - subnation: string; - use_subnation_flag: boolean; - type_slug: string; - level: number; - roman_level: string; - user_string: string; - image_url: string; - preview_image_url: string; - is_premium: boolean; - is_collectible: boolean; - }; - } - | { - type: 'stuff'; - - stuff: { - name: string; - count: number; - title: string; - image_url: string; - type: string; - - sizes: {}; - }; - } -); - -export interface RatingLeague { - title: string; - small_icon: string; - big_icon: string; - background: string; - index: number; - percentile: number; -} - -export type RatingInfo = - | { - detail: undefined; - - title: string; - icon: string | null; - start_at: string; - finish_at: string; - current_season: number; - updated_at: string; - count: number; - - rewards: RatingReward[]; - leagues: RatingLeague[]; - } - | { detail: { error: string } }; - -export interface RatingNeighbors { - neighbors: RatingPlayer[]; -} interface SimplifiedPlayer { id: number; diff --git a/src/commands/replay.tsx b/packages/bot/src/commands/replay.tsx similarity index 93% rename from src/commands/replay.tsx rename to packages/bot/src/commands/replay.tsx index 9adc9fc31..c8dacfce8 100644 --- a/src/commands/replay.tsx +++ b/packages/bot/src/commands/replay.tsx @@ -1,19 +1,23 @@ -import { clamp } from 'lodash'; -import CommandWrapper from '../components/CommandWrapper'; -import TitleBar from '../components/TitleBar'; -import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo'; -import { idToRegion } from '../core/blitz/idToRegion'; -import { emblemURL } from '../core/blitzkit/emblemURL'; +import { + calculateWN8, + emblemURL, + getClanAccountInfo, + idToRegion, + tankIcon, + TIER_ROMAN_NUMERALS, +} from '@blitzkit/core'; +import { clamp } from 'lodash-es'; +import { CommandWrapper } from '../components/CommandWrapper'; +import { TitleBar } from '../components/TitleBar'; import { iconPng } from '../core/blitzkit/iconPng'; -import { mapDefinitions } from '../core/blitzkit/mapDefinitions'; +import { + mapDefinitions, + tankDefinitions, +} from '../core/blitzkit/nonBlockingPromises'; import { RenderConfiguration } from '../core/blitzkit/renderConfiguration'; -import { tankDefinitions } from '../core/blitzkit/tankDefinitions'; -import { TIER_ROMAN_NUMERALS } from '../core/blitzkit/tankDefinitions/constants'; -import { tankIcon } from '../core/blitzkit/tankIcon'; -import { tankAverages } from '../core/blitzstars/tankAverages'; -import buttonLink from '../core/discord/buttonLink'; +import { blitzStarsTankAverages } from '../core/blitzstars/tankAverages'; +import { buttonLink } from '../core/discord/buttonLink'; import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; -import calculateWN8 from '../core/statistics/calculateWN8'; import { CommandRegistry } from '../events/interactionCreate'; import { theme } from '../stitches.config'; @@ -219,9 +223,9 @@ async function playerListing( winningTeam: number, recordingPlayer = false, ) { - const awaitedTankAverages = await tankAverages; + const awaitedTankAverages = await blitzStarsTankAverages; const awaitedTankDefinitions = await tankDefinitions; - const tank = awaitedTankDefinitions[player.vehicle_descr]; + const tank = awaitedTankDefinitions.tanks[player.vehicle_descr]; const blockAccent = recordingPlayer ? '_amber' : ''; const healthAccent = protagonistTeam ? recordingPlayer @@ -500,7 +504,7 @@ export const replayCommand = new Promise((resolve) => { replayData.protagonist_team === replayData.winner_team ? 'Victory' : 'Defeat' - } β€’ ${awaitedMapDefinitions[replayData.map_id].name}`} + } β€’ ${awaitedMapDefinitions.maps[replayData.map_id].name}`} />
((resolve) => { true, ); const startingTankRaw = interaction.options.getString('starting-tank'); - const targetTank = awaitedTankDefinitions[targetTankId]; + const targetTank = awaitedTankDefinitions.tanks[targetTankId]; const { id, region } = await resolvePlayerFromCommand(interaction); let startingTankId: number; const targetTankAncestry = await resolveAncestry(targetTankId); @@ -94,7 +95,7 @@ export const researchCommand = new Promise((resolve) => { ]); } - const startingTank = awaitedTankDefinitions[startingTankId]; + const startingTank = awaitedTankDefinitions.tanks[startingTankId]; if (startingTank.tier > targetTank.tier) { return translate('bot.commands.research.errors.unordered', [ @@ -111,7 +112,7 @@ export const researchCommand = new Promise((resolve) => { ]); } } else { - if (targetTank.treeType !== 'researchable') { + if (targetTank.type !== TankType.RESEARCHABLE) { return translate('bot.commands.research.errors.non_tech_tree', [ escapeMarkdown(targetTank.name), ]); @@ -137,7 +138,7 @@ export const researchCommand = new Promise((resolve) => { const foundAncestor = targetTankAncestry.find( (id) => - awaitedTankDefinitions[id].tier === 1 || + awaitedTankDefinitions.tanks[id].tier === 1 || tankStats.some(({ tank_id }) => tank_id === id), ); @@ -159,7 +160,7 @@ export const researchCommand = new Promise((resolve) => { const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; const costs = await Promise.all( line.map(async (id) => { - const tank = awaitedTankDefinitions[id]; + const tank = awaitedTankDefinitions.tanks[id]; const turretXps = new Map(); const gunXps = new Map(); const engineXps = new Map(); @@ -171,8 +172,11 @@ export const researchCommand = new Promise((resolve) => { } turret.guns.forEach((gun) => { - if (gun.xp !== undefined) { - gunXps.set(gun.id, gun.xp); + if (gun.gunType!.value.base.xp !== undefined) { + gunXps.set( + gun.gunType!.value.base.id, + gun.gunType!.value.base.xp, + ); } }); }); @@ -220,7 +224,9 @@ export const researchCommand = new Promise((resolve) => {
((resolve) => { {await Promise.all( line.map(async (id, index) => { - const tank = awaitedTankDefinitions[id]; + const tank = awaitedTankDefinitions.tanks[id]; return (
- {type === 'tank' && tankType !== undefined && ( + {displayType === 'tank' && tankClass !== undefined && ( {tankType} )} @@ -78,8 +81,8 @@ export function Row({ {stats.map((stat) => ( diff --git a/src/components/GenericStats/components/GenericStatsRow.tsx b/packages/bot/src/components/GenericStats/components/GenericStatsRow.tsx similarity index 87% rename from src/components/GenericStats/components/GenericStatsRow.tsx rename to packages/bot/src/components/GenericStats/components/GenericStatsRow.tsx index 1f458a158..57e0db989 100644 --- a/src/components/GenericStats/components/GenericStatsRow.tsx +++ b/packages/bot/src/components/GenericStats/components/GenericStatsRow.tsx @@ -1,12 +1,12 @@ import { GenericStat } from '..'; import { theme } from '../../../stitches.config'; -import PercentileIndicator from '../../PercentileIndicator'; +import { PercentileIndicator } from '../../PercentileIndicator'; interface GenericStatsRowProps { stat: GenericStat; } -export default function GenericStatsRow({ stat }: GenericStatsRowProps) { +export function GenericStatsRow({ stat }: GenericStatsRowProps) { return (
value !== undefined); const itemsPerRow = Math.ceil(filteredStats.length / columnCount); const columns: GenericStat[][] = []; diff --git a/src/components/Graph/components/Line/constants.ts b/packages/bot/src/components/Graph/components/Line/constants.ts similarity index 100% rename from src/components/Graph/components/Line/constants.ts rename to packages/bot/src/components/Graph/components/Line/constants.ts diff --git a/src/components/Graph/components/Line/index.tsx b/packages/bot/src/components/Graph/components/Line/index.tsx similarity index 100% rename from src/components/Graph/components/Line/index.tsx rename to packages/bot/src/components/Graph/components/Line/index.tsx diff --git a/src/components/Graph/components/Margin/constants.ts b/packages/bot/src/components/Graph/components/Margin/constants.ts similarity index 100% rename from src/components/Graph/components/Margin/constants.ts rename to packages/bot/src/components/Graph/components/Margin/constants.ts diff --git a/src/components/Graph/components/Margin/index.tsx b/packages/bot/src/components/Graph/components/Margin/index.tsx similarity index 97% rename from src/components/Graph/components/Margin/index.tsx rename to packages/bot/src/components/Graph/components/Margin/index.tsx index 66b64df5e..049eda311 100644 --- a/src/components/Graph/components/Margin/index.tsx +++ b/packages/bot/src/components/Graph/components/Margin/index.tsx @@ -1,4 +1,4 @@ -import { times } from 'lodash'; +import { times } from 'lodash-es'; import { theme } from '../../../../stitches.config'; import { MarginInputProps } from '../Root'; import { MarginOrientation } from './constants'; diff --git a/src/components/Graph/components/Root/constants.ts b/packages/bot/src/components/Graph/components/Root/constants.ts similarity index 100% rename from src/components/Graph/components/Root/constants.ts rename to packages/bot/src/components/Graph/components/Root/constants.ts diff --git a/src/components/Graph/components/Root/index.tsx b/packages/bot/src/components/Graph/components/Root/index.tsx similarity index 98% rename from src/components/Graph/components/Root/index.tsx rename to packages/bot/src/components/Graph/components/Root/index.tsx index 6f621f07d..9d13064bb 100644 --- a/src/components/Graph/components/Root/index.tsx +++ b/packages/bot/src/components/Graph/components/Root/index.tsx @@ -1,4 +1,4 @@ -import { times } from 'lodash'; +import { times } from 'lodash-es'; import { ReactNode } from 'react'; import { theme } from '../../../../stitches.config'; import { Margin } from '../Margin'; diff --git a/src/components/Graph/index.ts b/packages/bot/src/components/Graph/index.ts similarity index 100% rename from src/components/Graph/index.ts rename to packages/bot/src/components/Graph/index.ts diff --git a/src/components/Leaderboard/components/Gap.tsx b/packages/bot/src/components/Leaderboard/components/Gap.tsx similarity index 100% rename from src/components/Leaderboard/components/Gap.tsx rename to packages/bot/src/components/Leaderboard/components/Gap.tsx diff --git a/src/components/Leaderboard/components/Item.tsx b/packages/bot/src/components/Leaderboard/components/Item.tsx similarity index 100% rename from src/components/Leaderboard/components/Item.tsx rename to packages/bot/src/components/Leaderboard/components/Item.tsx diff --git a/src/components/Leaderboard/components/Root.tsx b/packages/bot/src/components/Leaderboard/components/Root.tsx similarity index 100% rename from src/components/Leaderboard/components/Root.tsx rename to packages/bot/src/components/Leaderboard/components/Root.tsx diff --git a/src/components/Leaderboard/index.ts b/packages/bot/src/components/Leaderboard/index.ts similarity index 100% rename from src/components/Leaderboard/index.ts rename to packages/bot/src/components/Leaderboard/index.ts diff --git a/src/components/NoData/constants.ts b/packages/bot/src/components/NoData/constants.ts similarity index 100% rename from src/components/NoData/constants.ts rename to packages/bot/src/components/NoData/constants.ts diff --git a/src/components/NoData/index.tsx b/packages/bot/src/components/NoData/index.tsx similarity index 90% rename from src/components/NoData/index.tsx rename to packages/bot/src/components/NoData/index.tsx index 4a23defcb..cf2d46004 100644 --- a/src/components/NoData/index.tsx +++ b/packages/bot/src/components/NoData/index.tsx @@ -11,7 +11,7 @@ interface NoDataProps { locale: Locale; } -export default function NoData({ type, locale }: NoDataProps) { +export function NoData({ type, locale }: NoDataProps) { const { translate } = translator(locale); return ( diff --git a/src/components/PercentileIndicator/constants.ts b/packages/bot/src/components/PercentileIndicator/constants.ts similarity index 90% rename from src/components/PercentileIndicator/constants.ts rename to packages/bot/src/components/PercentileIndicator/constants.ts index ae4fface8..b5cefb554 100644 --- a/src/components/PercentileIndicator/constants.ts +++ b/packages/bot/src/components/PercentileIndicator/constants.ts @@ -1,3 +1,4 @@ +import { Percentile } from '@blitzkit/core'; import { amber, blue, @@ -10,7 +11,6 @@ import { slate, teal, } from '@radix-ui/colors'; -import { Percentile } from '../../constants/percentiles'; export const PERCENTILE_COLORS = { [Percentile.VeryBad]: slate.slate9, diff --git a/src/components/PercentileIndicator/index.tsx b/packages/bot/src/components/PercentileIndicator/index.tsx similarity index 66% rename from src/components/PercentileIndicator/index.tsx rename to packages/bot/src/components/PercentileIndicator/index.tsx index 2099966a3..f7c0f5b68 100644 --- a/src/components/PercentileIndicator/index.tsx +++ b/packages/bot/src/components/PercentileIndicator/index.tsx @@ -1,13 +1,11 @@ -import { Percentile } from '../../constants/percentiles'; +import { Percentile } from '@blitzkit/core'; import { PERCENTILE_COLORS } from './constants'; interface PercentileIndicatorProps { percentile: Percentile; } -export default function PercentileIndicator({ - percentile, -}: PercentileIndicatorProps) { +export function PercentileIndicator({ percentile }: PercentileIndicatorProps) { return (
>; - interface TierWeightsProps { weights: TierWeightsRecord; } -export default function TierWeights({ weights }: TierWeightsProps) { +export function TierWeights({ weights }: TierWeightsProps) { return (
{Object.entries(weights).map(([tier, weight]) => ( diff --git a/src/components/TitleBar.tsx b/packages/bot/src/components/TitleBar.tsx similarity index 93% rename from src/components/TitleBar.tsx rename to packages/bot/src/components/TitleBar.tsx index 96b2739ce..e64d0db7b 100644 --- a/src/components/TitleBar.tsx +++ b/packages/bot/src/components/TitleBar.tsx @@ -6,7 +6,7 @@ interface TitleBarProps { description?: string; } -export default function TitleBar({ title, image, description }: TitleBarProps) { +export function TitleBar({ title, image, description }: TitleBarProps) { return (
awaitedTankDefinitions[b].tier - awaitedTankDefinitions[a].tier, + (a, b) => tankDefinitions.tanks[b].tier - tankDefinitions.tanks[a].tier, ); } diff --git a/src/core/blitzkit/svgToPng.ts b/packages/bot/src/core/blitzkit/svgToPng.ts similarity index 64% rename from src/core/blitzkit/svgToPng.ts rename to packages/bot/src/core/blitzkit/svgToPng.ts index 601c8648c..06ace7446 100644 --- a/src/core/blitzkit/svgToPng.ts +++ b/packages/bot/src/core/blitzkit/svgToPng.ts @@ -1,5 +1,5 @@ import { Resvg } from '@resvg/resvg-js'; -export default function svgToPng(svg: string) { +export function svgToPng(svg: string) { return new Resvg(svg).render().asPng(); } diff --git a/src/core/blitzkit/svgToPngThreaded.ts b/packages/bot/src/core/blitzkit/svgToPngThreaded.ts similarity index 100% rename from src/core/blitzkit/svgToPngThreaded.ts rename to packages/bot/src/core/blitzkit/svgToPngThreaded.ts diff --git a/src/core/blitzkit/tankIconPng.ts b/packages/bot/src/core/blitzkit/tankIconPng.ts similarity index 72% rename from src/core/blitzkit/tankIconPng.ts rename to packages/bot/src/core/blitzkit/tankIconPng.ts index 97b076bf9..a15b09c8b 100644 --- a/src/core/blitzkit/tankIconPng.ts +++ b/packages/bot/src/core/blitzkit/tankIconPng.ts @@ -1,5 +1,5 @@ +import { tankIcon } from '@blitzkit/core'; import { iconPng } from './iconPng'; -import { tankIcon } from './tankIcon'; export function tankIconPng(id: number) { return iconPng(tankIcon(id)); diff --git a/src/hooks/userError.ts b/packages/bot/src/core/blitzkit/userError.ts similarity index 100% rename from src/hooks/userError.ts rename to packages/bot/src/core/blitzkit/userError.ts diff --git a/src/core/statistics/filterStats.ts b/packages/bot/src/core/blitzstars/filterStats.ts similarity index 51% rename from src/core/statistics/filterStats.ts rename to packages/bot/src/core/blitzstars/filterStats.ts index 604254928..b2c770a2b 100644 --- a/src/core/statistics/filterStats.ts +++ b/packages/bot/src/core/blitzstars/filterStats.ts @@ -1,16 +1,16 @@ -import { TreeType } from '../../components/Tanks'; -import { SupplementaryStats } from '../blitz/getAccountInfo'; -import { tankDefinitions } from '../blitzkit/tankDefinitions'; -import { DiffedTankStats } from '../blitzstars/getStatsInPeriod'; -import { tankAverages } from '../blitzstars/tankAverages'; -import calculateWN8 from './calculateWN8'; -import sumStats from './sumStats'; +import { TankClass, TankType } from '@blitzkit/core'; +import { SupplementaryStats } from '@blitzkit/core/src/blitz/getAccountInfo'; +import { calculateWN8 } from '@blitzkit/core/src/statistics/calculateWN8'; +import { BlitzStats } from '@blitzkit/core/src/statistics/compositeStats'; +import { sumAllStats } from '@blitzkit/core/src/statistics/sumAllStats'; +import { tankDefinitions } from '../blitzkit/nonBlockingPromises'; +import { blitzStarsTankAverages } from './tankAverages'; export interface StatFilters { nation?: string; tier?: number; - tankType?: string; - treeType?: TreeType; + class?: TankClass; + type?: TankType; tank?: number; } @@ -22,24 +22,26 @@ export async function filterStats( if (filters.tank) filters = { tank: filters.tank }; const awaitedTankDefinitions = await tankDefinitions; - const awaitedTankAverages = await tankAverages; + const awaitedTankAverages = await blitzStarsTankAverages; const filteredOrder = order.filter((id) => { - const entry = awaitedTankDefinitions[id]; + const entry = awaitedTankDefinitions.tanks[id]; return ( entry && (filters.nation === undefined || entry.nation === filters.nation) && (filters.tier === undefined || entry.tier === filters.tier) && - (filters.tankType === undefined || entry.class === filters.tankType) && - (filters.treeType === undefined || - (filters.treeType === 'collector' && entry.treeType === 'collector') || - (filters.treeType === 'premium' && entry.treeType === 'premium') || - (filters.treeType === 'researchable' && - entry.treeType === 'researchable')) && + (filters.class === undefined || entry.class === filters.class) && + (filters.type === undefined || + (filters.type === TankType.COLLECTOR && + entry.type === TankType.COLLECTOR) || + (filters.type === TankType.PREMIUM && + entry.type === TankType.PREMIUM) || + (filters.type === TankType.RESEARCHABLE && + entry.type === TankType.RESEARCHABLE)) && (filters.tank === undefined || entry.id === filters.tank) ); }); - const stats = sumStats(filteredOrder.map((id) => diff[id])); + const stats = sumAllStats(filteredOrder.map((id) => diff[id])); const battlesOfTanksWithAverages = filteredOrder.reduce( (accumulator, id) => awaitedTankAverages[id] ? accumulator + diff[id].battles : accumulator, @@ -47,7 +49,9 @@ export async function filterStats( ); const battlesOfTanksWithTankDefinition = filteredOrder.reduce( (accumulator, id) => - awaitedTankDefinitions[id] ? accumulator + diff[id].battles : accumulator, + awaitedTankDefinitions.tanks[id] + ? accumulator + diff[id].battles + : accumulator, 0, ); const supplementary = { @@ -64,8 +68,9 @@ export async function filterStats( tier: filteredOrder.reduce( (accumulator, id) => - awaitedTankDefinitions[id] - ? accumulator + awaitedTankDefinitions[id]!.tier * diff[id].battles + awaitedTankDefinitions.tanks[id] + ? accumulator + + awaitedTankDefinitions.tanks[id]!.tier * diff[id].battles : accumulator, 0, ) / battlesOfTanksWithTankDefinition, @@ -73,3 +78,8 @@ export async function filterStats( return { stats, supplementary, filteredOrder }; } + +export interface DiffedTankStats { + diff: Record; + order: number[]; +} diff --git a/src/core/blitzstars/getBlitzStarsLinkButton.ts b/packages/bot/src/core/blitzstars/getBlitzStarsLinkButton.ts similarity index 67% rename from src/core/blitzstars/getBlitzStarsLinkButton.ts rename to packages/bot/src/core/blitzstars/getBlitzStarsLinkButton.ts index da2074adc..f732417f2 100644 --- a/src/core/blitzstars/getBlitzStarsLinkButton.ts +++ b/packages/bot/src/core/blitzstars/getBlitzStarsLinkButton.ts @@ -1,6 +1,5 @@ -import { Region } from '../../constants/regions'; -import { getAccountInfo } from '../blitz/getAccountInfo'; -import buttonLink from '../discord/buttonLink'; +import { getAccountInfo, Region } from '@blitzkit/core'; +import { buttonLink } from '../discord/buttonLink'; export async function getBlitzStarsLinkButton( region: Region, diff --git a/src/core/blitzstars/getPlayerHistories.ts b/packages/bot/src/core/blitzstars/getPlayerHistories.ts similarity index 88% rename from src/core/blitzstars/getPlayerHistories.ts rename to packages/bot/src/core/blitzstars/getPlayerHistories.ts index 5d876ebd0..8babf352a 100644 --- a/src/core/blitzstars/getPlayerHistories.ts +++ b/packages/bot/src/core/blitzstars/getPlayerHistories.ts @@ -1,15 +1,13 @@ -import { Region } from '../../constants/regions'; +import { Region, emptyAllStats, getAccountInfo } from '@blitzkit/core'; import { GetHistoriesOptions, Histories, History, getHistoriesDefaultOptions, } from '../../types/histories'; -import { getAccountInfo } from '../blitz/getAccountInfo'; import { PlayerStats } from './getPlayerStats'; -import { emptyAllStats } from './getStatsInPeriod/constants'; -export default async function getPlayerHistories( +export async function getPlayerHistories( server: Region, id: number, options?: Partial, diff --git a/src/core/blitzstars/getPlayerStats.ts b/packages/bot/src/core/blitzstars/getPlayerStats.ts similarity index 88% rename from src/core/blitzstars/getPlayerStats.ts rename to packages/bot/src/core/blitzstars/getPlayerStats.ts index 1ba54703a..0cd37eda4 100644 --- a/src/core/blitzstars/getPlayerStats.ts +++ b/packages/bot/src/core/blitzstars/getPlayerStats.ts @@ -1,5 +1,4 @@ -import { Region } from '../../constants/regions'; -import { BlitzStats } from '../statistics/compositeStats/constants'; +import { BlitzStats, Region } from '@blitzkit/core'; interface IndividualPlayerStats { clan: { clan_id: number; name: string; tag: string }; diff --git a/src/core/blitzstars/getStatsInPeriod/index.ts b/packages/bot/src/core/blitzstars/getStatsInPeriod.ts similarity index 89% rename from src/core/blitzstars/getStatsInPeriod/index.ts rename to packages/bot/src/core/blitzstars/getStatsInPeriod.ts index 66ee8e8e6..b3867fc1b 100644 --- a/src/core/blitzstars/getStatsInPeriod/index.ts +++ b/packages/bot/src/core/blitzstars/getStatsInPeriod.ts @@ -1,11 +1,11 @@ +import { BlitzStats, emptyAllStats, Region } from '@blitzkit/core'; import { Locale } from 'discord.js'; -import { Region } from '../../../constants/regions'; -import getTankHistories, { +import { DiffedTankStats } from './filterStats'; +import { + getTankHistories, TankHistories, TankHistoryRaw, -} from '../../blitzkit/getTankHistories'; -import { BlitzStats } from '../../statistics/compositeStats/constants'; -import { emptyAllStats } from './constants'; +} from './getTankHistories'; const emptyTankHistoryNode: TankHistoryRaw = { account_id: 0, @@ -16,13 +16,8 @@ const emptyTankHistoryNode: TankHistoryRaw = { all: emptyAllStats, }; -export interface DiffedTankStats { - diff: Record; - order: number[]; -} - // BIG TODO: merge this neatly with diffNormalizedTankStats -export default async function getStatsInPeriod( +export async function getStatsInPeriod( server: Region, id: number, start: number, diff --git a/src/core/blitzkit/getTankHistories.ts b/packages/bot/src/core/blitzstars/getTankHistories.ts similarity index 92% rename from src/core/blitzkit/getTankHistories.ts rename to packages/bot/src/core/blitzstars/getTankHistories.ts index 1a281beec..fd45a2f17 100644 --- a/src/core/blitzkit/getTankHistories.ts +++ b/packages/bot/src/core/blitzstars/getTankHistories.ts @@ -1,14 +1,12 @@ +import { Region, emptyAllStats, getTankStats } from '@blitzkit/core'; import { Locale } from 'discord.js'; -import { Region } from '../../constants/regions'; -import { UserError } from '../../hooks/userError'; import { GetHistoriesOptions, Histories, History, getHistoriesDefaultOptions, } from '../../types/histories'; -import getTankStats from '../blitz/getTankStats'; -import { emptyAllStats } from '../blitzstars/getStatsInPeriod/constants'; +import { UserError } from '../blitzkit/userError'; import { translator } from '../localization/translator'; export interface TankHistory extends History { @@ -34,7 +32,7 @@ const getTankHistoriesDefaultOptions: GetTankHistoriesOptions = { tankId: undefined, }; -export default async function getTankHistories( +export async function getTankHistories( server: Region, id: number, locale: Locale, diff --git a/src/core/blitzstars/tankAverages.ts b/packages/bot/src/core/blitzstars/tankAverages.ts similarity index 78% rename from src/core/blitzstars/tankAverages.ts rename to packages/bot/src/core/blitzstars/tankAverages.ts index a6b0b5bd4..66c6edd36 100644 --- a/src/core/blitzstars/tankAverages.ts +++ b/packages/bot/src/core/blitzstars/tankAverages.ts @@ -1,6 +1,5 @@ -import { context } from '../blitzkit/context'; -import { tankDefinitions } from '../blitzkit/tankDefinitions'; -import { BlitzStats } from '../statistics/compositeStats/constants'; +import { BlitzStats } from '@blitzkit/core'; +import { context } from '@blitzkit/core/src/blitzkit/context'; interface SpecialStats { winrate: number; @@ -80,19 +79,15 @@ export interface IndividualTankAverage { last_update: number; } -tankDefinitions; +export type BlitzStarsTankAverages = Record; -export type TankAverages = Record; - -export const tankAverages = fetch( - context === 'website' - ? '/api/tank-averages' - : 'https://www.blitzstars.com/api/tankaverages.json', +export const blitzStarsTankAverages = fetch( + 'https://www.blitzstars.com/api/tankaverages.json', ) .then((response) => response.json()) .then((json) => { if (context === 'server') { - const partialTankAverages: TankAverages = {}; + const partialTankAverages: BlitzStarsTankAverages = {}; (json as IndividualTankAverage[]).forEach((individualTankAverage) => { partialTankAverages[individualTankAverage.tank_id] = @@ -101,6 +96,6 @@ export const tankAverages = fetch( return partialTankAverages; } else { - return json as TankAverages; + return json as BlitzStarsTankAverages; } }); diff --git a/src/core/discord/addClanChoices.ts b/packages/bot/src/core/discord/addClanChoices.ts similarity index 88% rename from src/core/discord/addClanChoices.ts rename to packages/bot/src/core/discord/addClanChoices.ts index 7e3a46be3..c03d6f5b9 100644 --- a/src/core/discord/addClanChoices.ts +++ b/packages/bot/src/core/discord/addClanChoices.ts @@ -2,7 +2,7 @@ import { Locale, SlashCommandStringOption } from 'discord.js'; import { translator } from '../localization/translator'; import { localizationObject } from './localizationObject'; -export default function addClanChoices(option: SlashCommandStringOption) { +export function addClanChoices(option: SlashCommandStringOption) { const { translate } = translator(Locale.EnglishUS); return option diff --git a/src/core/discord/addFilterOptions.ts b/packages/bot/src/core/discord/addFilterOptions.ts similarity index 94% rename from src/core/discord/addFilterOptions.ts rename to packages/bot/src/core/discord/addFilterOptions.ts index 3c874f7e5..b3792ddd6 100644 --- a/src/core/discord/addFilterOptions.ts +++ b/packages/bot/src/core/discord/addFilterOptions.ts @@ -1,16 +1,13 @@ +import { TANK_CLASSES, TREE_TYPES } from '@blitzkit/core'; import { APIApplicationCommandOptionChoice, Locale, SlashCommandBuilder, SlashCommandSubcommandBuilder, } from 'discord.js'; -import { - TANK_CLASSES, - TREE_TYPES, -} from '../../components/Tanks/components/Item/constants'; import { translator } from '../localization/translator'; -import addTankChoices from './addTankChoices'; -import addTierChoices from './addTierChoices'; +import { addTankChoices } from './addTankChoices'; +import { addTierChoices } from './addTierChoices'; import { localizationObject } from './localizationObject'; export function addFilterOptions< diff --git a/src/core/discord/addPeriodSubCommands.ts b/packages/bot/src/core/discord/addPeriodSubCommands.ts similarity index 100% rename from src/core/discord/addPeriodSubCommands.ts rename to packages/bot/src/core/discord/addPeriodSubCommands.ts diff --git a/src/core/discord/addPeriodicFilterOptions.ts b/packages/bot/src/core/discord/addPeriodicFilterOptions.ts similarity index 85% rename from src/core/discord/addPeriodicFilterOptions.ts rename to packages/bot/src/core/discord/addPeriodicFilterOptions.ts index b3b0eb3ab..90da0bf7f 100644 --- a/src/core/discord/addPeriodicFilterOptions.ts +++ b/packages/bot/src/core/discord/addPeriodicFilterOptions.ts @@ -1,13 +1,13 @@ +import { gameDefinitions } from '@blitzkit/core'; import { SlashCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder, } from 'discord.js'; -import { gameDefinitions } from '../blitzkit/gameDefinitions'; import { addFilterOptions } from './addFilterOptions'; import { addPeriodSubCommands } from './addPeriodSubCommands'; -export default async function addPeriodicFilterOptions< +export async function addPeriodicFilterOptions< OptionType extends SlashCommandBuilder | SlashCommandSubcommandGroupBuilder, >( option: OptionType, diff --git a/src/core/discord/addRegionChoices.ts b/packages/bot/src/core/discord/addRegionChoices.ts similarity index 88% rename from src/core/discord/addRegionChoices.ts rename to packages/bot/src/core/discord/addRegionChoices.ts index 9e53ca323..489741f65 100644 --- a/src/core/discord/addRegionChoices.ts +++ b/packages/bot/src/core/discord/addRegionChoices.ts @@ -1,13 +1,13 @@ +import { REGIONS } from '@blitzkit/core'; import { APIApplicationCommandOptionChoice, Locale, SlashCommandStringOption, } from 'discord.js'; -import { REGIONS } from '../../constants/regions'; import { translator } from '../localization/translator'; import { localizationObject } from './localizationObject'; -export default function addRegionChoices(option: SlashCommandStringOption) { +export function addRegionChoices(option: SlashCommandStringOption) { const { t, translate } = translator(Locale.EnglishUS); return option diff --git a/src/core/discord/addTankChoices.ts b/packages/bot/src/core/discord/addTankChoices.ts similarity index 88% rename from src/core/discord/addTankChoices.ts rename to packages/bot/src/core/discord/addTankChoices.ts index b224fc2a9..2b96591bc 100644 --- a/src/core/discord/addTankChoices.ts +++ b/packages/bot/src/core/discord/addTankChoices.ts @@ -2,7 +2,7 @@ import { Locale, SlashCommandStringOption } from 'discord.js'; import { translator } from '../localization/translator'; import { localizationObject } from './localizationObject'; -export default function addTankChoices(option: SlashCommandStringOption) { +export function addTankChoices(option: SlashCommandStringOption) { const { translate } = translator(Locale.EnglishUS); return option diff --git a/src/core/discord/addTierChoices.ts b/packages/bot/src/core/discord/addTierChoices.ts similarity index 86% rename from src/core/discord/addTierChoices.ts rename to packages/bot/src/core/discord/addTierChoices.ts index 15de98aa6..70f8bdfde 100644 --- a/src/core/discord/addTierChoices.ts +++ b/packages/bot/src/core/discord/addTierChoices.ts @@ -1,14 +1,14 @@ +import { numberToRomanNumeral } from '@blitzkit/core'; import { APIApplicationCommandOptionChoice, Locale, SlashCommandStringOption, } from 'discord.js'; -import { range } from 'lodash'; +import { range } from 'lodash-es'; import { translator } from '../localization/translator'; -import numberToRomanNumeral from '../math/numberToRomanNumeral'; import { localizationObject } from './localizationObject'; -export default function addTierChoices(option: SlashCommandStringOption) { +export function addTierChoices(option: SlashCommandStringOption) { const { t, translate } = translator(Locale.EnglishUS); return option diff --git a/src/core/discord/addUsernameChoices.ts b/packages/bot/src/core/discord/addUsernameChoices.ts similarity index 87% rename from src/core/discord/addUsernameChoices.ts rename to packages/bot/src/core/discord/addUsernameChoices.ts index 3665908c5..14d69f6a2 100644 --- a/src/core/discord/addUsernameChoices.ts +++ b/packages/bot/src/core/discord/addUsernameChoices.ts @@ -2,7 +2,7 @@ import { Locale, SlashCommandStringOption } from 'discord.js'; import { translator } from '../localization/translator'; import { localizationObject } from './localizationObject'; -export default function addUsernameChoices(option: SlashCommandStringOption) { +export function addUsernameChoices(option: SlashCommandStringOption) { const { t } = translator(Locale.EnglishUS); return option diff --git a/src/core/discord/autocompleteClan/constants.ts b/packages/bot/src/core/discord/autocompleteClan/constants.ts similarity index 100% rename from src/core/discord/autocompleteClan/constants.ts rename to packages/bot/src/core/discord/autocompleteClan/constants.ts diff --git a/src/core/discord/autocompleteClan/index.ts b/packages/bot/src/core/discord/autocompleteClan/index.ts similarity index 91% rename from src/core/discord/autocompleteClan/index.ts rename to packages/bot/src/core/discord/autocompleteClan/index.ts index ea317791b..a36c15713 100644 --- a/src/core/discord/autocompleteClan/index.ts +++ b/packages/bot/src/core/discord/autocompleteClan/index.ts @@ -1,13 +1,13 @@ +import { searchClansAcrossRegions } from '@blitzkit/core'; import { ApplicationCommandOptionChoiceData, AutocompleteInteraction, CacheType, } from 'discord.js'; -import searchClansAcrossRegions from '../../blitz/searchClansAcrossRegions'; import { translator } from '../../localization/translator'; import { DISCORD_CHOICES_MAX_NAME_SIZE, OVERFLOW_SUFFIX } from './constants'; -export default async function autocompleteClan( +export async function autocompleteClan( interaction: AutocompleteInteraction, ) { const { translate } = translator(interaction.locale); diff --git a/src/core/discord/autocompleteTanks.ts b/packages/bot/src/core/discord/autocompleteTanks.ts similarity index 82% rename from src/core/discord/autocompleteTanks.ts rename to packages/bot/src/core/discord/autocompleteTanks.ts index 39e2fd27e..7acafcb94 100644 --- a/src/core/discord/autocompleteTanks.ts +++ b/packages/bot/src/core/discord/autocompleteTanks.ts @@ -1,20 +1,21 @@ +import { fetchTankNames, TankType } from '@blitzkit/core'; import { ApplicationCommandOptionChoiceData, AutocompleteInteraction, CacheType, } from 'discord.js'; import { go } from 'fuzzysort'; -import { tankNames } from '../blitzkit/tankDefinitions/tankNames'; import { DISCORD_CHOICES_MAX_NAME_SIZE, OVERFLOW_SUFFIX, } from './autocompleteClan/constants'; +import { tankNames } from '../blitzkit/nonBlockingPromises'; -export const tankNamesTechTreeOnly = tankNames.then((names) => - names.filter((tank) => tank.treeType === 'researchable'), +export const tankNamesTechTreeOnly = fetchTankNames().then((names) => + names.filter((tank) => tank.treeType === TankType.RESEARCHABLE), ); -export default async function autocompleteTanks( +export async function autocompleteTanks( interaction: AutocompleteInteraction, techTreeOnly = false, fields = ['tank'], diff --git a/src/core/discord/autocompleteUsername.ts b/packages/bot/src/core/discord/autocompleteUsername.ts similarity index 91% rename from src/core/discord/autocompleteUsername.ts rename to packages/bot/src/core/discord/autocompleteUsername.ts index 7f459d1fd..2e5d9b18f 100644 --- a/src/core/discord/autocompleteUsername.ts +++ b/packages/bot/src/core/discord/autocompleteUsername.ts @@ -1,16 +1,16 @@ +import { searchPlayersAcrossRegions } from '@blitzkit/core'; import { ApplicationCommandOptionChoiceData, AutocompleteInteraction, CacheType, } from 'discord.js'; -import searchPlayersAcrossRegions from '../blitz/searchPlayersAcrossRegions'; import { translator } from '../localization/translator'; import { DISCORD_CHOICES_MAX_NAME_SIZE, OVERFLOW_SUFFIX, } from './autocompleteClan/constants'; -export default async function autocompleteUsername( +export async function autocompleteUsername( interaction: AutocompleteInteraction, ) { const { translate } = translator(interaction.locale); diff --git a/src/core/discord/buttonLink.ts b/packages/bot/src/core/discord/buttonLink.ts similarity index 90% rename from src/core/discord/buttonLink.ts rename to packages/bot/src/core/discord/buttonLink.ts index 5df2dfdf9..5c1068f15 100644 --- a/src/core/discord/buttonLink.ts +++ b/packages/bot/src/core/discord/buttonLink.ts @@ -4,7 +4,7 @@ import { ComponentEmojiResolvable, } from 'discord.js'; -export default function buttonLink( +export function buttonLink( url: string, label: string, emoji?: ComponentEmojiResolvable, diff --git a/src/core/discord/buttonPrimary.ts b/packages/bot/src/core/discord/buttonPrimary.ts similarity index 89% rename from src/core/discord/buttonPrimary.ts rename to packages/bot/src/core/discord/buttonPrimary.ts index 9a38a56b5..6c78a14a8 100644 --- a/src/core/discord/buttonPrimary.ts +++ b/packages/bot/src/core/discord/buttonPrimary.ts @@ -4,7 +4,7 @@ import { ComponentEmojiResolvable, } from 'discord.js'; -export default function buttonPrimary( +export function buttonPrimary( id: string, label: string, emoji?: ComponentEmojiResolvable, diff --git a/src/core/discord/buttonRefresh.ts b/packages/bot/src/core/discord/buttonRefresh.ts similarity index 90% rename from src/core/discord/buttonRefresh.ts rename to packages/bot/src/core/discord/buttonRefresh.ts index 5802a2df2..caef84b41 100644 --- a/src/core/discord/buttonRefresh.ts +++ b/packages/bot/src/core/discord/buttonRefresh.ts @@ -1,6 +1,6 @@ import { ChatInputCommandInteraction } from 'discord.js'; import { translator } from '../localization/translator'; -import buttonPrimary from './buttonPrimary'; +import { buttonPrimary } from './buttonPrimary'; export function buttonRefresh( interaction: ChatInputCommandInteraction, diff --git a/src/core/discord/client.ts b/packages/bot/src/core/discord/client.ts similarity index 67% rename from src/core/discord/client.ts rename to packages/bot/src/core/discord/client.ts index c911a2408..5e9931914 100644 --- a/src/core/discord/client.ts +++ b/packages/bot/src/core/discord/client.ts @@ -1,6 +1,6 @@ import { Client, GatewayIntentBits } from 'discord.js'; -import interactionCreate from '../../events/interactionCreate'; -import ready from '../../events/ready'; +import { interactionCreate } from '../../events/interactionCreate'; +import { ready } from '../../events/ready'; export const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers], diff --git a/src/constants/colors.ts b/packages/bot/src/core/discord/colors.ts similarity index 100% rename from src/constants/colors.ts rename to packages/bot/src/core/discord/colors.ts diff --git a/src/core/discord/commandToURL.ts b/packages/bot/src/core/discord/commandToURL.ts similarity index 95% rename from src/core/discord/commandToURL.ts rename to packages/bot/src/core/discord/commandToURL.ts index bad50d302..7ac12213d 100644 --- a/src/core/discord/commandToURL.ts +++ b/packages/bot/src/core/discord/commandToURL.ts @@ -7,7 +7,7 @@ export interface Parameters { // TODO: automatically infer command options??? // but how would that work with the region and id options? -export default function commandToURL( +export function commandToURL( interaction: ChatInputCommandInteraction, parameters?: Parameters, ) { diff --git a/src/core/discord/createLocalizedCommand.ts b/packages/bot/src/core/discord/createLocalizedCommand.ts similarity index 100% rename from src/core/discord/createLocalizedCommand.ts rename to packages/bot/src/core/discord/createLocalizedCommand.ts diff --git a/src/core/discord/embedInfo.ts b/packages/bot/src/core/discord/embedInfo.ts similarity index 60% rename from src/core/discord/embedInfo.ts rename to packages/bot/src/core/discord/embedInfo.ts index 75ac86c80..5359e3212 100644 --- a/src/core/discord/embedInfo.ts +++ b/packages/bot/src/core/discord/embedInfo.ts @@ -1,7 +1,7 @@ import { EmbedBuilder } from 'discord.js'; -import { ACCENT_COLOR } from '../../constants/colors'; +import { ACCENT_COLOR } from './colors'; -export default function embedInfo(title: string, description: string) { +export function embedInfo(title: string, description: string) { const embed = new EmbedBuilder() .setColor(ACCENT_COLOR) .setDescription(description); diff --git a/src/core/discord/embedNegative.ts b/packages/bot/src/core/discord/embedNegative.ts similarity index 54% rename from src/core/discord/embedNegative.ts rename to packages/bot/src/core/discord/embedNegative.ts index 35704b20e..1d520500a 100644 --- a/src/core/discord/embedNegative.ts +++ b/packages/bot/src/core/discord/embedNegative.ts @@ -1,7 +1,7 @@ import { EmbedBuilder } from 'discord.js'; -import { NEGATIVE_COLOR } from '../../constants/colors'; +import { NEGATIVE_COLOR } from './colors'; -export default function embedNegative(title: string, description: string) { +export function embedNegative(title: string, description: string) { return new EmbedBuilder() .setColor(NEGATIVE_COLOR) .setTitle(title) diff --git a/src/core/discord/embedPositive.ts b/packages/bot/src/core/discord/embedPositive.ts similarity index 54% rename from src/core/discord/embedPositive.ts rename to packages/bot/src/core/discord/embedPositive.ts index 47174a0d1..5f157a851 100644 --- a/src/core/discord/embedPositive.ts +++ b/packages/bot/src/core/discord/embedPositive.ts @@ -1,7 +1,7 @@ import { EmbedBuilder } from 'discord.js'; -import { POSITIVE_COLOR } from '../../constants/colors'; +import { POSITIVE_COLOR } from './colors'; -export default function embedPositive(title: string, description: string) { +export function embedPositive(title: string, description: string) { return new EmbedBuilder() .setColor(POSITIVE_COLOR) .setTitle(title) diff --git a/src/core/discord/embedWarning.ts b/packages/bot/src/core/discord/embedWarning.ts similarity index 54% rename from src/core/discord/embedWarning.ts rename to packages/bot/src/core/discord/embedWarning.ts index 3148f7a7a..0cb912d9e 100644 --- a/src/core/discord/embedWarning.ts +++ b/packages/bot/src/core/discord/embedWarning.ts @@ -1,7 +1,7 @@ import { EmbedBuilder } from 'discord.js'; -import { WARNING_COLOR } from '../../constants/colors'; +import { WARNING_COLOR } from './colors'; -export default function embedWarning(title: string, description: string) { +export function embedWarning(title: string, description: string) { return new EmbedBuilder() .setColor(WARNING_COLOR) .setTitle(title) diff --git a/src/core/discord/getCustomPeriodParams.ts b/packages/bot/src/core/discord/getCustomPeriodParams.ts similarity index 100% rename from src/core/discord/getCustomPeriodParams.ts rename to packages/bot/src/core/discord/getCustomPeriodParams.ts diff --git a/src/core/discord/getFiltersFromButton.ts b/packages/bot/src/core/discord/getFiltersFromButton.ts similarity index 84% rename from src/core/discord/getFiltersFromButton.ts rename to packages/bot/src/core/discord/getFiltersFromButton.ts index 3ad62a16c..4aa8f1716 100644 --- a/src/core/discord/getFiltersFromButton.ts +++ b/packages/bot/src/core/discord/getFiltersFromButton.ts @@ -1,6 +1,5 @@ +import { StatFilters, TreeType } from '@blitzkit/core'; import { ButtonInteraction } from 'discord.js'; -import { TreeType } from '../../components/Tanks'; -import { StatFilters } from '../statistics/filterStats'; export function getFiltersFromButton(interaction: ButtonInteraction) { const url = new URL(`https://example.com/${interaction.customId}`); diff --git a/src/core/discord/getFiltersFromCommand.ts b/packages/bot/src/core/discord/getFiltersFromCommand.ts similarity index 81% rename from src/core/discord/getFiltersFromCommand.ts rename to packages/bot/src/core/discord/getFiltersFromCommand.ts index 0ebf09157..ac15de9ff 100644 --- a/src/core/discord/getFiltersFromCommand.ts +++ b/packages/bot/src/core/discord/getFiltersFromCommand.ts @@ -1,7 +1,6 @@ +import { StatFilters, TreeType } from '@blitzkit/core'; import { ChatInputCommandInteraction } from 'discord.js'; -import { TreeType } from '../../components/Tanks'; -import resolveTankId from '../blitz/resolveTankId'; -import { StatFilters } from '../statistics/filterStats'; +import { resolveTankId } from '../blitz/resolveTankId'; export async function getFiltersFromCommand( interaction: ChatInputCommandInteraction, diff --git a/src/core/discord/getPeriodOptionName.ts b/packages/bot/src/core/discord/getPeriodOptionName.ts similarity index 100% rename from src/core/discord/getPeriodOptionName.ts rename to packages/bot/src/core/discord/getPeriodOptionName.ts diff --git a/src/core/discord/localizationObject.ts b/packages/bot/src/core/discord/localizationObject.ts similarity index 100% rename from src/core/discord/localizationObject.ts rename to packages/bot/src/core/discord/localizationObject.ts diff --git a/src/core/discord/manager.ts b/packages/bot/src/core/discord/manager.ts similarity index 77% rename from src/core/discord/manager.ts rename to packages/bot/src/core/discord/manager.ts index 830c32a80..280d1d67d 100644 --- a/src/core/discord/manager.ts +++ b/packages/bot/src/core/discord/manager.ts @@ -1,5 +1,5 @@ +import { assertSecret } from '@blitzkit/core'; import { ShardingManager } from 'discord.js'; -import { assertSecret } from '../blitzkit/secret'; export const manager = new ShardingManager('dist/bot/workers/bot.js', { token: assertSecret(process.env.DISCORD_TOKEN), diff --git a/src/core/discord/markdownTable.ts b/packages/bot/src/core/discord/markdownTable.ts similarity index 81% rename from src/core/discord/markdownTable.ts rename to packages/bot/src/core/discord/markdownTable.ts index af2f3a475..6ad0b6f64 100644 --- a/src/core/discord/markdownTable.ts +++ b/packages/bot/src/core/discord/markdownTable.ts @@ -1,7 +1,7 @@ export type TableInputEntry = [string, string | number] | []; export type TableInput = TableInputEntry[]; -export default function markdownTable(input: TableInput) { +export function markdownTable(input: TableInput) { return input .filter((array) => array[1] !== undefined) .map((array) => (array.length === 0 ? '' : `**${array[0]}**: ${array[1]}`)) diff --git a/src/core/discord/normalizeInteractionReturnable.ts b/packages/bot/src/core/discord/normalizeInteractionReturnable.ts similarity index 94% rename from src/core/discord/normalizeInteractionReturnable.ts rename to packages/bot/src/core/discord/normalizeInteractionReturnable.ts index a6532f2e6..3996f98bf 100644 --- a/src/core/discord/normalizeInteractionReturnable.ts +++ b/packages/bot/src/core/discord/normalizeInteractionReturnable.ts @@ -9,10 +9,10 @@ import { } from 'discord.js'; import { InteractionReturnable } from '../../events/interactionCreate'; import { Writeable } from '../../types/writable'; -import jsxToPngThreaded from '../blitzkit/jsxToPngThreaded'; +import { jsxToPngThreaded } from '../blitzkit/jsxToPngThreaded'; import { RenderConfiguration } from '../blitzkit/renderConfiguration'; -export default async function normalizeInteractionReturnable( +export async function normalizeInteractionReturnable( returnable: InteractionReturnable, ) { const images: [number, Buffer][] = []; diff --git a/src/core/discord/psa.ts b/packages/bot/src/core/discord/psa.ts similarity index 100% rename from src/core/discord/psa.ts rename to packages/bot/src/core/discord/psa.ts diff --git a/src/core/discord/resolveClanFromCommand.ts b/packages/bot/src/core/discord/resolveClanFromCommand.ts similarity index 78% rename from src/core/discord/resolveClanFromCommand.ts rename to packages/bot/src/core/discord/resolveClanFromCommand.ts index 5b062736b..526da9b79 100644 --- a/src/core/discord/resolveClanFromCommand.ts +++ b/packages/bot/src/core/discord/resolveClanFromCommand.ts @@ -1,12 +1,11 @@ +import { Region, searchClansAcrossRegions } from '@blitzkit/core'; import { ChatInputCommandInteraction } from 'discord.js'; import markdownEscape from 'markdown-escape'; -import { Region } from '../../constants/regions'; -import { UserError } from '../../hooks/userError'; -import searchClansAcrossRegions from '../blitz/searchClansAcrossRegions'; import { translator } from '../localization/translator'; import { serverAndIdPattern } from './resolvePlayerFromCommand/constants'; +import { UserError } from '../blitzkit/userError'; -export default async function resolveClanFromCommand( +export async function resolveClanFromCommand( interaction: ChatInputCommandInteraction, ) { const { translate } = translator(interaction.locale); diff --git a/src/core/discord/resolvePeriodFromButton.ts b/packages/bot/src/core/discord/resolvePeriodFromButton.ts similarity index 81% rename from src/core/discord/resolvePeriodFromButton.ts rename to packages/bot/src/core/discord/resolvePeriodFromButton.ts index d0bebfb6e..c9472d41f 100644 --- a/src/core/discord/resolvePeriodFromButton.ts +++ b/packages/bot/src/core/discord/resolvePeriodFromButton.ts @@ -1,13 +1,12 @@ +import { getTimeDaysAgo, Region } from '@blitzkit/core'; import { ButtonInteraction } from 'discord.js'; -import { Region } from '../../constants/regions'; -import getPeriodNow from '../blitzkit/getPeriodNow'; -import getPeriodStart from '../blitzkit/getPeriodStart'; -import getTimeDaysAgo from '../blitzkit/getTimeDaysAgo'; +import { getPeriodNow } from '../blitzkit/getPeriodNow'; +import { getPeriodStart } from '../blitzkit/getPeriodStart'; import { PeriodType } from './addPeriodSubCommands'; import { getPeriodOptionName } from './getPeriodOptionName'; import { ResolvedPeriod } from './resolvePeriodFromCommand'; -export default function resolvePeriodFromButton( +export function resolvePeriodFromButton( region: Region, interaction: ButtonInteraction, ) { diff --git a/src/core/discord/resolvePeriodFromCommand.ts b/packages/bot/src/core/discord/resolvePeriodFromCommand.ts similarity index 84% rename from src/core/discord/resolvePeriodFromCommand.ts rename to packages/bot/src/core/discord/resolvePeriodFromCommand.ts index c4084dd74..61569e087 100644 --- a/src/core/discord/resolvePeriodFromCommand.ts +++ b/packages/bot/src/core/discord/resolvePeriodFromCommand.ts @@ -1,8 +1,7 @@ +import { getTimeDaysAgo, Region } from '@blitzkit/core'; import { CacheType, ChatInputCommandInteraction } from 'discord.js'; -import { Region } from '../../constants/regions'; -import getPeriodNow from '../blitzkit/getPeriodNow'; -import getPeriodStart from '../blitzkit/getPeriodStart'; -import getTimeDaysAgo from '../blitzkit/getTimeDaysAgo'; +import { getPeriodNow } from '../blitzkit/getPeriodNow'; +import { getPeriodStart } from '../blitzkit/getPeriodStart'; import { translator } from '../localization/translator'; import { PeriodType } from './addPeriodSubCommands'; import { getPeriodOptionName } from './getPeriodOptionName'; @@ -13,7 +12,7 @@ export interface ResolvedPeriod { end: number; } -export default function resolvePeriodFromCommand( +export function resolvePeriodFromCommand( region: Region, interaction: ChatInputCommandInteraction, forcedPeriod?: PeriodType, diff --git a/src/core/discord/resolvePlayerFromButton.ts b/packages/bot/src/core/discord/resolvePlayerFromButton.ts similarity index 69% rename from src/core/discord/resolvePlayerFromButton.ts rename to packages/bot/src/core/discord/resolvePlayerFromButton.ts index 8d5a5a4b1..01cf30ac3 100644 --- a/src/core/discord/resolvePlayerFromButton.ts +++ b/packages/bot/src/core/discord/resolvePlayerFromButton.ts @@ -1,10 +1,8 @@ +import { Region } from '@blitzkit/core'; import { ButtonInteraction } from 'discord.js'; -import { Region } from '../../constants/regions'; import { ResolvedPlayer } from './resolvePlayerFromCommand'; -export default async function resolvePlayerFromButton( - interaction: ButtonInteraction, -) { +export async function resolvePlayerFromButton(interaction: ButtonInteraction) { const url = new URL(`https://exmaple.com/${interaction.customId}`); return { diff --git a/src/core/discord/resolvePlayerFromCommand/constants.ts b/packages/bot/src/core/discord/resolvePlayerFromCommand/constants.ts similarity index 100% rename from src/core/discord/resolvePlayerFromCommand/constants.ts rename to packages/bot/src/core/discord/resolvePlayerFromCommand/constants.ts diff --git a/src/core/discord/resolvePlayerFromCommand/index.ts b/packages/bot/src/core/discord/resolvePlayerFromCommand/index.ts similarity index 81% rename from src/core/discord/resolvePlayerFromCommand/index.ts rename to packages/bot/src/core/discord/resolvePlayerFromCommand/index.ts index e6cdf460a..c8b269d7d 100644 --- a/src/core/discord/resolvePlayerFromCommand/index.ts +++ b/packages/bot/src/core/discord/resolvePlayerFromCommand/index.ts @@ -1,18 +1,17 @@ +import { Region, searchPlayersAcrossRegions } from '@blitzkit/core'; import { CacheType, ChatInputCommandInteraction } from 'discord.js'; import markdownEscape from 'markdown-escape'; -import { Region } from '../../../constants/regions'; -import { UserError } from '../../../hooks/userError'; -import searchPlayersAcrossRegions from '../../blitz/searchPlayersAcrossRegions'; -import { getBlitzFromDiscord } from '../../blitzkit/discordBlitzLink'; +import { getBlitzFromDiscord } from '../../blitzkit/getBlitzFromDiscord'; import { translator } from '../../localization/translator'; import { serverAndIdPattern } from './constants'; +import { UserError } from '../../blitzkit/userError'; export interface ResolvedPlayer { region: Region; id: number; } -export default async function resolvePlayerFromCommand( +export async function resolvePlayerFromCommand( interaction: ChatInputCommandInteraction, ) { const { t, translate } = translator(interaction.locale); diff --git a/src/core/localization/strings/constants.ts b/packages/bot/src/core/localization/strings/constants.ts similarity index 100% rename from src/core/localization/strings/constants.ts rename to packages/bot/src/core/localization/strings/constants.ts diff --git a/src/core/localization/strings/index.ts b/packages/bot/src/core/localization/strings/index.ts similarity index 100% rename from src/core/localization/strings/index.ts rename to packages/bot/src/core/localization/strings/index.ts diff --git a/src/core/localization/translator.ts b/packages/bot/src/core/localization/translator.ts similarity index 100% rename from src/core/localization/translator.ts rename to packages/bot/src/core/localization/translator.ts diff --git a/src/constants/radixColors.ts b/packages/bot/src/core/radix/radixColors.ts similarity index 100% rename from src/constants/radixColors.ts rename to packages/bot/src/core/radix/radixColors.ts diff --git a/src/core/streams/wotbreplay.ts b/packages/bot/src/core/streams/wotbreplay.ts similarity index 97% rename from src/core/streams/wotbreplay.ts rename to packages/bot/src/core/streams/wotbreplay.ts index 07a25ebbd..c62a18a11 100644 --- a/src/core/streams/wotbreplay.ts +++ b/packages/bot/src/core/streams/wotbreplay.ts @@ -1,8 +1,8 @@ +import { ReadStream } from '@blitzkit/core'; import AdmZip from 'adm-zip'; import { readFile, writeFile } from 'fs/promises'; import { Parser } from 'pickleparser'; import protobuf from 'protobufjs'; -import { ReadStream } from './buffer'; interface WotbReplayMetaJson { version: string; diff --git a/src/events/interactionCreate/handlers/autocomplete.ts b/packages/bot/src/events/interactionCreate/handlers/autocomplete.ts similarity index 88% rename from src/events/interactionCreate/handlers/autocomplete.ts rename to packages/bot/src/events/interactionCreate/handlers/autocomplete.ts index c688cd491..78b9f7afb 100644 --- a/src/events/interactionCreate/handlers/autocomplete.ts +++ b/packages/bot/src/events/interactionCreate/handlers/autocomplete.ts @@ -1,7 +1,7 @@ import { AutocompleteInteraction, CacheType } from 'discord.js'; import { commands } from '..'; -export default async function handleAutocomplete( +export async function handleAutocomplete( interaction: AutocompleteInteraction, ) { const command = (await commands)[interaction.commandName]; diff --git a/src/events/interactionCreate/handlers/button.tsx b/packages/bot/src/events/interactionCreate/handlers/button.tsx similarity index 78% rename from src/events/interactionCreate/handlers/button.tsx rename to packages/bot/src/events/interactionCreate/handlers/button.tsx index 9a0be8196..96b78e4a6 100644 --- a/src/events/interactionCreate/handlers/button.tsx +++ b/packages/bot/src/events/interactionCreate/handlers/button.tsx @@ -1,10 +1,8 @@ import { ButtonInteraction, CacheType } from 'discord.js'; import { commands } from '..'; -import normalizeInteractionReturnable from '../../../core/discord/normalizeInteractionReturnable'; +import { normalizeInteractionReturnable } from '../../../core/discord/normalizeInteractionReturnable'; -export default async function handleButton( - interaction: ButtonInteraction, -) { +export async function handleButton(interaction: ButtonInteraction) { await interaction.deferUpdate(); const url = new URL(`https://example.com/${interaction.customId}`); diff --git a/src/events/interactionCreate/handlers/chatInputCommand.ts b/packages/bot/src/events/interactionCreate/handlers/chatInputCommand.ts similarity index 92% rename from src/events/interactionCreate/handlers/chatInputCommand.ts rename to packages/bot/src/events/interactionCreate/handlers/chatInputCommand.ts index 807861844..e75a0f8d3 100644 --- a/src/events/interactionCreate/handlers/chatInputCommand.ts +++ b/packages/bot/src/events/interactionCreate/handlers/chatInputCommand.ts @@ -8,15 +8,15 @@ import { InteractionReplyOptions, } from 'discord.js'; import { InteractionRawReturnable, commands } from '..'; -import buttonLink from '../../../core/discord/buttonLink'; -import embedWarning from '../../../core/discord/embedWarning'; -import normalizeInteractionReturnable from '../../../core/discord/normalizeInteractionReturnable'; +import { buttonLink } from '../../../core/discord/buttonLink'; +import { embedWarning } from '../../../core/discord/embedWarning'; +import { normalizeInteractionReturnable } from '../../../core/discord/normalizeInteractionReturnable'; import { psa } from '../../../core/discord/psa'; import { translator } from '../../../core/localization/translator'; -import { UserError } from '../../../hooks/userError'; import { Writeable } from '../../../types/writable'; +import { UserError } from '../../../core/blitzkit/userError'; -export default async function handleChatInputCommand( +export async function handleChatInputCommand( interaction: ChatInputCommandInteraction, ) { const awaitedCommands = await commands; diff --git a/src/events/interactionCreate/index.ts b/packages/bot/src/events/interactionCreate/index.ts similarity index 92% rename from src/events/interactionCreate/index.ts rename to packages/bot/src/events/interactionCreate/index.ts index 53ae9dbb9..6b8d84021 100644 --- a/src/events/interactionCreate/index.ts +++ b/packages/bot/src/events/interactionCreate/index.ts @@ -1,3 +1,4 @@ +import { assertSecret } from '@blitzkit/core'; import { AttachmentBuilder, AutocompleteInteraction, @@ -33,10 +34,9 @@ import { searchPlayersCommand } from '../../commands/searchPlayers'; import { statsCommand } from '../../commands/stats'; import { todayCommand } from '../../commands/today'; import { RenderConfiguration } from '../../core/blitzkit/renderConfiguration'; -import { assertSecret } from '../../core/blitzkit/secret'; -import handleAutocomplete from './handlers/autocomplete'; -import handleButton from './handlers/button'; -import handleChatInputCommand from './handlers/chatInputCommand'; +import { handleAutocomplete } from './handlers/autocomplete'; +import { handleButton } from './handlers/button'; +import { handleChatInputCommand } from './handlers/chatInputCommand'; export type InteractionRawReturnable = | string @@ -130,9 +130,7 @@ commands.then((awaitedCommands) => { ); }); -export default async function interactionCreate( - interaction: Interaction, -) { +export async function interactionCreate(interaction: Interaction) { if (interaction.isAutocomplete()) { handleAutocomplete(interaction); } else if (interaction.isChatInputCommand()) { diff --git a/src/events/ready.ts b/packages/bot/src/events/ready.ts similarity index 93% rename from src/events/ready.ts rename to packages/bot/src/events/ready.ts index a6278013e..135767422 100644 --- a/src/events/ready.ts +++ b/packages/bot/src/events/ready.ts @@ -1,6 +1,6 @@ import { ActivityType, Client } from 'discord.js'; -export default function ready(client: Client) { +export function ready(client: Client) { console.log(`🟒 Launched bot ${client.shard?.ids[0] ?? 'default'}`); const activities: (() => string)[] = [ diff --git a/src/index.ts b/packages/bot/src/index.ts similarity index 100% rename from src/index.ts rename to packages/bot/src/index.ts diff --git a/src/stitches.config.ts b/packages/bot/src/stitches.config.ts similarity index 100% rename from src/stitches.config.ts rename to packages/bot/src/stitches.config.ts diff --git a/src/types/global.d.ts b/packages/bot/src/types.d.ts similarity index 64% rename from src/types/global.d.ts rename to packages/bot/src/types.d.ts index e5265e5ce..29102695c 100644 --- a/src/types/global.d.ts +++ b/packages/bot/src/types.d.ts @@ -1,5 +1,3 @@ -/// - declare module '*.ttf' { const path: string; export default path; diff --git a/src/types/histories.ts b/packages/bot/src/types/histories.ts similarity index 87% rename from src/types/histories.ts rename to packages/bot/src/types/histories.ts index 47309fae3..322d807a6 100644 --- a/src/types/histories.ts +++ b/packages/bot/src/types/histories.ts @@ -1,6 +1,6 @@ // a cleaner simplification of Blitz Stars' histories because it's a mess there -import { BlitzStats } from '../core/statistics/compositeStats/constants'; +import { BlitzStats } from '@blitzkit/core'; export interface History { all: BlitzStats; diff --git a/src/types/possiblyPromise.ts b/packages/bot/src/types/possiblyPromise.ts similarity index 100% rename from src/types/possiblyPromise.ts rename to packages/bot/src/types/possiblyPromise.ts diff --git a/packages/bot/src/types/ttf.d.ts b/packages/bot/src/types/ttf.d.ts new file mode 100644 index 000000000..29102695c --- /dev/null +++ b/packages/bot/src/types/ttf.d.ts @@ -0,0 +1,4 @@ +declare module '*.ttf' { + const path: string; + export default path; +} diff --git a/src/types/writable.ts b/packages/bot/src/types/writable.ts similarity index 100% rename from src/types/writable.ts rename to packages/bot/src/types/writable.ts diff --git a/src/workers/bot.ts b/packages/bot/src/workers/bot.ts similarity index 81% rename from src/workers/bot.ts rename to packages/bot/src/workers/bot.ts index 948916ed5..513ad305e 100644 --- a/src/workers/bot.ts +++ b/packages/bot/src/workers/bot.ts @@ -1,5 +1,5 @@ +import { assertSecret } from '@blitzkit/core'; import { registerProcesses } from '../core/blitzkit/processes'; -import { assertSecret } from '../core/blitzkit/secret'; import { client } from '../core/discord/client'; console.log(`🟑 Launching bot ${client.shard?.ids[0]}`); diff --git a/src/workers/render.ts b/packages/bot/src/workers/render.ts similarity index 80% rename from src/workers/render.ts rename to packages/bot/src/workers/render.ts index 122e69ead..0950d7028 100644 --- a/src/workers/render.ts +++ b/packages/bot/src/workers/render.ts @@ -1,5 +1,5 @@ import { parentPort, threadId } from 'worker_threads'; -import svgToPng from '../core/blitzkit/svgToPng'; +import { svgToPng } from '../core/blitzkit/svgToPng'; console.log(`🟒 Launched render worker ${threadId}`); diff --git a/packages/bot/tsconfig.json b/packages/bot/tsconfig.json new file mode 100644 index 000000000..52d43eaaa --- /dev/null +++ b/packages/bot/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*"] +} diff --git a/src/lang/en-US.json b/packages/core/lang/en-US.json similarity index 98% rename from src/lang/en-US.json rename to packages/core/lang/en-US.json index 9902033f5..7a22c9011 100644 --- a/src/lang/en-US.json +++ b/packages/core/lang/en-US.json @@ -52,23 +52,26 @@ }, "tank_class_short": { - "lightTank": "Light", - "mediumTank": "Medium", - "heavyTank": "Heavy", - "AT-SPG": "TD" + "-1": "unrecognized", + "0": "Light", + "1": "Medium", + "2": "Heavy", + "3": "TD" }, "tank_class_medium": { - "lightTank": "Light", - "mediumTank": "Medium", - "heavyTank": "Heavy", - "AT-SPG": "Tank destroyer" + "-1": "unrecognized", + "0": "Light", + "1": "Medium", + "2": "Heavy", + "3": "Tank destroyer" }, "tree_type": { - "researchable": "Tech tree", - "premium": "Premium", - "collector": "Collector" + "-1": "unrecognized", + "0": "Tech tree", + "1": "Premium", + "2": "Collector" }, "regions": { diff --git a/src/lang/es-ES.json b/packages/core/lang/es-ES.json similarity index 100% rename from src/lang/es-ES.json rename to packages/core/lang/es-ES.json diff --git a/src/lang/hr.json b/packages/core/lang/hr.json similarity index 100% rename from src/lang/hr.json rename to packages/core/lang/hr.json diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 000000000..6c1379350 --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,26 @@ +{ + "name": "@blitzkit/core", + "private": true, + "type": "module", + "main": "src/index.ts", + "dependencies": { + "@octokit/plugin-throttling": "^8.2.0", + "@octokit/rest": "^20.1.1", + "@prisma/client": "^5.19.1", + "adm-zip": "^0.5.16", + "crc": "^4.3.2", + "dotenv": "^16.4.5", + "lodash": "^4.17.21", + "lz4js": "^0.2.0", + "pickleparser": "^0.2.1", + "protobufjs": "^7.4.0", + "sharp": "^0.33.5", + "ts-proto": "^2.2.2", + "yaml": "^2.5.0" + }, + "devDependencies": { + "@types/adm-zip": "^0.5.5", + "@types/lodash": "^4.17.7", + "@types/lz4js": "^0.2.1" + } +} diff --git a/src/core/blitz/canSplash.ts b/packages/core/src/blitz/canSplash.ts similarity index 61% rename from src/core/blitz/canSplash.ts rename to packages/core/src/blitz/canSplash.ts index 9d1b32067..d9b4a8c5b 100644 --- a/src/core/blitz/canSplash.ts +++ b/packages/core/src/blitz/canSplash.ts @@ -1,4 +1,4 @@ -import { ShellDefinition, ShellType } from '../blitzkit/tankDefinitions'; +import { type ShellDefinition, ShellType } from '@blitzkit/core'; export function canSplash(type: ShellDefinition['type']): type is ShellType.HE { return type === ShellType.HE; diff --git a/src/types/clanList.ts b/packages/core/src/blitz/clans.ts similarity index 100% rename from src/types/clanList.ts rename to packages/core/src/blitz/clans.ts diff --git a/src/core/blitzstars/getStatsInPeriod/constants.ts b/packages/core/src/blitz/constants.ts similarity index 52% rename from src/core/blitzstars/getStatsInPeriod/constants.ts rename to packages/core/src/blitz/constants.ts index bee13b582..f2ae72204 100644 --- a/src/core/blitzstars/getStatsInPeriod/constants.ts +++ b/packages/core/src/blitz/constants.ts @@ -1,4 +1,14 @@ -import { BlitzStats } from '../../statistics/compositeStats/constants'; +import { TankClass } from '../protos'; +import { BlitzStats } from '../statistics'; + +export const TREE_TYPES = ['researchable', 'premium', 'collector'] as const; + +export const TANK_CLASSES = [ + TankClass.LIGHT, + TankClass.MEDIUM, + TankClass.HEAVY, + TankClass.TANK_DESTROYER, +] as const; export const emptyAllStats: BlitzStats = { battles: 0, diff --git a/packages/core/src/blitz/equipmentPrice.ts b/packages/core/src/blitz/equipmentPrice.ts new file mode 100644 index 000000000..1d263c3d3 --- /dev/null +++ b/packages/core/src/blitz/equipmentPrice.ts @@ -0,0 +1,15 @@ +import { Vector3Tuple } from 'three'; +import { Tier } from '../protos'; + +export const equipmentPriceMatrix: Record = { + [Tier.I]: [100, 200, 300], + [Tier.II]: [200, 300, 400], + [Tier.III]: [400, 500, 600], + [Tier.IV]: [4000, 5000, 6000], + [Tier.V]: [40_000, 50_000, 60_000], + [Tier.VI]: [100_000, 120_000, 140_000], + [Tier.VII]: [150_000, 170_000, 190_000], + [Tier.VIII]: [200_000, 225_000, 250_000], + [Tier.IX]: [250_000, 275_000, 300_000], + [Tier.X]: [300_000, 350_000, 400_000], +}; diff --git a/src/core/blitz/fetchBlitz.ts b/packages/core/src/blitz/fetchBlitz.ts similarity index 88% rename from src/core/blitz/fetchBlitz.ts rename to packages/core/src/blitz/fetchBlitz.ts index 5194d1cbe..fb17c42ee 100644 --- a/src/core/blitz/fetchBlitz.ts +++ b/packages/core/src/blitz/fetchBlitz.ts @@ -1,7 +1,6 @@ -import { Region } from '../../constants/regions'; -import { WARGAMING_APPLICATION_ID } from '../../constants/wargamingApplicationID'; -import { EventManager } from '../blitzkit/eventManager'; +import { assertSecret, EventManager } from '../blitzkit'; import { patientFetch } from '../blitzkit/patientFetch'; +import { Region } from './regions'; const RETRY_ERRORS = ['REQUEST_LIMIT_EXCEEDED', 'SOURCE_NOT_AVAILABLE']; @@ -65,7 +64,7 @@ async function manageQueue() { export type FetchBlitzParams = Record; -export default function fetchBlitz( +export function fetchBlitz( region: Region, path: string, params: FetchBlitzParams = {}, @@ -73,7 +72,9 @@ export default function fetchBlitz( return new Promise((resolve) => { queue.push({ url: `https://api.wotblitz.${region}/wotb/${path}/?${Object.entries({ - application_id: WARGAMING_APPLICATION_ID, + application_id: assertSecret( + import.meta.env.PUBLIC_WARGAMING_APPLICATION_ID, + ), ...params, }) .filter(([_, value]) => value !== undefined) diff --git a/src/core/blitz/generateStats.ts b/packages/core/src/blitz/generateStats.ts similarity index 88% rename from src/core/blitz/generateStats.ts rename to packages/core/src/blitz/generateStats.ts index 7dfb6115a..84f8ea95e 100644 --- a/src/core/blitz/generateStats.ts +++ b/packages/core/src/blitz/generateStats.ts @@ -1,5 +1,4 @@ -import calculateWN8 from '../statistics/calculateWN8'; -import { BlitzStats } from '../statistics/compositeStats/constants'; +import { BlitzStats, calculateWN8 } from '@blitzkit/core'; export type Stat = keyof ReturnType; @@ -36,7 +35,7 @@ export function prettifyStats(s: ReturnType) { } satisfies Record; } -export function sumStats(s: ReturnType[]) { +export function sumBlitzStarsStats(s: ReturnType[]) { function sum(slice: (stat: ReturnType) => number) { return s.reduce((a, b) => a + slice(b), 0); } diff --git a/src/core/blitz/getAccountAchievements.ts b/packages/core/src/blitz/getAccountAchievements.ts similarity index 90% rename from src/core/blitz/getAccountAchievements.ts rename to packages/core/src/blitz/getAccountAchievements.ts index c87e34118..b212b3513 100644 --- a/src/core/blitz/getAccountAchievements.ts +++ b/packages/core/src/blitz/getAccountAchievements.ts @@ -1,5 +1,4 @@ -import { Region } from '../../constants/regions'; -import fetchBlitz from './fetchBlitz'; +import { fetchBlitz, Region } from '@blitzkit/core'; import { normalizeIds } from './normalizeIds'; interface IndividualAccountAchievements { diff --git a/src/core/blitz/getAccountInfo.ts b/packages/core/src/blitz/getAccountInfo.ts similarity index 91% rename from src/core/blitz/getAccountInfo.ts rename to packages/core/src/blitz/getAccountInfo.ts index 50a21ee0a..d0c1dfb7a 100644 --- a/src/core/blitz/getAccountInfo.ts +++ b/packages/core/src/blitz/getAccountInfo.ts @@ -1,6 +1,9 @@ -import { Region } from '../../constants/regions'; -import { BlitzStats } from '../statistics/compositeStats/constants'; -import fetchBlitz, { FetchBlitzParams } from './fetchBlitz'; +import { + BlitzStats, + FetchBlitzParams, + Region, + fetchBlitz, +} from '@blitzkit/core'; import { normalizeIds } from './normalizeIds'; export interface SupplementaryStats { diff --git a/src/core/blitz/getClanAccountInfo.ts b/packages/core/src/blitz/getClanAccountInfo.ts similarity index 91% rename from src/core/blitz/getClanAccountInfo.ts rename to packages/core/src/blitz/getClanAccountInfo.ts index 0a986eac7..715721f52 100644 --- a/src/core/blitz/getClanAccountInfo.ts +++ b/packages/core/src/blitz/getClanAccountInfo.ts @@ -1,5 +1,4 @@ -import { Region } from '../../constants/regions'; -import fetchBlitz from './fetchBlitz'; +import { fetchBlitz, Region } from '@blitzkit/core'; import { normalizeIds } from './normalizeIds'; type IndividualClanAccountInfo = { diff --git a/src/core/blitz/getClanInfo.ts b/packages/core/src/blitz/getClanInfo.ts similarity index 92% rename from src/core/blitz/getClanInfo.ts rename to packages/core/src/blitz/getClanInfo.ts index 9ac36d92d..c6ef99a9f 100644 --- a/src/core/blitz/getClanInfo.ts +++ b/packages/core/src/blitz/getClanInfo.ts @@ -1,5 +1,4 @@ -import { Region } from '../../constants/regions'; -import fetchBlitz from './fetchBlitz'; +import { fetchBlitz, Region } from '@blitzkit/core'; import { normalizeIds } from './normalizeIds'; interface IndividualClanInfo { diff --git a/src/core/blitz/getLeagueFromScore.ts b/packages/core/src/blitz/getLeagueFromScore.ts similarity index 69% rename from src/core/blitz/getLeagueFromScore.ts rename to packages/core/src/blitz/getLeagueFromScore.ts index d0f881be2..ee58bcbb5 100644 --- a/src/core/blitz/getLeagueFromScore.ts +++ b/packages/core/src/blitz/getLeagueFromScore.ts @@ -1,4 +1,4 @@ -import { LEAGUES } from '../../constants/leagues'; +import { LEAGUES } from '@blitzkit/core'; export function getLeagueFromScore(score: number) { return LEAGUES.find(({ minScore }) => score >= minScore)!; diff --git a/src/core/blitz/getRatingInfo.ts b/packages/core/src/blitz/getRatingInfo.ts similarity index 69% rename from src/core/blitz/getRatingInfo.ts rename to packages/core/src/blitz/getRatingInfo.ts index d85a7e1d9..8ddaa809a 100644 --- a/src/core/blitz/getRatingInfo.ts +++ b/packages/core/src/blitz/getRatingInfo.ts @@ -1,12 +1,11 @@ -import { RatingInfo } from '../../commands/ratingLeaderboard'; -import { Region } from '../../constants/regions'; +import { RatingInfo, Region } from '@blitzkit/core'; import { context } from '../blitzkit/context'; import { patientFetch } from '../blitzkit/patientFetch'; -import regionToRegionSubdomain from './regionToRegionSubdomain'; +import { regionToRegionSubdomain } from './regionToRegionSubdomain'; const cache: Partial> = {}; -export default async function getRatingInfo(region: Region) { +export async function getRatingInfo(region: Region) { if (cache[region]) return cache[region]!; const response = await patientFetch( diff --git a/src/core/blitz/getRatingLeague.ts b/packages/core/src/blitz/getRatingLeague.ts similarity index 80% rename from src/core/blitz/getRatingLeague.ts rename to packages/core/src/blitz/getRatingLeague.ts index dd96cb335..9946586ca 100644 --- a/src/core/blitz/getRatingLeague.ts +++ b/packages/core/src/blitz/getRatingLeague.ts @@ -1,8 +1,7 @@ -import { LeagueTop, RatingPlayer } from '../../commands/ratingLeaderboard'; -import { Region } from '../../constants/regions'; +import { LeagueTop, RatingPlayer, Region } from '@blitzkit/core'; import { context } from '../blitzkit/context'; import { patientFetch } from '../blitzkit/patientFetch'; -import regionToRegionSubdomain from './regionToRegionSubdomain'; +import { regionToRegionSubdomain } from './regionToRegionSubdomain'; export async function getRatingLeague( region: Region, diff --git a/src/core/blitz/getRatingNeighbors.ts b/packages/core/src/blitz/getRatingNeighbors.ts similarity index 78% rename from src/core/blitz/getRatingNeighbors.ts rename to packages/core/src/blitz/getRatingNeighbors.ts index 879c1e14e..6a8e71962 100644 --- a/src/core/blitz/getRatingNeighbors.ts +++ b/packages/core/src/blitz/getRatingNeighbors.ts @@ -1,8 +1,7 @@ -import { RatingNeighbors } from '../../commands/ratingLeaderboard'; -import { Region } from '../../constants/regions'; +import { RatingNeighbors, Region } from '@blitzkit/core'; import { patientFetch } from '../blitzkit/patientFetch'; import { withCORSProxy } from '../blitzkit/withCORSProxy'; -import regionToRegionSubdomain from './regionToRegionSubdomain'; +import { regionToRegionSubdomain } from './regionToRegionSubdomain'; export async function getRatingNeighbors( region: Region, diff --git a/src/core/blitz/getTankStats.ts b/packages/core/src/blitz/getTankStats.ts similarity index 50% rename from src/core/blitz/getTankStats.ts rename to packages/core/src/blitz/getTankStats.ts index 61e73f9e4..30c277a6a 100644 --- a/src/core/blitz/getTankStats.ts +++ b/packages/core/src/blitz/getTankStats.ts @@ -1,8 +1,11 @@ -import { Region } from '../../constants/regions'; -import { TanksStats } from '../../types/tanksStats'; -import fetchBlitz, { FetchBlitzParams } from './fetchBlitz'; +import { + fetchBlitz, + FetchBlitzParams, + Region, + TanksStats, +} from '@blitzkit/core'; -export default async function getTankStats( +export async function getTankStats( region: Region, id: number, params?: FetchBlitzParams, diff --git a/src/core/blitz/idToRegion.ts b/packages/core/src/blitz/idToRegion.ts similarity index 69% rename from src/core/blitz/idToRegion.ts rename to packages/core/src/blitz/idToRegion.ts index 4eee68b40..64f15d810 100644 --- a/src/core/blitz/idToRegion.ts +++ b/packages/core/src/blitz/idToRegion.ts @@ -1,15 +1,15 @@ -import { Region } from '../../constants/regions'; +import { Region } from './regions'; -export const MIN_IDS: Record = { +export const MIN_REGION_IDS: Record = { asia: 20e8, com: 10e8, eu: 5e8, }; -export const MAX_IDS: Record = { +export const MAX_REGION_IDS: Record = { asia: 31e8 - 1, - com: MIN_IDS.asia - 1, - eu: MIN_IDS.com - 1, + com: MIN_REGION_IDS.asia - 1, + eu: MIN_REGION_IDS.com - 1, }; export function idToRegion(id: number): Region { diff --git a/packages/core/src/blitz/index.ts b/packages/core/src/blitz/index.ts new file mode 100644 index 000000000..aa2aadf58 --- /dev/null +++ b/packages/core/src/blitz/index.ts @@ -0,0 +1,30 @@ +export * from './canSplash'; +export * from './clans'; +export * from './constants'; +export * from './equipmentPrice'; +export * from './fetchBlitz'; +export * from './generateStats'; +export * from './getAccountAchievements'; +export * from './getAccountInfo'; +export * from './getClanAccountInfo'; +export * from './getClanInfo'; +export * from './getLeagueFromScore'; +export * from './getRatingInfo'; +export * from './getRatingLeague'; +export * from './getRatingNeighbors'; +export * from './getTankStats'; +export * from './idToRegion'; +export * from './isOnGoingRatingSeason'; +export * from './isValidBlitzId'; +export * from './nations'; +export * from './normalizeExtra'; +export * from './normalizeIds'; +export * from './permanentSkills'; +export * from './rating'; +export * from './regions'; +export * from './regionSubdomainToRegion'; +export * from './regionToRegionSubdomain'; +export * from './searchClansAcrossRegions'; +export * from './searchCurrentRatingPlayers'; +export * from './searchPlayersAcrossRegions'; +export * from './toUniqueId'; diff --git a/src/core/blitz/isOnGoingRatingSeason.ts b/packages/core/src/blitz/isOnGoingRatingSeason.ts similarity index 74% rename from src/core/blitz/isOnGoingRatingSeason.ts rename to packages/core/src/blitz/isOnGoingRatingSeason.ts index 14efb9b42..b4adf9e7f 100644 --- a/src/core/blitz/isOnGoingRatingSeason.ts +++ b/packages/core/src/blitz/isOnGoingRatingSeason.ts @@ -1,4 +1,4 @@ -import getRatingInfo from './getRatingInfo'; +import { getRatingInfo } from '@blitzkit/core'; export async function isOnGoingRatingSeason() { const ratingInfo = await getRatingInfo('com'); diff --git a/packages/core/src/blitz/isValidBlitzId.ts b/packages/core/src/blitz/isValidBlitzId.ts new file mode 100644 index 000000000..89ee96b03 --- /dev/null +++ b/packages/core/src/blitz/isValidBlitzId.ts @@ -0,0 +1,30 @@ +import { Region, assertSecret, idToRegion } from '@blitzkit/core'; + +export async function isValidBlitzId(id: number, token?: string) { + let region: Region; + + try { + region = idToRegion(id); + } catch (error) { + return false; + } + + const json = await fetch( + `https://api.wotblitz.${region}/wotb/account/info/?account_id=${id}&application_id=${assertSecret( + process.env.PUBLIC_WARGAMING_APPLICATION_ID, + )}${ + token === undefined ? '' : `&access_token=${token}` + }&fields=account_id%2C-account_id`, + ).then( + (response) => + response.json() as Promise< + | { + status: 'ok'; + data: Record; + } + | { status: 'error' } + >, + ); + + return json.status === 'ok' && json.data[id] !== null; +} diff --git a/src/constants/nations.ts b/packages/core/src/blitz/nations.ts similarity index 100% rename from src/constants/nations.ts rename to packages/core/src/blitz/nations.ts diff --git a/src/core/blitz/normalizeExtra.ts b/packages/core/src/blitz/normalizeExtra.ts similarity index 100% rename from src/core/blitz/normalizeExtra.ts rename to packages/core/src/blitz/normalizeExtra.ts diff --git a/src/core/blitz/normalizeIds.ts b/packages/core/src/blitz/normalizeIds.ts similarity index 100% rename from src/core/blitz/normalizeIds.ts rename to packages/core/src/blitz/normalizeIds.ts diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/components/Skills/constants.tsx b/packages/core/src/blitz/permanentSkills.tsx similarity index 100% rename from src/app/tools/tankopedia/[id]/components/Characteristics/components/Skills/constants.tsx rename to packages/core/src/blitz/permanentSkills.tsx diff --git a/packages/core/src/blitz/rating.ts b/packages/core/src/blitz/rating.ts new file mode 100644 index 000000000..b4a634a3e --- /dev/null +++ b/packages/core/src/blitz/rating.ts @@ -0,0 +1,79 @@ +import { RatingPlayer } from '../statistics'; + +export const LEAGUES = [ + { name: 'diamond', minScore: 5000, index: 0 }, + { name: 'platinum', minScore: 4000, index: 1 }, + { name: 'gold', minScore: 3000, index: 2 }, + { name: 'silver', minScore: 2000, index: 3 }, + { name: 'bronze', minScore: -Infinity, index: 4 }, +]; +export type RatingInfo = + | { + detail: undefined; + + title: string; + icon: string | null; + start_at: string; + finish_at: string; + current_season: number; + updated_at: string; + count: number; + + rewards: RatingReward[]; + leagues: RatingLeague[]; + } + | { detail: { error: string } }; +export interface RatingNeighbors { + neighbors: RatingPlayer[]; +} +export const FIRST_COMPREHENSIVE1_ARCHIVED_RATING_SEASON = 53; +export const FIRST_MINIMAL_ARCHIVED_RATING_SEASON = 49; +export interface LeagueTop { + result: RatingPlayer[]; +} +export interface RatingLeague { + title: string; + small_icon: string; + big_icon: string; + background: string; + index: number; + percentile: number; +} +export type RatingReward = { + from_position: number; + to_position: number; + count: number; +} & ( + | { + type: 'vehicle'; + + vehicle: { + id: number; + name: string; + nation: string; + subnation: string; + use_subnation_flag: boolean; + type_slug: string; + level: number; + roman_level: string; + user_string: string; + image_url: string; + preview_image_url: string; + is_premium: boolean; + is_collectible: boolean; + }; + } + | { + type: 'stuff'; + + stuff: { + name: string; + count: number; + title: string; + image_url: string; + type: string; + + sizes: {}; + }; + } +); diff --git a/packages/core/src/blitz/regionSubdomainToRegion.ts b/packages/core/src/blitz/regionSubdomainToRegion.ts new file mode 100644 index 000000000..2df097250 --- /dev/null +++ b/packages/core/src/blitz/regionSubdomainToRegion.ts @@ -0,0 +1,5 @@ +import { Region, RegionSubdomain } from '@blitzkit/core'; + +export function regionSubdomainToRegion(regionDomain: RegionSubdomain): Region { + return regionDomain === 'na' ? 'com' : regionDomain; +} diff --git a/packages/core/src/blitz/regionToRegionSubdomain.ts b/packages/core/src/blitz/regionToRegionSubdomain.ts new file mode 100644 index 000000000..8cdaf8f9c --- /dev/null +++ b/packages/core/src/blitz/regionToRegionSubdomain.ts @@ -0,0 +1,5 @@ +import { Region, RegionSubdomain } from '@blitzkit/core'; + +export function regionToRegionSubdomain(regionDomain: Region): RegionSubdomain { + return regionDomain === 'com' ? 'na' : regionDomain; +} diff --git a/src/constants/regions.ts b/packages/core/src/blitz/regions.ts similarity index 100% rename from src/constants/regions.ts rename to packages/core/src/blitz/regions.ts diff --git a/src/core/blitz/searchClansAcrossRegions.ts b/packages/core/src/blitz/searchClansAcrossRegions.ts similarity index 83% rename from src/core/blitz/searchClansAcrossRegions.ts rename to packages/core/src/blitz/searchClansAcrossRegions.ts index 6d14f7e8d..f0b868616 100644 --- a/src/core/blitz/searchClansAcrossRegions.ts +++ b/packages/core/src/blitz/searchClansAcrossRegions.ts @@ -1,11 +1,7 @@ -import { Region } from '../../constants/regions'; -import { ClanList } from '../../types/clanList'; -import fetchBlitz from './fetchBlitz'; +import { fetchBlitz, Region } from '@blitzkit/core'; +import { ClanList } from './clans'; -export default async function searchClansAcrossRegions( - search: string, - limit = 25, -) { +export async function searchClansAcrossRegions(search: string, limit = 25) { const trimmed = search.trim(); if (trimmed.length < 3 && trimmed.length > 100) return []; const normalizedLimit = Math.floor(limit / 3); diff --git a/src/core/blitz/searchCurrentRatingPlayers.ts b/packages/core/src/blitz/searchCurrentRatingPlayers.ts similarity index 89% rename from src/core/blitz/searchCurrentRatingPlayers.ts rename to packages/core/src/blitz/searchCurrentRatingPlayers.ts index 4b5b5b2c3..e2c10edb0 100644 --- a/src/core/blitz/searchCurrentRatingPlayers.ts +++ b/packages/core/src/blitz/searchCurrentRatingPlayers.ts @@ -1,6 +1,6 @@ -import { Region } from '../../constants/regions'; +import { Region } from '@blitzkit/core'; import { context } from '../blitzkit/context'; -import regionToRegionSubdomain from './regionToRegionSubdomain'; +import { regionToRegionSubdomain } from './regionToRegionSubdomain'; type CurrentRatingPlayerSearch = Record< number, diff --git a/src/core/blitz/searchPlayersAcrossRegions/constants.ts b/packages/core/src/blitz/searchPlayersAcrossRegions/constants.ts similarity index 100% rename from src/core/blitz/searchPlayersAcrossRegions/constants.ts rename to packages/core/src/blitz/searchPlayersAcrossRegions/constants.ts diff --git a/src/core/blitz/searchPlayersAcrossRegions/index.ts b/packages/core/src/blitz/searchPlayersAcrossRegions/index.ts similarity index 88% rename from src/core/blitz/searchPlayersAcrossRegions/index.ts rename to packages/core/src/blitz/searchPlayersAcrossRegions/index.ts index 8ca9130a7..49ba8ab27 100644 --- a/src/core/blitz/searchPlayersAcrossRegions/index.ts +++ b/packages/core/src/blitz/searchPlayersAcrossRegions/index.ts @@ -1,5 +1,4 @@ -import { Region } from '../../../constants/regions'; -import fetchBlitz from '../fetchBlitz'; +import { fetchBlitz, Region } from '@blitzkit/core'; import { usernamePattern } from './constants'; export interface AccountListItem { @@ -11,10 +10,7 @@ export type AccountListWithServer = (AccountListItem & { region: Region; })[]; -export default async function searchPlayersAcrossRegions( - search: string, - limit = 25, -) { +export async function searchPlayersAcrossRegions(search: string, limit = 25) { const trimmedSearch = search.trim(); const normalizedLimit = Math.floor(limit / 3); @@ -62,3 +58,5 @@ export default async function searchPlayersAcrossRegions( return [] as AccountListWithServer; } } + +export * from './constants'; diff --git a/src/core/blitz/toUniqueId.ts b/packages/core/src/blitz/toUniqueId.ts similarity index 67% rename from src/core/blitz/toUniqueId.ts rename to packages/core/src/blitz/toUniqueId.ts index 53eb45c6f..3c080081a 100644 --- a/src/core/blitz/toUniqueId.ts +++ b/packages/core/src/blitz/toUniqueId.ts @@ -1,4 +1,4 @@ -import { NATION_IDS } from '../../constants/nations'; +import { NATION_IDS } from "@blitzkit/core"; export function toUniqueId(nation: string, id: number) { return (id << 8) + (NATION_IDS[nation] << 4) + 1; diff --git a/src/core/blitzkit/secret.ts b/packages/core/src/blitzkit/assertSecret.ts similarity index 100% rename from src/core/blitzkit/secret.ts rename to packages/core/src/blitzkit/assertSecret.ts diff --git a/packages/core/src/blitzkit/asset.ts b/packages/core/src/blitzkit/asset.ts new file mode 100644 index 000000000..f749f347f --- /dev/null +++ b/packages/core/src/blitzkit/asset.ts @@ -0,0 +1,7 @@ +import { assertSecret } from './assertSecret'; + +export function asset(path: string) { + return `https://raw.githubusercontent.com/${assertSecret( + import.meta.env.PUBLIC_ASSET_REPO, + )}/${assertSecret(import.meta.env.PUBLIC_ASSET_BRANCH)}/${path}`; +} diff --git a/src/core/blitzkit/availableProvisions.ts b/packages/core/src/blitzkit/availableProvisions.ts similarity index 60% rename from src/core/blitzkit/availableProvisions.ts rename to packages/core/src/blitzkit/availableProvisions.ts index 143ad7158..f4799f24c 100644 --- a/src/core/blitzkit/availableProvisions.ts +++ b/packages/core/src/blitzkit/availableProvisions.ts @@ -1,13 +1,16 @@ +import { + GunDefinition, + ProvisionDefinitions, + TankDefinition, +} from '@blitzkit/core'; import { checkConsumableProvisionInclusivity } from './checkConsumableProvisionInclusivity'; -import { ProvisionDefinitions } from './provisionDefinitions'; -import { GunDefinition, TankDefinition } from './tankDefinitions'; export function availableProvisions( tank: TankDefinition, gun: GunDefinition, provisionDefinitions: ProvisionDefinitions, ) { - return Object.values(provisionDefinitions).filter((provision) => + return Object.values(provisionDefinitions.provisions).filter((provision) => checkConsumableProvisionInclusivity(provision, tank, gun), ); } diff --git a/src/core/blitzkit/averageDefinitions/constants.ts b/packages/core/src/blitzkit/averageDefinitions/constants.ts similarity index 66% rename from src/core/blitzkit/averageDefinitions/constants.ts rename to packages/core/src/blitzkit/averageDefinitions/constants.ts index b25afdf7c..7c96d8543 100644 --- a/src/core/blitzkit/averageDefinitions/constants.ts +++ b/packages/core/src/blitzkit/averageDefinitions/constants.ts @@ -1,6 +1,6 @@ -import { Samples } from '.'; -import { emptyAllStats } from '../../blitzstars/getStatsInPeriod/constants'; -import { BlitzkitStats } from '../../statistics/compositeStats/constants'; +import { emptyAllStats } from '../../blitz/constants'; +import { Samples } from '../../protos'; +import { BlitzkitStats } from '../../statistics'; export const emptyAverageDefinitionsAllStats: BlitzkitStats = { ...emptyAllStats, diff --git a/packages/core/src/blitzkit/averageDefinitions/index.ts b/packages/core/src/blitzkit/averageDefinitions/index.ts new file mode 100644 index 000000000..61ddb2c57 --- /dev/null +++ b/packages/core/src/blitzkit/averageDefinitions/index.ts @@ -0,0 +1,23 @@ +import { fetchPB } from '../../protobuf'; +import { AverageDefinitions } from '../../protos'; +import { asset } from '../asset'; + +export interface AverageDefinitionsManifest { + version: 1; + /** + * epoch in days + */ + latest: number; +} + +export async function fetchAverageDefinitions() { + const manifestResponse = await fetch(asset('averages/manifest.json')); + const manifestJson = + (await manifestResponse.json()) as AverageDefinitionsManifest; + return await fetchPB( + asset(`averages/${manifestJson.latest}.pb`), + AverageDefinitions, + ); +} + +export * from './constants'; diff --git a/packages/core/src/blitzkit/camouflageDefinitions.ts b/packages/core/src/blitzkit/camouflageDefinitions.ts new file mode 100644 index 000000000..20315860c --- /dev/null +++ b/packages/core/src/blitzkit/camouflageDefinitions.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { CamouflageDefinitions } from '../protos'; +import { asset } from './asset'; + +export function fetchCamouflageDefinitions() { + return fetchPB(asset('definitions/camouflages.pb'), CamouflageDefinitions); +} diff --git a/packages/core/src/blitzkit/checkConsumableProvisionInclusivity.ts b/packages/core/src/blitzkit/checkConsumableProvisionInclusivity.ts new file mode 100644 index 000000000..471b76482 --- /dev/null +++ b/packages/core/src/blitzkit/checkConsumableProvisionInclusivity.ts @@ -0,0 +1,66 @@ +import { + Consumable, + ConsumableTankCategoryFilterCategory, + GunDefinition, + Provision, + TankDefinition, +} from '../protos'; + +export function checkConsumableProvisionInclusivity( + consumableProvision: Consumable | Provision, + tank: TankDefinition, + gun: GunDefinition, +) { + const included = + !consumableProvision.game_mode_exclusive && + consumableProvision.include?.every((rule) => { + switch (rule.filter_type!.$case) { + case 'tiers': + return ( + rule.filter_type!.value.min <= tank.tier && + tank.tier <= rule.filter_type!.value.max + ); + + case 'ids': + return rule.filter_type!.value.ids.includes(tank.id); + + case 'nations': + return rule.filter_type!.value.nations.includes(tank.nation); + + case 'categories': + throw new SyntaxError('Category filtering found in include rule'); + } + }); + const excluded = + consumableProvision.game_mode_exclusive || + consumableProvision.exclude?.some((rule) => { + switch (rule.filter_type!.$case) { + case 'tiers': + return ( + rule.filter_type!.value.min <= tank.tier && + tank.tier <= rule.filter_type!.value.max + ); + + case 'ids': + return rule.filter_type!.value.ids.includes(tank.id); + + case 'nations': + return rule.filter_type!.value.nations.includes(tank.nation); + + case 'categories': + return rule.filter_type!.value.categories.some((category) => { + switch (category) { + case ConsumableTankCategoryFilterCategory.CLIP: + return gun.gun_type!.$case !== 'regular'; + } + }); + } + }); + + return ( + !consumableProvision.game_mode_exclusive && + consumableProvision.include?.length > 0 && + included && + !excluded + ); +} diff --git a/src/core/blitzkit/coefficient.ts b/packages/core/src/blitzkit/coefficient.ts similarity index 100% rename from src/core/blitzkit/coefficient.ts rename to packages/core/src/blitzkit/coefficient.ts diff --git a/packages/core/src/blitzkit/consumableDefinitions.ts b/packages/core/src/blitzkit/consumableDefinitions.ts new file mode 100644 index 000000000..077e2e3b3 --- /dev/null +++ b/packages/core/src/blitzkit/consumableDefinitions.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { ConsumableDefinitions } from '../protos'; +import { asset } from './asset'; + +export function fetchConsumableDefinitions() { + return fetchPB(asset('definitions/consumables.pb'), ConsumableDefinitions); +} diff --git a/src/core/blitzkit/context.ts b/packages/core/src/blitzkit/context.ts similarity index 100% rename from src/core/blitzkit/context.ts rename to packages/core/src/blitzkit/context.ts diff --git a/src/core/blitzkit/createDefaultSkills.ts b/packages/core/src/blitzkit/createDefaultSkills.ts similarity index 57% rename from src/core/blitzkit/createDefaultSkills.ts rename to packages/core/src/blitzkit/createDefaultSkills.ts index 8b97e671a..25e3604bf 100644 --- a/src/core/blitzkit/createDefaultSkills.ts +++ b/packages/core/src/blitzkit/createDefaultSkills.ts @@ -1,11 +1,11 @@ -import { permanentSkills } from '../../app/tools/tankopedia/[id]/components/Characteristics/components/Skills/constants'; -import { SkillDefinitions } from './skillDefinitions'; +import { SkillDefinitions } from '@blitzkit/core'; +import { permanentSkills } from '../blitz/permanentSkills'; export function createDefaultSkills(skillDefinitions: SkillDefinitions) { const skills: Record = {}; Object.values(skillDefinitions.classes).forEach((tankSkills) => { - tankSkills.forEach((skill) => { + tankSkills.skills.forEach((skill) => { skills[skill] = permanentSkills.includes(skill) ? 7 : 0; }); }); diff --git a/src/core/blitzkit/degressiveStat.ts b/packages/core/src/blitzkit/degressiveStat.ts similarity index 100% rename from src/core/blitzkit/degressiveStat.ts rename to packages/core/src/blitzkit/degressiveStat.ts diff --git a/packages/core/src/blitzkit/discoveredIdDefinitions.ts b/packages/core/src/blitzkit/discoveredIdDefinitions.ts new file mode 100644 index 000000000..c6830554c --- /dev/null +++ b/packages/core/src/blitzkit/discoveredIdDefinitions.ts @@ -0,0 +1,12 @@ +import { asset } from './asset'; + +export interface DiscoveredIdsDefinitions { + time: number; + chunks: number; + count: number; +} + +export async function fetchDiscoveredIdsDefinitions() { + const response = await fetch(asset('ids/manifest.json')); + return response.json() as Promise; +} diff --git a/src/core/blitzkit/emblemURL.ts b/packages/core/src/blitzkit/emblemURL.ts similarity index 100% rename from src/core/blitzkit/emblemURL.ts rename to packages/core/src/blitzkit/emblemURL.ts diff --git a/packages/core/src/blitzkit/equipmentDefinitions.ts b/packages/core/src/blitzkit/equipmentDefinitions.ts new file mode 100644 index 000000000..a42f5bced --- /dev/null +++ b/packages/core/src/blitzkit/equipmentDefinitions.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { EquipmentDefinitions } from '../protos'; +import { asset } from './asset'; + +export function fetchEquipmentDefinitions() { + return fetchPB(asset('definitions/equipment.pb'), EquipmentDefinitions); +} diff --git a/src/core/blitzkit/eventManager.ts b/packages/core/src/blitzkit/eventManager.ts similarity index 100% rename from src/core/blitzkit/eventManager.ts rename to packages/core/src/blitzkit/eventManager.ts diff --git a/packages/core/src/blitzkit/flagUserActivity.ts b/packages/core/src/blitzkit/flagUserActivity.ts new file mode 100644 index 000000000..986e0a666 --- /dev/null +++ b/packages/core/src/blitzkit/flagUserActivity.ts @@ -0,0 +1,9 @@ +import { usersDatabase } from '@blitzkit/core'; + +export async function flagUserActivity(blitzId: number) { + await usersDatabase.user.upsert({ + where: { blitz_id: blitzId }, + update: {}, + create: { blitz_id: blitzId }, + }); +} diff --git a/packages/core/src/blitzkit/gameDefinitions.ts b/packages/core/src/blitzkit/gameDefinitions.ts new file mode 100644 index 000000000..d7573adb0 --- /dev/null +++ b/packages/core/src/blitzkit/gameDefinitions.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { GameDefinitions } from '../protos'; +import { asset } from './asset'; + +export function fetchGameDefinitions() { + return fetchPB(asset('definitions/game.pb'), GameDefinitions); +} diff --git a/src/core/blitzkit/getArchivedLatestSeasonNumber.ts b/packages/core/src/blitzkit/getArchivedLatestSeasonNumber.ts similarity index 86% rename from src/core/blitzkit/getArchivedLatestSeasonNumber.ts rename to packages/core/src/blitzkit/getArchivedLatestSeasonNumber.ts index e613eaf6d..9da80ed52 100644 --- a/src/core/blitzkit/getArchivedLatestSeasonNumber.ts +++ b/packages/core/src/blitzkit/getArchivedLatestSeasonNumber.ts @@ -1,5 +1,4 @@ -import { ASSETS_REPO } from '../../constants/assets'; -import getRatingInfo from '../blitz/getRatingInfo'; +import { assertSecret, getRatingInfo } from '@blitzkit/core'; interface GitHubTrees { tree: { path: string; url: string }[]; @@ -17,7 +16,9 @@ export async function getArchivedLatestSeasonNumber() { if (ratingInfo.detail) { const regionsURL = ( (await fetch( - `https://api.github.com/repos/tresabhi/${ASSETS_REPO}/git/trees/main`, + `https://api.github.com/repos/tresabhi/${assertSecret( + process.env.PUBLIC_ASSET_REPO, + )}/git/trees/main`, ).then((response) => response.json())) as GitHubTrees ).tree.find(({ path }) => path === 'regions')!.url; const comURL = ( diff --git a/packages/core/src/blitzkit/getArchivedRatingInfo.ts b/packages/core/src/blitzkit/getArchivedRatingInfo.ts new file mode 100644 index 000000000..782838baf --- /dev/null +++ b/packages/core/src/blitzkit/getArchivedRatingInfo.ts @@ -0,0 +1,30 @@ +// import { RatingInfo, Region, asset } from '@blitzkit/core'; + +// const cache: Record< +// Region, +// Record< +// number, +// RatingInfo & { +// detail: undefined; +// } +// > +// > = { +// com: {}, +// eu: {}, +// asia: {}, +// }; + +// export async function getArchivedRatingInfo(region: Region, season: number) { +// if (!cache[region][season]) { +// const info = await fetch( +// asset(`regions/${region}/rating/${season}/info.cdon.lz4`), +// ) +// .then((response) => response.arrayBuffer()) +// .then((buffer) => +// superDecompress(buffer), +// ); +// cache[region][season] = info; +// } + +// return cache[region][season]; +// } diff --git a/src/core/blitzkit/getArchivedRatingLeaderboard.ts b/packages/core/src/blitzkit/getArchivedRatingLeaderboard.ts similarity index 76% rename from src/core/blitzkit/getArchivedRatingLeaderboard.ts rename to packages/core/src/blitzkit/getArchivedRatingLeaderboard.ts index be9a5278f..0991d783c 100644 --- a/src/core/blitzkit/getArchivedRatingLeaderboard.ts +++ b/packages/core/src/blitzkit/getArchivedRatingLeaderboard.ts @@ -1,6 +1,9 @@ -import { Region } from '../../constants/regions'; -import { BkrlDiscriminatedEntries, BkrlReadStream } from '../streams/bkrl'; -import { asset } from './asset'; +import { + asset, + BkrlDiscriminatedEntries, + BkrlReadStream, + Region, +} from '@blitzkit/core'; const cache: Record> = { asia: {}, diff --git a/src/core/blitzkit/getArchivedRatingMidnightLeaderboard.ts b/packages/core/src/blitzkit/getArchivedRatingMidnightLeaderboard.ts similarity index 71% rename from src/core/blitzkit/getArchivedRatingMidnightLeaderboard.ts rename to packages/core/src/blitzkit/getArchivedRatingMidnightLeaderboard.ts index 2413c7396..d40df8ea1 100644 --- a/src/core/blitzkit/getArchivedRatingMidnightLeaderboard.ts +++ b/packages/core/src/blitzkit/getArchivedRatingMidnightLeaderboard.ts @@ -1,6 +1,9 @@ -import { Region } from '../../constants/regions'; -import { BkrlDiscriminatedEntries, BkrlReadStream } from '../streams/bkrl'; -import { asset } from './asset'; +import { + asset, + BkrlDiscriminatedEntries, + BkrlReadStream, + Region, +} from '@blitzkit/core'; const cache: Record> = { com: {}, @@ -8,7 +11,7 @@ const cache: Record> = { asia: {}, }; -export default async function getArchivedRatingMidnightLeaderboard( +export async function getArchivedRatingMidnightLeaderboard( region: Region, season: number, ) { diff --git a/src/core/blitzkit/getTimeDaysAgo.ts b/packages/core/src/blitzkit/getTimeDaysAgo.ts similarity index 79% rename from src/core/blitzkit/getTimeDaysAgo.ts rename to packages/core/src/blitzkit/getTimeDaysAgo.ts index 0d388ddce..579d38cc8 100644 --- a/src/core/blitzkit/getTimeDaysAgo.ts +++ b/packages/core/src/blitzkit/getTimeDaysAgo.ts @@ -1,4 +1,4 @@ -import { Region } from '../../constants/regions'; +import { Region } from '@blitzkit/core'; const TIME_ZONE_MAPPINGS: Record = { com: -5, // Central North American Time @@ -6,7 +6,7 @@ const TIME_ZONE_MAPPINGS: Record = { asia: +7, // Central Asia Standard Time }; -export default function getTimeDaysAgo(region: Region, daysAgo: number) { +export function getTimeDaysAgo(region: Region, daysAgo: number) { const now = new Date(); if (daysAgo === 0) now.getTime() / 1000; diff --git a/packages/core/src/blitzkit/index.ts b/packages/core/src/blitzkit/index.ts new file mode 100644 index 000000000..ce31cc01b --- /dev/null +++ b/packages/core/src/blitzkit/index.ts @@ -0,0 +1,46 @@ +export * from './assertSecret'; +export * from './asset'; +export * from './availableProvisions'; +export * from './averageDefinitions'; +// export * from './camouflageDefinitions'; +// export * from './checkConsumableProvisionInclusivity'; +export * from './coefficient'; +export * from './consumableDefinitions'; +// export * from './context'; +export * from './createDefaultSkills'; +export * from './degressiveStat'; +export * from './discoveredIdDefinitions'; +export * from './emblemURL'; +export * from './equipmentDefinitions'; +export * from './eventManager'; +// export * from './flagUserActivity'; +export * from './gameDefinitions'; +// export * from './getArchivedLatestSeasonNumber'; +// export * from './getArchivedRatingInfo'; +// export * from './getArchivedRatingLeaderboard'; +// export * from './getArchivedRatingMidnightLeaderboard'; +// export * from './getTimeDaysAgo'; +export * from './isExplosive'; +// export * from './linkBlitzAndDiscord'; +export * from './mapDefinitions'; +export * from './modelDefinitions'; +export * from './normalizeBoundingBox'; +// export * from './parseBkni'; +// export * from './patientFetch'; +export * from './patientFetchJSON'; +export * from './progressiveStat'; +export * from './provisionDefinitions'; +export * from './resolveDpm'; +export * from './resolvePenetrationCoefficient'; +export * from './reviews'; +export * from './skillDefinitions'; +export * from './sum'; +export * from './tankDefinitions'; +export * from './tankIcon'; +export * from './tankNames'; +export * from './unionBoundingBox'; +export * from './uniqueGuns'; +export * from './unwrapBlitzkitResponse'; +export * from './votes'; +// export * from './withCORSProxy'; +export * from './youtubers'; diff --git a/src/core/blitz/isExplosive.ts b/packages/core/src/blitzkit/isExplosive.ts similarity index 69% rename from src/core/blitz/isExplosive.ts rename to packages/core/src/blitzkit/isExplosive.ts index 08847774f..d487d17b8 100644 --- a/src/core/blitz/isExplosive.ts +++ b/packages/core/src/blitzkit/isExplosive.ts @@ -1,4 +1,4 @@ -import { ShellDefinition, ShellType } from '../blitzkit/tankDefinitions'; +import { ShellDefinition, ShellType } from '@blitzkit/core'; export function isExplosive( type: ShellDefinition['type'], diff --git a/packages/core/src/blitzkit/linkBlitzAndDiscord.ts b/packages/core/src/blitzkit/linkBlitzAndDiscord.ts new file mode 100644 index 000000000..813ea0aab --- /dev/null +++ b/packages/core/src/blitzkit/linkBlitzAndDiscord.ts @@ -0,0 +1,11 @@ +import { usersDatabase } from '@blitzkit/core'; +import { flagUserActivity } from './flagUserActivity'; + +export async function linkBlitzAndDiscord(discordId: bigint, blitzId: number) { + await usersDatabase.discordUser.upsert({ + where: { discord_id: discordId }, + update: { blitz_id: blitzId }, + create: { discord_id: discordId, blitz_id: blitzId }, + }); + await flagUserActivity(blitzId); +} diff --git a/packages/core/src/blitzkit/mapDefinitions.ts b/packages/core/src/blitzkit/mapDefinitions.ts new file mode 100644 index 000000000..50bf8525a --- /dev/null +++ b/packages/core/src/blitzkit/mapDefinitions.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { MapDefinitions } from '../protos'; +import { asset } from './asset'; + +export function fetchMapDefinitions() { + return fetchPB(asset('definitions/maps.pb'), MapDefinitions); +} diff --git a/packages/core/src/blitzkit/modelDefinitions.ts b/packages/core/src/blitzkit/modelDefinitions.ts new file mode 100644 index 000000000..59ca764e5 --- /dev/null +++ b/packages/core/src/blitzkit/modelDefinitions.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { ModelDefinitions } from '../protos'; +import { asset } from './asset'; + +export function fetchModelDefinitions() { + return fetchPB(asset('definitions/models.pb'), ModelDefinitions); +} diff --git a/packages/core/src/blitzkit/normalizeBoundingBox.ts b/packages/core/src/blitzkit/normalizeBoundingBox.ts new file mode 100644 index 000000000..f50d3e435 --- /dev/null +++ b/packages/core/src/blitzkit/normalizeBoundingBox.ts @@ -0,0 +1,9 @@ +import { BoundingBox, Vector3 } from '@blitzkit/core'; + +export function normalizeBoundingBox(boundingBox: BoundingBox) { + return { + x: boundingBox.max.x - boundingBox.min.x, + y: boundingBox.max.y - boundingBox.min.y, + z: boundingBox.max.z - boundingBox.min.z, + } satisfies Vector3; +} diff --git a/src/core/blitzkit/parseBkni.ts b/packages/core/src/blitzkit/parseBkni.ts similarity index 83% rename from src/core/blitzkit/parseBkni.ts rename to packages/core/src/blitzkit/parseBkni.ts index feec1ae08..c6074b093 100644 --- a/src/core/blitzkit/parseBkni.ts +++ b/packages/core/src/blitzkit/parseBkni.ts @@ -1,7 +1,4 @@ -import getBkniPercentile, { - BKNI_COLORS, - BkniPercentile, -} from '../statistics/getBkniPercentile'; +import { BKNI_COLORS, BkniPercentile, getBkniPercentile } from '@blitzkit/core'; export function parseBkni(bkni: number) { const bkniFraction = (bkni + 1) / 2; diff --git a/src/core/blitzkit/patientFetch.ts b/packages/core/src/blitzkit/patientFetch.ts similarity index 100% rename from src/core/blitzkit/patientFetch.ts rename to packages/core/src/blitzkit/patientFetch.ts diff --git a/src/core/blitzkit/patientFetchJSON.ts b/packages/core/src/blitzkit/patientFetchJSON.ts similarity index 100% rename from src/core/blitzkit/patientFetchJSON.ts rename to packages/core/src/blitzkit/patientFetchJSON.ts diff --git a/src/core/blitzkit/progressiveStat.ts b/packages/core/src/blitzkit/progressiveStat.ts similarity index 100% rename from src/core/blitzkit/progressiveStat.ts rename to packages/core/src/blitzkit/progressiveStat.ts diff --git a/packages/core/src/blitzkit/provisionDefinitions.ts b/packages/core/src/blitzkit/provisionDefinitions.ts new file mode 100644 index 000000000..6c85d2d5b --- /dev/null +++ b/packages/core/src/blitzkit/provisionDefinitions.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { ProvisionDefinitions } from '../protos'; +import { asset } from './asset'; + +export function fetchProvisionDefinitions() { + return fetchPB(asset('definitions/provisions.pb'), ProvisionDefinitions); +} diff --git a/packages/core/src/blitzkit/resolveDpm.ts b/packages/core/src/blitzkit/resolveDpm.ts new file mode 100644 index 000000000..fc0f268dc --- /dev/null +++ b/packages/core/src/blitzkit/resolveDpm.ts @@ -0,0 +1,51 @@ +import { + GunDefinition, + GunDefinitionAutoReloaderProperties, + ShellDefinition, +} from '../protos'; + +export function resolveDpm( + gun: GunDefinition, + shell: ShellDefinition, + damageCoefficient = 1, + reloadCoefficient = 1, + intraClipCoefficient = 1, +) { + const alpha = shell.armor_damage * damageCoefficient; + let dps: number; + + if (gun.gun_type!.$case === 'regular') { + dps = alpha / (reloadCoefficient * gun.gun_type!.value.extension.reload); + } else if (gun.gun_type!.$case === 'auto_loader') { + dps = + (alpha * gun.gun_type!.value.extension.shell_count) / + (gun.gun_type!.value.extension.clip_reload * reloadCoefficient + + (gun.gun_type!.value.extension.shell_count - 1) * + gun.gun_type!.value.extension.intra_clip * + intraClipCoefficient); + } else { + const mostOptimalShell = + gun.gun_type!.value.extension.shell_reloads.reduce((current, reloadRaw, index) => { + const reload = + reloadRaw * reloadCoefficient + + (index > 0 + ? ( + gun.gun_type!.value + .extension as GunDefinitionAutoReloaderProperties + ).intra_clip * intraClipCoefficient + : 0); + + if (current === null || reload < current.reload) { + return { index, reload }; + } + return current; + }, null)!; + + dps = alpha / mostOptimalShell?.reload; + } + + return dps * 60; +} diff --git a/src/core/blitz/resolvePenetrationCoefficient.ts b/packages/core/src/blitzkit/resolvePenetrationCoefficient.ts similarity index 59% rename from src/core/blitz/resolvePenetrationCoefficient.ts rename to packages/core/src/blitzkit/resolvePenetrationCoefficient.ts index 6f2f6acd0..1cd746e5f 100644 --- a/src/core/blitz/resolvePenetrationCoefficient.ts +++ b/packages/core/src/blitzkit/resolvePenetrationCoefficient.ts @@ -1,4 +1,4 @@ -import { ShellType } from '../blitzkit/tankDefinitions'; +import { ShellType } from '../protos'; export function resolvePenetrationCoefficient( calibratedShells: boolean, @@ -6,11 +6,11 @@ export function resolvePenetrationCoefficient( ) { if (!calibratedShells) return 1; - return type === 'ap' + return type === ShellType.AP ? 1.08 - : type === 'ap_cr' + : type === ShellType.APCR ? 1.05 - : type === 'hc' + : type === ShellType.HEAT ? 1.13 : 1.08; } diff --git a/packages/core/src/blitzkit/reviews.ts b/packages/core/src/blitzkit/reviews.ts new file mode 100644 index 000000000..40922fca4 --- /dev/null +++ b/packages/core/src/blitzkit/reviews.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { Reviews } from '../protos'; +import { asset } from './asset'; + +export function fetchReviews() { + return fetchPB(asset('definitions/reviews.pb'), Reviews); +} diff --git a/packages/core/src/blitzkit/skillDefinitions.ts b/packages/core/src/blitzkit/skillDefinitions.ts new file mode 100644 index 000000000..a2bebd8f0 --- /dev/null +++ b/packages/core/src/blitzkit/skillDefinitions.ts @@ -0,0 +1,7 @@ +import { fetchPB } from '../protobuf'; +import { SkillDefinitions } from '../protos'; +import { asset } from './asset'; + +export function fetchSkillDefinitions() { + return fetchPB(asset('definitions/skills.pb'), SkillDefinitions); +} diff --git a/src/core/blitzkit/sum.ts b/packages/core/src/blitzkit/sum.ts similarity index 100% rename from src/core/blitzkit/sum.ts rename to packages/core/src/blitzkit/sum.ts diff --git a/packages/core/src/blitzkit/tankDefinitions/constants.ts b/packages/core/src/blitzkit/tankDefinitions/constants.ts new file mode 100644 index 000000000..36178c3cb --- /dev/null +++ b/packages/core/src/blitzkit/tankDefinitions/constants.ts @@ -0,0 +1,98 @@ +import { + CrewType, + GunDefinition, + ShellType, + TankClass, + TankType, + Tier, +} from '../../protos'; + +export const SHELL_NAMES: Record = { + [ShellType.AP]: 'AP', + [ShellType.APCR]: 'APCR', + [ShellType.HEAT]: 'HEAT', + [ShellType.HE]: 'HE', +}; +export const CREW_MEMBER_NAMES: Record = { + [CrewType.COMMANDER]: 'Commander', + [CrewType.DRIVER]: 'Driver', + [CrewType.GUNNER]: 'Gunner', + [CrewType.LOADER]: 'Loader', + [CrewType.RADIOMAN]: 'Radioman', +}; +export const GUN_TYPE_NAMES: Record< + Exclude['$case'], + string +> = { + auto_loader: 'Auto loader', + auto_reloader: 'Auto reloader', + regular: 'Regular', +}; +/** + * @deprecated use svg + */ +export const TANK_ICONS: Record = { + [TankClass.TANK_DESTROYER]: 'https://i.imgur.com/BIHSEH0.png', + [TankClass.LIGHT]: 'https://i.imgur.com/CSNha5V.png', + [TankClass.MEDIUM]: 'https://i.imgur.com/wvf3ltm.png', + [TankClass.HEAVY]: 'https://i.imgur.com/ECeqlZa.png', +}; +/** + * @deprecated use svg + */ +export const TANK_ICONS_PREMIUM: Record = { + [TankClass.TANK_DESTROYER]: 'https://i.imgur.com/TCu3EdR.png', + [TankClass.LIGHT]: 'https://i.imgur.com/zdkpTRb.png', + [TankClass.MEDIUM]: 'https://i.imgur.com/3z7eHX6.png', + [TankClass.HEAVY]: 'https://i.imgur.com/P3vbmyA.png', +}; +/** + * @deprecated use svg + */ +export const TANK_ICONS_COLLECTOR: Record = { + [TankClass.TANK_DESTROYER]: 'https://i.imgur.com/WTjeirB.png', + [TankClass.LIGHT]: 'https://i.imgur.com/EwhtKkU.png', + [TankClass.MEDIUM]: 'https://i.imgur.com/u8YDMBh.png', + [TankClass.HEAVY]: 'https://i.imgur.com/8xRf3nc.png', +}; +export const TIERS = [ + Tier.I, + Tier.II, + Tier.III, + Tier.IV, + Tier.V, + Tier.VI, + Tier.VII, + Tier.VIII, + Tier.IX, + Tier.X, +]; +export const TIER_ROMAN_NUMERALS: Record = { + [Tier.I]: 'I', + [Tier.II]: 'II', + [Tier.III]: 'III', + [Tier.IV]: 'IV', + [Tier.V]: 'V', + [Tier.VI]: 'VI', + [Tier.VII]: 'VII', + [Tier.VIII]: 'VIII', + [Tier.IX]: 'IX', + [Tier.X]: 'X', +}; + +export const flags: Record = { + ussr: '<:ussr:1218421042033197197>', + germany: 'πŸ‡©πŸ‡ͺ', + usa: 'πŸ‡ΊπŸ‡Έ', + china: 'πŸ‡¨πŸ‡³', + uk: 'πŸ‡¬πŸ‡§', + france: 'πŸ‡«πŸ‡·', + japan: 'πŸ‡―πŸ‡΅', + european: 'πŸ‡ͺπŸ‡Ί', + other: '<:other:1218421572243558482>', +}; +export const TREE_TYPE_ICONS: Record> = { + [TankType.RESEARCHABLE]: TANK_ICONS, + [TankType.PREMIUM]: TANK_ICONS_PREMIUM, + [TankType.COLLECTOR]: TANK_ICONS_COLLECTOR, +}; diff --git a/packages/core/src/blitzkit/tankDefinitions/index.ts b/packages/core/src/blitzkit/tankDefinitions/index.ts new file mode 100644 index 000000000..18bdfcd2a --- /dev/null +++ b/packages/core/src/blitzkit/tankDefinitions/index.ts @@ -0,0 +1,9 @@ +import { fetchPB } from '../../protobuf'; +import { TankDefinitions } from '../../protos'; +import { asset } from '../asset'; + +export function fetchTankDefinitions() { + return fetchPB(asset('definitions/tanks.pb'), TankDefinitions); +} + +export * from './constants'; diff --git a/src/core/blitzkit/tankIcon.ts b/packages/core/src/blitzkit/tankIcon.ts similarity index 75% rename from src/core/blitzkit/tankIcon.ts rename to packages/core/src/blitzkit/tankIcon.ts index 1ebe0aef3..1a2c0d5e9 100644 --- a/src/core/blitzkit/tankIcon.ts +++ b/packages/core/src/blitzkit/tankIcon.ts @@ -1,4 +1,4 @@ -import { asset } from './asset'; +import { asset } from '@blitzkit/core'; export function tankIcon(id: number, size: 'big' | 'small' = 'big') { return asset(`icons/tanks/${size}/${id}.webp`); diff --git a/packages/core/src/blitzkit/tankNames.ts b/packages/core/src/blitzkit/tankNames.ts new file mode 100644 index 000000000..c871ea40c --- /dev/null +++ b/packages/core/src/blitzkit/tankNames.ts @@ -0,0 +1,28 @@ +import { deburr } from 'lodash-es'; +import { fetchCamouflageDefinitions } from './camouflageDefinitions'; +import { fetchTankDefinitions } from './tankDefinitions'; + +export async function fetchTankNames() { + const [tankDefinitions, camouflageDefinitions] = await Promise.all([ + fetchTankDefinitions(), + fetchCamouflageDefinitions(), + ]); + const tankDefinitionsArray = Object.values(tankDefinitions.tanks); + + return await Promise.all( + tankDefinitionsArray.map(async (tank) => { + return { + id: tank.id, + name: tank.name, + nameFull: tank.name_full, + searchableName: tank.name_full ?? tank.name, + searchableNameDeburr: deburr(tank.name_full ?? tank.name), + camouflages: tank.camouflages + ?.map((id) => camouflageDefinitions.camouflages[id]?.name) + .filter(Boolean) + .join(' '), + treeType: tank.type, + }; + }), + ); +} diff --git a/packages/core/src/blitzkit/unionBoundingBox.ts b/packages/core/src/blitzkit/unionBoundingBox.ts new file mode 100644 index 000000000..b20748087 --- /dev/null +++ b/packages/core/src/blitzkit/unionBoundingBox.ts @@ -0,0 +1,16 @@ +import { BoundingBox } from '@blitzkit/core'; + +export function unionBoundingBox(a: BoundingBox, b: BoundingBox) { + return { + min: { + x: Math.min(a.min.x, b.min.x), + y: Math.min(a.min.y, b.min.y), + z: Math.min(a.min.z, b.min.z), + }, + max: { + x: Math.max(a.max.x, b.max.x), + y: Math.max(a.max.y, b.max.y), + z: Math.max(a.max.z, b.max.z), + }, + } satisfies BoundingBox; +} diff --git a/src/core/blitzkit/uniqueGuns.ts b/packages/core/src/blitzkit/uniqueGuns.ts similarity index 60% rename from src/core/blitzkit/uniqueGuns.ts rename to packages/core/src/blitzkit/uniqueGuns.ts index f6af5ac55..6eb453372 100644 --- a/src/core/blitzkit/uniqueGuns.ts +++ b/packages/core/src/blitzkit/uniqueGuns.ts @@ -1,5 +1,5 @@ -import { forEachRight } from 'lodash'; -import { GunDefinition, TurretDefinition } from './tankDefinitions'; +import { forEachRight } from 'lodash-es'; +import { GunDefinition, TurretDefinition } from '../protos'; export function uniqueGuns(turrets: TurretDefinition[]) { const gunIds = new Set(); @@ -7,8 +7,8 @@ export function uniqueGuns(turrets: TurretDefinition[]) { forEachRight(turrets, (turret) => { forEachRight(turret.guns, (gun) => { - if (!gunIds.has(gun.id)) { - gunIds.add(gun.id); + if (!gunIds.has(gun.gun_type!.value.base.id)) { + gunIds.add(gun.gun_type!.value.base.id); guns.push({ turret, gun }); } }); diff --git a/packages/core/src/blitzkit/unwrapBlitzkitResponse.ts b/packages/core/src/blitzkit/unwrapBlitzkitResponse.ts new file mode 100644 index 000000000..ffc46f458 --- /dev/null +++ b/packages/core/src/blitzkit/unwrapBlitzkitResponse.ts @@ -0,0 +1,18 @@ +export function unwrapBlitzkitResponse(response: BlitzkitResponse) { + if (response.status === 'error') { + throw new Error(response.error, { cause: response.message }); + } + + return response.data; +} +export interface BlitzkitResponseError { + status: 'error'; + error: string; + message?: unknown; +} +export type BlitzkitResponse = + | BlitzkitResponseError + | { + status: 'ok'; + data: Data; + }; diff --git a/packages/core/src/blitzkit/votes.ts b/packages/core/src/blitzkit/votes.ts new file mode 100644 index 000000000..51e943950 --- /dev/null +++ b/packages/core/src/blitzkit/votes.ts @@ -0,0 +1,13 @@ +export interface TankVotes { + categories: Record; + votes: number; + last_updated?: number; +} +export const TANK_VOTE_CATEGORIES = [ + 'easiness', + 'firepower', + 'maneuverability', + 'survivability', +]; +export type TankVoteCategory = (typeof TANK_VOTE_CATEGORIES)[number]; +export type StarsInt = 1 | 2 | 3 | 4 | 5; diff --git a/src/core/blitzkit/withCORSProxy.ts b/packages/core/src/blitzkit/withCORSProxy.ts similarity index 100% rename from src/core/blitzkit/withCORSProxy.ts rename to packages/core/src/blitzkit/withCORSProxy.ts diff --git a/src/constants/youtubers.ts b/packages/core/src/blitzkit/youtubers.ts similarity index 100% rename from src/constants/youtubers.ts rename to packages/core/src/blitzkit/youtubers.ts diff --git a/packages/core/src/databases/index.ts b/packages/core/src/databases/index.ts new file mode 100644 index 000000000..b18bf4cae --- /dev/null +++ b/packages/core/src/databases/index.ts @@ -0,0 +1 @@ +export * from './users'; diff --git a/src/databases/users.ts b/packages/core/src/databases/users.ts similarity index 100% rename from src/databases/users.ts rename to packages/core/src/databases/users.ts diff --git a/src/core/blitzkit/imgur.ts b/packages/core/src/imgur/imgur.ts similarity index 100% rename from src/core/blitzkit/imgur.ts rename to packages/core/src/imgur/imgur.ts diff --git a/packages/core/src/imgur/index.ts b/packages/core/src/imgur/index.ts new file mode 100644 index 000000000..6daa175fb --- /dev/null +++ b/packages/core/src/imgur/index.ts @@ -0,0 +1 @@ +export * from './imgur'; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts new file mode 100644 index 000000000..12021e51e --- /dev/null +++ b/packages/core/src/index.ts @@ -0,0 +1,12 @@ +export * from './blitz'; +export * from './blitzkit'; +export * from './databases'; +export * from './imgur'; +export * from './math'; +export * from './patreon'; +export * from './protobuf'; +export * from './protos'; +export * from './statistics'; +export * from './streams'; +export * from './types'; + diff --git a/src/core/math/NaNFallback.ts b/packages/core/src/math/NaNFallback.ts similarity index 100% rename from src/core/math/NaNFallback.ts rename to packages/core/src/math/NaNFallback.ts diff --git a/src/constants/axis.ts b/packages/core/src/math/axis.ts similarity index 100% rename from src/constants/axis.ts rename to packages/core/src/math/axis.ts diff --git a/src/core/math/formatCompact.ts b/packages/core/src/math/formatCompact.ts similarity index 100% rename from src/core/math/formatCompact.ts rename to packages/core/src/math/formatCompact.ts diff --git a/packages/core/src/math/index.ts b/packages/core/src/math/index.ts new file mode 100644 index 000000000..bb4a1859b --- /dev/null +++ b/packages/core/src/math/index.ts @@ -0,0 +1,7 @@ +export * from './axis'; +export * from './formatCompact'; +export * from './isNumber'; +export * from './NaNFallback'; +export * from './normalizeAngleRad'; +export * from './normalToEuler'; +export * from './numberToRomanNumeral'; diff --git a/src/core/math/isNumber.ts b/packages/core/src/math/isNumber.ts similarity index 54% rename from src/core/math/isNumber.ts rename to packages/core/src/math/isNumber.ts index 3ad11be0a..a6b5e2816 100644 --- a/src/core/math/isNumber.ts +++ b/packages/core/src/math/isNumber.ts @@ -1,3 +1,3 @@ -export default function isNumber(value: any) { +export function isNumber(value: any) { return typeof value === 'number' && isFinite(value); } diff --git a/src/core/math/normalToEuler.ts b/packages/core/src/math/normalToEuler.ts similarity index 88% rename from src/core/math/normalToEuler.ts rename to packages/core/src/math/normalToEuler.ts index b3b005e96..f89d2970c 100644 --- a/src/core/math/normalToEuler.ts +++ b/packages/core/src/math/normalToEuler.ts @@ -1,5 +1,5 @@ import { Euler, Quaternion, Vector3 } from 'three'; -import { J_HAT } from '../../constants/axis'; +import { J_HAT } from './axis'; const quaternion = new Quaternion(); const axis = new Vector3(); diff --git a/src/core/math/normalizeAngleRad.ts b/packages/core/src/math/normalizeAngleRad.ts similarity index 100% rename from src/core/math/normalizeAngleRad.ts rename to packages/core/src/math/normalizeAngleRad.ts diff --git a/src/core/math/numberToRomanNumeral.ts b/packages/core/src/math/numberToRomanNumeral.ts similarity index 88% rename from src/core/math/numberToRomanNumeral.ts rename to packages/core/src/math/numberToRomanNumeral.ts index e71b20ab8..b31082359 100644 --- a/src/core/math/numberToRomanNumeral.ts +++ b/packages/core/src/math/numberToRomanNumeral.ts @@ -19,7 +19,7 @@ const ROMAN = { }; const ROMAN_KEYS = Object.keys(ROMAN) as (keyof typeof ROMAN)[]; -export default function numberToRomanNumeral(value: number) { +export function numberToRomanNumeral(value: number) { let string = ''; ROMAN_KEYS.forEach((index) => { diff --git a/packages/core/src/patreon/index.ts b/packages/core/src/patreon/index.ts new file mode 100644 index 000000000..7dd103586 --- /dev/null +++ b/packages/core/src/patreon/index.ts @@ -0,0 +1 @@ +export * from './patreonLoginUrl'; diff --git a/packages/core/src/patreon/patreonLoginUrl.ts b/packages/core/src/patreon/patreonLoginUrl.ts new file mode 100644 index 000000000..104b8537f --- /dev/null +++ b/packages/core/src/patreon/patreonLoginUrl.ts @@ -0,0 +1,12 @@ +import { assertSecret } from '../blitzkit/assertSecret'; + +export function patreonLoginUrl() { + const params = new URLSearchParams({ + response_type: 'code', + client_id: assertSecret(import.meta.env.PUBLIC_PATREON_CLIENT_ID), + redirect_uri: assertSecret(import.meta.env.PUBLIC_PATREON_REDIRECT_URI), + scope: 'identity', + }); + + return `https://www.patreon.com/oauth2/authorize?${params}`; +} diff --git a/packages/core/src/protobuf/encodePBBuffer.ts b/packages/core/src/protobuf/encodePBBuffer.ts new file mode 100644 index 000000000..55828bb80 --- /dev/null +++ b/packages/core/src/protobuf/encodePBBuffer.ts @@ -0,0 +1,5 @@ +import { MessageFns } from '../protos'; + +export function encodePBBuffer(message: MessageFns, data: Type) { + return Buffer.from(message.encode(data).finish()); +} diff --git a/packages/core/src/protobuf/fetchPB.ts b/packages/core/src/protobuf/fetchPB.ts new file mode 100644 index 000000000..4d725ee00 --- /dev/null +++ b/packages/core/src/protobuf/fetchPB.ts @@ -0,0 +1,8 @@ +import { MessageFns } from '../protos'; + +export async function fetchPB(url: string, message: MessageFns) { + const response = await fetch(url); + const buffer = await response.arrayBuffer(); + const array = new Uint8Array(buffer); + return message.decode(array); +} diff --git a/packages/core/src/protobuf/index.ts b/packages/core/src/protobuf/index.ts new file mode 100644 index 000000000..773b86baa --- /dev/null +++ b/packages/core/src/protobuf/index.ts @@ -0,0 +1,3 @@ +export * from './encodePBBuffer'; +export * from './fetchPB'; +export * from './pbMap'; diff --git a/packages/core/src/protobuf/pbMap.ts b/packages/core/src/protobuf/pbMap.ts new file mode 100644 index 000000000..74e031394 --- /dev/null +++ b/packages/core/src/protobuf/pbMap.ts @@ -0,0 +1 @@ +export type PBMap = T[keyof T] extends number ? T[keyof T] : never; diff --git a/packages/core/src/protos/average_definitions.proto b/packages/core/src/protos/average_definitions.proto new file mode 100644 index 000000000..3844b4738 --- /dev/null +++ b/packages/core/src/protos/average_definitions.proto @@ -0,0 +1,47 @@ +syntax = "proto2"; + +package blitzkit; + +message AverageDefinitions { + map 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; +} \ No newline at end of file diff --git a/packages/core/src/protos/average_definitions.ts b/packages/core/src/protos/average_definitions.ts new file mode 100644 index 000000000..507678f6d --- /dev/null +++ b/packages/core/src/protos/average_definitions.ts @@ -0,0 +1,944 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/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; + time: number; +} + +export interface AverageDefinitions_AveragesEntry { + key: number; + value: AverageDefinitionsEntry | undefined; +} + +export interface AverageDefinitionsEntry { + mu: AverageDefinitionsAllStats; + sigma: AverageDefinitionsAllStats; + r: AverageDefinitionsAllStats; + samples: Samples; +} + +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: createBaseSamples(), time: 0 }; +} + +export const AverageDefinitions: MessageFns = { + 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); + let 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: Samples.fromJSON(assertSet("AverageDefinitions.samples", object.samples)), + time: globalThis.Number(assertSet("AverageDefinitions.time", object.time)), + }; + }, + + 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>>(base?: I): AverageDefinitions { + return AverageDefinitions.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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) + : createBaseSamples(); + message.time = object.time ?? 0; + return message; + }, +}; + +function createBaseAverageDefinitions_AveragesEntry(): AverageDefinitions_AveragesEntry { + return { key: 0, value: createBaseAverageDefinitionsEntry() }; +} + +export const AverageDefinitions_AveragesEntry: MessageFns = { + encode(message: AverageDefinitions_AveragesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + 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); + let 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: globalThis.Number(assertSet("AverageDefinitions_AveragesEntry.key", object.key)), + value: AverageDefinitionsEntry.fromJSON(assertSet("AverageDefinitions_AveragesEntry.value", object.value)), + }; + }, + + toJSON(message: AverageDefinitions_AveragesEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = AverageDefinitionsEntry.toJSON(message.value); + } + return obj; + }, + + create, I>>( + base?: I, + ): AverageDefinitions_AveragesEntry { + return AverageDefinitions_AveragesEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: createBaseAverageDefinitionsAllStats(), + sigma: createBaseAverageDefinitionsAllStats(), + r: createBaseAverageDefinitionsAllStats(), + samples: createBaseSamples(), + }; +} + +export const AverageDefinitionsEntry: MessageFns = { + 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); + let 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: AverageDefinitionsAllStats.fromJSON(assertSet("AverageDefinitionsEntry.mu", object.mu)), + sigma: AverageDefinitionsAllStats.fromJSON(assertSet("AverageDefinitionsEntry.sigma", object.sigma)), + r: AverageDefinitionsAllStats.fromJSON(assertSet("AverageDefinitionsEntry.r", object.r)), + samples: Samples.fromJSON(assertSet("AverageDefinitionsEntry.samples", object.samples)), + }; + }, + + 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>>(base?: I): AverageDefinitionsEntry { + return AverageDefinitionsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): AverageDefinitionsEntry { + const message = createBaseAverageDefinitionsEntry(); + message.mu = (object.mu !== undefined && object.mu !== null) + ? AverageDefinitionsAllStats.fromPartial(object.mu) + : createBaseAverageDefinitionsAllStats(); + message.sigma = (object.sigma !== undefined && object.sigma !== null) + ? AverageDefinitionsAllStats.fromPartial(object.sigma) + : createBaseAverageDefinitionsAllStats(); + message.r = (object.r !== undefined && object.r !== null) + ? AverageDefinitionsAllStats.fromPartial(object.r) + : createBaseAverageDefinitionsAllStats(); + message.samples = (object.samples !== undefined && object.samples !== null) + ? Samples.fromPartial(object.samples) + : createBaseSamples(); + 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 = { + 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); + let 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: globalThis.Number(assertSet("AverageDefinitionsAllStats.battles", object.battles)), + capture_points: globalThis.Number(assertSet("AverageDefinitionsAllStats.capture_points", object.capture_points)), + damage_dealt: globalThis.Number(assertSet("AverageDefinitionsAllStats.damage_dealt", object.damage_dealt)), + damage_received: globalThis.Number( + assertSet("AverageDefinitionsAllStats.damage_received", object.damage_received), + ), + dropped_capture_points: globalThis.Number( + assertSet("AverageDefinitionsAllStats.dropped_capture_points", object.dropped_capture_points), + ), + frags: globalThis.Number(assertSet("AverageDefinitionsAllStats.frags", object.frags)), + frags8p: globalThis.Number(assertSet("AverageDefinitionsAllStats.frags8p", object.frags8p)), + hits: globalThis.Number(assertSet("AverageDefinitionsAllStats.hits", object.hits)), + losses: globalThis.Number(assertSet("AverageDefinitionsAllStats.losses", object.losses)), + max_frags: globalThis.Number(assertSet("AverageDefinitionsAllStats.max_frags", object.max_frags)), + max_xp: globalThis.Number(assertSet("AverageDefinitionsAllStats.max_xp", object.max_xp)), + shots: globalThis.Number(assertSet("AverageDefinitionsAllStats.shots", object.shots)), + spotted: globalThis.Number(assertSet("AverageDefinitionsAllStats.spotted", object.spotted)), + survived_battles: globalThis.Number( + assertSet("AverageDefinitionsAllStats.survived_battles", object.survived_battles), + ), + win_and_survived: globalThis.Number( + assertSet("AverageDefinitionsAllStats.win_and_survived", object.win_and_survived), + ), + wins: globalThis.Number(assertSet("AverageDefinitionsAllStats.wins", object.wins)), + xp: globalThis.Number(assertSet("AverageDefinitionsAllStats.xp", object.xp)), + battle_life_time: globalThis.Number( + assertSet("AverageDefinitionsAllStats.battle_life_time", object.battle_life_time), + ), + }; + }, + + 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>>(base?: I): AverageDefinitionsAllStats { + return AverageDefinitionsAllStats.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 = { + 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); + let 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: globalThis.Number(assertSet("Samples.d_1", object.d_1)), + d_7: globalThis.Number(assertSet("Samples.d_7", object.d_7)), + d_30: globalThis.Number(assertSet("Samples.d_30", object.d_30)), + d_60: globalThis.Number(assertSet("Samples.d_60", object.d_60)), + d_90: globalThis.Number(assertSet("Samples.d_90", object.d_90)), + d_120: globalThis.Number(assertSet("Samples.d_120", object.d_120)), + total: globalThis.Number(assertSet("Samples.total", object.total)), + }; + }, + + 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>>(base?: I): Samples { + return Samples.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: 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; +} + +function assertSet(field: string, value: T | undefined): T { + if (!isSet(value)) { + throw new TypeError(`Required field ${field} is not set`); + } + + return value as T; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/packages/core/src/protos/camouflage_definitions.proto b/packages/core/src/protos/camouflage_definitions.proto new file mode 100644 index 000000000..80f101a5a --- /dev/null +++ b/packages/core/src/protos/camouflage_definitions.proto @@ -0,0 +1,14 @@ +syntax = "proto2"; + +package blitzkit; + +message CamouflageDefinitions { + map camouflages = 1; +} + +message Camouflage { + required uint32 id = 1; + required string name = 2; + optional string tank_name = 3; + optional string tank_name_full = 4; +} \ No newline at end of file diff --git a/packages/core/src/protos/camouflage_definitions.ts b/packages/core/src/protos/camouflage_definitions.ts new file mode 100644 index 000000000..1399490b5 --- /dev/null +++ b/packages/core/src/protos/camouflage_definitions.ts @@ -0,0 +1,336 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/camouflage_definitions.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +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: string; + tank_name?: string | undefined; + tank_name_full?: string | undefined; +} + +function createBaseCamouflageDefinitions(): CamouflageDefinitions { + return { camouflages: {} }; +} + +export const CamouflageDefinitions: MessageFns = { + 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); + let 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>>(base?: I): CamouflageDefinitions { + return CamouflageDefinitions.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: createBaseCamouflage() }; +} + +export const CamouflageDefinitions_CamouflagesEntry: MessageFns = { + encode(message: CamouflageDefinitions_CamouflagesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + 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); + let 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: globalThis.Number(assertSet("CamouflageDefinitions_CamouflagesEntry.key", object.key)), + value: Camouflage.fromJSON(assertSet("CamouflageDefinitions_CamouflagesEntry.value", object.value)), + }; + }, + + toJSON(message: CamouflageDefinitions_CamouflagesEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = Camouflage.toJSON(message.value); + } + return obj; + }, + + create, I>>( + base?: I, + ): CamouflageDefinitions_CamouflagesEntry { + return CamouflageDefinitions_CamouflagesEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: "", tank_name: undefined, tank_name_full: undefined }; +} + +export const Camouflage: MessageFns = { + encode(message: Camouflage, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.id !== 0) { + writer.uint32(8).uint32(message.id); + } + if (message.name !== "") { + writer.uint32(18).string(message.name); + } + if (message.tank_name !== undefined && message.tank_name !== undefined) { + writer.uint32(26).string(message.tank_name); + } + if (message.tank_name_full !== undefined && message.tank_name_full !== undefined) { + writer.uint32(34).string(message.tank_name_full); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Camouflage { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let 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 = reader.string(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.tank_name = reader.string(); + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + message.tank_name_full = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Camouflage { + return { + id: globalThis.Number(assertSet("Camouflage.id", object.id)), + name: globalThis.String(assertSet("Camouflage.name", object.name)), + tank_name: isSet(object.tank_name) ? globalThis.String(object.tank_name) : undefined, + tank_name_full: isSet(object.tank_name_full) ? globalThis.String(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 !== "") { + obj.name = message.name; + } + if (message.tank_name !== undefined && message.tank_name !== undefined) { + obj.tank_name = message.tank_name; + } + if (message.tank_name_full !== undefined && message.tank_name_full !== undefined) { + obj.tank_name_full = message.tank_name_full; + } + return obj; + }, + + create, I>>(base?: I): Camouflage { + return Camouflage.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Camouflage { + const message = createBaseCamouflage(); + message.id = object.id ?? 0; + message.name = object.name ?? ""; + message.tank_name = object.tank_name ?? undefined; + message.tank_name_full = object.tank_name_full ?? undefined; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +function assertSet(field: string, value: T | undefined): T { + if (!isSet(value)) { + throw new TypeError(`Required field ${field} is not set`); + } + + return value as T; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/packages/core/src/protos/consumable_definitions.proto b/packages/core/src/protos/consumable_definitions.proto new file mode 100644 index 000000000..c045e65b7 --- /dev/null +++ b/packages/core/src/protos/consumable_definitions.proto @@ -0,0 +1,49 @@ +syntax = "proto2"; + +package blitzkit; + +import "packages/core/src/protos/tank_definitions.proto"; + +message ConsumableDefinitions { + map consumables = 1; +} + +message Consumable { + required uint32 id = 1; + required string 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 ConsumableTankFilter { + oneof filter_type { + ConsumableTankTierFilter tiers = 1; + ConsumableTankIdsFilter ids = 2; + ConsumableTankCategoryFilter categories = 3; + ConsumableTankNationFilter nations = 4; + } +} + +message ConsumableTankTierFilter { + required Tier min = 1; + required Tier max = 2; +} + +message ConsumableTankIdsFilter { + repeated uint32 ids = 1; +} + +message ConsumableTankCategoryFilter { + repeated ConsumableTankCategoryFilterCategory categories = 1; +} + +enum ConsumableTankCategoryFilterCategory { + CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP = 0; +} + +message ConsumableTankNationFilter { + repeated string nations = 1; +} \ No newline at end of file diff --git a/packages/core/src/protos/consumable_definitions.ts b/packages/core/src/protos/consumable_definitions.ts new file mode 100644 index 000000000..9923a358a --- /dev/null +++ b/packages/core/src/protos/consumable_definitions.ts @@ -0,0 +1,873 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/consumable_definitions.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; +import { Tier, tierFromJSON, tierToJSON } from "./tank_definitions"; + +export const protobufPackage = "blitzkit"; + +export enum ConsumableTankCategoryFilterCategory { + CLIP = 0, +} + +export function consumableTankCategoryFilterCategoryFromJSON(object: any): ConsumableTankCategoryFilterCategory { + switch (object) { + case 0: + case "CONSUMABLE_TANK_CATEGORY_FILTER_CATEGORY_CLIP": + return ConsumableTankCategoryFilterCategory.CLIP; + default: + throw new globalThis.Error( + "Unrecognized enum value " + object + " for enum ConsumableTankCategoryFilterCategory", + ); + } +} + +export function consumableTankCategoryFilterCategoryToJSON(object: ConsumableTankCategoryFilterCategory): string { + switch (object) { + case ConsumableTankCategoryFilterCategory.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: string; + 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: Tier; + max: Tier; +} + +export interface ConsumableTankIdsFilter { + ids: number[]; +} + +export interface ConsumableTankCategoryFilter { + categories: ConsumableTankCategoryFilterCategory[]; +} + +export interface ConsumableTankNationFilter { + nations: string[]; +} + +function createBaseConsumableDefinitions(): ConsumableDefinitions { + return { consumables: {} }; +} + +export const ConsumableDefinitions: MessageFns = { + 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); + let 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>>(base?: I): ConsumableDefinitions { + return ConsumableDefinitions.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: createBaseConsumable() }; +} + +export const ConsumableDefinitions_ConsumablesEntry: MessageFns = { + encode(message: ConsumableDefinitions_ConsumablesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + 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); + let 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: globalThis.Number(assertSet("ConsumableDefinitions_ConsumablesEntry.key", object.key)), + value: Consumable.fromJSON(assertSet("ConsumableDefinitions_ConsumablesEntry.value", object.value)), + }; + }, + + toJSON(message: ConsumableDefinitions_ConsumablesEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = Consumable.toJSON(message.value); + } + return obj; + }, + + create, I>>( + base?: I, + ): ConsumableDefinitions_ConsumablesEntry { + return ConsumableDefinitions_ConsumablesEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: "", cooldown: 0, duration: undefined, game_mode_exclusive: false, include: [], exclude: [] }; +} + +export const Consumable: MessageFns = { + encode(message: Consumable, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.id !== 0) { + writer.uint32(8).uint32(message.id); + } + if (message.name !== "") { + writer.uint32(18).string(message.name); + } + if (message.cooldown !== 0) { + writer.uint32(24).uint32(message.cooldown); + } + if (message.duration !== undefined && message.duration !== undefined) { + 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); + let 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 = reader.string(); + 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: globalThis.Number(assertSet("Consumable.id", object.id)), + name: globalThis.String(assertSet("Consumable.name", object.name)), + cooldown: globalThis.Number(assertSet("Consumable.cooldown", object.cooldown)), + duration: isSet(object.duration) ? globalThis.Number(object.duration) : undefined, + game_mode_exclusive: globalThis.Boolean(assertSet("Consumable.game_mode_exclusive", object.game_mode_exclusive)), + 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 !== "") { + obj.name = message.name; + } + if (message.cooldown !== 0) { + obj.cooldown = Math.round(message.cooldown); + } + if (message.duration !== undefined && message.duration !== undefined) { + 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>>(base?: I): Consumable { + return Consumable.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Consumable { + const message = createBaseConsumable(); + message.id = object.id ?? 0; + message.name = object.name ?? ""; + message.cooldown = object.cooldown ?? 0; + message.duration = object.duration ?? undefined; + 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 = { + 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); + let 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); + } + if (message.filter_type?.$case === "ids") { + obj.ids = ConsumableTankIdsFilter.toJSON(message.filter_type.value); + } + if (message.filter_type?.$case === "categories") { + obj.categories = ConsumableTankCategoryFilter.toJSON(message.filter_type.value); + } + if (message.filter_type?.$case === "nations") { + obj.nations = ConsumableTankNationFilter.toJSON(message.filter_type.value); + } + return obj; + }, + + create, I>>(base?: I): ConsumableTankFilter { + return ConsumableTankFilter.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ConsumableTankFilter { + const message = createBaseConsumableTankFilter(); + if ( + object.filter_type?.$case === "tiers" && + object.filter_type?.value !== undefined && + object.filter_type?.value !== null + ) { + message.filter_type = { $case: "tiers", value: ConsumableTankTierFilter.fromPartial(object.filter_type.value) }; + } + if ( + object.filter_type?.$case === "ids" && + object.filter_type?.value !== undefined && + object.filter_type?.value !== null + ) { + message.filter_type = { $case: "ids", value: ConsumableTankIdsFilter.fromPartial(object.filter_type.value) }; + } + if ( + object.filter_type?.$case === "categories" && + object.filter_type?.value !== undefined && + object.filter_type?.value !== null + ) { + message.filter_type = { + $case: "categories", + value: ConsumableTankCategoryFilter.fromPartial(object.filter_type.value), + }; + } + if ( + object.filter_type?.$case === "nations" && + object.filter_type?.value !== undefined && + object.filter_type?.value !== null + ) { + message.filter_type = { + $case: "nations", + value: ConsumableTankNationFilter.fromPartial(object.filter_type.value), + }; + } + return message; + }, +}; + +function createBaseConsumableTankTierFilter(): ConsumableTankTierFilter { + return { min: 0, max: 0 }; +} + +export const ConsumableTankTierFilter: MessageFns = { + encode(message: ConsumableTankTierFilter, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.min !== 0) { + writer.uint32(8).int32(message.min); + } + if (message.max !== 0) { + writer.uint32(16).int32(message.max); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ConsumableTankTierFilter { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let 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.int32() as any; + continue; + } + case 2: { + if (tag !== 16) { + break; + } + + message.max = reader.int32() as any; + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ConsumableTankTierFilter { + return { + min: tierFromJSON(assertSet("ConsumableTankTierFilter.min", object.min)), + max: tierFromJSON(assertSet("ConsumableTankTierFilter.max", object.max)), + }; + }, + + toJSON(message: ConsumableTankTierFilter): unknown { + const obj: any = {}; + if (message.min !== 0) { + obj.min = tierToJSON(message.min); + } + if (message.max !== 0) { + obj.max = tierToJSON(message.max); + } + return obj; + }, + + create, I>>(base?: I): ConsumableTankTierFilter { + return ConsumableTankTierFilter.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 = { + encode(message: ConsumableTankIdsFilter, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + writer.uint32(10).fork(); + for (const v of message.ids) { + writer.uint32(v); + } + writer.join(); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ConsumableTankIdsFilter { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let 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>>(base?: I): ConsumableTankIdsFilter { + return ConsumableTankIdsFilter.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 = { + encode(message: ConsumableTankCategoryFilter, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + writer.uint32(10).fork(); + for (const v of message.categories) { + writer.int32(v); + } + writer.join(); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ConsumableTankCategoryFilter { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let 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>>(base?: I): ConsumableTankCategoryFilter { + return ConsumableTankCategoryFilter.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 = { + 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); + let 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>>(base?: I): ConsumableTankNationFilter { + return ConsumableTankNationFilter.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +function assertSet(field: string, value: T | undefined): T { + if (!isSet(value)) { + throw new TypeError(`Required field ${field} is not set`); + } + + return value as T; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/packages/core/src/protos/equipment_definitions.proto b/packages/core/src/protos/equipment_definitions.proto new file mode 100644 index 000000000..c954424d4 --- /dev/null +++ b/packages/core/src/protos/equipment_definitions.proto @@ -0,0 +1,22 @@ +syntax = "proto2"; + +package blitzkit; + +message EquipmentDefinitions { + map presets = 1; + map equipments = 2; +} + +message Equipment { + required string name = 1; + required string description = 2; +} + +message EquipmentPreset { + repeated EquipmentSlot slots = 1; +} + +message EquipmentSlot { + required uint32 left = 1; + required uint32 right = 2; +} \ No newline at end of file diff --git a/packages/core/src/protos/equipment_definitions.ts b/packages/core/src/protos/equipment_definitions.ts new file mode 100644 index 000000000..aaec6db7c --- /dev/null +++ b/packages/core/src/protos/equipment_definitions.ts @@ -0,0 +1,573 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/equipment_definitions.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +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: string; + description: string; +} + +export interface EquipmentPreset { + slots: EquipmentSlot[]; +} + +export interface EquipmentSlot { + left: number; + right: number; +} + +function createBaseEquipmentDefinitions(): EquipmentDefinitions { + return { presets: {}, equipments: {} }; +} + +export const EquipmentDefinitions: MessageFns = { + 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); + let 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>>(base?: I): EquipmentDefinitions { + return EquipmentDefinitions.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: createBaseEquipmentPreset() }; +} + +export const EquipmentDefinitions_PresetsEntry: MessageFns = { + encode(message: EquipmentDefinitions_PresetsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + 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); + let 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: globalThis.String(assertSet("EquipmentDefinitions_PresetsEntry.key", object.key)), + value: EquipmentPreset.fromJSON(assertSet("EquipmentDefinitions_PresetsEntry.value", object.value)), + }; + }, + + toJSON(message: EquipmentDefinitions_PresetsEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = message.key; + } + if (message.value !== undefined) { + obj.value = EquipmentPreset.toJSON(message.value); + } + return obj; + }, + + create, I>>( + base?: I, + ): EquipmentDefinitions_PresetsEntry { + return EquipmentDefinitions_PresetsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: createBaseEquipment() }; +} + +export const EquipmentDefinitions_EquipmentsEntry: MessageFns = { + encode(message: EquipmentDefinitions_EquipmentsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + 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); + let 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: globalThis.Number(assertSet("EquipmentDefinitions_EquipmentsEntry.key", object.key)), + value: Equipment.fromJSON(assertSet("EquipmentDefinitions_EquipmentsEntry.value", object.value)), + }; + }, + + toJSON(message: EquipmentDefinitions_EquipmentsEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = Equipment.toJSON(message.value); + } + return obj; + }, + + create, I>>( + base?: I, + ): EquipmentDefinitions_EquipmentsEntry { + return EquipmentDefinitions_EquipmentsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: "", description: "" }; +} + +export const Equipment: MessageFns = { + encode(message: Equipment, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.name !== "") { + writer.uint32(10).string(message.name); + } + if (message.description !== "") { + writer.uint32(18).string(message.description); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Equipment { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let 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 = reader.string(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.description = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Equipment { + return { + name: globalThis.String(assertSet("Equipment.name", object.name)), + description: globalThis.String(assertSet("Equipment.description", object.description)), + }; + }, + + toJSON(message: Equipment): unknown { + const obj: any = {}; + if (message.name !== "") { + obj.name = message.name; + } + if (message.description !== "") { + obj.description = message.description; + } + return obj; + }, + + create, I>>(base?: I): Equipment { + return Equipment.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Equipment { + const message = createBaseEquipment(); + message.name = object.name ?? ""; + message.description = object.description ?? ""; + return message; + }, +}; + +function createBaseEquipmentPreset(): EquipmentPreset { + return { slots: [] }; +} + +export const EquipmentPreset: MessageFns = { + 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); + let 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>>(base?: I): EquipmentPreset { + return EquipmentPreset.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 = { + 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); + let 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: globalThis.Number(assertSet("EquipmentSlot.left", object.left)), + right: globalThis.Number(assertSet("EquipmentSlot.right", object.right)), + }; + }, + + 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>>(base?: I): EquipmentSlot { + return EquipmentSlot.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +function assertSet(field: string, value: T | undefined): T { + if (!isSet(value)) { + throw new TypeError(`Required field ${field} is not set`); + } + + return value as T; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/packages/core/src/protos/game_definitions.proto b/packages/core/src/protos/game_definitions.proto new file mode 100644 index 000000000..7d3ffcb48 --- /dev/null +++ b/packages/core/src/protos/game_definitions.proto @@ -0,0 +1,19 @@ +syntax = "proto2"; + +package blitzkit; + +message GameDefinitions { + required string version = 1; + repeated string nations = 2; + map gameModes = 3; + map roles = 4; +} + +message GameMode { + required string name = 1; +} + +message GameModeRole { + repeated uint32 provisions = 1; + repeated uint32 consumables = 2; +} \ No newline at end of file diff --git a/packages/core/src/protos/game_definitions.ts b/packages/core/src/protos/game_definitions.ts new file mode 100644 index 000000000..3d6b5e93d --- /dev/null +++ b/packages/core/src/protos/game_definitions.ts @@ -0,0 +1,543 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/game_definitions.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export const protobufPackage = "blitzkit"; + +export interface GameDefinitions { + version: string; + nations: string[]; + gameModes: { [key: number]: GameMode }; + roles: { [key: number]: GameModeRole }; +} + +export interface GameDefinitions_GameModesEntry { + key: number; + value: GameMode | undefined; +} + +export interface GameDefinitions_RolesEntry { + key: number; + value: GameModeRole | undefined; +} + +export interface GameMode { + name: string; +} + +export interface GameModeRole { + provisions: number[]; + consumables: number[]; +} + +function createBaseGameDefinitions(): GameDefinitions { + return { version: "", nations: [], gameModes: {}, roles: {} }; +} + +export const GameDefinitions: MessageFns = { + 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); + let 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: globalThis.String(assertSet("GameDefinitions.version", 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: number]: GameMode }>((acc, [key, value]) => { + acc[globalThis.Number(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>>(base?: I): GameDefinitions { + return GameDefinitions.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: number]: GameMode }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(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: 0, value: createBaseGameMode() }; +} + +export const GameDefinitions_GameModesEntry: MessageFns = { + encode(message: GameDefinitions_GameModesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(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); + let 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 !== 8) { + break; + } + + message.key = reader.uint32(); + 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: globalThis.Number(assertSet("GameDefinitions_GameModesEntry.key", object.key)), + value: GameMode.fromJSON(assertSet("GameDefinitions_GameModesEntry.value", object.value)), + }; + }, + + toJSON(message: GameDefinitions_GameModesEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = GameMode.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): GameDefinitions_GameModesEntry { + return GameDefinitions_GameModesEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): GameDefinitions_GameModesEntry { + const message = createBaseGameDefinitions_GameModesEntry(); + message.key = object.key ?? 0; + message.value = (object.value !== undefined && object.value !== null) + ? GameMode.fromPartial(object.value) + : undefined; + return message; + }, +}; + +function createBaseGameDefinitions_RolesEntry(): GameDefinitions_RolesEntry { + return { key: 0, value: createBaseGameModeRole() }; +} + +export const GameDefinitions_RolesEntry: MessageFns = { + encode(message: GameDefinitions_RolesEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + 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); + let 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: globalThis.Number(assertSet("GameDefinitions_RolesEntry.key", object.key)), + value: GameModeRole.fromJSON(assertSet("GameDefinitions_RolesEntry.value", object.value)), + }; + }, + + toJSON(message: GameDefinitions_RolesEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = GameModeRole.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): GameDefinitions_RolesEntry { + return GameDefinitions_RolesEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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: "" }; +} + +export const GameMode: MessageFns = { + encode(message: GameMode, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.name !== "") { + writer.uint32(10).string(message.name); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GameMode { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let 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 = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GameMode { + return { name: globalThis.String(assertSet("GameMode.name", object.name)) }; + }, + + toJSON(message: GameMode): unknown { + const obj: any = {}; + if (message.name !== "") { + obj.name = message.name; + } + return obj; + }, + + create, I>>(base?: I): GameMode { + return GameMode.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): GameMode { + const message = createBaseGameMode(); + message.name = object.name ?? ""; + return message; + }, +}; + +function createBaseGameModeRole(): GameModeRole { + return { provisions: [], consumables: [] }; +} + +export const GameModeRole: MessageFns = { + encode(message: GameModeRole, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + writer.uint32(10).fork(); + for (const v of message.provisions) { + writer.uint32(v); + } + writer.join(); + writer.uint32(18).fork(); + for (const v of message.consumables) { + writer.uint32(v); + } + writer.join(); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GameModeRole { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let 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>>(base?: I): GameModeRole { + return GameModeRole.fromPartial(base ?? ({} as any)); + }, + fromPartial, 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 extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +function assertSet(field: string, value: T | undefined): T { + if (!isSet(value)) { + throw new TypeError(`Required field ${field} is not set`); + } + + return value as T; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/packages/core/src/protos/index.ts b/packages/core/src/protos/index.ts new file mode 100644 index 000000000..8f8085d62 --- /dev/null +++ b/packages/core/src/protos/index.ts @@ -0,0 +1,12 @@ +// @ts-nocheck +export * from './average_definitions.ts'; +export * from './camouflage_definitions.ts'; +export * from './consumable_definitions.ts'; +export * from './equipment_definitions.ts'; +export * from './game_definitions.ts'; +export * from './map_definitions.ts'; +export * from './model_definitions.ts'; +export * from './provision_definitions.ts'; +export * from './reviews.ts'; +export * from './skill_definitions.ts'; +export * from './tank_definitions.ts'; \ No newline at end of file diff --git a/packages/core/src/protos/map_definitions.proto b/packages/core/src/protos/map_definitions.proto new file mode 100644 index 000000000..27c11112e --- /dev/null +++ b/packages/core/src/protos/map_definitions.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; + +package blitzkit; + +message MapDefinitions { + map maps = 1; +} + +message MapDefinition { + required uint32 id = 1; + required string name = 2; +} \ No newline at end of file diff --git a/packages/core/src/protos/map_definitions.ts b/packages/core/src/protos/map_definitions.ts new file mode 100644 index 000000000..4485541a6 --- /dev/null +++ b/packages/core/src/protos/map_definitions.ts @@ -0,0 +1,295 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/map_definitions.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export const protobufPackage = "blitzkit"; + +export interface MapDefinitions { + maps: { [key: number]: MapDefinition }; +} + +export interface MapDefinitions_MapsEntry { + key: number; + value: MapDefinition | undefined; +} + +export interface MapDefinition { + id: number; + name: string; +} + +function createBaseMapDefinitions(): MapDefinitions { + return { maps: {} }; +} + +export const MapDefinitions: MessageFns = { + encode(message: MapDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + Object.entries(message.maps).forEach(([key, value]) => { + MapDefinitions_MapsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + }); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): MapDefinitions { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseMapDefinitions(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + const entry1 = MapDefinitions_MapsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.maps[entry1.key] = entry1.value; + } + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): MapDefinitions { + return { + maps: isObject(object.maps) + ? Object.entries(object.maps).reduce<{ [key: number]: MapDefinition }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = MapDefinition.fromJSON(value); + return acc; + }, {}) + : {}, + }; + }, + + toJSON(message: MapDefinitions): unknown { + const obj: any = {}; + if (message.maps) { + const entries = Object.entries(message.maps); + if (entries.length > 0) { + obj.maps = {}; + entries.forEach(([k, v]) => { + obj.maps[k] = MapDefinition.toJSON(v); + }); + } + } + return obj; + }, + + create, I>>(base?: I): MapDefinitions { + return MapDefinitions.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): MapDefinitions { + const message = createBaseMapDefinitions(); + message.maps = Object.entries(object.maps ?? {}).reduce<{ [key: number]: MapDefinition }>((acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = MapDefinition.fromPartial(value); + } + return acc; + }, {}); + return message; + }, +}; + +function createBaseMapDefinitions_MapsEntry(): MapDefinitions_MapsEntry { + return { key: 0, value: createBaseMapDefinition() }; +} + +export const MapDefinitions_MapsEntry: MessageFns = { + encode(message: MapDefinitions_MapsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).int32(message.key); + } + if (message.value !== undefined) { + MapDefinition.encode(message.value, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): MapDefinitions_MapsEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseMapDefinitions_MapsEntry(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 8) { + break; + } + + message.key = reader.int32(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.value = MapDefinition.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): MapDefinitions_MapsEntry { + return { + key: globalThis.Number(assertSet("MapDefinitions_MapsEntry.key", object.key)), + value: MapDefinition.fromJSON(assertSet("MapDefinitions_MapsEntry.value", object.value)), + }; + }, + + toJSON(message: MapDefinitions_MapsEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = MapDefinition.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): MapDefinitions_MapsEntry { + return MapDefinitions_MapsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): MapDefinitions_MapsEntry { + const message = createBaseMapDefinitions_MapsEntry(); + message.key = object.key ?? 0; + message.value = (object.value !== undefined && object.value !== null) + ? MapDefinition.fromPartial(object.value) + : undefined; + return message; + }, +}; + +function createBaseMapDefinition(): MapDefinition { + return { id: 0, name: "" }; +} + +export const MapDefinition: MessageFns = { + encode(message: MapDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.id !== 0) { + writer.uint32(8).uint32(message.id); + } + if (message.name !== "") { + writer.uint32(18).string(message.name); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): MapDefinition { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseMapDefinition(); + 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 = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): MapDefinition { + return { + id: globalThis.Number(assertSet("MapDefinition.id", object.id)), + name: globalThis.String(assertSet("MapDefinition.name", object.name)), + }; + }, + + toJSON(message: MapDefinition): unknown { + const obj: any = {}; + if (message.id !== 0) { + obj.id = Math.round(message.id); + } + if (message.name !== "") { + obj.name = message.name; + } + return obj; + }, + + create, I>>(base?: I): MapDefinition { + return MapDefinition.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): MapDefinition { + const message = createBaseMapDefinition(); + message.id = object.id ?? 0; + message.name = object.name ?? ""; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +function assertSet(field: string, value: T | undefined): T { + if (!isSet(value)) { + throw new TypeError(`Required field ${field} is not set`); + } + + return value as T; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/packages/core/src/protos/model_definitions.proto b/packages/core/src/protos/model_definitions.proto new file mode 100644 index 000000000..170141c14 --- /dev/null +++ b/packages/core/src/protos/model_definitions.proto @@ -0,0 +1,79 @@ +syntax = "proto2"; + +package blitzkit; + +message ModelDefinitions { + map models = 1; +} + +message ModelDefinition { + required Armor armor = 1; + required Vector3 turret_origin = 2; + optional InitialTurretRotation initial_turret_rotation = 3; + map turrets = 4; + map tracks = 5; + required BoundingBox bounding_box = 6; +} + +message Armor { + map thickness = 1; + repeated uint32 spaced = 2; +} + +message Vector3 { + required float x = 1; + required float y = 2; + required float z = 3; +} + +message InitialTurretRotation { + required float yaw = 1; + required float pitch = 2; + required float roll = 3; +} + +message TurretModelDefinition { + required BoundingBox bounding_box = 1; + required Armor armor = 2; + required uint32 model_id = 3; + required Vector3 gun_origin = 4; + map guns = 5; + optional YawLimits yaw = 6; +} + +message YawLimits { + required float min = 1; + required float max = 2; +} + +message BoundingBox { + required Vector3 min = 1; + required Vector3 max = 2; +} + +message TrackModelDefinition { + required float thickness = 1; + required Vector3 origin = 2; +} + +message GunModelDefinition { + required Armor armor = 1; + required float thickness = 2; + required uint32 model_id = 3; + required PitchLimits pitch = 4; + optional float mask = 5; +} + +message PitchLimits { + required float min = 1; + required float max = 2; + optional PitchLimitsExtrema front = 3; + optional PitchLimitsExtrema back = 4; + optional float transition = 5; +} + +message PitchLimitsExtrema { + required float min = 1; + required float max = 2; + required float range = 3; +} \ No newline at end of file diff --git a/packages/core/src/protos/model_definitions.ts b/packages/core/src/protos/model_definitions.ts new file mode 100644 index 000000000..3adb2b49a --- /dev/null +++ b/packages/core/src/protos/model_definitions.ts @@ -0,0 +1,1874 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/model_definitions.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export const protobufPackage = "blitzkit"; + +export interface ModelDefinitions { + models: { [key: number]: ModelDefinition }; +} + +export interface ModelDefinitions_ModelsEntry { + key: number; + value: ModelDefinition | undefined; +} + +export interface ModelDefinition { + armor: Armor; + turret_origin: Vector3; + initial_turret_rotation?: InitialTurretRotation | undefined; + turrets: { [key: number]: TurretModelDefinition }; + tracks: { [key: number]: TrackModelDefinition }; + bounding_box: BoundingBox; +} + +export interface ModelDefinition_TurretsEntry { + key: number; + value: TurretModelDefinition | undefined; +} + +export interface ModelDefinition_TracksEntry { + key: number; + value: TrackModelDefinition | undefined; +} + +export interface Armor { + thickness: { [key: number]: number }; + spaced: number[]; +} + +export interface Armor_ThicknessEntry { + key: number; + value: number; +} + +export interface Vector3 { + x: number; + y: number; + z: number; +} + +export interface InitialTurretRotation { + yaw: number; + pitch: number; + roll: number; +} + +export interface TurretModelDefinition { + bounding_box: BoundingBox; + armor: Armor; + model_id: number; + gun_origin: Vector3; + guns: { [key: number]: GunModelDefinition }; + yaw?: YawLimits | undefined; +} + +export interface TurretModelDefinition_GunsEntry { + key: number; + value: GunModelDefinition | undefined; +} + +export interface YawLimits { + min: number; + max: number; +} + +export interface BoundingBox { + min: Vector3; + max: Vector3; +} + +export interface TrackModelDefinition { + thickness: number; + origin: Vector3; +} + +export interface GunModelDefinition { + armor: Armor; + thickness: number; + model_id: number; + pitch: PitchLimits; + mask?: number | undefined; +} + +export interface PitchLimits { + min: number; + max: number; + front?: PitchLimitsExtrema | undefined; + back?: PitchLimitsExtrema | undefined; + transition?: number | undefined; +} + +export interface PitchLimitsExtrema { + min: number; + max: number; + range: number; +} + +function createBaseModelDefinitions(): ModelDefinitions { + return { models: {} }; +} + +export const ModelDefinitions: MessageFns = { + encode(message: ModelDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + Object.entries(message.models).forEach(([key, value]) => { + ModelDefinitions_ModelsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + }); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ModelDefinitions { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseModelDefinitions(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + const entry1 = ModelDefinitions_ModelsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.models[entry1.key] = entry1.value; + } + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ModelDefinitions { + return { + models: isObject(object.models) + ? Object.entries(object.models).reduce<{ [key: number]: ModelDefinition }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = ModelDefinition.fromJSON(value); + return acc; + }, {}) + : {}, + }; + }, + + toJSON(message: ModelDefinitions): unknown { + const obj: any = {}; + if (message.models) { + const entries = Object.entries(message.models); + if (entries.length > 0) { + obj.models = {}; + entries.forEach(([k, v]) => { + obj.models[k] = ModelDefinition.toJSON(v); + }); + } + } + return obj; + }, + + create, I>>(base?: I): ModelDefinitions { + return ModelDefinitions.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ModelDefinitions { + const message = createBaseModelDefinitions(); + message.models = Object.entries(object.models ?? {}).reduce<{ [key: number]: ModelDefinition }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = ModelDefinition.fromPartial(value); + } + return acc; + }, + {}, + ); + return message; + }, +}; + +function createBaseModelDefinitions_ModelsEntry(): ModelDefinitions_ModelsEntry { + return { key: 0, value: createBaseModelDefinition() }; +} + +export const ModelDefinitions_ModelsEntry: MessageFns = { + encode(message: ModelDefinitions_ModelsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(message.key); + } + if (message.value !== undefined) { + ModelDefinition.encode(message.value, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ModelDefinitions_ModelsEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseModelDefinitions_ModelsEntry(); + 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 = ModelDefinition.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ModelDefinitions_ModelsEntry { + return { + key: globalThis.Number(assertSet("ModelDefinitions_ModelsEntry.key", object.key)), + value: ModelDefinition.fromJSON(assertSet("ModelDefinitions_ModelsEntry.value", object.value)), + }; + }, + + toJSON(message: ModelDefinitions_ModelsEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = ModelDefinition.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): ModelDefinitions_ModelsEntry { + return ModelDefinitions_ModelsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ModelDefinitions_ModelsEntry { + const message = createBaseModelDefinitions_ModelsEntry(); + message.key = object.key ?? 0; + message.value = (object.value !== undefined && object.value !== null) + ? ModelDefinition.fromPartial(object.value) + : undefined; + return message; + }, +}; + +function createBaseModelDefinition(): ModelDefinition { + return { + armor: createBaseArmor(), + turret_origin: createBaseVector3(), + initial_turret_rotation: undefined, + turrets: {}, + tracks: {}, + bounding_box: createBaseBoundingBox(), + }; +} + +export const ModelDefinition: MessageFns = { + encode(message: ModelDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.armor !== undefined) { + Armor.encode(message.armor, writer.uint32(10).fork()).join(); + } + if (message.turret_origin !== undefined) { + Vector3.encode(message.turret_origin, writer.uint32(18).fork()).join(); + } + if (message.initial_turret_rotation !== undefined) { + InitialTurretRotation.encode(message.initial_turret_rotation, writer.uint32(26).fork()).join(); + } + Object.entries(message.turrets).forEach(([key, value]) => { + ModelDefinition_TurretsEntry.encode({ key: key as any, value }, writer.uint32(34).fork()).join(); + }); + Object.entries(message.tracks).forEach(([key, value]) => { + ModelDefinition_TracksEntry.encode({ key: key as any, value }, writer.uint32(42).fork()).join(); + }); + if (message.bounding_box !== undefined) { + BoundingBox.encode(message.bounding_box, writer.uint32(50).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ModelDefinition { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseModelDefinition(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.armor = Armor.decode(reader, reader.uint32()); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.turret_origin = Vector3.decode(reader, reader.uint32()); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.initial_turret_rotation = InitialTurretRotation.decode(reader, reader.uint32()); + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + const entry4 = ModelDefinition_TurretsEntry.decode(reader, reader.uint32()); + if (entry4.value !== undefined) { + message.turrets[entry4.key] = entry4.value; + } + continue; + } + case 5: { + if (tag !== 42) { + break; + } + + const entry5 = ModelDefinition_TracksEntry.decode(reader, reader.uint32()); + if (entry5.value !== undefined) { + message.tracks[entry5.key] = entry5.value; + } + continue; + } + case 6: { + if (tag !== 50) { + break; + } + + message.bounding_box = BoundingBox.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ModelDefinition { + return { + armor: Armor.fromJSON(assertSet("ModelDefinition.armor", object.armor)), + turret_origin: Vector3.fromJSON(assertSet("ModelDefinition.turret_origin", object.turret_origin)), + initial_turret_rotation: isSet(object.initial_turret_rotation) + ? InitialTurretRotation.fromJSON(object.initial_turret_rotation) + : undefined, + turrets: isObject(object.turrets) + ? Object.entries(object.turrets).reduce<{ [key: number]: TurretModelDefinition }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = TurretModelDefinition.fromJSON(value); + return acc; + }, {}) + : {}, + tracks: isObject(object.tracks) + ? Object.entries(object.tracks).reduce<{ [key: number]: TrackModelDefinition }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = TrackModelDefinition.fromJSON(value); + return acc; + }, {}) + : {}, + bounding_box: BoundingBox.fromJSON(assertSet("ModelDefinition.bounding_box", object.bounding_box)), + }; + }, + + toJSON(message: ModelDefinition): unknown { + const obj: any = {}; + if (message.armor !== undefined) { + obj.armor = Armor.toJSON(message.armor); + } + if (message.turret_origin !== undefined) { + obj.turret_origin = Vector3.toJSON(message.turret_origin); + } + if (message.initial_turret_rotation !== undefined) { + obj.initial_turret_rotation = InitialTurretRotation.toJSON(message.initial_turret_rotation); + } + if (message.turrets) { + const entries = Object.entries(message.turrets); + if (entries.length > 0) { + obj.turrets = {}; + entries.forEach(([k, v]) => { + obj.turrets[k] = TurretModelDefinition.toJSON(v); + }); + } + } + if (message.tracks) { + const entries = Object.entries(message.tracks); + if (entries.length > 0) { + obj.tracks = {}; + entries.forEach(([k, v]) => { + obj.tracks[k] = TrackModelDefinition.toJSON(v); + }); + } + } + if (message.bounding_box !== undefined) { + obj.bounding_box = BoundingBox.toJSON(message.bounding_box); + } + return obj; + }, + + create, I>>(base?: I): ModelDefinition { + return ModelDefinition.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ModelDefinition { + const message = createBaseModelDefinition(); + message.armor = (object.armor !== undefined && object.armor !== null) + ? Armor.fromPartial(object.armor) + : createBaseArmor(); + message.turret_origin = (object.turret_origin !== undefined && object.turret_origin !== null) + ? Vector3.fromPartial(object.turret_origin) + : createBaseVector3(); + message.initial_turret_rotation = + (object.initial_turret_rotation !== undefined && object.initial_turret_rotation !== null) + ? InitialTurretRotation.fromPartial(object.initial_turret_rotation) + : undefined; + message.turrets = Object.entries(object.turrets ?? {}).reduce<{ [key: number]: TurretModelDefinition }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = TurretModelDefinition.fromPartial(value); + } + return acc; + }, + {}, + ); + message.tracks = Object.entries(object.tracks ?? {}).reduce<{ [key: number]: TrackModelDefinition }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = TrackModelDefinition.fromPartial(value); + } + return acc; + }, + {}, + ); + message.bounding_box = (object.bounding_box !== undefined && object.bounding_box !== null) + ? BoundingBox.fromPartial(object.bounding_box) + : createBaseBoundingBox(); + return message; + }, +}; + +function createBaseModelDefinition_TurretsEntry(): ModelDefinition_TurretsEntry { + return { key: 0, value: createBaseTurretModelDefinition() }; +} + +export const ModelDefinition_TurretsEntry: MessageFns = { + encode(message: ModelDefinition_TurretsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(message.key); + } + if (message.value !== undefined) { + TurretModelDefinition.encode(message.value, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ModelDefinition_TurretsEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseModelDefinition_TurretsEntry(); + 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 = TurretModelDefinition.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ModelDefinition_TurretsEntry { + return { + key: globalThis.Number(assertSet("ModelDefinition_TurretsEntry.key", object.key)), + value: TurretModelDefinition.fromJSON(assertSet("ModelDefinition_TurretsEntry.value", object.value)), + }; + }, + + toJSON(message: ModelDefinition_TurretsEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = TurretModelDefinition.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): ModelDefinition_TurretsEntry { + return ModelDefinition_TurretsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ModelDefinition_TurretsEntry { + const message = createBaseModelDefinition_TurretsEntry(); + message.key = object.key ?? 0; + message.value = (object.value !== undefined && object.value !== null) + ? TurretModelDefinition.fromPartial(object.value) + : undefined; + return message; + }, +}; + +function createBaseModelDefinition_TracksEntry(): ModelDefinition_TracksEntry { + return { key: 0, value: createBaseTrackModelDefinition() }; +} + +export const ModelDefinition_TracksEntry: MessageFns = { + encode(message: ModelDefinition_TracksEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(message.key); + } + if (message.value !== undefined) { + TrackModelDefinition.encode(message.value, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ModelDefinition_TracksEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseModelDefinition_TracksEntry(); + 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 = TrackModelDefinition.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ModelDefinition_TracksEntry { + return { + key: globalThis.Number(assertSet("ModelDefinition_TracksEntry.key", object.key)), + value: TrackModelDefinition.fromJSON(assertSet("ModelDefinition_TracksEntry.value", object.value)), + }; + }, + + toJSON(message: ModelDefinition_TracksEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = TrackModelDefinition.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): ModelDefinition_TracksEntry { + return ModelDefinition_TracksEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ModelDefinition_TracksEntry { + const message = createBaseModelDefinition_TracksEntry(); + message.key = object.key ?? 0; + message.value = (object.value !== undefined && object.value !== null) + ? TrackModelDefinition.fromPartial(object.value) + : undefined; + return message; + }, +}; + +function createBaseArmor(): Armor { + return { thickness: {}, spaced: [] }; +} + +export const Armor: MessageFns = { + encode(message: Armor, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + Object.entries(message.thickness).forEach(([key, value]) => { + Armor_ThicknessEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + }); + writer.uint32(18).fork(); + for (const v of message.spaced) { + writer.uint32(v); + } + writer.join(); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Armor { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseArmor(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + const entry1 = Armor_ThicknessEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.thickness[entry1.key] = entry1.value; + } + continue; + } + case 2: { + if (tag === 16) { + message.spaced.push(reader.uint32()); + + continue; + } + + if (tag === 18) { + const end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) { + message.spaced.push(reader.uint32()); + } + + continue; + } + + break; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Armor { + return { + thickness: isObject(object.thickness) + ? Object.entries(object.thickness).reduce<{ [key: number]: number }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = Number(value); + return acc; + }, {}) + : {}, + spaced: globalThis.Array.isArray(object?.spaced) ? object.spaced.map((e: any) => globalThis.Number(e)) : [], + }; + }, + + toJSON(message: Armor): unknown { + const obj: any = {}; + if (message.thickness) { + const entries = Object.entries(message.thickness); + if (entries.length > 0) { + obj.thickness = {}; + entries.forEach(([k, v]) => { + obj.thickness[k] = v; + }); + } + } + if (message.spaced?.length) { + obj.spaced = message.spaced.map((e) => Math.round(e)); + } + return obj; + }, + + create, I>>(base?: I): Armor { + return Armor.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Armor { + const message = createBaseArmor(); + message.thickness = Object.entries(object.thickness ?? {}).reduce<{ [key: number]: number }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = globalThis.Number(value); + } + return acc; + }, + {}, + ); + message.spaced = object.spaced?.map((e) => e) || []; + return message; + }, +}; + +function createBaseArmor_ThicknessEntry(): Armor_ThicknessEntry { + return { key: 0, value: 0 }; +} + +export const Armor_ThicknessEntry: MessageFns = { + encode(message: Armor_ThicknessEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(message.key); + } + if (message.value !== undefined) { + writer.uint32(21).float(message.value); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Armor_ThicknessEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseArmor_ThicknessEntry(); + 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 !== 21) { + break; + } + + message.value = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Armor_ThicknessEntry { + return { + key: globalThis.Number(assertSet("Armor_ThicknessEntry.key", object.key)), + value: globalThis.Number(assertSet("Armor_ThicknessEntry.value", object.value)), + }; + }, + + toJSON(message: Armor_ThicknessEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = message.value; + } + return obj; + }, + + create, I>>(base?: I): Armor_ThicknessEntry { + return Armor_ThicknessEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Armor_ThicknessEntry { + const message = createBaseArmor_ThicknessEntry(); + message.key = object.key ?? 0; + message.value = object.value ?? 0; + return message; + }, +}; + +function createBaseVector3(): Vector3 { + return { x: 0, y: 0, z: 0 }; +} + +export const Vector3: MessageFns = { + encode(message: Vector3, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.x !== 0) { + writer.uint32(13).float(message.x); + } + if (message.y !== 0) { + writer.uint32(21).float(message.y); + } + if (message.z !== 0) { + writer.uint32(29).float(message.z); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Vector3 { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseVector3(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.x = reader.float(); + continue; + } + case 2: { + if (tag !== 21) { + break; + } + + message.y = reader.float(); + continue; + } + case 3: { + if (tag !== 29) { + break; + } + + message.z = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Vector3 { + return { + x: globalThis.Number(assertSet("Vector3.x", object.x)), + y: globalThis.Number(assertSet("Vector3.y", object.y)), + z: globalThis.Number(assertSet("Vector3.z", object.z)), + }; + }, + + toJSON(message: Vector3): unknown { + const obj: any = {}; + if (message.x !== 0) { + obj.x = message.x; + } + if (message.y !== 0) { + obj.y = message.y; + } + if (message.z !== 0) { + obj.z = message.z; + } + return obj; + }, + + create, I>>(base?: I): Vector3 { + return Vector3.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Vector3 { + const message = createBaseVector3(); + message.x = object.x ?? 0; + message.y = object.y ?? 0; + message.z = object.z ?? 0; + return message; + }, +}; + +function createBaseInitialTurretRotation(): InitialTurretRotation { + return { yaw: 0, pitch: 0, roll: 0 }; +} + +export const InitialTurretRotation: MessageFns = { + encode(message: InitialTurretRotation, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.yaw !== 0) { + writer.uint32(13).float(message.yaw); + } + if (message.pitch !== 0) { + writer.uint32(21).float(message.pitch); + } + if (message.roll !== 0) { + writer.uint32(29).float(message.roll); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): InitialTurretRotation { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseInitialTurretRotation(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.yaw = reader.float(); + continue; + } + case 2: { + if (tag !== 21) { + break; + } + + message.pitch = reader.float(); + continue; + } + case 3: { + if (tag !== 29) { + break; + } + + message.roll = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): InitialTurretRotation { + return { + yaw: globalThis.Number(assertSet("InitialTurretRotation.yaw", object.yaw)), + pitch: globalThis.Number(assertSet("InitialTurretRotation.pitch", object.pitch)), + roll: globalThis.Number(assertSet("InitialTurretRotation.roll", object.roll)), + }; + }, + + toJSON(message: InitialTurretRotation): unknown { + const obj: any = {}; + if (message.yaw !== 0) { + obj.yaw = message.yaw; + } + if (message.pitch !== 0) { + obj.pitch = message.pitch; + } + if (message.roll !== 0) { + obj.roll = message.roll; + } + return obj; + }, + + create, I>>(base?: I): InitialTurretRotation { + return InitialTurretRotation.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): InitialTurretRotation { + const message = createBaseInitialTurretRotation(); + message.yaw = object.yaw ?? 0; + message.pitch = object.pitch ?? 0; + message.roll = object.roll ?? 0; + return message; + }, +}; + +function createBaseTurretModelDefinition(): TurretModelDefinition { + return { + bounding_box: createBaseBoundingBox(), + armor: createBaseArmor(), + model_id: 0, + gun_origin: createBaseVector3(), + guns: {}, + yaw: undefined, + }; +} + +export const TurretModelDefinition: MessageFns = { + encode(message: TurretModelDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.bounding_box !== undefined) { + BoundingBox.encode(message.bounding_box, writer.uint32(10).fork()).join(); + } + if (message.armor !== undefined) { + Armor.encode(message.armor, writer.uint32(18).fork()).join(); + } + if (message.model_id !== 0) { + writer.uint32(24).uint32(message.model_id); + } + if (message.gun_origin !== undefined) { + Vector3.encode(message.gun_origin, writer.uint32(34).fork()).join(); + } + Object.entries(message.guns).forEach(([key, value]) => { + TurretModelDefinition_GunsEntry.encode({ key: key as any, value }, writer.uint32(42).fork()).join(); + }); + if (message.yaw !== undefined) { + YawLimits.encode(message.yaw, writer.uint32(50).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): TurretModelDefinition { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseTurretModelDefinition(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.bounding_box = BoundingBox.decode(reader, reader.uint32()); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.armor = Armor.decode(reader, reader.uint32()); + continue; + } + case 3: { + if (tag !== 24) { + break; + } + + message.model_id = reader.uint32(); + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + message.gun_origin = Vector3.decode(reader, reader.uint32()); + continue; + } + case 5: { + if (tag !== 42) { + break; + } + + const entry5 = TurretModelDefinition_GunsEntry.decode(reader, reader.uint32()); + if (entry5.value !== undefined) { + message.guns[entry5.key] = entry5.value; + } + continue; + } + case 6: { + if (tag !== 50) { + break; + } + + message.yaw = YawLimits.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): TurretModelDefinition { + return { + bounding_box: BoundingBox.fromJSON(assertSet("TurretModelDefinition.bounding_box", object.bounding_box)), + armor: Armor.fromJSON(assertSet("TurretModelDefinition.armor", object.armor)), + model_id: globalThis.Number(assertSet("TurretModelDefinition.model_id", object.model_id)), + gun_origin: Vector3.fromJSON(assertSet("TurretModelDefinition.gun_origin", object.gun_origin)), + guns: isObject(object.guns) + ? Object.entries(object.guns).reduce<{ [key: number]: GunModelDefinition }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = GunModelDefinition.fromJSON(value); + return acc; + }, {}) + : {}, + yaw: isSet(object.yaw) ? YawLimits.fromJSON(object.yaw) : undefined, + }; + }, + + toJSON(message: TurretModelDefinition): unknown { + const obj: any = {}; + if (message.bounding_box !== undefined) { + obj.bounding_box = BoundingBox.toJSON(message.bounding_box); + } + if (message.armor !== undefined) { + obj.armor = Armor.toJSON(message.armor); + } + if (message.model_id !== 0) { + obj.model_id = Math.round(message.model_id); + } + if (message.gun_origin !== undefined) { + obj.gun_origin = Vector3.toJSON(message.gun_origin); + } + if (message.guns) { + const entries = Object.entries(message.guns); + if (entries.length > 0) { + obj.guns = {}; + entries.forEach(([k, v]) => { + obj.guns[k] = GunModelDefinition.toJSON(v); + }); + } + } + if (message.yaw !== undefined) { + obj.yaw = YawLimits.toJSON(message.yaw); + } + return obj; + }, + + create, I>>(base?: I): TurretModelDefinition { + return TurretModelDefinition.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): TurretModelDefinition { + const message = createBaseTurretModelDefinition(); + message.bounding_box = (object.bounding_box !== undefined && object.bounding_box !== null) + ? BoundingBox.fromPartial(object.bounding_box) + : createBaseBoundingBox(); + message.armor = (object.armor !== undefined && object.armor !== null) + ? Armor.fromPartial(object.armor) + : createBaseArmor(); + message.model_id = object.model_id ?? 0; + message.gun_origin = (object.gun_origin !== undefined && object.gun_origin !== null) + ? Vector3.fromPartial(object.gun_origin) + : createBaseVector3(); + message.guns = Object.entries(object.guns ?? {}).reduce<{ [key: number]: GunModelDefinition }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = GunModelDefinition.fromPartial(value); + } + return acc; + }, + {}, + ); + message.yaw = (object.yaw !== undefined && object.yaw !== null) ? YawLimits.fromPartial(object.yaw) : undefined; + return message; + }, +}; + +function createBaseTurretModelDefinition_GunsEntry(): TurretModelDefinition_GunsEntry { + return { key: 0, value: createBaseGunModelDefinition() }; +} + +export const TurretModelDefinition_GunsEntry: MessageFns = { + encode(message: TurretModelDefinition_GunsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(message.key); + } + if (message.value !== undefined) { + GunModelDefinition.encode(message.value, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): TurretModelDefinition_GunsEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseTurretModelDefinition_GunsEntry(); + 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 = GunModelDefinition.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): TurretModelDefinition_GunsEntry { + return { + key: globalThis.Number(assertSet("TurretModelDefinition_GunsEntry.key", object.key)), + value: GunModelDefinition.fromJSON(assertSet("TurretModelDefinition_GunsEntry.value", object.value)), + }; + }, + + toJSON(message: TurretModelDefinition_GunsEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = GunModelDefinition.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): TurretModelDefinition_GunsEntry { + return TurretModelDefinition_GunsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): TurretModelDefinition_GunsEntry { + const message = createBaseTurretModelDefinition_GunsEntry(); + message.key = object.key ?? 0; + message.value = (object.value !== undefined && object.value !== null) + ? GunModelDefinition.fromPartial(object.value) + : undefined; + return message; + }, +}; + +function createBaseYawLimits(): YawLimits { + return { min: 0, max: 0 }; +} + +export const YawLimits: MessageFns = { + encode(message: YawLimits, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.min !== 0) { + writer.uint32(13).float(message.min); + } + if (message.max !== 0) { + writer.uint32(21).float(message.max); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): YawLimits { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseYawLimits(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.min = reader.float(); + continue; + } + case 2: { + if (tag !== 21) { + break; + } + + message.max = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): YawLimits { + return { + min: globalThis.Number(assertSet("YawLimits.min", object.min)), + max: globalThis.Number(assertSet("YawLimits.max", object.max)), + }; + }, + + toJSON(message: YawLimits): unknown { + const obj: any = {}; + if (message.min !== 0) { + obj.min = message.min; + } + if (message.max !== 0) { + obj.max = message.max; + } + return obj; + }, + + create, I>>(base?: I): YawLimits { + return YawLimits.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): YawLimits { + const message = createBaseYawLimits(); + message.min = object.min ?? 0; + message.max = object.max ?? 0; + return message; + }, +}; + +function createBaseBoundingBox(): BoundingBox { + return { min: createBaseVector3(), max: createBaseVector3() }; +} + +export const BoundingBox: MessageFns = { + encode(message: BoundingBox, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.min !== undefined) { + Vector3.encode(message.min, writer.uint32(10).fork()).join(); + } + if (message.max !== undefined) { + Vector3.encode(message.max, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): BoundingBox { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseBoundingBox(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.min = Vector3.decode(reader, reader.uint32()); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.max = Vector3.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): BoundingBox { + return { + min: Vector3.fromJSON(assertSet("BoundingBox.min", object.min)), + max: Vector3.fromJSON(assertSet("BoundingBox.max", object.max)), + }; + }, + + toJSON(message: BoundingBox): unknown { + const obj: any = {}; + if (message.min !== undefined) { + obj.min = Vector3.toJSON(message.min); + } + if (message.max !== undefined) { + obj.max = Vector3.toJSON(message.max); + } + return obj; + }, + + create, I>>(base?: I): BoundingBox { + return BoundingBox.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): BoundingBox { + const message = createBaseBoundingBox(); + message.min = (object.min !== undefined && object.min !== null) + ? Vector3.fromPartial(object.min) + : createBaseVector3(); + message.max = (object.max !== undefined && object.max !== null) + ? Vector3.fromPartial(object.max) + : createBaseVector3(); + return message; + }, +}; + +function createBaseTrackModelDefinition(): TrackModelDefinition { + return { thickness: 0, origin: createBaseVector3() }; +} + +export const TrackModelDefinition: MessageFns = { + encode(message: TrackModelDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.thickness !== 0) { + writer.uint32(13).float(message.thickness); + } + if (message.origin !== undefined) { + Vector3.encode(message.origin, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): TrackModelDefinition { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseTrackModelDefinition(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.thickness = reader.float(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.origin = Vector3.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): TrackModelDefinition { + return { + thickness: globalThis.Number(assertSet("TrackModelDefinition.thickness", object.thickness)), + origin: Vector3.fromJSON(assertSet("TrackModelDefinition.origin", object.origin)), + }; + }, + + toJSON(message: TrackModelDefinition): unknown { + const obj: any = {}; + if (message.thickness !== 0) { + obj.thickness = message.thickness; + } + if (message.origin !== undefined) { + obj.origin = Vector3.toJSON(message.origin); + } + return obj; + }, + + create, I>>(base?: I): TrackModelDefinition { + return TrackModelDefinition.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): TrackModelDefinition { + const message = createBaseTrackModelDefinition(); + message.thickness = object.thickness ?? 0; + message.origin = (object.origin !== undefined && object.origin !== null) + ? Vector3.fromPartial(object.origin) + : createBaseVector3(); + return message; + }, +}; + +function createBaseGunModelDefinition(): GunModelDefinition { + return { armor: createBaseArmor(), thickness: 0, model_id: 0, pitch: createBasePitchLimits(), mask: undefined }; +} + +export const GunModelDefinition: MessageFns = { + encode(message: GunModelDefinition, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.armor !== undefined) { + Armor.encode(message.armor, writer.uint32(10).fork()).join(); + } + if (message.thickness !== 0) { + writer.uint32(21).float(message.thickness); + } + if (message.model_id !== 0) { + writer.uint32(24).uint32(message.model_id); + } + if (message.pitch !== undefined) { + PitchLimits.encode(message.pitch, writer.uint32(34).fork()).join(); + } + if (message.mask !== undefined && message.mask !== undefined) { + writer.uint32(45).float(message.mask); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): GunModelDefinition { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGunModelDefinition(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.armor = Armor.decode(reader, reader.uint32()); + continue; + } + case 2: { + if (tag !== 21) { + break; + } + + message.thickness = reader.float(); + continue; + } + case 3: { + if (tag !== 24) { + break; + } + + message.model_id = reader.uint32(); + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + message.pitch = PitchLimits.decode(reader, reader.uint32()); + continue; + } + case 5: { + if (tag !== 45) { + break; + } + + message.mask = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): GunModelDefinition { + return { + armor: Armor.fromJSON(assertSet("GunModelDefinition.armor", object.armor)), + thickness: globalThis.Number(assertSet("GunModelDefinition.thickness", object.thickness)), + model_id: globalThis.Number(assertSet("GunModelDefinition.model_id", object.model_id)), + pitch: PitchLimits.fromJSON(assertSet("GunModelDefinition.pitch", object.pitch)), + mask: isSet(object.mask) ? globalThis.Number(object.mask) : undefined, + }; + }, + + toJSON(message: GunModelDefinition): unknown { + const obj: any = {}; + if (message.armor !== undefined) { + obj.armor = Armor.toJSON(message.armor); + } + if (message.thickness !== 0) { + obj.thickness = message.thickness; + } + if (message.model_id !== 0) { + obj.model_id = Math.round(message.model_id); + } + if (message.pitch !== undefined) { + obj.pitch = PitchLimits.toJSON(message.pitch); + } + if (message.mask !== undefined && message.mask !== undefined) { + obj.mask = message.mask; + } + return obj; + }, + + create, I>>(base?: I): GunModelDefinition { + return GunModelDefinition.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): GunModelDefinition { + const message = createBaseGunModelDefinition(); + message.armor = (object.armor !== undefined && object.armor !== null) + ? Armor.fromPartial(object.armor) + : createBaseArmor(); + message.thickness = object.thickness ?? 0; + message.model_id = object.model_id ?? 0; + message.pitch = (object.pitch !== undefined && object.pitch !== null) + ? PitchLimits.fromPartial(object.pitch) + : createBasePitchLimits(); + message.mask = object.mask ?? undefined; + return message; + }, +}; + +function createBasePitchLimits(): PitchLimits { + return { min: 0, max: 0, front: undefined, back: undefined, transition: undefined }; +} + +export const PitchLimits: MessageFns = { + encode(message: PitchLimits, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.min !== 0) { + writer.uint32(13).float(message.min); + } + if (message.max !== 0) { + writer.uint32(21).float(message.max); + } + if (message.front !== undefined) { + PitchLimitsExtrema.encode(message.front, writer.uint32(26).fork()).join(); + } + if (message.back !== undefined) { + PitchLimitsExtrema.encode(message.back, writer.uint32(34).fork()).join(); + } + if (message.transition !== undefined && message.transition !== undefined) { + writer.uint32(45).float(message.transition); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): PitchLimits { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePitchLimits(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.min = reader.float(); + continue; + } + case 2: { + if (tag !== 21) { + break; + } + + message.max = reader.float(); + continue; + } + case 3: { + if (tag !== 26) { + break; + } + + message.front = PitchLimitsExtrema.decode(reader, reader.uint32()); + continue; + } + case 4: { + if (tag !== 34) { + break; + } + + message.back = PitchLimitsExtrema.decode(reader, reader.uint32()); + continue; + } + case 5: { + if (tag !== 45) { + break; + } + + message.transition = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): PitchLimits { + return { + min: globalThis.Number(assertSet("PitchLimits.min", object.min)), + max: globalThis.Number(assertSet("PitchLimits.max", object.max)), + front: isSet(object.front) ? PitchLimitsExtrema.fromJSON(object.front) : undefined, + back: isSet(object.back) ? PitchLimitsExtrema.fromJSON(object.back) : undefined, + transition: isSet(object.transition) ? globalThis.Number(object.transition) : undefined, + }; + }, + + toJSON(message: PitchLimits): unknown { + const obj: any = {}; + if (message.min !== 0) { + obj.min = message.min; + } + if (message.max !== 0) { + obj.max = message.max; + } + if (message.front !== undefined) { + obj.front = PitchLimitsExtrema.toJSON(message.front); + } + if (message.back !== undefined) { + obj.back = PitchLimitsExtrema.toJSON(message.back); + } + if (message.transition !== undefined && message.transition !== undefined) { + obj.transition = message.transition; + } + return obj; + }, + + create, I>>(base?: I): PitchLimits { + return PitchLimits.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): PitchLimits { + const message = createBasePitchLimits(); + message.min = object.min ?? 0; + message.max = object.max ?? 0; + message.front = (object.front !== undefined && object.front !== null) + ? PitchLimitsExtrema.fromPartial(object.front) + : undefined; + message.back = (object.back !== undefined && object.back !== null) + ? PitchLimitsExtrema.fromPartial(object.back) + : undefined; + message.transition = object.transition ?? undefined; + return message; + }, +}; + +function createBasePitchLimitsExtrema(): PitchLimitsExtrema { + return { min: 0, max: 0, range: 0 }; +} + +export const PitchLimitsExtrema: MessageFns = { + encode(message: PitchLimitsExtrema, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.min !== 0) { + writer.uint32(13).float(message.min); + } + if (message.max !== 0) { + writer.uint32(21).float(message.max); + } + if (message.range !== 0) { + writer.uint32(29).float(message.range); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): PitchLimitsExtrema { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePitchLimitsExtrema(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.min = reader.float(); + continue; + } + case 2: { + if (tag !== 21) { + break; + } + + message.max = reader.float(); + continue; + } + case 3: { + if (tag !== 29) { + break; + } + + message.range = reader.float(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): PitchLimitsExtrema { + return { + min: globalThis.Number(assertSet("PitchLimitsExtrema.min", object.min)), + max: globalThis.Number(assertSet("PitchLimitsExtrema.max", object.max)), + range: globalThis.Number(assertSet("PitchLimitsExtrema.range", object.range)), + }; + }, + + toJSON(message: PitchLimitsExtrema): unknown { + const obj: any = {}; + if (message.min !== 0) { + obj.min = message.min; + } + if (message.max !== 0) { + obj.max = message.max; + } + if (message.range !== 0) { + obj.range = message.range; + } + return obj; + }, + + create, I>>(base?: I): PitchLimitsExtrema { + return PitchLimitsExtrema.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): PitchLimitsExtrema { + const message = createBasePitchLimitsExtrema(); + message.min = object.min ?? 0; + message.max = object.max ?? 0; + message.range = object.range ?? 0; + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +function assertSet(field: string, value: T | undefined): T { + if (!isSet(value)) { + throw new TypeError(`Required field ${field} is not set`); + } + + return value as T; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/packages/core/src/protos/provision_definitions.proto b/packages/core/src/protos/provision_definitions.proto new file mode 100644 index 000000000..357c9975c --- /dev/null +++ b/packages/core/src/protos/provision_definitions.proto @@ -0,0 +1,18 @@ +syntax = "proto2"; + +package blitzkit; + +import "packages/core/src/protos/consumable_definitions.proto"; + +message ProvisionDefinitions { + map provisions = 1; +} + +message Provision { + required uint32 id = 1; + required string name = 2; + optional float crew = 3; + required bool game_mode_exclusive = 5; + repeated ConsumableTankFilter include = 6; + repeated ConsumableTankFilter exclude = 7; +} \ No newline at end of file diff --git a/packages/core/src/protos/provision_definitions.ts b/packages/core/src/protos/provision_definitions.ts new file mode 100644 index 000000000..2914a07de --- /dev/null +++ b/packages/core/src/protos/provision_definitions.ts @@ -0,0 +1,375 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/provision_definitions.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; +import { ConsumableTankFilter } from "./consumable_definitions"; + +export const protobufPackage = "blitzkit"; + +export interface ProvisionDefinitions { + provisions: { [key: number]: Provision }; +} + +export interface ProvisionDefinitions_ProvisionsEntry { + key: number; + value: Provision | undefined; +} + +export interface Provision { + id: number; + name: string; + crew?: number | undefined; + game_mode_exclusive: boolean; + include: ConsumableTankFilter[]; + exclude: ConsumableTankFilter[]; +} + +function createBaseProvisionDefinitions(): ProvisionDefinitions { + return { provisions: {} }; +} + +export const ProvisionDefinitions: MessageFns = { + encode(message: ProvisionDefinitions, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + Object.entries(message.provisions).forEach(([key, value]) => { + ProvisionDefinitions_ProvisionsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + }); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ProvisionDefinitions { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseProvisionDefinitions(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + const entry1 = ProvisionDefinitions_ProvisionsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.provisions[entry1.key] = entry1.value; + } + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ProvisionDefinitions { + return { + provisions: isObject(object.provisions) + ? Object.entries(object.provisions).reduce<{ [key: number]: Provision }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = Provision.fromJSON(value); + return acc; + }, {}) + : {}, + }; + }, + + toJSON(message: ProvisionDefinitions): unknown { + const obj: any = {}; + if (message.provisions) { + const entries = Object.entries(message.provisions); + if (entries.length > 0) { + obj.provisions = {}; + entries.forEach(([k, v]) => { + obj.provisions[k] = Provision.toJSON(v); + }); + } + } + return obj; + }, + + create, I>>(base?: I): ProvisionDefinitions { + return ProvisionDefinitions.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): ProvisionDefinitions { + const message = createBaseProvisionDefinitions(); + message.provisions = Object.entries(object.provisions ?? {}).reduce<{ [key: number]: Provision }>( + (acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = Provision.fromPartial(value); + } + return acc; + }, + {}, + ); + return message; + }, +}; + +function createBaseProvisionDefinitions_ProvisionsEntry(): ProvisionDefinitions_ProvisionsEntry { + return { key: 0, value: createBaseProvision() }; +} + +export const ProvisionDefinitions_ProvisionsEntry: MessageFns = { + encode(message: ProvisionDefinitions_ProvisionsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(message.key); + } + if (message.value !== undefined) { + Provision.encode(message.value, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): ProvisionDefinitions_ProvisionsEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseProvisionDefinitions_ProvisionsEntry(); + 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 = Provision.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): ProvisionDefinitions_ProvisionsEntry { + return { + key: globalThis.Number(assertSet("ProvisionDefinitions_ProvisionsEntry.key", object.key)), + value: Provision.fromJSON(assertSet("ProvisionDefinitions_ProvisionsEntry.value", object.value)), + }; + }, + + toJSON(message: ProvisionDefinitions_ProvisionsEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = Provision.toJSON(message.value); + } + return obj; + }, + + create, I>>( + base?: I, + ): ProvisionDefinitions_ProvisionsEntry { + return ProvisionDefinitions_ProvisionsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>( + object: I, + ): ProvisionDefinitions_ProvisionsEntry { + const message = createBaseProvisionDefinitions_ProvisionsEntry(); + message.key = object.key ?? 0; + message.value = (object.value !== undefined && object.value !== null) + ? Provision.fromPartial(object.value) + : undefined; + return message; + }, +}; + +function createBaseProvision(): Provision { + return { id: 0, name: "", crew: undefined, game_mode_exclusive: false, include: [], exclude: [] }; +} + +export const Provision: MessageFns = { + encode(message: Provision, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.id !== 0) { + writer.uint32(8).uint32(message.id); + } + if (message.name !== "") { + writer.uint32(18).string(message.name); + } + if (message.crew !== undefined && message.crew !== undefined) { + writer.uint32(29).float(message.crew); + } + 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): Provision { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseProvision(); + 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 = reader.string(); + continue; + } + case 3: { + if (tag !== 29) { + break; + } + + message.crew = 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): Provision { + return { + id: globalThis.Number(assertSet("Provision.id", object.id)), + name: globalThis.String(assertSet("Provision.name", object.name)), + crew: isSet(object.crew) ? globalThis.Number(object.crew) : undefined, + game_mode_exclusive: globalThis.Boolean(assertSet("Provision.game_mode_exclusive", object.game_mode_exclusive)), + 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: Provision): unknown { + const obj: any = {}; + if (message.id !== 0) { + obj.id = Math.round(message.id); + } + if (message.name !== "") { + obj.name = message.name; + } + if (message.crew !== undefined && message.crew !== undefined) { + obj.crew = message.crew; + } + 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>>(base?: I): Provision { + return Provision.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Provision { + const message = createBaseProvision(); + message.id = object.id ?? 0; + message.name = object.name ?? ""; + message.crew = object.crew ?? undefined; + 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; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; + +export type DeepPartial = T extends Builtin ? T + : T extends globalThis.Array ? globalThis.Array> + : T extends ReadonlyArray ? ReadonlyArray> + : T extends { $case: string; value: unknown } ? { $case: T["$case"]; value?: DeepPartial } + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin ? P + : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; + +function isObject(value: any): boolean { + return typeof value === "object" && value !== null; +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} + +function assertSet(field: string, value: T | undefined): T { + if (!isSet(value)) { + throw new TypeError(`Required field ${field} is not set`); + } + + return value as T; +} + +export interface MessageFns { + encode(message: T, writer?: BinaryWriter): BinaryWriter; + decode(input: BinaryReader | Uint8Array, length?: number): T; + fromJSON(object: any): T; + toJSON(message: T): unknown; + create, I>>(base?: I): T; + fromPartial, I>>(object: I): T; +} diff --git a/public/protos/reviews.proto b/packages/core/src/protos/reviews.proto similarity index 56% rename from public/protos/reviews.proto rename to packages/core/src/protos/reviews.proto index 482daeb75..2ad85ed16 100644 --- a/public/protos/reviews.proto +++ b/packages/core/src/protos/reviews.proto @@ -1,4 +1,4 @@ -syntax = "proto3"; +syntax = "proto2"; package blitzkit; @@ -7,11 +7,11 @@ message Reviews { } message Review { - float last_updated = 1; + required float last_updated = 1; repeated Video videos = 2; } message Video { - string id = 1; - string author = 2; + required string id = 1; + required string author = 2; } \ No newline at end of file diff --git a/packages/core/src/protos/reviews.ts b/packages/core/src/protos/reviews.ts new file mode 100644 index 000000000..4081dafb5 --- /dev/null +++ b/packages/core/src/protos/reviews.ts @@ -0,0 +1,376 @@ +// Code generated by protoc-gen-ts_proto. DO NOT EDIT. +// versions: +// protoc-gen-ts_proto v2.2.2 +// protoc v5.28.2 +// source: packages/core/src/protos/reviews.proto + +/* eslint-disable */ +import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; + +export const protobufPackage = "blitzkit"; + +export interface Reviews { + reviews: { [key: number]: Review }; +} + +export interface Reviews_ReviewsEntry { + key: number; + value: Review | undefined; +} + +export interface Review { + last_updated: number; + videos: Video[]; +} + +export interface Video { + id: string; + author: string; +} + +function createBaseReviews(): Reviews { + return { reviews: {} }; +} + +export const Reviews: MessageFns = { + encode(message: Reviews, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + Object.entries(message.reviews).forEach(([key, value]) => { + Reviews_ReviewsEntry.encode({ key: key as any, value }, writer.uint32(10).fork()).join(); + }); + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Reviews { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseReviews(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + const entry1 = Reviews_ReviewsEntry.decode(reader, reader.uint32()); + if (entry1.value !== undefined) { + message.reviews[entry1.key] = entry1.value; + } + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Reviews { + return { + reviews: isObject(object.reviews) + ? Object.entries(object.reviews).reduce<{ [key: number]: Review }>((acc, [key, value]) => { + acc[globalThis.Number(key)] = Review.fromJSON(value); + return acc; + }, {}) + : {}, + }; + }, + + toJSON(message: Reviews): unknown { + const obj: any = {}; + if (message.reviews) { + const entries = Object.entries(message.reviews); + if (entries.length > 0) { + obj.reviews = {}; + entries.forEach(([k, v]) => { + obj.reviews[k] = Review.toJSON(v); + }); + } + } + return obj; + }, + + create, I>>(base?: I): Reviews { + return Reviews.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Reviews { + const message = createBaseReviews(); + message.reviews = Object.entries(object.reviews ?? {}).reduce<{ [key: number]: Review }>((acc, [key, value]) => { + if (value !== undefined) { + acc[globalThis.Number(key)] = Review.fromPartial(value); + } + return acc; + }, {}); + return message; + }, +}; + +function createBaseReviews_ReviewsEntry(): Reviews_ReviewsEntry { + return { key: 0, value: createBaseReview() }; +} + +export const Reviews_ReviewsEntry: MessageFns = { + encode(message: Reviews_ReviewsEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.key !== undefined) { + writer.uint32(8).uint32(message.key); + } + if (message.value !== undefined) { + Review.encode(message.value, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Reviews_ReviewsEntry { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseReviews_ReviewsEntry(); + 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 = Review.decode(reader, reader.uint32()); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Reviews_ReviewsEntry { + return { + key: globalThis.Number(assertSet("Reviews_ReviewsEntry.key", object.key)), + value: Review.fromJSON(assertSet("Reviews_ReviewsEntry.value", object.value)), + }; + }, + + toJSON(message: Reviews_ReviewsEntry): unknown { + const obj: any = {}; + if (message.key !== undefined) { + obj.key = Math.round(message.key); + } + if (message.value !== undefined) { + obj.value = Review.toJSON(message.value); + } + return obj; + }, + + create, I>>(base?: I): Reviews_ReviewsEntry { + return Reviews_ReviewsEntry.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Reviews_ReviewsEntry { + const message = createBaseReviews_ReviewsEntry(); + message.key = object.key ?? 0; + message.value = (object.value !== undefined && object.value !== null) + ? Review.fromPartial(object.value) + : undefined; + return message; + }, +}; + +function createBaseReview(): Review { + return { last_updated: 0, videos: [] }; +} + +export const Review: MessageFns = { + encode(message: Review, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.last_updated !== 0) { + writer.uint32(13).float(message.last_updated); + } + for (const v of message.videos) { + Video.encode(v!, writer.uint32(18).fork()).join(); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): Review { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseReview(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 13) { + break; + } + + message.last_updated = reader.float(); + continue; + } + case 2: { + if (tag !== 18) { + break; + } + + message.videos.push(Video.decode(reader, reader.uint32())); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): Review { + return { + last_updated: globalThis.Number(assertSet("Review.last_updated", object.last_updated)), + videos: globalThis.Array.isArray(object?.videos) ? object.videos.map((e: any) => Video.fromJSON(e)) : [], + }; + }, + + toJSON(message: Review): unknown { + const obj: any = {}; + if (message.last_updated !== 0) { + obj.last_updated = message.last_updated; + } + if (message.videos?.length) { + obj.videos = message.videos.map((e) => Video.toJSON(e)); + } + return obj; + }, + + create, I>>(base?: I): Review { + return Review.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): Review { + const message = createBaseReview(); + message.last_updated = object.last_updated ?? 0; + message.videos = object.videos?.map((e) => Video.fromPartial(e)) || []; + return message; + }, +}; + +function createBaseVideo(): Video { + return { id: "", author: "" }; +} + +export const Video: MessageFns